LXD

来自 ArchWiki

此条目或章节需要扩充。

原因: 是否有可能通过引用上游来改进介绍?(在 Talk:LXD 中讨论)

LXD 是 Canonical 针对容器(通过 LXC)和虚拟机(通过 QEMU)的管理器/虚拟机监控器。

安装

安装 lxd 软件包,然后启用 lxd.socket

或者,您可以直接启用/启动 lxd.service,以防您希望实例自动启动等。

配置

非特权容器

建议使用非特权容器(有关差异的解释,请参阅Linux 容器#特权或非特权容器)。

为此,请修改 /etc/subuid/etc/subgid(如果这些文件不存在,请创建它们),以包含每个能够运行容器的用户的容器化 uid/gid 对的映射。以下示例仅适用于 root 用户(和 systemd 系统单元)

# usermod -v 1000000-1000999999 -w 1000000-1000999999 root

现在,默认情况下,每个容器都将以 unprivileged 方式启动。

有关替代方法,请参阅#特权容器

配置 LXD

首次启动时,需要配置 LXD。

以 root 身份运行

# lxd init

这将启动终端中的交互式配置指南,其中涵盖了存储、网络等不同主题。

您可以在官方入门指南中找到概述。

以非特权用户身份访问 LXD

默认情况下,LXD 守护进程允许 lxd 组中的用户访问,因此将您的用户添加到此组。

警告: 添加到 lxd 组的任何人都等同于 root 用户。有关更多信息,请参阅[1][2]

用法

LXD 由两部分组成

  • 守护进程(lxd 二进制文件)
  • 客户端(lxc 二进制文件)
注意: LXD 不是 LXC;命名有点混乱,您可以阅读关于比较 LXD 与 LXC 的论坛帖子,了解它们之间的区别。

客户端用于控制一个或多个守护进程。

客户端也可以用于控制远程 LXD 服务器。

命令概览

您可以通过输入以下内容获取所有可用命令的概览

$ lxc

创建容器

您可以使用 lxc launch 创建容器,例如

$ lxc launch ubuntu:20.04

容器基于镜像,这些镜像从镜像服务器或远程 LXD 服务器下载。

您可以使用以下命令查看已添加服务器的列表

$ lxc remote list

您可以使用 lxc image list 列出服务器上的所有镜像,例如

$ lxc image list images:

这将显示默认服务器之一上的所有镜像:images.linuxcontainers.org

您还可以通过添加发行版名称等术语来搜索镜像

$ lxc image list images:debian

使用来自特定服务器的镜像启动容器,使用

$ lxc launch servername:imagename

例如

$ lxc launch images:centos/8/amd64 centos

要创建 amd64 Arch 容器

$ lxc launch images:archlinux/current/amd64 arch

创建虚拟机

只需将标志 --vm 添加到 lxc launch

$ lxc launch ubuntu:20.04 --vm
注意
  • 目前,虚拟机支持的功能比容器少(例如,有关详细信息,请参阅关于虚拟机的详细信息)。
  • 只有官方镜像的 cloud 变体默认启用 lxd-agent(这是 lxc exec 等常用 lxc 命令所必需的)。
    您可以使用 lxc image list images: cloudlxc image list images: distribution-name cloud 搜索云镜像。
    如果您使用其他镜像或遇到问题,请查看#虚拟机内的 lxd-agent

使用和管理容器或虚拟机

请参阅LXD 官方入门指南中的“管理实例”

容器/虚拟机配置

您可以向实例(容器和虚拟机)添加各种选项。

有关详细信息,请参阅LXD 官方高级指南中的实例配置

技巧和窍门

在主机上通过名称访问容器

这假设您正在使用名为 lxdbr0 的默认桥接,并且您正在使用 systemd-resolved

# systemd-resolve --interface lxdbr0 --set-domain '~lxd' --set-dns $(lxc network get lxdbr0 ipv4.address | cut -d / -f 1)

现在您可以通过名称访问容器

$ ping containername.lxd

其他解决方案

此条目或章节的事实准确性存在争议。

原因: systemd-resolve 何时停止工作?是否有错误报告或其他参考资料?(在 Talk:LXD 中讨论)

似乎 systemd-resolve 解决方案在一段时间后停止工作。

另一种解决方案是将 systemd-networkd 与以下 lxd.network 一起使用(替换 xy 以匹配您的桥接 IP)

/etc/systemd/network/lxd.network
[Match]
Name=lxdbr0

[Network]
DNS=10.x.y.1
Domains=~lxd
IgnoreCarrierLoss=yes

[Address]
Address=10.x.y.1/24
Gateway=10.x.y.1

使用 Wayland 和 Xorg 应用程序

注意: 始终考虑安全隐患,因为所描述的某些方法可能会削弱容器和主机之间的隔离。

在容器内使用 GUI 应用程序有多种方法,您可以在官方 LXD 论坛中找到概述。

以下方法授予容器访问主机 Wayland (+Xwayland) 或 Xorg 套接字的权限。

注意: 使用 Xorg 可能会削弱容器和主机之间的隔离,因为 Xorg 允许应用程序访问其他应用程序窗口。因此,容器应用程序可能可以访问主机应用程序窗口。请改用 Wayland(但请注意 Xorg 的缺点也适用于 Xwayland)。

将以下设备添加到容器配置文件

另请参阅有关设备的 LXD 文档

GPU 的通用设备

mygpu:
   type: gpu
注意: “listen”下的路径不同,因为 /run/tmp 目录可能会被覆盖,请参阅https://github.com/canonical/lxd/issues/4540

Wayland 套接字的设备

注意
  • 相应地调整显示 (wayland-0)。
  • 如果 /mnt/tmp 中的目录尚不存在,请在容器内添加它们。
Waylandsocket:
    bind: container
    connect: unix:/run/user/1000/wayland-0
    listen: unix:/mnt/wayland1/wayland-0
    uid: "1000"
    gid: "1000"
    security.gid: "1000"
    security.uid: "1000"
    mode: "0777"
    type: proxy

Xorg(或 Xwayland)套接字的设备

注意: 相应地调整显示编号(例如,X1 而不是 X0)。
Xsocket:
    bind: container
    connect: unix:/tmp/.X11-unix/X0
    listen: unix:/mnt/xorg1/X0
    uid: "1000"
    gid: "1000"
    security.gid: "1000"
    security.uid: "1000"
    mode: "0777"
    type: proxy

将套接字链接到容器内的正确位置

注意: 这些脚本需要在每次容器启动后运行;您可以使用 systemd 等自动化此过程。

链接 Wayland 套接字的 Shell 脚本

#!/bin/sh
mkdir /run/user/1000
ln -s /mnt/wayland1/wayland-0 /run/user/1000/wayland-0

链接 Xorg(或 Xwayland)套接字

#!/bin/sh
ln -s /mnt/xorg1/X0 /tmp/.X11-unix/X0

将环境变量添加到容器内用户的配置

注意: 相应地调整显示编号和/或文件名 (.profile)。

对于 Wayland

$ echo "export XDG_RUNTIME_DIR=/run/user/1000" >> ~/.profile
$ echo "export WAYLAND_DISPLAY=wayland-0" >> ~/.profile
$ echo "export QT_QPA_PLATFORM=wayland" >> ~/.profile

对于 Xorg(或 Xwayland)

$ echo "export DISPLAY=:0" >> ~/.profile

重新加载 ~/.profile

$ source ~/.profile

在容器中安装必要的软件

需要添加必要的软件。目前,您可以安装示例 GUI 应用程序;这可能会安装所有必要的软件包。

启动 GUI 应用程序

现在,您应该能够在容器内启动 GUI 应用程序(例如,通过终端),并使它们作为窗口出现在主机显示器上。

您可以尝试 glxgears 例如。

特权容器

注意
  • 特权容器未与主机隔离!
  • 容器中的 root 用户是主机上的 root 用户。
  • 尽可能使用非特权容器。

如果要设置特权容器,则必须提供配置键 security.privileged=true

在容器创建期间

$ lxc launch ubuntu:20.04 ubuntu -c security.privileged=true

或者对于已经存在的容器,您可以编辑配置

$ lxc config edit ubuntu
name: ubuntu
profiles:
- default
config:
  ...
  security.privileged: "true"
  ...

添加磁盘设备

只读

如果要将磁盘设备从主机共享到容器,您只需向容器添加 disk 设备。虚拟 disk 设备需要一个名称(仅在 LXC 配置文件中内部使用)、主机文件系统上指向要挂载的磁盘的路径,以及容器文件系统上所需的挂载点。

$ lxc config device add containername virtualdiskname disk source=/path/to/host/disk/ path=/path/to/mountpoint/on/container

读写(非特权容器)

读/写访问的首选方法是使用 LXD 中包含的“shift”方法。

shift 基于 Linux 内核功能,并提供两个不同的版本

  • 最新版本称为“idmapped mounts”,默认包含在所有上游内核 >5.12 中。因此,它也包含在常规 Arch Linux 内核 (linux) 中。
  • 旧版本称为“shiftfs”,需要手动添加到大多数内核中作为内核模块。它作为遗留版本提供,以支持较旧的内核。您可以查看此 GitHub 仓库,该仓库使用来自 Ubuntu 内核的 shiftfs 内核模块:https://github.com/toby63/shiftfs-dkms

Shift 应该在安装了常规 Arch Linux 内核 (linux) 和 lxd 软件包的 Arch 系统上默认可用并激活。

1. 要检查您的系统上是否可用 shift,请运行 lxc info

输出的第一部分显示

 kernel_features:
    idmapped_mounts: "true"
    shiftfs: "false"

如果 idmapped_mounts 或 shiftfs 为 true,则您的内核已包含它,您可以直接使用 shift。如果不是 true,您应该检查您的内核版本,并可能尝试上面提到的“shiftfs”遗留版本。

输出的第二部分显示

  lxc_features:
    idmapped_mounts_v2: "true"

  lxc_features:
    shiftfs: "true"

如果 idmapped_mounts 或 shiftfs 为 true,则 LXD 已启用它。如果未启用,您必须首先启用它。

2. 用法

然后,您可以简单地在磁盘设备选项中将“shift”配置键设置为“true”。请参阅:关于磁盘设备的 LXD 文档

另请参阅:LXD 论坛中的教程

Bash 补全不起作用

此解决方法可能会修复此问题

# ln -s /usr/share/bash-completion/completions/lxd /usr/share/bash-completion/completions/lxc

故障排除

虚拟机内的 lxd-agent

在某些虚拟机镜像中,默认情况下未启用 lxd-agent

在这种情况下,您必须手动启用它,例如通过挂载 9p 网络共享。这需要使用有效用户的控制台访问权限。

1. 使用 lxc console 登录,并相应地替换 virtualmachine-name

$ lxc console virtualmachine-name

以 root 身份登录

注意: 在某些系统上,您必须首先设置 root 密码才能以 root 身份登录,您可以使用 cloud-init 来实现此目的。
$ su root

挂载网络共享

$ mount -t 9p config /mnt/

进入文件夹并运行安装脚本(这将在虚拟机内启用 lxd-agent)

$ cd /mnt/
$ ./install.sh

成功安装后,使用以下命令重启

$ reboot

之后,lxd-agent 可用,lxc exec 应该可以工作。

检查内核配置

默认情况下,Arch Linux 内核已针对 Linux 容器及其前端 LXD 正确编译。但是,如果您使用的是自定义内核或更改了内核选项,则内核配置可能不正确。验证您的内核是否已正确配置

$ lxc-checkconfig

从容器内部查看时,资源限制未应用

安装 lxcfs启动 lxcfs.service

lxd 将需要重启。启用 lxcfs.service 以便在启动时启动该服务。

启动虚拟机失败

如果您看到错误

Error: Couldn't find one of the required UEFI firmware files: [{code:OVMF_CODE.4MB.fd vars:OVMF_VARS.4MB.ms.fd} {code:OVMF_CODE.2MB.fd vars:OVMF_VARS.2MB.ms.fd} {code:OVMF_CODE.fd vars:OVMF_VARS.ms.fd} {code:OVMF_CODE.fd vars:qemu.nvram}]

这是因为 Arch Linux 不分发安全启动签名的 ovmf 固件。要启动虚拟机,您需要暂时禁用安全启动

$ lxc launch ubuntu:18.04 test-vm --vm -c security.secureboot=false

也可以通过执行以下操作将其添加到默认配置文件

$ lxc profile set default security.secureboot=false

systemd-networkd 没有 IPv4

从版本 244.1 开始,systemd 检测 /sys 是否可由容器写入。如果是,则 udev 会自动启动并破坏非特权容器中的 IPv4。请参阅commit bf331d8linuxcontainers 上的讨论

在 2020 年之后创建的容器上,应该已经存在 systemd-networkd.service 覆盖来解决此问题,如果不存在,则创建它

/etc/systemd/system/systemd-networkd.service.d/lxc.conf
[Service]
BindReadOnlyPaths=/sys

您也可以通过在容器的配置文件中设置 raw.lxc: lxc.mount.auto = proc:rw sys:ro 来解决此问题,以确保 /sys 对于整个容器都是只读的,尽管这可能存在问题,如上面链接的讨论中所述。

ufw 没有网络连接

当在安装了 ufw 的系统上运行 LXD 时,lxc ls 的输出将包含一个空的 IPv4 字段,出站请求不会转发到容器外部,入站请求也不会转发到容器内部。正如在 LXC Discourse 实例上的一个帖子 中看到的,ufw 默认会阻止来自 LXD 网桥的流量。解决方案是为每个网桥配置两个新的 ufw 规则

# ufw route allow in on lxdbr0
# ufw allow in on lxdbr0

有关这两个命令的更多信息,请查看此帖子,其中更详细地描述了这些命令及其局限性。

安装 Docker 后没有网络连接

您在主机上安装了 Docker,并且无法从 lxc 容器内访问 LAN 或互联网。

# iptables -I DOCKER-USER -i lxdbr0 -o interface -j ACCEPT
# iptables -I DOCKER-USER -o lxdbr0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

在第一行中,将 interface 替换为外部网络接口(将主机连接到 LAN/互联网的接口,例如 enp6sowlp5s0 等)。如果需要,也请替换 lxdbr0

有关更多详细信息,请参阅LXD 文档中的此注释

使用 snapcraft 构建 snap:craft-providers 错误:LXD 需要额外的权限。

如果您收到以下错误

craft-providers error: LXD requires additional permissions.
Ensure that the user is in the 'lxd' group.
Visit https://documentation.ubuntu.com/lxd/en/latest/getting_started/ for instructions on installing and configuring LXD for your operating system.
Full execution log: '/home/your_user/.local/state/snapcraft/log/snapcraft-20231129-221308.209638.log'

如果您尝试使用 snapcraft 命令构建 snap,则可能会发生这种情况。如果您已将自己添加到 lxd 组并重新启动后错误仍然存在,请尝试通过 snap 而不是作为 Arch 软件包安装 lxd(不要同时安装两者),这可能会解决此问题。

卸载

停止 并禁用 lxd.servicelxd.socket。然后卸载 lxd 软件包。

如果您在未禁用服务的情况下卸载了软件包,则 /etc/systemd/system/multi-user.wants/lxd.service 处可能存在残留的损坏的符号链接。

如果要删除所有数据

# rm -r /var/lib/lxd

如果您使用了任何示例网络配置,则还应删除这些配置。

参见