容器是完全虚拟化机器(VM)的轻量级替代方案。它们使用所在主机系统的内核,而不是模拟完整操作系统(OS)。这意味着容器可以直接访问主机系统上的资源。

容器的运行时开销很低,通常可以忽略不计。但也需要考虑一些缺点:

  • Proxmox 容器中只能运行 Linux 发行版。无法在容器内运行其他操作系统,例如 FreeBSD 或 Microsoft Windows。

  • 出于安全原因,需要限制对主机资源的访问。因此,容器运行在各自独立的 namespace 中。此外,容器内不允许执行某些 syscall(用户空间对 Linux 内核的请求)。

Proxmox VE 使用 Linux Containers (LXC) 作为底层容器技术。“Proxmox Container Toolkit”(pct)通过提供抽象复杂任务的接口,简化 LXC 的使用和管理。

容器与 Proxmox VE 紧密集成。这意味着它们感知集群设置,并且可以与虚拟机使用相同的网络和存储资源。也可以使用 Proxmox VE 防火墙,或通过 HA 框架管理容器。

主要目标是提供一种既具备虚拟机优势、又没有额外开销的环境。这意味着 Proxmox 容器可归类为`‘系统容器’,而不是`‘应用容器’。

Note 如果要运行应用容器,例如 Docker 镜像,建议在 Proxmox QEMU 虚拟机内运行它们。这样既可以获得应用容器化的所有优势,也能获得虚拟机提供的优势,例如与主机的强隔离以及在线迁移能力;这些能力在普通容器中并不可用。

