如何在Ubuntu20.04上安装和配置LXD

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

作为 Write for DOnations 计划的一部分,作者选择了 Free and Open Source Fund 来接受捐赠。

介绍

Linux 容器 是一组与系统其余部分分离的进程。 对于最终用户来说,Linux 容器可以用作虚拟机,但它更轻量级。 您没有运行额外 Linux 内核的开销,并且容器不需要任何 CPU 硬件虚拟化支持。 这意味着您可以在同一台服务器上创建比虚拟机更多的容器。

想象一下,您有一个应该为您的客户运行多个网站的服务器。 一方面,每个网站都可以是 Apache 或 Nginx Web 服务器的同一实例的虚拟主机/服务器块。 另一方面,在使用虚拟机时,您将为每个网站创建一个单独的嵌套虚拟机。 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 块存储 配合使用。 要在 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 命令后跟一个操作来管理容器,例如 listlaunchstartstopdelete

使用 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 命令创建并启动一个名为 webserver 的 Ubuntu 18.04 容器。

创建 webserver 容器。 ubuntu:18.04 中的 18.04 是 Ubuntu 18.04 的快捷方式。 ubuntu: 是 LXD 映像的预配置存储库的标识符。 您还可以使用 ubuntu:bionic 作为图像名称:

lxc launch ubuntu:20.04 webserver

注意:您可以通过运行 lxc image list ubuntu: 和其他 Linux 发行版通过运行 lxc image list images: 找到所有可用 Ubuntu 映像的完整列表。 ubuntu:images: 都是容器镜像的存储库。 对于每个容器镜像,您可以使用命令 lxc image info ubuntu:20.04 获取更多信息。


因为这是您第一次创建容器,所以此命令会从 Internet 下载容器映像并将其缓存。 新容器完成下载后,您将看到以下输出:

OutputCreating webserver
Starting webserver

启动 webserver 容器后,使用 lxc list 命令显示有关它的信息。 我们添加了 --columns ns4 以便仅显示 namestateIPv4 地址的列。 默认的 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 分配。 首先,您将覆盖从默认 LXD 配置文件继承的 eth0 设备的网络配置。 这允许您设置静态 IP 地址,以确保 Web 流量进出容器的正确通信。

具体来说,lxc config device 是执行 config 动作以配置 device 的命令。 第一行有子操作 override 来覆盖容器 webserver 中的设备 eth0。 第二行的子操作将 webserver 容器的 eth0 设备的 ipv4.address 字段设置为 DHCP 服务器在开始时提供的 IP 地址.

运行第一个 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 提示符将如下所示:

[environment second]  

这个shell,即使是root shell,也仅限于容器。 您在此 shell 中运行的任何内容都保留在容器中,并且无法逃逸到主机服务器。

注意: 将shell放入容器时,您可能会看到mesg: ttyname failed: No such device等警告。 当容器中的 shell 尝试从配置文件 /root/.profile 运行命令 mesg 时,会产生此消息。 您可以放心地忽略它。 为避免看到它,您可以从 /root/.profile 中删除命令 mesg n || true


进入容器后,更新包列表并安装 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 容器连接到互联网了。 首先,您需要设置服务器以将它可能在端口 80 上接收到的任何连接转发到 webserver 容器。 为此,您将创建一个 iptables 规则来转发网络连接。 您可以在我们的教程 IPtables 防火墙的工作原理IPtables Essentials:通用防火墙规则和命令 中了解有关 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指定接口eth0,这是Droplet在主机上的默认公网接口。
  • -p TCP 表示我们正在使用 TCP 协议。
  • -d $PUBLIC_IP 指定规则的目标 IP 地址。
  • --dport $PORT:指定目的端口(如80)。
  • -j DNAT 表示我们要跳转到目标 NAT (DNAT)。
  • --to-destination $CONTAINER_IP:$PORT 表示我们希望请求到达特定容器的 IP 地址和目标端口。

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


现在列出您的 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 命令测试连接:

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 将其公开。

从这里,您可以配置更多网站,每个网站都限制在自己的容器中,并使用反向代理将流量引导到适当的容器。 教程 How to Host Multiple Web Sites with Nginx and HAProxy Using LXD on Ubuntu 16.04 将引导您完成该设置。

有关如何使用 LXD 的更多信息,请参阅 LXD 参考文档

要练习 LXD,您可以 在线尝试 LXD 并按照基于网络的教程进行操作。

要获得 LXD 的用户支持,请访问 LXD 论坛