如何在Ubuntu16.04上设置和使用LXD

来自菜鸟教程
跳转至:导航、​搜索

介绍

Linux 容器 是一组进程,通过使用 Linux 内核安全功能(例如命名空间和控制组)与系统的其余部分隔离。 它是一个类似于虚拟机的结构,但它更轻量级; 您没有运行额外内核或模拟硬件的开销。 这意味着您可以轻松地在同一台服务器上创建多个容器。

例如,假设您有一台为您的客户运行多个网站的服务器。 在传统安装中,每个网站都是 Apache 或 Nginx Web 服务器的同一实例的虚拟主机。 但是使用 Linux 容器,每个网站都可以设置在自己的容器中,并带有自己的 Web 服务器。 使用 Linux 容器,您可以将应用程序及其依赖项捆绑在一个容器中,而不会影响系统的其余部分。

LXD 允许您创建和管理这些容器。 LXD 提供管理程序服务来管理容器的整个生命周期。 在本教程中,您将配置 LXD 并使用它在容器中运行 Nginx。 然后,您将流量路由到容器,以使网站可以从 Internet 访问。

先决条件

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

第 1 步 — 配置 LXD

LXD 已经安装在 Ubuntu 上,但需要适当配置才能在服务器上使用它。 您必须设置您的用户帐户来管理容器,然后配置存储后端的类型来存储容器并配置网络。

使用非 root 用户帐户登录服务器。 然后将您的用户添加到 lxd 组,以便您可以使用它来执行所有容器管理任务:

sudo usermod --append --groups lxd sammy

注销服务器并重新登录,以便您的新 SSH 会话将使用新的组成员身份进行更新。 登录后,您可以开始配置 LXD。

现在配置存储后端。 LXD 推荐的存储后端是 ZFS 文件系统,存储在预先分配的文件中或使用 Block Storage 存储。 要在 LXD 中使用 ZFS 支持,请更新您的软件包列表并安装 zfsutils-linux 软件包:

sudo apt-get update
sudo apt-get install zfsutils-linux

您现在可以配置 LXD。 使用 lxd init 命令启动 LXD 初始化过程:

sudo lxd init

系统将提示您指定存储后端的详细信息。 完成该配置后,您将为容器配置网络。

首先,系统会询问您是否要配置新的存储池。 你应该回答yes.

Do you want to configure a new storage pool (yes/no) [default=yes]? yes

然后系统会提示您选择存储后端,您将有两个选择:dirzfsdir 选项告诉 LXD 将容器存储在服务器文件系统的目录中。 zfs 选项使用 ZFS 组合文件系统和逻辑卷管理器。

我们将使用 zfs 选项。 通过使用 zfs,我们获得了存储效率和更好的响应能力。 例如,如果我们从同一个初始容器镜像创建十个容器,它们都只使用一个容器镜像的磁盘空间。 从那时起,只有他们对初始容器镜像所做的更改才会存储在存储后端。

OutputName of the storage backend to use (dir or zfs) [default=zfs]: zfs

选择 zfs 后,系统会要求您创建一个新的 ZFS 池并命名该池。 选择yes创建池,调用池lxd

OutputCreate a new ZFS pool (yes/no) [default=yes]? yes
Name of the new ZFS pool [default=lxd]: lxd

然后会询问您是否要使用现有的块设备:

OutputWould you like to use an existing block device (yes/no) [default=no]?

如果你说 yes,你必须告诉 LXD 在哪里可以找到那个设备。 如果你说 no,LXD 将使用预先分配的文件。 使用此选项,您将使用服务器本身的可用空间。

接下来有两个部分,具体取决于您是要使用预分配文件还是块设备。 根据您的情况执行适当的步骤。 指定存储机制后,您将为容器配置网络选项。

选项 1 – 使用预分配文件

如果您无权访问单独的块存储设备来存储容器,则可以使用预分配文件。 按照以下步骤将 LXD 配置为使用预分配的文件来存储容器。

首先,当要求使用现有的块设备时,输入 no

OutputWould you like to use an existing block device (yes/no) [default=no]? no

接下来,您将被要求指定 循环设备 的大小,这就是 LXD 所说的预分配文件。 为预分配的文件使用建议的默认大小:

OutputSize in GB of the new loop device (1GB minimum) [default=15]: 15

根据经验,15GB 确实是您应该创建的最小大小; 您想预先分配足够的空间,以便在创建容器后至少有 10GB 的可用空间。

配置设备后,系统会要求您配置网络设置。 进入步骤2继续设置。

选项 2 – 使用块设备

如果你打算使用块存储作为你的存储后端,你需要找到指向你创建的块存储卷的设备,以便在 LXD 的配置中指定它。 进入DigitalOcean控制面板中的Volumes选项卡,找到你的音量,点击弹出的More,然后点击配置说明

通过查看格式化卷的命令找到设备。 具体来说,查找 sudo mkfs.ext4 -F 命令中指定的路径。 不要从该页面运行任何命令,因为我们只需要找到正确的设备名称来提供给 LXD。 下图显示了卷的设备名称示例。 您只需要红线下划线的部分:

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