技术概览

  • LXC (https://linuxcontainers.org/)

  • 集成到 Proxmox VE 图形化 Web 用户界面(GUI)

  • 易用的命令行工具 pct

  • 可通过 Proxmox VE REST API 访问

  • 使用 lxcfs 提供容器化的 /proc 文件系统

  • 使用 control groups(cgroups)进行资源隔离和限制

  • 使用 AppArmorseccomp 提升安全性

  • 现代 Linux 内核

  • 基于镜像的部署(模板

  • 使用 Proxmox VE 存储库

  • 从主机配置容器(网络、DNS、存储等)

支持的发行版

官方支持的发行版列表如下。

以下发行版的模板可通过我们的软件仓库获取。可以使用 pveam 工具或图形化用户界面下载它们。

Alpine Linux

Alpine Linux 是基于 musl libc 和 busybox 的安全导向轻量级 Linux 发行版。

当前支持版本请参见:

Arch Linux

Arch Linux 是一种轻量且灵活的 Linux® 发行版,追求 Keep It Simple。

Arch Linux 使用滚动发布模型,详情请参见其 wiki:

CentOS, Almalinux, Rocky Linux

CentOS / CentOS Stream

CentOS Linux 发行版是一个稳定、可预测、可管理且可复现的平台,源自 Red Hat Enterprise Linux (RHEL)的源码。

当前支持版本请参见:

Almalinux

一个开源、由社区拥有和治理、永久免费使用的企业级 Linux 发行版,专注于长期稳定性,提供稳健的生产级平台。AlmaLinux OS 与 RHEL® 和 pre-Stream CentOS 保持 1:1 二进制兼容。

当前支持版本请参见:

Rocky Linux

Rocky Linux 是社区企业级操作系统,设计目标是在其下游伙伴转向之后,与美国顶级企业级 Linux 发行版保持 100% bug-for-bug 兼容。

当前支持版本请参见:

Debian

Debian 是由 Debian 项目开发和维护的自由操作系统。它是一个自由 Linux 发行版,包含数千个应用程序,以满足用户需求。

当前支持版本请参见:

Devuan

Devuan GNU+Linux 是不含 systemd 的 Debian 分支,通过避免不必要的耦合并确保 Init Freedom,让用户重新掌控自己的系统。

当前支持版本请参见:

Fedora

Fedora 为硬件、云和容器创建创新、自由且开源的平台,使软件开发者和社区成员能够为用户构建定制解决方案。

当前支持版本请参见:

Gentoo

一个高度灵活、基于源码的 Linux 发行版。

Gentoo 使用滚动发布模型。

OpenSUSE

面向系统管理员、开发者和桌面用户的创作者之选。

当前支持版本请参见:

Ubuntu

Ubuntu 是面向企业服务器、桌面、云和 IoT 的现代开源 Linux 操作系统。

当前支持版本请参见:

容器镜像

容器镜像有时也称为 “templates” 或 “appliances”,是包含运行容器所需全部内容的 tar 归档文件。

Proxmox VE 本身为 最常见的 Linux 发行版 提供多种基础模板。可以使用 GUI 或 pveam(Proxmox VE Appliance Manager 的缩写)命令行工具下载它们。此外,也可以下载 TurnKey Linux 容器模板。

可用模板列表会通过 pve-daily-update timer 每日更新。也可以执行以下命令手动触发更新:

# pveam update

要查看可用镜像列表,请运行:

# pveam available

可以通过指定感兴趣的 section 来限制这个较大的列表,例如基础 system 镜像:

列出可用 system 镜像
# pveam available --section system
system          alpine-3.12-default_20200823_amd64.tar.xz
system          alpine-3.13-default_20210419_amd64.tar.xz
system          alpine-3.14-default_20210623_amd64.tar.xz
system          archlinux-base_20210420-1_amd64.tar.gz
system          centos-7-default_20190926_amd64.tar.xz
system          centos-8-default_20201210_amd64.tar.xz
system          debian-9.0-standard_9.7-1_amd64.tar.gz
system          debian-10-standard_10.7-1_amd64.tar.gz
system          devuan-3.0-standard_3.0_amd64.tar.gz
system          fedora-33-default_20201115_amd64.tar.xz
system          fedora-34-default_20210427_amd64.tar.xz
system          gentoo-current-default_20200310_amd64.tar.xz
system          opensuse-15.2-default_20200824_amd64.tar.xz
system          ubuntu-16.04-standard_16.04.5-1_amd64.tar.gz
system          ubuntu-18.04-standard_18.04.1-1_amd64.tar.gz
system          ubuntu-20.04-standard_20.04-1_amd64.tar.gz
system          ubuntu-20.10-standard_20.10-1_amd64.tar.gz
system          ubuntu-21.04-standard_21.04-1_amd64.tar.gz

使用这类模板前,需要先将它们下载到某个存储中。如果不确定使用哪个存储,可以直接使用名为 local 的存储。对于集群安装,建议使用共享存储,以便所有节点都能访问这些镜像。

# pveam download local debian-10.0-standard_10.0-1_amd64.tar.gz

现在可以使用该镜像创建容器,并可使用以下命令列出存储 local 上已下载的所有镜像:

# pveam list local
local:vztmpl/debian-10.0-standard_10.0-1_amd64.tar.gz  219.95MB
Tip 也可以使用 Proxmox VE Web 界面 GUI 下载、列出和删除容器模板。

pct 使用这些模板创建新容器,例如:

# pct create 999 local:vztmpl/debian-10.0-standard_10.0-1_amd64.tar.gz

上面的命令展示了完整的 Proxmox VE 卷标识符。它们包含存储名称,且大多数其他 Proxmox VE 命令都可以使用它们。例如,稍后可以使用以下命令删除该镜像:

# pveam remove local:vztmpl/debian-10.0-standard_10.0-1_amd64.tar.gz

容器设置

常规设置

screenshot/gui-create-ct-general.png

容器的常规设置包括:

  • Node:容器将运行所在的物理服务器

  • CT ID:此 Proxmox VE 安装中用于标识容器的唯一编号

  • Hostname:容器主机名

  • Resource Pool:容器和虚拟机的逻辑分组

  • Password:容器 root 密码

  • SSH Public Key:用于通过 SSH 连接 root 账户的公钥

  • Unprivileged container:该选项允许在创建时选择创建特权容器还是非特权容器。

非特权容器

非特权容器使用名为 user namespaces 的新内核特性。容器内的 root UID 0 会映射到容器外的非特权用户。这意味着这些容器中的大多数安全问题(容器逃逸、资源滥用等)会影响某个随机非特权用户,并且属于通用内核安全缺陷,而不是 LXC 问题。LXC 团队认为非特权容器在设计上是安全的。

这是创建新容器时的默认选项。

Note 如果容器使用 systemd 作为 init 系统,请注意容器内运行的 systemd 版本应等于或高于 220。

特权容器

容器安全性通过强制访问控制 AppArmor 限制、seccomp 过滤器和 Linux 内核 namespace 实现。LXC 团队认为这类容器不安全,并且不会将新的容器逃逸漏洞视为值得分配 CVE 并快速修复的安全问题。因此,特权容器只应在可信环境中使用。

CPU

screenshot/gui-create-ct-cpu.png

可以使用 cores 选项限制容器内可见 CPU 数量。它通过 Linux cpuset cgroup(control group)实现。pvestatd 内部的一个特殊任务会定期尝试将正在运行的容器分布到可用 CPU 上。 要查看已分配 CPU,请运行以下命令:

# pct cpusets
 ---------------------
 102:              6 7
 105:      2 3 4 5
 108:  0 1
 ---------------------

容器直接使用主机内核。容器内所有任务都由主机 CPU 调度器处理。Proxmox VE 默认使用 Linux CFSCompletely Fair Scheduler)调度器,该调度器提供额外的带宽控制选项。

cpulimit:

可以使用该选项进一步限制分配的 CPU 时间。请注意,这是浮点数,因此可以为容器分配两个核心,但将总体 CPU 消耗限制为半个核心。

cores: 2
cpulimit: 0.5
cpuunits:

这是传递给内核调度器的相对权重。数值越大,该容器获得的 CPU 时间越多。该数值相对于所有其他正在运行容器的权重。默认值为 100(如果主机使用 legacy cgroup v1,则为 1024)。可以使用该设置为某些容器赋予更高优先级。

内存

screenshot/gui-create-ct-memory.png

容器内存通过 cgroup memory controller 控制。

memory:

限制总体内存使用量。对应 memory.limit_in_bytes cgroup 设置。

swap:

允许容器从主机 swap 空间使用额外 swap 内存。对应 memory.memsw.limit_in_bytes cgroup 设置,该值设置为二者之和(memory + swap)。

挂载点

screenshot/gui-create-ct-root-disk.png

根挂载点通过 rootfs 属性配置。最多可以额外配置 256 个挂载点。对应选项名为 mp0mp255,可包含以下设置:

rootfs: [volume=]<volume> [,acl=<1|0>] [,mountoptions=<opt[;opt...]>] [,quota=<1|0>] [,replicate=<1|0>] [,ro=<1|0>] [,shared=<1|0>] [,size=<DiskSize>]

将卷用作容器根文件系统。各选项的详细说明见下文。

mp[n]: [volume=]<volume> ,mp=<Path> [,acl=<1|0>] [,backup=<1|0>] [,mountoptions=<opt[;opt...]>] [,quota=<1|0>] [,replicate=<1|0>] [,ro=<1|0>] [,shared=<1|0>] [,size=<DiskSize>]

将卷用作容器挂载点。可使用特殊语法 STORAGE_ID:SIZE_IN_GiB 分配新卷。

acl=<boolean>

显式启用或禁用 ACL 支持。

backup=<boolean>

是否将该挂载点包含在备份中(仅用于卷挂载点)。

mountoptions=<opt[;opt...]>

rootfs/mps 的额外挂载选项。

mp=<Path>

从容器内部看到的挂载点路径。

Note 出于安全原因,不得包含任何符号链接。
quota=<boolean>

在容器内启用用户配额(zfs subvolume 不支持)。

replicate=<boolean> (default = 1)

会将该卷包含在存储复制任务中。

ro=<boolean>

只读挂载点。

shared=<boolean> (default = 0)

将此非卷挂载点标记为在所有节点上可用。

Warning 此选项不会自动共享该挂载点,而是假定它已经被共享!
size=<DiskSize>

卷大小(只读值)。

volume=<volume>

要挂载到容器中的卷、设备或目录。

当前有三类挂载点:由存储支持的挂载点、bind mount 和 device mount。

典型容器 rootfs 配置
rootfs: thin1:base-100-disk-1,size=8G

由存储支持的挂载点

由存储支持的挂载点由 Proxmox VE 存储子系统管理,并有三种不同形式:

  • 基于镜像:这是包含单个 ext4 格式文件系统的 raw 镜像。

  • ZFS 子卷:从技术上讲它们是 bind mount,但带有托管存储,因此允许调整大小和创建快照。

  • 目录:传递 size=0 会触发特殊情况,即创建目录而不是 raw 镜像。

Note 对于由存储支持的挂载点卷,特殊选项语法 STORAGE_ID:SIZE_IN_GB 会在指定存储上自动分配指定大小的卷。例如,调用:
pct set 100 -mp0 thin1:10,mp=/path/in/container

会在存储 thin1 上分配一个 10GB 卷,并用已分配的卷 ID 替换卷 ID 占位符 10,然后在容器中的 /path/in/container 设置挂载点。

Bind 挂载点

Bind mount 允许在容器内访问 Proxmox VE 主机上的任意目录。一些可能的使用场景包括:

  • 在客户机中访问主目录

  • 在客户机中访问 USB 设备目录

  • 在客户机中访问主机上的 NFS 挂载

Bind mount 被视为不受存储子系统管理,因此不能在容器内创建快照或处理 quota。对于非特权容器,可能会遇到由用户映射导致的权限问题,并且无法使用 ACL。

Note 使用 vzdump 时不会备份 bind mount 挂载点的内容。
Warning 出于安全原因,bind mount 只能使用专门为此保留的源目录建立,例如 /mnt/bindmounts 下的目录层级。绝不要将 //var/etc 等系统目录 bind mount 到容器中,这会带来很大的安全风险。
Note bind mount 源路径不得包含任何符号链接。

例如,要让 ID 为 100 的容器在路径 /shared 下访问目录 /mnt/bindmounts/shared,请添加如下配置行:

mp0: /mnt/bindmounts/shared,mp=/shared

/etc/pve/lxc/100.conf 中。

或者使用 pct 工具:

pct set 100 -mp0 /mnt/bindmounts/shared,mp=/shared

实现相同结果。

设备挂载点

设备挂载点允许将主机块设备直接挂载到容器中。与 bind mount 类似,device mount 不受 Proxmox VE 存储子系统管理,但会遵循 quotaacl 选项。

Note 设备挂载点只应在特殊情况下使用。多数情况下,由存储支持的挂载点能提供相同性能以及更多功能。
Note 使用 vzdump 时不会备份设备挂载点的内容。

网络

screenshot/gui-create-ct-network.png

单个容器最多可以配置 10 个网络接口。对应选项名为 net0net9,可包含以下设置:

net[n]: name=<string> [,bridge=<bridge>] [,firewall=<1|0>] [,gw=<GatewayIPv4>] [,gw6=<GatewayIPv6>] [,hwaddr=<XX:XX:XX:XX:XX:XX>] [,ip=<(IPv4/CIDR|dhcp|manual)>] [,ip6=<(IPv6/CIDR|auto|dhcp|manual)>] [,link_down=<1|0>] [,mtu=<integer>] [,rate=<mbps>] [,tag=<integer>] [,trunks=<vlanid[;vlanid...]>] [,type=<veth>]

指定容器的网络接口。

bridge=<bridge>

要连接该网络设备的网桥。

firewall=<boolean>

控制是否使用此接口的防火墙规则。

gw=<GatewayIPv4>

IPv4 流量的默认网关。

gw6=<GatewayIPv6>

IPv6 流量的默认网关。

hwaddr=<XX:XX:XX:XX:XX:XX>

未设置 I/G(Individual/Group)位的普通 MAC 地址。

ip=<(IPv4/CIDR|dhcp|manual)>

CIDR 格式的 IPv4 地址。

ip6=<(IPv6/CIDR|auto|dhcp|manual)>

CIDR 格式的 IPv6 地址。

link_down=<boolean>

此接口是否应断开连接(类似拔掉网线)。

mtu=<integer> (64 - 65535)

接口的最大传输单元。 (lxc.network.mtu)

name=<string>

从容器内部看到的网络设备名称。 (lxc.network.name)

rate=<mbps>

对该接口应用速率限制。

tag=<integer> (1 - 4094)

此接口的 VLAN 标签。

trunks=<vlanid[;vlanid...]>

允许通过此接口的 VLAN ID。

type=<veth>

网络接口类型。

容器的自动启动和关闭

要在主机系统启动时自动启动容器,可以在 Web 界面中容器的 Options 面板选择 Start at boot 选项,或运行以下命令:

# pct set CTID -onboot 1
screenshot/gui-qemu-edit-start-order.png
启动和关闭顺序

如果要微调容器启动顺序,可以使用以下参数:

  • Start/Shutdown order:定义启动顺序优先级。例如,如果希望 CT 最先启动,可将其设置为 1。(关闭时使用反向启动顺序,因此启动顺序为 1 的容器会最后关闭)

  • Startup delay:定义该容器启动与后续容器启动之间的间隔。例如,如果希望等待 240 秒后再启动其他容器,可将其设置为 240。

  • Shutdown timeout:定义 Proxmox VE 在发出关闭命令后等待容器离线的秒数。默认值为 60,这意味着 Proxmox VE 会发出关闭请求,等待 60s 让机器离线;如果 60s 后机器仍在线,则通知关闭操作失败。

请注意,未设置启动/关闭顺序参数的容器始终会在已设置该参数的容器之后启动,并且该参数只对同一主机本地运行的机器有意义,不是集群范围参数。

如果需要在主机启动与第一个容器启动之间加入延迟,请参见 Proxmox VE 节点管理 章节。

Hook 脚本

可以通过配置属性 hookscript 为 CT 添加 hook script。

# pct set 100 -hookscript local:snippets/hookscript.pl

它会在客户机生命周期的不同阶段被调用。示例和文档请参见 /usr/share/pve-docs/examples/guest-example-hookscript.pl 下的示例脚本。

安全注意事项

容器使用主机系统内核。这会向恶意用户暴露攻击面。通常,完整虚拟机提供更好的隔离。如果向未知或不可信人员提供容器,应考虑这一点。

为了降低攻击面,LXC 使用 AppArmor、CGroups 和内核 namespace 等多种安全特性。

AppArmor

AppArmor profile 用于限制对潜在危险操作的访问。某些系统调用(例如 mount)会被禁止执行。

要跟踪 AppArmor 活动,请使用:

# dmesg | grep apparmor

虽然不建议这样做,但可以为容器禁用 AppArmor。这会带来安全风险。如果系统配置错误,或存在 LXC/Linux 内核漏洞,某些 syscall 在容器内执行时可能导致权限提升。

要为容器禁用 AppArmor,请在位于 /etc/pve/lxc/CTID.conf 的容器配置文件中添加以下行:

lxc.apparmor.profile = unconfined
Warning 请注意,不建议在生产环境中这样做。

Control Groups(cgroup

cgroup 是一种内核机制,用于按层级组织进程并分配系统资源。

通过 cgroups 控制的主要资源包括 CPU 时间、内存和 swap 限制,以及对设备节点的访问。cgroups 也用于在创建快照前 "freeze" 容器。

当前有 2 个可用的 cgroups 版本: legacy and cgroupv2.

自 Proxmox VE 7.0 起,默认环境为纯 cgroupv2。此前使用 "hybrid" 设置,资源控制主要在 cgroupv1 中完成,并额外使用一个 cgroupv2 controller;该 controller 可通过 cgroup_no_v1 内核命令行参数接管部分子系统。(详情请参见 内核参数文档。)

CGroup 版本兼容性

就 Proxmox VE 而言,纯 cgroupv2 与旧 hybrid 环境的主要区别在于:使用 cgroupv2 时,内存和 swap 现在可以独立控制。容器的内存和 swap 设置可以直接映射到这些值;而此前只能限制内存上限以及内存与 swap *总和*的上限。

另一个重要区别是 devices controller 的配置方式完全不同。因此,纯 cgroupv2 环境目前不支持文件系统 quota。

要在纯 cgroupv2 环境中运行,容器操作系统需要支持 cgroupv2。运行 systemd 231 或更新版本的容器支持 cgroupv2
[this includes all newest major versions of container templates shipped by Proxmox VE]
;不使用 systemd 作为 init 系统的容器也支持
[for example Alpine Linux]

Note

CentOS 7 和 Ubuntu 16.10 是两个典型的 Linux 发行版版本,其 systemd 版本过旧,无法在 cgroupv2 环境中运行。可以选择:

  • 将整个发行版升级到较新版本。对于上述示例,可以是 Ubuntu 18.04 或 20.04,以及 CentOS 8(或 AlmaLinux、Rocky Linux 等 RHEL/CentOS 衍生版)。这样可以获得最新 bug 和安全修复,通常也能获得新功能,并将 EOL 日期推后。

  • 升级容器的 systemd 版本。如果发行版提供 backports 仓库,这可以作为一种简单快速的临时措施。

  • 将容器或其中的服务迁移到虚拟机。虚拟机与主机的交互少得多,因此可以在其中正常安装年代久远的 OS 版本。

  • 切换回 legacy cgroup controller。请注意,虽然这可能是有效方案,但不是永久方案。从 Proxmox VE 9.0 起,将不再支持 legacy controller。

更改 CGroup 版本

Tip 如果不需要文件系统 quota,且所有容器都支持 cgroupv2,建议保持使用新的默认设置。

要切换回先前版本,可以使用以下内核命令行参数:

systemd.unified_cgroup_hierarchy=0

关于应在何处添加该参数,请参见 本节 中关于编辑内核启动命令行的说明。

客户机操作系统配置

Proxmox VE 会尝试检测容器中的 Linux 发行版,并修改一些文件。容器启动时会执行的事项简要列表如下:

set /etc/hostname

设置容器名称

modify /etc/hosts

允许解析本地主机名

network setup

将完整网络设置传递给容器

configure DNS

传递 DNS 服务器信息

adapt the init system

例如,修正生成的 getty 进程数量

set the root password

创建新容器时设置 root 密码

rewrite ssh_host_keys

确保每个容器拥有唯一密钥

randomize crontab

避免所有容器中的 cron 同时启动

Proxmox VE 所做更改会被注释标记包围:

# --- BEGIN PVE ---
<data>
# --- END PVE ---

这些标记会插入到文件中的合理位置。如果此类段落已存在,则会就地更新且不会移动。

可以通过为某个文件添加 .pve-ignore. 文件来阻止修改。例如,如果文件 /etc/.pve-ignore.hosts 存在,则不会触碰 /etc/hosts 文件。可以通过以下命令创建一个简单空文件:

# touch /etc/.pve-ignore.hosts

大多数修改依赖 OS,因此会因发行版和版本不同而不同。可以通过手动将 ostype 设置为 unmanaged 完全禁用修改。

OS 类型检测通过检查容器内的特定文件完成。Proxmox VE 首先检查 /etc/os-release 文件
[/etc/os-release replaces the multitude of per-distribution release files https://manpages.debian.org/stable/systemd/os-release.5.en.html]
。 如果该文件不存在,或不包含清晰可识别的发行版标识符,则检查以下发行版专用 release 文件。

Ubuntu

检查 /etc/lsb-release(DISTRIB_ID=Ubuntu

Debian

测试 /etc/debian_version

Fedora

测试 /etc/fedora-release

RedHat 或 CentOS

测试 /etc/redhat-release

ArchLinux

测试 /etc/arch-release

Alpine

测试 /etc/alpine-release

Gentoo

测试 /etc/gentoo-release

Note 如果配置的 ostype 与自动检测到的类型不同,容器启动会失败。

容器存储

Proxmox VE LXC 容器存储模型比传统容器存储模型更灵活。一个容器可以有多个挂载点。这使得每个应用都可以使用最适合的存储。

例如,容器的根文件系统可以位于较慢且廉价的存储上,而数据库可以通过第二个挂载点放在快速的分布式存储上。更多详情请参见 挂载点 章节。

可以使用 Proxmox VE 存储库支持的任何存储类型。这意味着容器可以存储在本地存储(例如 lvmzfs 或目录)、共享外部存储(如 iSCSINFS),甚至 Ceph 等分布式存储系统上。如果底层存储支持快照或克隆等高级存储特性,也可以使用这些特性。vzdump 备份工具可以使用快照提供一致的容器备份。

此外,本地设备或本地目录可以使用 bind mounts 直接挂载。这使容器能够以几乎零开销访问本地资源。Bind mount 也可作为容器之间共享数据的简单方式。

FUSE 挂载

Warning 由于 Linux 内核 freezer 子系统存在问题,强烈不建议在容器内使用 FUSE 挂载,因为在 suspend 或 snapshot 模式备份时需要冻结容器。

如果无法用其他挂载机制或存储技术替代 FUSE 挂载,可以在 Proxmox 主机上建立 FUSE 挂载,并使用 bind mount 挂载点使其在容器内可访问。

在容器内使用 Quota

Quota 允许在容器内限制每个用户可使用的磁盘空间量。

Note 这目前需要使用 legacy cgroups
Note 这只适用于基于 ext4 镜像的存储类型,并且目前只适用于特权容器。

启用 quota 选项会使挂载点使用以下挂载选项: usrjquota=aquota.user,grpjquota=aquota.group,jqfmt=vfsv0

这允许像在其他系统上一样使用 quota。可以运行以下命令初始化 /aquota.user/aquota.group 文件:

# quotacheck -cmug /
# quotaon /

然后使用 edquota 命令编辑 quota。详情请参考容器内所运行发行版的文档。

Note 需要为每个挂载点运行上述命令,并传入挂载点路径,而不是只传入 /

在容器内使用 ACL

标准 Posix Access Control Lists 在容器内同样可用。ACL 允许设置比传统 user/group/others 模型更细粒度的文件所有权。

容器挂载点备份

要将挂载点包含在备份中,请在容器配置中为其启用 backup 选项。对于现有挂载点 mp0

mp0: guests:subvol-100-disk-1,mp=/root/files,size=8G

添加 backup=1 以启用:

mp0: guests:subvol-100-disk-1,mp=/root/files,size=8G,backup=1
Note 在 GUI 中创建新挂载点时,该选项默认启用。

要为挂载点禁用备份,请按上述方式添加 backup=0,或在 GUI 中取消勾选 Backup 复选框。

容器挂载点复制

默认情况下,复制 Root Disk 时也会复制额外挂载点。如果希望 Proxmox VE 存储复制机制跳过某个挂载点,可以为该挂载点设置 Skip replication 选项。从 Proxmox VE 5.0 起,复制要求使用 zfspool 类型的存储。当容器已配置复制时,如果向不同类型的存储添加挂载点,则需要为该挂载点启用 Skip replication

备份和还原

容器备份

可以使用 vzdump 工具备份容器。详情请参见 vzdump manual page。

还原容器备份

可以使用 pct restore 命令还原由 vzdump 创建的容器备份。默认情况下,pct restore 会尽量还原备份中的容器配置。也可以在命令行手动设置容器选项,从而覆盖备份配置(详情请参见 pct manual page)。

Note 可以使用 pvesm extractconfig 查看 vzdump 归档中包含的备份配置。

有两种基本还原模式,区别仅在于对挂载点的处理:

“简单” 还原模式

如果既未显式设置 rootfs 参数,也未显式设置任何可选 mpX 参数,则会按以下步骤从备份的配置文件还原挂载点配置:

  1. 从备份中提取挂载点及其选项

  2. storage 参数提供的存储(默认:local)上,为由存储支持的挂载点创建卷。

  3. 从备份归档中提取文件

  4. 将 bind 和 device 挂载点添加到还原后的配置(仅限 root 用户)

Note 由于 bind 和 device 挂载点从不备份,因此最后一步不会还原任何文件,只会还原配置选项。其假设是这类挂载点要么通过其他机制备份(例如 bind mount 到多个容器中的 NFS 空间),要么根本不打算备份。

Web 界面中的容器还原操作也使用该简单模式。

“高级” 还原模式

通过设置 rootfs 参数(以及可选的任意 mpX 参数组合),pct restore 命令会自动切换到高级模式。该高级模式会完全忽略备份归档中包含的 rootfsmpX 配置选项,而只使用作为参数显式提供的选项。

该模式允许在还原时灵活配置挂载点设置,例如:

  • 为每个挂载点单独设置目标存储、卷大小和其他选项

  • 根据新的挂载点方案重新分布备份文件

  • 还原到 device 和/或 bind 挂载点(仅限 root 用户)

使用 pct 管理容器

“Proxmox Container Toolkit”(pct)是用于管理 Proxmox VE 容器的命令行工具。它可用于创建或销毁容器,并控制容器执行(启动、停止、重启、迁移等)。也可用于设置容器配置文件中的参数,例如网络配置或内存限制。

CLI 使用示例

基于 Debian 模板创建容器(假设已通过 Web 界面下载该模板):

# pct create 100 /var/lib/vz/template/cache/debian-10.0-standard_10.0-1_amd64.tar.gz

启动容器 100:

# pct start 100

通过 getty 启动登录会话:

# pct console 100

进入 LXC namespace,并以 root 用户运行 shell:

# pct enter 100

显示配置:

# pct config 100

在容器运行时,添加名为 eth0 的网络接口,将其桥接到主机网桥 vmbr0,并设置地址和网关:

# pct set 100 -net0 name=eth0,bridge=vmbr0,ip=192.168.15.147/24,gw=192.168.15.1

将容器内存减少到 512MB:

# pct set 100 -memory 512

销毁容器始终会将其从 Access Control Lists 中移除,并始终移除该容器的防火墙配置。如果还要额外将容器从复制任务、备份任务和 HA 资源配置中移除,必须启用 --purge

# pct destroy 100 --purge

将挂载点卷移动到其他存储。

# pct move-volume 100 mp0 other-storage

将卷重新分配给其他 CT。这会从源 CT 移除卷 mp0,并将其作为 mp1 附加到目标 CT。在后台,该卷会被重命名,使名称与新的所有者匹配。

#  pct move-volume 100 mp0 --target-vmid 200 --target-volume mp1

常用命令示例

列出当前节点上的容器:

# pct list

查看容器状态并显示配置:

# pct status 100
# pct config 100

获取调试日志

如果 pct start 无法启动某个特定容器,可以通过传递 --debug 标志收集调试输出(将 CTID 替换为容器的 CTID):

# pct start CTID --debug

或者,可以使用以下 lxc-start 命令,该命令会将调试日志保存到 -o 输出选项指定的文件:

# lxc-start -n CTID -F -l DEBUG -o /tmp/lxc-CTID.log

该命令会尝试以前台模式启动容器。要停止容器,请在第二个终端中运行 pct shutdown CTIDpct stop CTID

收集到的调试日志会写入 /tmp/lxc-CTID.log

Note 如果自上次尝试使用 pct start 启动以来修改过容器配置,则需要至少运行一次 pct start,以同时更新 lxc-start 使用的配置。

迁移

如果有集群,可以使用以下命令迁移容器:

# pct migrate <ctid> <target>

只要容器处于离线状态,该命令即可工作。如果容器定义了本地卷或挂载点,并且目标主机上定义了相同存储,则迁移会通过网络将内容复制到目标主机。

由于技术限制,正在运行的容器无法在线迁移。可以执行 restart migration:先关闭容器,将其移动,然后在目标节点上重新启动。由于容器非常轻量,这通常只会导致数百毫秒停机时间。

可以通过 Web 界面执行 restart migration,也可以在 pct migrate 命令中使用 --restart 标志。

restart migration 会关闭容器,并在指定超时时间后终止它(默认 180 秒)。然后会像离线迁移一样迁移容器,并在完成后在目标节点上启动容器。

配置

/etc/pve/lxc/<CTID>.conf 文件保存容器配置,其中 <CTID> 是给定容器的数字 ID。与存储在 /etc/pve/ 中的所有其他文件一样,它们会自动复制到所有其他集群节点。

Note CTID < 100 保留用于内部用途,且 CTID 需要在整个集群范围内唯一。
容器配置示例
ostype: debian
arch: amd64
hostname: www
memory: 512
swap: 512
net0: bridge=vmbr0,hwaddr=66:64:66:64:64:36,ip=dhcp,name=eth0,type=veth
rootfs: local:107/vm-107-disk-1.raw,size=7G

配置文件是简单文本文件。可以使用普通文本编辑器编辑,例如 vinano。这有时适合进行小幅修正,但请记住,需要重启容器才能应用此类更改。

因此,通常最好使用 pct 命令生成和修改这些文件,或通过 GUI 完成整个操作。该工具足够智能,可以即时将大多数更改应用到正在运行的容器。此功能称为 “hot plug”,在这种情况下无需重启容器。

如果更改无法热插拔应用,则会注册为待处理更改(在 GUI 中以红色显示)。这些更改只有在重启容器后才会应用。

文件格式

容器配置文件使用简单的冒号分隔 key/value 格式。每行格式如下:

# this is a comment
OPTION: value

这些文件中的空行会被忽略,以 # 字符开头的行会被视为注释并同样忽略。

可以直接添加低层 LXC 风格配置,例如:

lxc.init_cmd: /sbin/my_own_init

or

lxc.init_cmd = /sbin/my_own_init

这些设置会直接传递给 LXC 低层工具。

快照

创建快照时,pct 会将快照时刻的配置存储到同一配置文件中的独立快照段。例如,创建名为 “testsnapshot” 的快照后,配置文件会类似如下:

带快照的容器配置
memory: 512
swap: 512
parent: testsnaphot
...

[testsnaphot]
memory: 512
swap: 512
snaptime: 1457170803
...

有一些与快照相关的属性,例如 parentsnaptimeparent 属性用于存储快照之间的父/子关系。snaptime 是快照创建时间戳(Unix epoch)。

选项

arch: <amd64 | arm64 | armhf | i386 | riscv32 | riscv64> (default = amd64)

操作系统架构类型。

cmode: <console | shell | tty> (default = tty)

控制台模式。默认情况下,console 命令会尝试连接到一个可用的 tty 设备。将 cmode 设置为 console 时,它会改为尝试附加到 /dev/console。如果将 cmode 设置为 shell,则会直接在容器内调用 shell(不登录)。

console: <boolean> (default = 1)

为容器附加一个控制台设备(/dev/console)。

cores: <integer> (1 - 8192)

分配给容器的核心数量。默认情况下,容器可以使用所有可用核心。

cpulimit: <number> (0 - 8192) (default = 0)

CPU 使用限制。

Note 如果计算机有 2 个 CPU,则总共有 2 份 CPU 时间。值 0 表示不限制 CPU。
cpuunits: <integer> (0 - 500000) (default = cgroup v1: 1024, cgroup v2: 100)

容器的 CPU 权重。该参数用于内核公平调度器。数值越大,该容器获得的 CPU 时间越多。 该数值相对于所有其他正在运行的来宾的权重。

debug: <boolean> (default = 0)

尝试输出更详细的信息。目前这只会在启动时启用 debug 日志级别。

description: <string>

容器的描述。显示在 Web 界面中 CT 的概要页。该内容会作为注释保存在配置文件中。

dev[n]: [[path=]<Path>] [,deny-write=<1|0>] [,gid=<integer>] [,mode=<Octal access mode>] [,uid=<integer>]

要直通给容器的设备。

deny-write=<boolean> (default = 0)

禁止容器写入该设备。

gid=<integer> (0 - N)

要分配给设备节点的组 ID。

mode=<Octal access mode>

要在设备节点上设置的访问模式。

path=<Path>

要直通给容器的设备路径。

uid=<integer> (0 - N)

要分配给设备节点的用户 ID。

features: [force_rw_sys=<1|0>] [,fuse=<1|0>] [,keyctl=<1|0>] [,mknod=<1|0>] [,mount=<fstype;fstype;...>] [,nesting=<1|0>]

允许容器访问高级功能。

force_rw_sys=<boolean> (default = 0)

在非特权容器中将 /sys 挂载为 rw,而不是 mixed。这可能会破坏较新版 (>= v245)systemd-network 下的网络功能。

fuse=<boolean> (default = 0)

允许在容器中使用 fuse 文件系统。请注意,fuse 与 freezer cgroup 之间的交互 可能导致 I/O 死锁。

keyctl=<boolean> (default = 0)

仅用于非特权容器:允许使用 keyctl() 系统调用。在容器内使用 docker 需要此功能。 默认情况下,非特权容器会看到该系统调用不存在。这主要是针对 systemd-networkd 的 变通措施,因为当部分 keyctl() 操作因权限不足而被内核拒绝时,它会将其视为致命错误。 本质上,需要在运行 systemd-networkd 和 docker 之间做出选择。

mknod=<boolean> (default = 0)

允许非特权容器使用 mknod() 添加某些设备节点。这需要内核支持 seccomp trap 到用户空间 (5.3 或更新版本)。此功能为实验性。

mount=<fstype;fstype;...>

允许挂载特定类型的文件系统。该值应为 mount 命令所使用的文件系统类型列表。请注意, 这可能对容器安全性产生负面影响。如果可以访问 loop 设备,挂载文件可能绕过 devices cgroup 的 mknod 权限;挂载 NFS 文件系统可能完全阻塞主机 I/O 并阻止其重启,等等。

nesting=<boolean> (default = 0)

允许嵌套。最好与带有额外 ID 映射的非特权容器一起使用。请注意,这会将主机的 procfs 和 sysfs 内容暴露给来宾。

hookscript: <string>

在容器生命周期的多个阶段执行的脚本。

hostname: <string>

设置容器的主机名。

lock: <backup | create | destroyed | disk | fstrim | migrate | mounted | rollback | snapshot | snapshot-delete>

锁定或解锁容器。

memory: <integer> (16 - N) (default = 512)

容器的 RAM 容量,单位为 MB。

mp[n]: [volume=]<volume> ,mp=<Path> [,acl=<1|0>] [,backup=<1|0>] [,mountoptions=<opt[;opt...]>] [,quota=<1|0>] [,replicate=<1|0>] [,ro=<1|0>] [,shared=<1|0>] [,size=<DiskSize>]

将卷用作容器挂载点。使用特殊语法 STORAGE_ID:SIZE_IN_GiB 可分配新卷。

acl=<boolean>

显式启用或禁用 ACL 支持。

backup=<boolean>

是否将该挂载点包含在备份中(仅用于卷挂载点)。

mountoptions=<opt[;opt...]>

rootfs/mps 的额外挂载选项。

mp=<Path>

从容器内部看到的挂载点路径。

Note 出于安全原因,不得包含任何符号链接。
quota=<boolean>

在容器内启用用户配额(zfs 子卷不支持)。

replicate=<boolean> (default = 1)

会将该卷包含到存储复制作业中。

ro=<boolean>

只读挂载点。

shared=<boolean> (default = 0)

将此非卷挂载点标记为在所有节点上可用。

Warning 此选项不会自动共享挂载点,而是假定它已经被共享。
size=<DiskSize>

卷大小(只读值)。

volume=<volume>

要挂载到容器中的卷、设备或目录。

nameserver: <string>

设置容器的 DNS 服务器 IP 地址。如果既未设置 searchdomain 也未设置 nameserver, 创建时会自动使用主机上的设置。

net[n]: name=<string> [,bridge=<bridge>] [,firewall=<1|0>] [,gw=<GatewayIPv4>] [,gw6=<GatewayIPv6>] [,hwaddr=<XX:XX:XX:XX:XX:XX>] [,ip=<(IPv4/CIDR|dhcp|manual)>] [,ip6=<(IPv6/CIDR|auto|dhcp|manual)>] [,link_down=<1|0>] [,mtu=<integer>] [,rate=<mbps>] [,tag=<integer>] [,trunks=<vlanid[;vlanid...]>] [,type=<veth>]

指定容器的网络接口。

bridge=<bridge>

要附加网络设备的网桥。

firewall=<boolean>

控制是否使用此接口的防火墙规则。

gw=<GatewayIPv4>

IPv4 流量的默认网关。

gw6=<GatewayIPv6>

IPv6 流量的默认网关。

hwaddr=<XX:XX:XX:XX:XX:XX>

常规 MAC 地址,未设置 I/G(Individual/Group)位。

ip=<(IPv4/CIDR|dhcp|manual)>

CIDR 格式的 IPv4 地址。

ip6=<(IPv6/CIDR|auto|dhcp|manual)>

CIDR 格式的 IPv6 地址。

link_down=<boolean>

是否断开该接口(类似拔掉网线)。

mtu=<integer> (64 - 65535)

接口的最大传输单元。(lxc.network.mtu)

name=<string>

从容器内部看到的网络设备名称。(lxc.network.name)

rate=<mbps>

对该接口应用速率限制。

tag=<integer> (1 - 4094)

此接口的 VLAN 标签。

trunks=<vlanid[;vlanid...]>

允许通过该接口的 VLAN ID。

type=<veth>

网络接口类型。

onboot: <boolean> (default = 0)

指定容器是否在系统启动期间自动启动。

ostype: <alpine | archlinux | centos | debian | devuan | fedora | gentoo | nixos | opensuse | ubuntu | unmanaged>

操作系统类型。该值用于在容器内设置配置,并对应 /usr/share/lxc/config/<ostype>.common.conf 中的 lxc 设置脚本。值 unmanaged 可用于跳过特定于操作系统的设置。

protection: <boolean> (default = 0)

设置容器的保护标志。这会阻止对 CT 或 CT 磁盘执行移除/更新操作。

rootfs: [volume=]<volume> [,acl=<1|0>] [,mountoptions=<opt[;opt...]>] [,quota=<1|0>] [,replicate=<1|0>] [,ro=<1|0>] [,shared=<1|0>] [,size=<DiskSize>]

将卷用作容器根文件系统。

acl=<boolean>

显式启用或禁用 ACL 支持。

mountoptions=<opt[;opt...]>

rootfs/mps 的额外挂载选项。

quota=<boolean>

在容器内启用用户配额(zfs 子卷不支持)。

replicate=<boolean> (default = 1)

会将该卷包含到存储复制作业中。

ro=<boolean>

只读挂载点。

shared=<boolean> (default = 0)

将此非卷挂载点标记为在所有节点上可用。

Warning 此选项不会自动共享挂载点,而是假定它已经被共享。
size=<DiskSize>

卷大小(只读值)。

volume=<volume>

要挂载到容器中的卷、设备或目录。

searchdomain: <string>

设置容器的 DNS 搜索域。如果既未设置 searchdomain 也未设置 nameserver,创建时会自动使用主机上的设置。

startup: `[[order=]\d+] [,up=\d+] [,down=\d+] `

启动和关闭行为。Order 是一个非负数,用于定义总体启动顺序。关闭时按相反顺序执行。 此外,可以设置以秒为单位的 updown 延迟,用于指定启动或停止下一个虚拟机前等待的延迟。

swap: <integer> (0 - N) (default = 512)

容器的 SWAP 容量,单位为 MB。

tags: <string>

容器的标签。这只是元信息。

template: <boolean> (default = 0)

启用或禁用模板。

timezone: <string>

容器中使用的时区。如果未设置该选项,则不会执行任何操作。可设置为 host 以匹配主机时区, 也可以设置为 /usr/share/zoneinfo/zone.tab 中的任意时区选项。

tty: <integer> (0 - 6) (default = 2)

指定容器可用的 tty 数量。

unprivileged: <boolean> (default = 0)

使容器以非特权用户身份运行。(不应手动修改。)

unused[n]: [volume=]<volume>

对未使用卷的引用。该项供内部使用,不应手动修改。

volume=<volume>

当前未使用的卷。

容器迁移、快照和备份(vzdump)会设置锁,以防止对受影响容器执行不兼容的并发操作。有时需要手动移除这类锁(例如断电后)。

# pct unlock <CTID>
Caution 只有在确定设置该锁的操作已不再运行时,才执行此操作。