介绍
一个 Linux 容器是由使用 Linux 内核安全功能(如名称空间和控制组)与其他系统隔离的过程的组合,它类似于虚拟机的构造,但重量更轻;你没有执行额外的内核或模拟硬件的能力,这意味着你可以在同一服务器上轻松创建多个容器。
例如,想象一下你有一个服务器,为你的客户运行多个网站。在传统的安装中,每个网站都将是同一个 Apache 或 Nginx 网页服务器实例的虚拟主机。但是在 Linux 容器中,每个网页都可以设置在自己的容器中,有自己的网页服务器。
LXD允许您创建和管理这些容器。LXD提供一个超视觉服务来管理容器的整个生命周期。在本教程中,您将配置LXD并使用它在容器中运行 Nginx。
前提条件
要完成本教程,您将需要以下内容:
- 一个 Ubuntu 16.04 服务器,根据教程 Initial Server Setup with Ubuntu 16.04配置,具有 sudo 非根用户和防火墙。
- 可选地,按照教程 Getting Started with DigitalOcean Block Storage添加 20GB 或更多区块存储空间。
步骤 1 – 配置 LXD
LXD已经安装在Ubuntu上,但在您可以在服务器上使用它之前需要正确配置,您必须设置您的用户帐户来管理容器,然后配置存储备份类型来存储容器并配置网络。
使用非根用户帐户登录到服务器,然后将您的用户添加到lxd
组,以便您可以使用它来执行所有容器管理任务:
1sudo usermod --append --groups lxd sammy
退出服务器并再次登录,以便您的新的 SSH 会话将与新组成员更新。
现在配置存储后端. LXD 推荐的存储后端是 ZFS 文件系统,存储在预分配的文件中或使用 Block Storage。
1sudo apt-get update
2sudo apt-get install zfsutils-linux
您现在可以配置 LXD. 使用lxd init
命令启动 LXD 初始化过程:
1sudo lxd init
您将被要求指定存储备端的详细信息.一旦完成该配置,您将为容器配置网络。
首先,您将被问到是否要配置新的存储池,您应该回答是
。
1Do you want to configure a new storage pool (yes/no) [default=yes]? yes
然后,您将被提示选择存储后端,您将得到两种选择:dir
或zfs
。dir
选项告诉LXD在服务器文件系统中的目录中存储容器。
我们将使用zfs
选项。通过使用zfs
,我们获得了存储效率和更好的响应性,例如,如果我们从相同的初始容器图像创建十个容器,它们都将只使用单个容器图像的磁盘空间。
1[secondary_label Output]
2Name of the storage backend to use (dir or zfs) [default=zfs]: zfs
一旦您选择zfs
,您将被要求创建一个新的ZFS池,并命名池. 选择是
来创建池,然后叫池lxd
:
1[secondary_label Output]
2Create a new ZFS pool (yes/no) [default=yes]? yes
3Name of the new ZFS pool [default=lxd]: lxd
然后,您将被问到是否想要使用现有区块设备:
1[secondary_label Output]
2Would you like to use an existing block device (yes/no) [default=no]?
如果你说是
,你将不得不告诉LXD在哪里找到该设备。如果你说不
,LXD将使用预分配的文件。
以下有两个部分,取决于您是否想要使用预分配文件或锁定设备。 按照适当的步骤执行您的案例。 一旦您指定了存储机制,您将为容器配置网络选项。
选择1 – 使用预分配的文件
如果您没有访问单独的区块存储设备来存储容器,则会使用预分配文件。
首先,当被要求使用现有区块设备时,请输入不
:
1[secondary_label Output]
2Would you like to use an existing block device (yes/no) [default=no]? no
接下来,您将被要求指定 **loop 设备的尺寸,这就是 LXD 称为预分配文件的尺寸。 使用预分配文件的建议默认尺寸:
1[secondary_label Output]
2Size in GB of the new loop device (1GB minimum) [default=15]: 15
一般来说,15GB确实是你应该创建的最小尺寸;你想预分配足够的空间,这样你一旦创建了容器,就至少有10GB的空闲空间。
一旦设备配置完毕,您将被要求配置网络设置,然后转到 步骤 2来继续设置。
选择2 – 使用一个区块设备
如果您将使用 Block Storage 作为存储备端,则需要找到指向您创建的 Block Storage 容量的设备,以便在 LXD 配置中指定它。
尋找裝置以尋找命令來格式化音量。 特別是,尋找在「sudo mkfs.ext4 -F」命令中指定的路徑。 不要從該頁面執行任何命令,因為我們只需要找到正確的裝置名稱來給LXD。 下面的圖表顯示了音量裝置名稱的例子。 您只需要由紅線突出的一部分:
您还可以使用以下命令识别设备名称:
1ls -l /dev/disk/by-id/
2total 0
3lrwxrwxrwx 1 root root 9 Sep 16 20:30 scsi-0DO_Volume_volume-fra1-01 -> ../../sda
在这种情况下,该卷的设备名称为 /dev/disk/by-id/scsi-0D0_Volume_volume-fra1-01
,尽管您的名称可能不同。
一旦您确定了音量设备名称,请继续进行LXD安装。当您被提示使用现有区块设备时,请选择是
并提供到您的设备的路径:
1[secondary_label Output of the "lxd init" command]
2Would you like to use an existing block device (yes/no) [default=no]? yes
3Path to the existing block device: /dev/disk/by-id/scsi-0DO_Volume_volume-fra1-01
一旦您指定磁盘,您将被要求配置网络选项。
步骤 2 - 配置网络
一旦配置了存储后端,您将被提示为 LXD 配置网络。
首先,LXD 询问您是否希望在网络上实现可访问性。选择是
将允许您从本地计算机管理 LXD,而无需 SSH 到该服务器。
1[secondary_label Output of the "lxd init" command — LXD over the network]
2Would you like LXD to be available over the network (yes/no) [default=no]? no
如果您想启用此选项,请阅读 LXD 2.0:远程主机和容器迁移以了解更多信息。
然后,我们被要求为 LXD 容器配置网络桥梁,从而实现以下功能:
- 每个集装箱都会自动获得一个私有 IP 地址。
- 集装箱可以通过私有网络相互通信。
- 每个集装箱都可以启动连接到互联网。
当被要求配置 LXD 桥梁时,选择是
:
1[secondary_label Output of the "lxd init" command — Networking for the containers]
2Do you want to configure the LXD bridge (yes/no) [default=yes]? yes
然后你会被介绍到以下对话:
确认您想要设置网络桥梁。
您将被要求命名桥梁. 接受默认值。
您将被要求执行IPv4和IPv6的网络配置。
当您被要求设置 IPv4 子网时,请选择 Yes. 您将被告知它为您配置了随机子网。
当被要求提供有效的 IPv4 地址时,请接受默认值。
当被提示获得有效的 CIDR 面具时,接受默认值。
当您被提示为第一个 DHCP 地址时,请接受默认值,并对最后一个 DHCP 地址以及最大 DHCP 客户端数执行相同操作。
当被要求NAT IPv4流量时,选择 Yes。
当您被要求配置 IPv6 子网时,请选择 No. 网络设置完成后,您将看到以下输出:
1[secondary_label Output]
2Warning: Stopping lxd.service, but it can still be activated by:
3 lxd.socket
4LXD has been successfully configured.
您已经准备好创建您的容器。
步骤三:创建 Nginx 容器
您已成功配置 LXD,现在您已经准备好创建和管理您的第一个容器。
使用lxc 列表
查看可用的安装容器:
1lxc list
您将看到以下输出:
1[secondary_label Output of the "lxd list" command]
2Generating a client certificate. This may take a minute...
3If this is your first time using LXD, you should also run: sudo lxd init
4To start your first container, try: lxc launch ubuntu:16.04
5
6+------+-------+------+------+------+-----------+
7| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
8+------+-------+------+------+------+-----------+
由于这是lxc
命令首次与 LXD 超视图进行通信,因此输出会告诉您,该命令会自动创建一个客户端证书,以便与 LXD 进行安全的通信。
要做到这一点,我们将使用lxc launch
命令创建并启动一个名为webserver
的Ubuntu 16.04容器。
创建Web服务器
容器:
1lxc launch ubuntu:x webserver
ubuntu:x
中的x
是Xenial的第一个字母的缩写,它是Ubuntu 16.04的代码名称,ubuntu:
是预先配置的LXD图像存储库的标识符。
<$>[注]
注:您可以通过运行lxc 图像列表 ubuntu:
和其他分布来找到所有可用的 Ubuntu 图像的完整列表,并运行lxc 图像列表图像:
。
因为这是您第一次创建一个容器,此命令将从互联网下载容器图像,并将其本地缓存,以便如果您创建一个新的容器,它将更快地创建。
1[secondary_label Output]
2Generating a client certificate. This may take a minute...
3If this is your first time using LXD, you should also run: sudo lxd init
4To start your first container, try: lxc launch ubuntu:16.04
5
6Creating webserver
7Retrieving image: 100%
8Starting webserver
现在容器正在运行,请使用lxc 列表
命令显示有关其信息:
1lxc list
输出显示了每个容器的名称、当前状态、IP地址、类型以及是否有截图。
1[label Output]
2+-----------+---------+-----------------------+------+------------+-----------+
3| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
4+-----------+---------+-----------------------+------+------------+-----------+
5| webserver | RUNNING | 10.10.10.100 (eth0) | | PERSISTENT | 0 |
6+-----------+---------+-----------------------+------+------------+-----------+
<$>[注]
注: 如果您在 LXD 中启用了 IPv6,则lxc 列表
命令的输出可能对您的屏幕来说太宽了。
请注意容器的IPv4地址,您将需要它来配置您的防火墙,以允许来自外部世界的流量。
现在让我们在容器内部设置 Nginx:
步骤 4 – 配置 Nginx 容器
让我们连接到Web服务器
容器并配置Web服务器。
使用「lxc exec」命令连接到容器,该命令采用容器名称和执行的命令:
1lxc exec webserver -- sudo --login --user ubuntu
第一个--
字符串表示lxc
的命令参数应该停留在那里,其余的行将作为在容器内部执行的命令传递。
<$>[注]
注: 如果您需要作为 root连接到容器,请使用命令 lxc exec webserver -- /bin/bash
。
一旦进入容器,你的壳提示现在看起来如下。
1[secondary_label Output]
2[environment second]
3ubuntu@webserver:~$
容器中的这个 ubuntu用户具有预配置的sudo
访问,并且可以运行sudo
命令而无需提供密码。这个壳仅限于容器的边界。
让我们在这个容器中设置 Nginx。 更新容器内的 Ubuntu 实例的包列表并安装 Nginx:
1[environment second]
2sudo apt-get update
3sudo apt-get install nginx
然后编辑该网站的默认网页,并添加一些文本,清楚地表明该网站是在网页服务器
容器中托管的。
1[environment second]
2sudo nano /var/www/html/index.nginx-debian.html
对文件进行以下更改:
1[label Edited file /var/www/html/index.nginx-debian.html]
2<!DOCTYPE html>
3<html>
4<head>
5<title>Welcome to nginx on LXD container webserver!</title>
6<style>
7 body {
8 width: 35em;
9 margin: 0 auto;
10 font-family: Tahoma, Verdana, Arial, sans-serif;
11 }
12</style>
13</head>
14<body>
15<h1>Welcome to nginx on LXD container webserver!</h1>
16<p>If you see this page, the nginx web server is successfully installed and
17working. Further configuration is required.</p>
18...
我们在两个地方编辑了文件,并特别添加了文本LXD 容器 Web 服务器
。
现在退出容器并返回主机服务器:
1[environment second]
2logout
使用curl
来测试容器中的 Web 服务器是否正在工作. 您需要使用lxd 列表
命令发现的 Web 容器的 IP 地址。
1curl http://10.10.10.100/
产量应该是:
1[secondary_label Output]
2<!DOCTYPE html>
3<html>
4<head>
5<title>Welcome to nginx on LXD container webserver!</title>
6<style>
7 body {
8 width: 35em;
9 margin: 0 auto;
10 font-family: Tahoma, Verdana, Arial, sans-serif;
11 }
12</style>
13</head>
14<body>
15<h1>Welcome to nginx on LXD container webserver!</h1>
16<p>If you see this page, the nginx web server is successfully installed and
17working. Further configuration is required.</p>
18...
网络服务器正在工作,但我们只能通过私人IP访问它,让我们将外部请求路由到这个容器,以便世界可以访问我们的网站。
步骤 5 – 向 Nginx 容器发送接入连接
拼图的最后一部分是将网页服务器容器连接到互联网。 Nginx 安装在一个容器中,并且默认情况下是无法从互联网上访问的。我们需要设置我们的服务器,以便将其在端口 80 上从互联网接收的任何连接传输到网页服务器
容器。 为了做到这一点,我们将创建一个iptables
规则来传输连接。 您可以在 How the IPtables Firewall Works和 IPtables Essentials: Common Firewall Rules and Commands中了解更多有关IPTables的信息。
iptables
命令需要两个IP地址:服务器的公共IP地址(your_server_ip
)和nginx
容器的私人IP地址(your_webserver_container_ip
),您可以使用lxc列表
命令获取。
运行此命令来创建规则:
1PORT=80 PUBLIC_IP=your_server_ip CONTAINER_IP=your_container_ip \
2sudo -E bash -c 'iptables -t nat -I PREROUTING -i eth0 -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 eth0
指明界面 eth0,这是Droplets上的默认公共接口。-p TCP
表示我们正在使用 TCP 协议。-d $PUBLIC_IP
指明规则的目的地 IP 地址。
<$>[注]
注: 您可以重复使用此命令来设置转发规则,只需在行开始时设置变量 PORT
、 PUBLIC_IP
和 CONTAINER_IP
。
您可以通过运行此命令列出 IPTables 规则:
1sudo iptables -t nat -L PREROUTING
你会看到类似于此的输出:
1[secondary_label Output]
2Chain PREROUTING (policy ACCEPT)
3target prot opt source destination
4DNAT tcp -- anywhere your_server_ip tcp dpt:http /* forward to this container */ to:your_container_ip:80
5...
现在测试网页服务器是否实际上可以从互联网访问,通过使用这样的弯曲
命令从本地计算机访问它:
1[environment local]
2curl --verbose 'http://your_server_ip'
您将看到标题,然后是您在容器中创建的网页的内容:
1[secondary_label Output]
2[environment local]
3* Trying your_server_ip...
4* Connected to your_server_ip (your_server_ip) port 80 (#0)
5> GET / HTTP/1.1
6> User-Agent: curl/7.47.0
7> Accept: */*
8>
9< HTTP/1.1 200 OK
10< Server: nginx/1.10.0 (Ubuntu)
11...
12<!DOCTYPE html>
13<html>
14<head>
15<title>Welcome to nginx on LXD container webserver!</title>
16<style>
17 body {
18...
这确认请求正在进入容器。
最后,要保存防火墙规则,以便在重新启动后重新应用,请安装iptables-persistent
包:
1sudo apt-get install iptables-persistent
安装包时,您将被要求保存当前的防火墙规则. 接受并保存所有当前的规则。
当您重新启动机器时,防火墙规则将存在,此外,您的 LXD 容器中的 Nginx 服务将自动重新启动。
现在你已经设置了一切,让我们看看如何打破它。
步骤 5 – 停止和移除容器
你可能会决定你想取下容器并更换它,让我们通过这个过程:
要停止容器,请使用lxc stop
:
1lxc stop webserver
使用lxc 列表
命令来验证状态。
1[secondary_label Output]
2+-----------+---------+------+------+------------+-----------+
3| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
4+-----------+---------+------+------+------------+-----------+
5| webserver | STOPPED | | | PERSISTENT | 0 |
6+-----------+---------+------+------+------------+-----------+
若要移除容器,请使用‘lxc delete’:
1lxc delete webserver
运行lxc 列表
再次显示没有运行容器:
1[secondary_label Output]
2+------+-------+------+------+------+-----------+
3| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
4+------+-------+------+------+------+-----------+
使用lxc 帮助
命令查看其他选项。
若要移除将流量路由到容器的防火墙规则,请先使用此命令在规则列表中找到该规则,该命令将一行号与每个规则关联:
1sudo iptables -t nat -L PREROUTING --line-numbers
您将看到您的规则,前缀为行号,如下:
1[secondary_label Output]
2Chain PREROUTING (policy ACCEPT)
3num target prot opt source destination
41 DNAT tcp -- anywhere your_server_ip tcp dpt:http /* forward to the Nginx container */ to:your_container_ip
使用该行数删除规则:
1sudo iptables -t nat -D PREROUTING 1
通过重新列出规则来确保规则消失:
1`sudo iptables -t nat -L PREROUTING --line-numbers`
规则将消失:
1[secondary_label Output]
2Chain PREROUTING (policy ACCEPT)
3num target prot opt source destination
现在将更改保存,以便在重新启动服务器时不返回规则:
1sudo netfilter-persistent save
您现在可以将另一个容器带上自己的设置,并添加一个新的防火墙规则来向其传输流量。
结论
你已经设置了使用 Nginx 在 LXD 容器中运行的网站,从这里开始,你可以配置更多的网站,每个网站都被限制在自己的容器上,并使用反向代理来将流量引导到相应的容器上。
LXD 还允许您拍摄集装箱的完整状态的截图,这使得更容易创建备份并在稍后重新滚动集装箱,并且如果您在两个不同的服务器上安装 LXD,则可以连接它们并通过互联网迁移服务器之间的集装箱。
有关 LXD 的更多信息,请参阅 LXD 2.0 上的此系列博客帖子由 LXD 的维护者撰写。
您也可以尝试LXD在线(https://linuxcontainers.org/lxd/try-it/),并遵循基于Web的教程来获得更多的实践。