作为Write for DOnations计划的一部分,作者选择了免费和开源基金来接受捐赠。
介绍
甲Linux的容器是一组从该系统的其余部分分离的处理。对于最终用户来说,Linux 容器就像一个虚拟机,但它要轻得多。您没有运行额外 Linux 内核的开销,并且容器不需要任何 CPU 硬件虚拟化支持。这意味着您可以在同一台服务器上创建比虚拟机更多的容器。
想象一下,您有一台服务器,应该为您的客户运行多个网站。一方面,每个网站都可以是同一 Apache 或 Nginx 网络服务器实例的虚拟主机/服务器块。另一方面,在使用虚拟机时,您将为每个网站创建一个单独的嵌套虚拟机。Linux 容器位于虚拟主机和虚拟机之间。
LXD允许您创建和管理这些容器。LXD 提供管理程序服务来管理容器的整个生命周期。在本教程中,您将配置 LXD 并使用它在容器中运行Nginx。然后,您会将来自 Internet 的流量路由到容器,以使示例网页可访问。
先决条件
要完成本教程,您需要具备以下条件:
-
运行 Ubuntu 20.04的服务器。要设置服务器,包括非 root sudo 用户和防火墙,您可以创建一个运行 Ubuntu 20.04 的 DigitalOcean Droplet,然后按照我们的初始服务器设置指南进行操作。记下您服务器的公共 IP 地址。我们稍后将其称为
your_server_ip
. -
至少 5GB 的块存储。要进行设置,您可以遵循DigitalOcean 的块存储卷快速入门。在 Block Storage 的配置中,选择
Manually Format & Mount
以允许 LXD 根据需要进行准备。您将使用它来存储与容器相关的所有数据。
注意:从 Ubuntu 20.04 开始,LXD 正式作为 snap 包提供。这是一种新的包格式,它有几个优点。snap 包可以安装在任何支持 snap 包的 Linux 发行版中。建议在运行 LXD snap 包时使用至少 2GB RAM 的服务器。下表总结了 LXD snap 包的特性:
特征 | 按包 |
---|---|
可用的 LXD 版本 | 2.0、3.0、4.0、4.x |
内存要求 | 中等,用于snapd服务。建议使用 2GB RAM 的服务器 |
升级注意事项 | 可以推迟 LXD 升级最多 60 天 |
从其他包格式升级的能力 | 可以从 deb 升级到 snap |
按照本教程的其余部分在 Ubuntu 20.04 中使用 snap 包中的 LXD。但是,如果您想使用 LXD deb 包,请参阅我们的教程如何在 Ubuntu 18.04 上安装和使用 LXD。
步骤 1 — 为 LXD 准备环境
在配置和运行 LXD 之前,您将准备服务器的环境。这涉及将您的 sudo 用户添加到该lxd
组并配置您的存储后端。
将您的非 root 帐户添加到lxd
Unix 组
设置非 root 帐户时,lxd
使用以下命令将它们添加到组中。该adduser
命令将用户帐户和 Unix 组作为参数,以便将用户帐户添加到现有的 Unix 组中:
- sudo adduser sammy lxd
现在申请新会员资格:
- su sammy
输入您的密码并按ENTER
。
最后,确认您的用户现在已添加到lxd
组中:
- id -nG
您将收到如下输出:
- sammy sudo lxd
现在您已准备好继续配置 LXD。
准备存储后端
首先,您将配置存储后端。
在 Ubuntu 上运行 LXD 时,推荐的存储后端是 ZFS 文件系统。ZFS 还可以与DigitalOcean Block Storage 配合使用。要在 LXD 中启用 ZFS 支持,首先更新您的软件包列表,然后安装zfsutils-linux
辅助软件包:
- sudo apt update
- sudo apt install -y zfsutils-linux
我们几乎准备好运行 LXD 初始化脚本。
在此之前,您必须确定并记下块存储的设备名称。
为此,请使用ls
检查/dev/disk/by-id/
目录:
- ls -l /dev/disk/by-id/
在此特定示例中,设备名称的完整路径为/dev/disk/by-id/scsi-0DO_Volume_volume-fra1-0
:
Outputtotal 0
lrwxrwxrwx 1 root root 9 Sep 16 20:30 scsi-0DO_Volume_volume-fra1-0 -> ../../sda
记下存储设备的完整文件路径。当您配置 LXD 时,您将在以下步骤中使用它。
第 2 步 – 初始化和配置 LXD
LXD 在 Ubuntu 20.04 中作为 snap 包提供。它是预先安装的,但您必须对其进行配置。
首先,验证是否安装了 LXD snap 包。该命令snap list
显示已安装的 snap 包:
- snap list
Ubuntu 20.04 预装了 LXD 4.0.3,并且正在跟踪4.0/stable
频道。LXD 4.0 支持五年(直到 2025 年)。它只会接收安全更新:
Output of the "snap list" command — Listing the installed snap packagesName Version Rev Tracking Publisher Notes
core18 20200724 1885 latest/stable canonical✓ base
lxd 4.0.3 16922 4.0/stable/… canonical✓ -
snapd 2.45.3.1 8790 latest/stable canonical✓ snapd
要查找有关 LXD 安装的 snap 包的更多信息,请运行snap info lxd
. 您将能够看到可用版本,包括上次更新包的时间。
您现在将配置 LXD。
为 LXD 配置存储选项
使用以下sudo lxd init
命令启动 LXD 初始化过程:
- sudo lxd init
首先,程序会询问您是否要启用 LXD 集群。就本教程而言,按ENTER
接受默认值no
,或键入no
然后按ENTER
。LXD 集群是一个高级主题,它可以为您的 LXD 设置实现高可用性,并且至少需要在集群中运行三个 LXD 服务器:
OutputWould you like to use LXD clustering? (yes/no) [default=no]: no
接下来的六个提示处理存储池。给出以下答复:
- 按
ENTER
配置新的存储池。 - 按
ENTER
接受默认存储池名称。 - 按
ENTER
接受默认zfs
存储后端。 - 按
ENTER
以创建新的 ZFS 池。 - 键入
yes
以使用现有块设备。 - 最后,输入块存储设备名称的完整路径(这是您之前记录的。它应该类似于:)。
/dev/disk/by-id/device_name
您的答案将如下所示:
OutputDo you want to configure a new storage pool? (yes/no) [default=yes]: yes
Name of the new storage pool [default=default]: default
Name of the storage backend to use (btrfs, dir, lvm, zfs) [default=zfs]: zfs
Create a new ZFS pool? (yes/no) [default=yes]: yes
Would you like to use an existing block device? (yes/no) [default=no]: yes
Path to the existing block device: /dev/disk/by-id/scsi-0DO_Volume_volume-fra1-01
您现在已经为 LXD 配置了存储后端。继续使用 LXD 的init
脚本,您现在将配置一些网络选项。
为 LXD 配置网络选项
LXD 现在询问您是否要连接到 MAAS(Metal As A Server)服务器。MAAS 是一种软件,它使裸机服务器看起来像一个虚拟机,并且像虚拟机一样被处理。
我们在独立模式下运行 LXD,因此接受默认值并回答no
:
OutputWould you like to connect to a MAAS server? (yes/no) [default=no]: no
然后要求您为 LXD 容器配置网桥。这将启用以下功能:
- 每个容器都会自动获得一个私有 IP 地址。
- 每个容器都可以通过专用网络相互通信。
- 每个容器都可以启动到 Internet 的连接。
- 默认情况下,每个容器都无法从 Internet 访问;除非您明确启用它,否则您无法从 Internet 启动连接并到达容器。您将在下一步中了解如何允许访问特定容器。
当被要求创建一个新的本地网桥时,选择yes
:
OutputWould you like to create a new local network bridge? (yes/no) [default=yes]: yes
然后接受默认名称,lxdbr0
:
OutputWhat should the new bridge be called? [default=lxdbr0]: lxdbr0
接受网桥专用 IP 地址范围的自动选择:
OutputWhat IPv4 address should be used? (CIDR subnet notation, “auto” or “none”) [default=auto]: auto
What IPv6 address should be used? (CIDR subnet notation, “auto” or “none”) [default=auto]: auto
最后,LXD 提出以下各种问题:
当询问您是否要通过网络管理 LXD 时,请按ENTER
或回答no
:
OutputWould you like LXD to be available over the network? (yes/no) [default=no]: no
当询问您是否要自动更新陈旧的容器映像时,请按ENTER
或回答yes
:
OutputWould you like stale cached images to be updated automatically? (yes/no) [default=yes] yes
当系统询问您是否要查看并保留刚刚创建的 YAML 配置时,请回答yes
是否要。否则,您按ENTER
或回答no
:
OutputWould you like a YAML "lxd init" preseed to be printed? (yes/no) [default=no]: no
脚本将在后台运行。没有收到任何输出是正常的。
您现在已经为 LXD 配置了网络和存储选项。接下来,您将创建您的第一个 LXD 容器。
第 2 步 – 创建和配置 LXD 容器
现在您已经成功配置了 LXD,您已经准备好创建和管理您的第一个容器。在LXD,你管理使用容器lxc
命令,随后的动作,如list
,launch
,start
,stop
和delete
。
使用lxc list
查看已安装的可用容器:
- lxc list
由于这是该lxc
命令第一次与 LXD 管理程序通信,因此它显示了有关如何启动容器的一些信息。最后,该命令显示一个空的容器列表。这是意料之中的,因为我们还没有创建:
Output of the "lxd list" commandTo start your first container, try: lxc launch ubuntu:18.04
+------+-------+------+------+------+-----------+
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
+------+-------+------+------+------+-----------+
现在创建一个运行 Nginx 的容器。为此,首先使用该lxc launch
命令创建并启动一个名为 的 Ubuntu 18.04 容器webserver
。
创建webserver
容器。在18.04
在ubuntu:18.04
是为Ubuntu 18.04的快捷方式。ubuntu:
是 LXD 图像的预配置存储库的标识符。您还可以使用ubuntu:bionic
图像名称:
- lxc launch ubuntu:20.04 webserver
注意:您可以通过运行找到所有可用 Ubuntu 映像的完整列表,lxc image list ubuntu:
通过运行lxc image list images:
. 这两个ubuntu:
和images:
是容器的图像库。对于每个容器映像,您可以使用命令获取更多信息lxc image info ubuntu:20.04
。
由于这是您第一次创建容器,因此此命令会从 Internet 下载容器映像并将其缓存。新容器完成下载后,您将看到以下输出:
OutputCreating webserver
Starting webserver
随着webserver
容器启动,使用lxc list
命令来显示它的相关信息。我们添加--columns ns4
是为了仅显示name
,state
和IPv4
address的列。默认lxc list
命令显示另外三列:IPv6 地址、容器是持久的还是临时的,以及每个容器是否有可用的快照:
- lxc list --columns ns4
输出显示一个表,其中包含每个容器的名称、当前状态、IP 地址和类型:
Output+-----------+---------+------------------------------------+
| NAME | STATE | IPV4 |
+-----------+---------+------------------------------------+
| webserver | RUNNING | your_webserver_container_ip (eth0) |
+-----------+---------+------------------------------------+
LXD 的 DHCP 服务器提供此 IP 地址,并且在大多数情况下,即使服务器重新启动,它也会保持不变。但是,在以下步骤中,您将创建iptables
规则以将连接从 Internet 转发到容器。因此,您应该指示 LXD 的 DHCP 服务器始终为容器提供相同的 IP 地址。
以下命令集将配置容器以获取静态 IP 分配。首先,您将覆盖eth0
从默认 LXD 配置文件继承的设备的网络配置。这允许您设置静态 IP 地址,以确保 Web 流量进出容器的正确通信。
具体来说,lxc config device
是一个执行config
操作以配置device
. 第一行具有从容器override
覆盖设备的子操作。第二行有一个子动作,将容器的设备字段设置为开始时DHCP服务器提供的IP地址。eth0
webserver
ipv4.address
eth0
webserver
运行第一个config
命令:
- lxc config device override webserver eth0
您将收到如下输出:
OutputDevice eth0 overridden for webserver
现在设置静态IP:
- lxc config device set webserver eth0 ipv4.address your_webserver_container_ip
如果命令成功,您将不会收到任何输出。
重启容器:
- lxc restart webserver
现在检查容器的状态:
- lxc list
您应该看到容器RUNNING
和IPV4
地址是您的静态地址。
您已准备好在容器内安装和配置 Nginx。
第 3 步 – 在 LXD 容器内配置 Nginx
在此步骤中,您将连接到webserver
容器并配置 Web 服务器。
使用lxc shell
命令连接到容器 ,该命令获取容器的名称并在容器内启动一个 shell:
- lxc shell webserver
进入容器后,您的 shell 提示符将如下所示:
-
这个shell,即使是root shell,也仅限于容器。你在这个 shell 中运行的任何东西都留在容器中,不能逃逸到主机服务器。
注意:将 shell 放入容器时,您可能会看到诸如mesg: ttyname failed: No such device
. 当容器中的 shell 尝试mesg
从配置文件运行命令时,会产生此消息/root/.profile
。您可以放心地忽略它。为避免看到它,您可以mesg n || true
从/root/.profile
.
进入容器后,更新包列表并安装 Nginx:
- apt update
- apt install nginx
安装 Nginx 后,您现在将编辑默认的 Nginx 网页。具体来说,您将添加两行文本,以便清楚地表明此站点托管在webserver
容器内。
使用nano
或您喜欢的编辑器,打开文件/var/www/html/index.nginx-debian.html
:
- nano /var/www/html/index.nginx-debian.html
将两个突出显示的短语添加到文件中:
/var/www/html/index.nginx-debian.html<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx on LXD container webserver!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx on LXD container webserver!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
...
您已经在两个地方编辑了该文件并专门添加了文本on LXD container webserver
。保存文件并退出文本编辑器。
现在注销容器:
- logout
一旦服务器的默认提示返回,用于curl
测试容器中的 Web 服务器是否正常工作。为此,您需要使用lxc list
之前使用命令找到的 Web 容器的 IP 地址。
使用curl
测试Web服务器:
- curl http://your_webserver_container_ip
您将收到 Nginx 默认的 HTML 欢迎页面作为输出。请注意,它包括您的编辑:
Output<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx on LXD container webserver!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx on LXD container webserver!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
...
Web 服务器正在运行,但您只能在使用私有 IP 的主机上访问它。在下一步中,您将外部请求路由到此容器,以便世界可以通过 Internet 访问您的网站。
第 4 步 – 使用 LXD 将传入连接转发到 Nginx 容器
现在您已经配置了 Nginx,是时候将 webserver 容器连接到 Internet。首先,您需要设置服务器以将其可能在端口80
上接收到的任何连接转发到webserver
容器。为此,您将创建一个iptables
规则来转发网络连接。您可以在我们的教程“IPtables 防火墙的工作原理”和“ IPtables 要点:常用防火墙规则和命令”中了解有关 IPTables 的更多信息。
该iptables
命令需要两个IP地址:服务器的公网IP地址(your_server_ip
)和webserver
容器的私网IP地址(your_webserver_container_ip
),可以通过lxc list
命令获取。
执行此命令以创建新的 IPtables 规则:
- PORT=80 PUBLIC_IP=your_server_ip CONTAINER_IP=your_container_ip IFACE=eth0 sudo -E bash -c 'iptables -t nat -I PREROUTING -i $IFACE -p TCP -d $PUBLIC_IP --dport $PORT -j DNAT --to-destination $CONTAINER_IP:$PORT -m comment --comment "forward to the Nginx container"'
让我们研究该命令:
-t nat
指定我们使用该nat
表进行地址转换。-I PREROUTING
指定我们将规则添加到 PREROUTING 链中。-i $IFACE
指定 interfaceeth0
,它是 Droplets 主机上的默认公共网络接口。-p TCP
说我们正在使用 TCP 协议。-d $PUBLIC_IP
指定规则的目标 IP 地址。--dport $PORT
: 指定目的端口(如80
)。-j DNAT
表示我们要执行跳转到目标 NAT (DNAT)。--to-destination $CONTAINER_IP:$PORT
表示我们希望请求转到特定容器的 IP 地址和目标端口。
注意:您可以重复使用此命令来设置转发规则。重置变量PORT
, PUBLIC_IP
,CONTAINER_IP
和IFACE
在行的开头。只需更改突出显示的值。
现在列出您的 IPTables 规则:
- sudo iptables -t nat -L PREROUTING
你会看到这样的输出:
Output Chain PREROUTING (policy ACCEPT)
target prot opt source destination
DNAT tcp -- anywhere your_server_ip tcp dpt:http /* forward to this container */ to:your_container_ip:80
...
现在测试网络服务器是否可以从互联网访问
使用curl
本地机器上的命令来测试连接:
- curl --verbose 'http://your_server_ip'
您将看到标题后跟您在容器中创建的网页内容:
Output* Trying your_server_ip...
* Connected to your_server_ip (your_server_ip) port 80 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.47.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: nginx/1.10.0 (Ubuntu)
...
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx on LXD container webserver!</title>
<style>
body {
...
这确认请求将发送到容器。
最后,您将保存防火墙规则,以便在重新启动后重新应用。
为此,首先安装iptables-persistent
软件包:
- sudo apt install iptables-persistent
安装软件包时,应用程序会提示您保存当前的防火墙规则。接受并保存所有当前规则。
当您重新启动计算机时,将加载防火墙规则。此外,您的 LXD 容器中的 Nginx 服务将自动重启。
您已成功配置 LXD。在最后一步中,您将学习如何停止和销毁服务。
第 5 步 – 使用 LXD 停止和删除容器
您可以决定要取下容器并将其删除。在此步骤中,您将停止并移除容器。
首先,停止容器:
- lxc stop webserver
使用lxc list
命令验证状态:
- lxc list
您将看到容器的状态显示为STOPPED
:
Output+-----------+---------+------+------+------------+-----------+
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
+-----------+---------+------+------+------------+-----------+
| webserver | STOPPED | | | PERSISTENT | 0 |
+-----------+---------+------+------+------------+-----------+
要移除容器,请使用lxc delete
:
- lxc delete webserver
lxc list
再次运行显示没有容器在运行:
- lxc list
该命令将输出以下内容:
+------+-------+------+------+------+-----------+
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
+------+-------+------+------+------+-----------+
使用该lxc help
命令查看其他选项。
要删除将流量路由到容器的防火墙规则,请首先使用此命令在规则列表中找到该规则,它将行号与每个规则相关联:
- sudo iptables -t nat -L PREROUTING --line-numbers
您将看到您的规则,以行号为前缀,如下所示:
OutputChain PREROUTING (policy ACCEPT)
num target prot opt source destination
1 DNAT tcp -- anywhere your_server_ip tcp dpt:http /* forward to the Nginx container */ to:your_container_ip
使用该行号删除规则:
- sudo iptables -t nat -D PREROUTING 1
再次列出规则以确保删除:
- sudo iptables -t nat -L PREROUTING --line-numbers
删除规则:
OutputChain PREROUTING (policy ACCEPT)
num target prot opt source destination
现在保存更改,以便在您重新启动服务器时规则不会返回:
- sudo netfilter-persistent save
您现在可以使用您自己的设置启动另一个容器并添加新的防火墙规则以将流量转发给它。
结论
在本教程中,您安装并配置了 LXD。然后,您使用在 LXD 容器内运行的 Nginx 创建了一个网站,并将其公开给我们 IPtables。
从这里,您可以配置更多网站,每个网站都限制在自己的容器中,并使用反向代理将流量定向到适当的容器。教程如何在 Ubuntu 16.04 上使用 LXD 使用 Nginx 和 HAProxy 托管多个网站将引导您完成该设置。
有关如何使用 LXD 的更多信息,请参阅LXD 参考文档。
要使用 LXD 进行练习,您可以在线试用 LXD并按照基于网络的教程进行操作。
要获得 LXD 的用户支持,请访问LXD 论坛。