ls -l /dev/disk/by-id/
total 0
lrwxrwxrwx 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 安装。 当系统提示您使用现有的块设备时,选择 yes 并提供设备的路径:

Output of the "lxd init" commandWould 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

指定磁盘后,系统会要求您配置网络选项。

第 2 步 — 配置网络

配置存储后端后,系统会提示您为 LXD 配置网络。

首先,LXD 询问您是否希望通过网络访问它。 选择 yes 可以让您从本地计算机管理 LXD,而无需通过 SSH 连接到该服务器。 保持 no 的默认值:

Output of the "lxd init" command — LXD over the networkWould you like LXD to be available over the network (yes/no) [default=no]? no

如果您想启用此选项,请阅读 LXD 2.0:远程主机和容器迁移 了解更多信息。

然后我们被要求为 LXD 容器配置一个网桥。 这启用了以下功能:

  • 每个容器都会自动获得一个私有 IP 地址。
  • 容器可以通过专用网络相互通信。
  • 每个容器都可以发起到 Internet 的连接。
  • 您创建的容器仍然无法从 Internet 访问; 除非您明确启用它,否则您无法从 Internet 建立连接并访问容器。 您将在下一步中学习如何允许访问特定容器。

当要求配置 LXD 网桥时,选择 yes

Output of the "lxd init" command — Networking for the containersDo you want to configure the LXD bridge (yes/no) [default=yes]? yes

然后您会看到以下对话框:

确认您要设置网桥。

系统会要求您命名这座桥。 接受默认值。

系统将要求您执行 IPv4 和 IPv6 的网络配置。 在本教程中,我们将只使用 IPv4。

当要求设置 IPv4 子网时,选择 。 您将被告知它为您配置了一个随机子网。 选择 确定 继续。

当提示输入有效的 IPv4 地址时,接受默认值。

当提示输入有效的 CIDR 掩码时,接受默认值。

当提示输入第一个 DHCP 地址时,接受默认值。 对最后一个 DHCP 地址以及 DHCP 客户端的最大数量执行相同的操作。

当要求对 IPv4 流量进行 NAT 时,选择 Yes

当要求配置 IPv6 子网时,选择 No。 网络设置完成后,您将看到以下输出:

OutputWarning: Stopping lxd.service, but it can still be activated by:
  lxd.socket
LXD has been successfully configured.

您已准备好创建容器。

第三步——创建 Nginx 容器

您已成功配置 LXD,现在可以创建和管理您的第一个容器。 您可以使用 lxc 命令管理容器。

使用 lxc list 查看可用的已安装容器:

lxc list

您将看到以下输出:

Output of the "lxd list" commandGenerating a client certificate. This may take a minute...
If this is your first time using LXD, you should also run: sudo lxd init
To start your first container, try: lxc launch ubuntu:16.04

+------+-------+------+------+------+-----------+
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
+------+-------+------+------+------+-----------+

由于这是 lxc 命令第一次与 LXD 管理程序通信,因此输出让您知道该命令自动创建了一个客户端证书,用于与 LXD 进行安全通信。 然后,它显示了一些有关如何启动容器的信息。 最后,该命令显示了一个空的容器列表,这是预期的,因为我们还没有创建任何容器。

让我们创建一个运行 Nginx 的容器。 为此,我们将使用 lxc launch 命令创建并启动一个名为 webserver 的 Ubuntu 16.04 容器。

创建 webserver 容器:

lxc launch ubuntu:x webserver

ubuntu:x中的x是Ubuntu 16.04代号Xenial首字母的快捷方式。 ubuntu: 是 LXD 映像的预配置存储库的标识符。 您也可以使用 ubuntu:16.04 作为图像名称。

注意:您可以通过运行 lxc image list ubuntu: 和其他发行版通过运行 lxc image list images: 找到所有可用 Ubuntu 映像的完整列表。


因为这是您第一次创建容器,所以该命令会从 Internet 下载容器映像并将其缓存到本地,以便您创建新容器时,它会更快地创建。 创建新容器时,您将看到此输出:

OutputGenerating a client certificate. This may take a minute...
If this is your first time using LXD, you should also run: sudo lxd init
To start your first container, try: lxc launch ubuntu:16.04

Creating webserver
Retrieving image: 100%
Starting webserver

现在容器正在运行,使用 lxc list 命令显示有关它的信息:

lxc list

输出显示一个表格,其中包含每个容器的名称、当前状态、IP 地址、类型以及是否拍摄了快照。

输出

+-----------+---------+-----------------------+------+------------+-----------+
|  NAME     |  STATE  |         IPV4          | IPV6 |    TYPE    | SNAPSHOTS |
+-----------+---------+-----------------------+------+------------+-----------+
| webserver | RUNNING | 10.10.10.100 (eth0)   |      | PERSISTENT | 0         |
+-----------+---------+-----------------------+------+------------+-----------+

注意: 如果您在 LXD 中启用了 IPv6,则 lxc list 命令的输出可能对您的屏幕来说太宽。 您可以改用 lxc list --columns ns4tS,它只显示名称、状态、IPv4、类型以及是否有可用的快照。


