如何在 Ubuntu 16.04 上设置和使用 LXD

介绍

一个 Linux 容器是由使用 Linux 内核安全功能(如名称空间和控制组)与其他系统隔离的过程的组合,它类似于虚拟机的构造,但重量更轻;你没有执行额外的内核或模拟硬件的能力,这意味着你可以在同一服务器上轻松创建多个容器。

例如,想象一下你有一个服务器,为你的客户运行多个网站。在传统的安装中,每个网站都将是同一个 Apache 或 Nginx 网页服务器实例的虚拟主机。但是在 Linux 容器中,每个网页都可以设置在自己的容器中,有自己的网页服务器。

LXD允许您创建和管理这些容器。LXD提供一个超视觉服务来管理容器的整个生命周期。在本教程中,您将配置LXD并使用它在容器中运行 Nginx。

前提条件

要完成本教程,您将需要以下内容:

步骤 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

然后,您将被提示选择存储后端,您将得到两种选择:dirzfsdir选项告诉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。 下面的圖表顯示了音量裝置名稱的例子。 您只需要由紅線突出的一部分:

The config instructions show the device for the created block Storage volume.

您还可以使用以下命令识别设备名称:

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

然后你会被介绍到以下对话:

LXD networking configuration, start of configuration wizard

确认您想要设置网络桥梁。

您将被要求命名桥梁. 接受默认值。

您将被要求执行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 WorksIPtables 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 地址。

<$>[注] 注: 您可以重复使用此命令来设置转发规则,只需在行开始时设置变量 PORTPUBLIC_IPCONTAINER_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的教程来获得更多的实践。

Published At
Categories with 技术
comments powered by Disqus