记下容器的 IPv4 地址。 您需要它来配置防火墙以允许来自外部世界的流量。

现在让我们在容器内设置 Nginx:

第 4 步 — 配置 Nginx 容器

让我们连接到 webserver 容器并配置 Web 服务器。

使用 lxc exec 命令连接到容器,该命令获取容器的名称和要执行的命令:

lxc exec webserver -- sudo --login --user ubuntu

第一个 -- 字符串表示 lxc 的命令参数应该停在那里,该行的其余部分将作为要在容器内执行的命令传递。 命令为sudo --login --user ubuntu,为容器内预配置的账号ubuntu提供登录shell。

注意:如果需要以root身份连接容器,请改用命令lxc exec webserver -- /bin/bash


进入容器后,您的 shell 提示符现在如下所示。

Outputubuntu@webserver:~$

容器中的这个 ubuntu 用户预先配置了 sudo 访问权限,并且可以在不提供密码的情况下运行 sudo 命令。 该外壳仅限于容器的范围。 您在此 shell 中运行的任何内容都保留在容器中,并且无法逃逸到主机服务器。

让我们在这个容器中设置 Nginx。 更新容器内 Ubuntu 实例的包列表并安装 Nginx:

sudo apt-get update
sudo apt-get install nginx

然后编辑该站点的默认网页并添加一些文本,明确表明该站点托管在 webserver 容器中。 打开文件/var/www/html/index.nginx-debian.html

sudo 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 服务器是否正常工作。 您将需要之前使用 lxd list 命令找到的 Web 容器的 IP 地址。

curl http://10.10.10.100/

输出应该是:

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 访问它。 让我们将外部请求路由到这个容器,以便全世界都可以访问我们的网站。

第 5 步 - 将传入连接转发到 Nginx 容器

最后一个难题是将 Web 服务器容器连接到 Internet。 Nginx 安装在容器中,默认情况下无法从 Internet 访问。 我们需要设置我们的服务器,将它可能在端口 80 上从 Internet 接收到的任何连接转发到 webserver 容器。 为此,我们将创建一个 iptables 规则来转发连接。 您可以在 IPtables 防火墙的工作原理IPtables Essentials:通用防火墙规则和命令 中了解有关 IPTables 的更多信息。

iptables 命令需要两个 IP 地址:服务器的公共 IP 地址(your_server_ip)和 nginx 容器的私有 IP 地址(your_webserver_container_ip) ,您可以使用 lxc list 命令获取。

执行此命令以创建规则:

PORT=80 PUBLIC_IP=your_server_ip CONTAINER_IP=your_container_ip \
sudo -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 地址。
  • --dport $PORT:指定目的端口(如80)。
  • -j DNAT 表示我们要跳转到目标 NAT (DNAT)。
  • --to-destination $CONTAINER_IP:$PORT 表示我们希望请求到达特定容器的 IP 地址和目标端口。

注意: 您可以重复使用该命令来设置转发规则,只需在行首设置变量PORTPUBLIC_IPCONTAINER_IP。 只需更改突出显示的值。


您可以通过运行以下命令列出 IPTables 规则:

sudo iptables -t nat -L PREROUTING

您将看到与此类似的输出:

[secondary_label 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 命令从本地计算机访问 Web 服务器来测试 Web 服务器实际上是否可以从 Internet 访问,如下所示:

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-get install iptables-persistent

安装软件包时,系统会提示您保存当前的防火墙规则。 接受并保存所有当前规则。

当您重新启动计算机时,防火墙规则将出现。 另外,你的 LXD 容器中的 Nginx 服务会自动重启。

现在您已经设置了所有内容,让我们看看如何将其拆除。

第 5 步 — 停止和移除容器

您可能决定要取下容器并更换它。 让我们来看看这个过程:

要停止容器,请使用 lxc stop

lxc stop webserver

使用 lxc list 命令验证状态。

Output+-----------+---------+------+------+------------+-----------+
|   NAME    |  STATE  | IPV4 | IPV6 |    TYPE    | SNAPSHOTS |
+-----------+---------+------+------+------------+-----------+
| webserver | STOPPED |      |      | PERSISTENT | 0         |
+-----------+---------+------+------+------------+-----------+

要移除容器,请使用 lxc delete

lxc delete webserver

再次运行 lxc list 表明没有容器在运行:

Output+------+-------+------+------+------+-----------+
| 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 容器中运行的 Nginx 建立了一个网站。 从这里,您可以配置更多网站,每个网站都限制在自己的容器中,并使用反向代理将流量引导到适当的容器。 教程 How to Host Multiple Web Sites with Nginx and HAProxy Using LXD on Ubuntu 16.04 将引导您完成设置。

LXD 还允许您拍摄容器的完整状态的快照,从而可以轻松地创建备份并在以后回滚容器。 如果你在两台不同的服务器上安装 LXD,那么就可以通过 Internet 连接它们并在服务器之间迁移容器。

有关 LXD 的更多信息,请参阅 LXD 维护者撰写的关于 LXD 2.0 的系列博文

您也可以 在线尝试 LXD 并按照基于网络的教程进行更多练习。