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

容器的运行时成本很低,通常可以忽略不计。然而,需要考虑一些缺点:

  • 只有Linux发行版可以在Proxmox容器中运行。不可能在容器内运行其他操作系统,比如FreeBSD或者Microsoft Windows。

  • 出于安全原因,需要对主机资源的访问进行限制。因此,容器在它们自己的独立命名空间中运行。此外,一些系统调用(用户空间对Linux内核的请求)在容器内是不被允许的。

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

容器与{pve}紧密集成。这意味着它们能够识别集群设置,并且可以像虚拟机一样使用相同的网络和存储资源。你还可以使用{pve}防火墙,或者利用HA框架来管理容器。

我们的主要目标是提供一个类似使用虚拟机的环境,但不会带来额外的开销。这意味着Proxmox容器可以被归类为“系统容器”,而不是“应用容器”。

Note
如果你想要运行应用程序容器,例如 Docker 镜像,推荐你在Proxmox QEMU虚拟机内运行它们。这样做可以让你享受到应用程序容器化的所有优势,同时也能享有虚拟机提供的好处,如与宿主机的强隔离以及支持在线迁移,这些是容器本身无法实现的。

技术概述

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

  • 整合到 {pve} 图形化网络用户界面(GUI)中

  • 易于使用的命令行工具 `pct

  • 通过 {pve} REST API 访问

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

  • 用于资源隔离和限制的控制组(cgroups

  • 使用’AppArmor’和’seccomp’来提高安全性

  • 现代Linux内核

  • 基于图像的部署 (模板)

  • 使用 {pve} 存储库

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

支持的分布

官方支持的发行版列表可以在下面找到。

我们的存储库中提供了以下分布的模板。您可以使用pveam工具或图形用户界面来下载它们。

Alpine Linux

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

— https://alpinelinux.org

目前支持的版本请参见:

Arch Linux

Arch Linux,一款轻量级且灵活的Linux®发行版,它努力保持简单。

— https://archlinux.org/

Arch Linux 使用滚动发布模型,请参阅其维基以获取更多详细信息:

CentOS、Almalinux、Rocky Linux

CentOS / CentOS Stream

CentOS Linux发行版是一个稳定、可预测、可管理和可复现的平台,它来源于红帽企业级Linux(RHEL)的源代码。

— https://centos.org

目前支持的版本请参见:

AlmaLinux

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

— https://almalinux.org

目前支持的版本请参见:

Rocky Linux

Rocky Linux 是一个社区企业操作系统,设计目标是与美国顶级企业级Linux发行版100%兼容(在其下游合作伙伴转变方向之后)。

— https://rockylinux.org

目前支持的版本请参见:

德比安

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

— ''''https://www.debian.org/intro/index#software''''

目前支持的版本请参见:

Devuan

Devuan GNU+Linux 是一个没有systemd的Debian分支,它允许用户通过避免不必要的纠葛并确保初始化自由来重新掌控他们的系统。

— https://www.devuan.org

目前支持的版本请参见:

费多拉

Fedora 创建了一个创新的、自由的、开源的平台,为硬件、云计算和容器提供支持,这使得软件开发人员和社区成员能够为他们的用户构建量身定制的解决方案。

— https://getfedora.org

目前支持的版本请参见:

Gentoo

一种高度灵活的基于源代码的Linux发行版。

— https://www.gentoo.org

Gentoo 使用的是滚动发布模型。

OpenSUSE

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

— https://www.opensuse.org

目前支持的版本请参见:

Ubuntu

Ubuntu是一个现代的,基于Linux的开源操作系统,适用于企业服务器、桌面、云计算和物联网。

— https://ubuntu.com/

目前支持的版本请参见:

容器镜像

容器镜像,有时也被称为“模板”或“设备”,是`tar`档案,包含了运行一个容器所需要的一切。

{pve} 自身提供了各种基础模板,支持 最常见的 Linux 发行版。它们可以通过 GUI 或者命令行工具 pveam({pve} Appliance Manager 的缩写)来下载。此外,https://www.turnkeylinux.org/[TurnKey Linux] 容器模板也可供下载。

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

# pveam update

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

# pveam available

你可以通过指定你感兴趣的`section`来限制这个大列表,例如基本的`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
您也可以使用 {pve} 网络界面 GUI 来下载、列出和删除容器模板。

pct`使用它们来创建一个新的容器,例如:

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

上述命令显示了完整的{pve}卷标识符。它们包括存储名称,大多数其他{pve}命令可以使用它们。例如,您稍后可以使用以下命令删除该镜像:

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

容器设置

通用设置

容器的一般设置包括

  • 节点:容器将运行在其上的物理服务器。

  • CT ID:在此{pve}安装中用来识别您容器的唯一编号

  • 主机名:容器的主机名

  • 资源池:容器和虚拟机的逻辑分组

  • 密码:容器的根密码

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

  • 无特权容器:这个选项允许你在创建时选择是要创建一个有特权的还是无特权的容器。

非特权容器

非特权容器使用一种称为用户命名空间的新内核功能。容器内的根UID 0被映射到容器外的一个非特权用户。这意味着这些容器中的大多数安全问题(容器逃逸、资源滥用等)会影响到一个随机的非特权用户,并且将是一个通用的内核安全漏洞,而不是LXC的问题。LXC团队认为,非特权容器在设计上是安全的。

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

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

特权容器

在容器中的安全性是通过使用强制访问控制的’AppArmor’限制、'seccomp’过滤器和Linux内核的命名空间来实现的。LXC团队认为这种类型的容器是不安全的,他们不会把新的容器逃逸漏洞视为值得分配CVE并快速修复的安全问题。这就是为什么只有在可信的环境中才应该使用特权容器。

中央处理器

您可以使用`cores`选项限制容器内可见的CPU数量。这是通过Linux的’cpuset’cgroup(控制 )来实现的。`pvestatd`中的一个特殊任务会尝试定期在可用的CPU之间分配运行中的容器。要查看分配的CPU,请运行以下命令:

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

容器直接使用宿主机的内核。容器内的所有任务都由宿主CPU调度程序处理。{pve} 默认使用Linux的“CFS”(Completely Fair Scheduler,完全公平调度器)调度器,该调度器具有额外的带宽控制选项。

cpulimit`:

您可以使用此选项进一步限制分配的CPU时间。请注意,这是一个浮点数,因此将两个核心分配给容器同时限制整体CPU消耗为半个核心是完全有效的。

cores: 2
cpulimit: 0.5
cpuunits`

这是一个传递给内核调度器的相对权重。数字越大,该容器获得的CPU时间就越多。数字是相对于所有其他运行容器的权重而言的。默认值是`100`(如果宿主机使用遗留的cgroup v1,则为`1024`)。您可以使用此设置来优先考虑某些容器。

内存

容器内存是通过cgroup内存控制器进行控制的。

内存:

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

swap

允许容器使用主机交换空间的额外交换内存。这对应于 memory.memsw.limit_in_bytes cgroup 设置,它被设定为两个值(memory + swap)的总和。

挂载点

根挂载点通过`rootfs`属性进行配置。您可以配置多达256个额外的挂载点。相应的选项被称为`mp0`到`mp255`。它们可以包含以下设置:

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子卷上使用)

replicate`参数设为`<boolean>(默认值为`1

将此卷包含到存储副本任务中。

ro`=`<boolean>

只读挂载点

shared`=<boolean> (default = 0)

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

Warning
这个选项不会自动共享挂载点,它假定挂载点已经被共享了!
size`=`<DiskSize>

卷大小(只读值)。

volume`=`<volume>

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

目前有三种类型的挂载点:存储支持的挂载点、绑定挂载点和设备挂载点。

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

存储后端挂载点

存储后端挂载点由 {pve} 存储子系统管理,并有三种不同类型:

  • 基于图像:这些是包含单个ext4格式文件系统的原始图像。

  • ZFS子卷:从技术上讲,这些是绑定挂载,但具有管理的存储,因此允许调整大小和快照。

  • 目录:传递 size=0 会触发一个特殊情况,在这种情况下不会创建原始图像,而是创建一个目录。

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

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

绑定挂载点

Bind mounts 允许您从 Proxmox VE 主机中访问容器内的任意目录。一些潜在的使用场景包括:

  • 在客人中访问您的主目录

  • 在客户端访问一个USB设备目录

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

绑定挂载被认为不受存储子系统管理,所以你无法在容器内部进行快照处理或管理配额。在非特权容器中,你可能会因为用户映射遇到权限问题,不能使用ACLs。

Note
使用`vzdump`时,绑定挂载点的内容不会被备份。
Warning
出于安全原因,绑定挂载应该仅使用专门为此目的保留的源目录来建立,例如,位于 /mnt/bindmounts 下的目录层次结构。切勿将系统目录比如 //var/etc 绑定挂载到容器中 - 这将带来很大的安全风险。
Note
绑定挂载的源路径中不能包含任何符号链接。

例如,要使目录`/mnt/bindmounts/shared`在容器中可访问,并且该容器的ID为`100`,访问路径为`/shared`,可以添加如下配置行:

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

进入 /etc/pve/lxc/100.conf

或者可以使用`pct`工具:

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

要达到相同的效果。

设备挂载点

设备挂载点允许将主机的块设备直接挂载到容器中。类似于绑定挂载,设备挂载不受 {PVE} 的存储子系统管理,但是 quotaacl 选项将被遵守。

Note
设备挂载点应仅在特殊情况下使用。在大多数情况下,存储后备的挂载点提供相同的性能和更多的功能。
Note
使用`vzdump`时,设备挂载点的内容不会被备份。

网络

你可以为单个容器配置多达10个网络接口。相应的选项称为`net0`到`net9`,它们可以包含以下设置:

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)>

IPv4地址的CIDR格式。

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

IPv6地址的CIDR格式。

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界面中容器的“选项”面板里选择“开机启动”选项,或者运行以下命令:

# pct set CTID -onboot 1
启动和关闭顺序

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

  • '启动/关闭顺序:定义启动的优先级顺序。例如,如果您希望该容器(CT)是第一个启动的,请将其设置为1。(我们对于关闭操作使用相反的启动顺序,所以启动顺序为1的容器将会是最后一个被关闭的)'

  • 启动延迟:定义了此容器启动和后续容器启动之间的时间间隔。例如,如果您想在启动其他容器前等待240秒,请将其设置为240。

  • '关机超时:定义了在发出关机命令后{pve}应该等待容器离线的秒数。默认情况下,此值设置为60,这意味着{pve}将发出关机请求,等待60秒让机器离线,如果60秒后机器仍然在线,将通知关机操作失败。'

请注意,没有设置启动/关闭顺序参数的容器总是会在设置了该参数的容器之后启动,而且这个参数只在本地主机上运行的机器之间有效,而不是在整个集群范围内有效。

如果您需要在宿主机启动和第一个容器启动之间设置一个延迟,请参阅Proxmox VE节点管理一节。

钩子脚本

你可以通过配置属性`hookscript`向容器(CTs)添加一个钩子脚本。

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

它将在客户生命周期的各个阶段被调用。有关示例和文档,请参见位于`/usr/share/pve-docs/examples/guest-example-hookscript.pl`下的示例脚本。

安全考虑

容器使用宿主系统的内核。这为恶意用户提供了一个攻击面。通常情况下,完整的虚拟机提供更好的隔离。如果容器提供给未知或不可信的人,应当考虑这一点。

为了减少攻击面,LXC使用了多种安全特性,比如AppArmor、CGroups和内核命名空间。

AppArmor

AppArmor 配置文件用于限制对可能危险操作的访问。一些系统调用,即 mount,被禁止执行。

要追踪AppArmor活动,请使用:

# dmesg | grep apparmor

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

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

lxc.apparmor.profile = unconfined
Warning
请注意,这不推荐用于生产环境。

控制组 (cgroup)

"cgroup"是一种内核机制,用于以层次化的方式组织进程和分配系统资源。

通过’cgroups’控制的主要资源包括CPU时间、内存和交换空间限制,以及对设备节点的访问。'cgroups’也用于在拍摄快照之前“冻结”一个容器。

自从 {pve} 7.0版本以来,默认设置为纯粹的“cgroupv2”环境。之前使用的是一种“混合”设置,在这种设置中资源控制主要在“cgroupv1”中完成,通过“cgroup_no_v1”内核命令行参数,额外的“cgroupv2”控制器可以接管一些子系统。(有关详细信息,请参见[内核参数文档](https://www.kernel.org/doc/html/latest/admin-guide/kernel-parameters.html)。)

CGroup 版本兼容性

''纯’cgroupv2’与旧的混合环境在{pve}方面的主要区别是,使用’cgroupv2’时,内存和交换空间现在可以独立控制。容器的内存和交换空间设置可以直接映射到这些值,而以前只能限制内存限制和内存与交换空间*总和*的限制。''

另一个重要的区别在于 devices 控制器的配置方式完全不同。正因为此,文件系统配额目前在纯 cgroupv2 环境中尚未得到支持。

容器的操作系统需要支持 cgroupv2 才能在纯 cgroupv2 环境中运行。运行 systemd 版本231或更高版本的容器支持 cgroupv2 脚注:[这包括由 {pve} 发货的所有最新主要版本的容器模板],不使用 systemd 作为初始化系统的容器也支持 cgroupv2 脚注:[例如 Alpine Linux]。

Note

CentOS 7和Ubuntu 16.10是两个突出的Linux发行版,它们拥有的’systemd’版本太旧,无法在’cgroupv2’环境中运行,你可以选择其他方法

  • 将整个发行版升级到更新的版本。以上述例子为例,那可以是Ubuntu 18.04或20.04,以及CentOS 8(或RHEL/CentOS的衍生版本,如AlmaLinux或Rocky Linux)。这样做的好处是能获得最新的错误修复和安全修补,通常也会有新的特性,并将结束支持的日期推到未来。

  • 升级容器的systemd版本。如果发行版提供了一个后端仓库,这可以成为一个简单快速的临时解决方法。

  • 将容器或其服务移动到虚拟机。虚拟机与主机的交互要少得多,这就是为什么可以在那里安装几十年旧的操作系统版本而不会有问题。

  • 切换回传统的 cgroup 控制器。请注意,虽然这可以是一个有效的解决方案,但它并不是一个永久的方案。从 {pve} 9.0 开始,传统控制器将不再得到支持。

更改CGroup版本

Tip
如果不需要文件系统配额并且所有容器都支持’cgroupv2',建议坚持使用新的默认设置。

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

systemd.unified_cgroup_hierarchy=0

参见本节关于编辑内核启动命令行以及在哪里添加参数的说明。

客户操作系统配置

{pve} 尝试检测容器中的 Linux 发行版,并修改一些文件。以下是容器启动时所做工作的简短列表:

set /etc/hostname

设置容器名称

修改 /etc/hosts

允许查找本地主机名

网络设置

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

配置 DNS

传递有关DNS服务器的信息

适应初始化系统

例如,修复已生成的getty进程数。

设置根密码

当创建一个新容器

重写ssh_host_keys

以便每个容器都有唯一的键

随机设置crontab

以便 cron 不会在所有容器上同时启动

由 {PVE} 所做的更改被注释标记所包围:

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

这些标记将被放置在文件中的合理位置。如果这样的部分已经存在,它将被原地更新,而不会被移动。

通过添加一个`.pve-ignore`文件可以防止修改文件。例如,如果存在文件`/etc/.pve-ignore.hosts`,那么`/etc/hosts`文件将不会被修改。这可以通过以下方式创建一个简单的空文件:

# touch /etc/.pve-ignore.hosts

大多数修改都依赖于操作系统,因此它们在不同的发行版和版本之间有所不同。你可以通过手动将`ostype`设置为`unmanaged`来完全禁用这些修改。

操作系统类型的检测是通过检查容器内的特定文件完成的。{pve}首先检查`/etc/os-release`文件脚注:[/etc/os-release取代了众多的每个发行版特有的发布文件https://manpages.debian.org/stable/systemd/os-release.5.en.html]。如果该文件不存在,或者它不包含一个清晰可识别的发行版标识符,那么将检查以下特定于发行版的发布文件。

Ubuntu

inspect /etc/lsb-release (DISTRIB_ID=Ubuntu)

德比安

test /etc/debian_version

费多拉

test /etc/fedora-release

红帽或者CentOS

test /etc/redhat-release

ArchLinux

test /etc/arch-release

阿尔卑斯

test /etc/alpine-release

Gentoo

test /etc/gentoo-release

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

容器存储

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

例如,容器的根文件系统可以位于慢速且便宜的存储上,而数据库可以通过第二个挂载点位于快速且分布式的存储上。有关进一步的细节,请查阅 挂载点 一节。

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

此外,本地设备或本地目录可以直接使用“绑定挂载”来挂载。这样就可以在容器内部几乎不增加任何开销地访问本地资源。绑定挂载可作为容器之间共享数据的一种简便方法。

FUSE 挂载

Warning
由于Linux内核的冻结子系统存在问题,强烈建议不要在容器内使用FUSE挂载,因为容器需要被冻结以进行暂停或快照模式备份。

如果FUSE挂载不能被其他挂载机制或存储技术替代,那么可以在Proxmox主机上建立FUSE挂载,并使用绑定挂载点使其在容器内部可访问。

在容器内使用配额

配额允许在容器内设置限制,以限制每个用户可以使用的磁盘空间量。

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

激活 quota 选项会导致以下挂载选项被用于一个挂载点:`usrjquota=aquota.user,grpjquota=aquota.group,jqfmt=vfsv0

这允许配额被像在任何其他系统上那样使用。你可以通过运行以下命令来初始化`/aquota.user`和`/aquota.group`文件:

# quotacheck -cmug /
# quotaon /

然后使用`edquota`命令编辑配额。有关详细信息,请参阅容器内运行的发行版的文档。

Note
你需要为每一个挂载点运行上述命令,通过传递挂载点的路径来替代仅仅使用的`/`。

在容器内使用ACLs

标准的Posix访问控制列表(ACL)也可以在容器内使用。ACL允许你设置比传统的用户/组/其他模型更详细的文件所有权。

容器挂载点的备份

要在备份中包含一个挂载点,请在容器配置中为其启用`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
在图形用户界面中创建新挂载点时,默认启用此选项。

要禁用挂载点的备份,请如上所述添加`backup=0`,或在图形用户界面取消选中*备份*复选框。

容器挂载点的复制

默认情况下,当根磁盘被复制时,其他挂载点也会被复制。如果你不希望{pve}存储复制机制复制某个挂载点,你可以为该挂载点设置*跳过复制*选项。从{pve} 5.0版本开始,复制需要类型为`zfspool`的存储。当容器配置了复制时,将挂载点添加到不同类型的存储中,需要为该挂载点启用*跳过复制*功能。

备份与恢复

容器备份

可以使用 vzdump 工具来备份容器。详情请参考 vzdump 手册页。

恢复容器备份

使用`pct restore`命令可以恢复用`vzdump`创建的容器备份。默认情况下,`pct restore`会尝试尽可能多地恢复备份的容器配置。通过在命令行上手动设置容器选项,可以覆盖备份的配置(详见`pct`手册页)。

Note
pvesm extractconfig` 可用于查看 vzdump 归档中备份的配置。

有两种基础的还原模式,它们唯一的区别在于对挂载点的处理方式:

"简单"恢复模式

如果既没有明确设置`rootfs`参数也没有设置任何可选的`mpX`参数,将按照以下步骤恢复备份配置文件中的挂载点配置:

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

  2. 创建卷用于存储后备的挂载点,这些存储使用`storage`参数提供(默认值:local)。

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

  4. 将绑定和设备挂载点添加到恢复的配置中(限于根用户)

Note
由于绑定和设备挂载点从不备份,因此在最后一步不会恢复任何文件,只恢复配置选项。假设是这样的挂载点要么通过其他机制备份(例如,绑定挂载到许多容器中的NFS空间),要么根本就不打算备份。

这种简单模式也被网页界面中的容器恢复操作所使用。

高级恢复模式

通过设置`rootfs`参数(以及可选的任何`mpX`参数组合),`pct restore`命令会自动切换到高级模式。这种高级模式完全忽略备份存档中包含的`rootfs`和`mpX`配置选项,而是仅使用作为参数明确提供的选项。

这种模式允许在恢复时灵活配置挂载点设置,例如:

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

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

  • 恢复到设备和/或绑定挂载点(仅限根用户)

使用 pct 管理容器

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

命令行界面使用示例

基于Debian模板创建一个容器(前提是你已经通过网页界面下载了模板)

# 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命名空间并以根用户身份运行一个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

销毁一个容器总是会将其从访问控制列表中移除,并且总是会移除该容器的防火墙配置。如果你还想要将容器从复制任务、备份任务和高可用性资源配置中移除,那么你必须激活'--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 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 CTID`或`pct stop CTID`。

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

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

迁移

如果你有一个集群,你可以迁移你的容器

# pct migrate <ctid> <target>

这只在您的容器处于离线状态时有效。如果它定义了本地卷或挂载点,只要目标主机上定义了相同的存储,迁移就会通过网络将内容复制到目标主机。

由于技术限制,正在运行的容器无法进行实时迁移。你可以执行重启迁移,这会关闭容器,然后将其移动到目标节点上再次启动。由于容器非常轻量,这通常只会导致几百毫秒的停机时间。

重新启动迁移可以通过网络界面完成,或者使用 --restart 标志与 pct migrate 命令一起使用。

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

配置

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

Note
CTIDs小于100的是为内部目的保留的,而CTIDs需要在整个集群中唯一。
示例容器配置
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)完成整个过程。我们的工具包足够智能,能够即时应用大多数更改到正在运行的容器中。这个功能被称为"热插拔",在这种情况下,没有必要重启容器。

在无法热插拔进行更改的情况下,它将被注册为待处理的更改(在图形用户界面中以红色显示)。只有在重启容器后,这些更改才会被应用。

文件格式

容器配置文件使用简单的冒号分隔键/值格式。每行遵循以下格式:

# this is a comment
OPTION: value

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

可以直接添加低级别的,类LXC风格的配置,例如:

lxc.init_cmd: /sbin/my_own_init

lxc.init_cmd = /sbin/my_own_init

设置直接传递给LXC底层工具。

快照

当您创建快照时,‘pct`会将快照时的配置存储到同一配置文件内的独立快照部分中。例如,在创建了一个名为``testsnapshot’'的快照之后,您的配置文件将如下所示:

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

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

有一些与快照相关的属性,比如`parent`和`snaptime`。`parent`属性用于存储快照之间的父子关系。`snaptime`是快照创建的时间戳(Unix纪元)。

选项

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

操作系统架构类型。

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

控制台模式。默认情况下,控制台命令尝试打开与可用tty设备之一的连接。通过将cmode设置为’console',它尝试连接到/dev/console。如果你将cmode设置为’shell',它将在容器内简单调用一个shell(无需登录)。

console`: <boolean> (default = 1)

将控制台设备(/dev/console)附加到容器上。

cores`: `<integer> (1 - 8192)

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

cpulimit`:<number> (0 - 8192)默认值 = 0

CPU使用的限制。

Note
如果计算机有2个CPU,它总共有'2’个CPU时间。值'0’表示没有CPU限制。
cpuunits`:<整数> (0 - 500000)默认值cgroup v1: 1024, cgroup v2: 100

容器的CPU权重。此参数在内核公平调度器中使用。数字越大,该容器获得的CPU时间越多。这个数字是相对于所有其他正在运行的客户机的权重而言的。

debug`: <boolean> (default = 0)

尽量详细些。目前,这只会在启动时启用调试日志级别。

description`: `<string>

容器的描述。在网页界面的CT概览中显示。这将作为注释保存在配置文件内。

dev[n]`: `[[path=]<Path>] [,gid=<integer>] [,mode=<Octal access mode>] [,uid=<integer>]

要传递给容器的设备

gid`=`<integer> (0 - N)

要分配给设备节点的组ID

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)

在非特权容器中以 rw 而不是 mixed 模式挂载 /sys。这可能会在较新的(>= v245) systemd-networkd 环境下破坏网络功能。

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 用户空间陷阱功能的内核版本(5.3 或更新版本)。这是实验性的。

mount`=`<fstype;fstype;…​>

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

nesting`=<boolean> (default = 0)

允许嵌套。最适合配合额外身份映射的非特权容器使用。请注意,这将会将宿主的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 地址。如果你既没有设置搜索域也没有设置名称服务器,创建操作将会自动使用主机的设置。

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)>

IPv4地址的CIDR格式。

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)

设置容器的保护标志。这将阻止容器或容器磁盘的移除/更新操作。

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+]

启动和关闭行为。顺序是一个非负数,用于定义一般启动顺序。关闭操作以相反顺序执行。此外,你可以设置启动(up)或关闭(down)的延迟时间(以秒为单位),这指定了在启动或停止下一个虚拟机之前等待的延迟时间。

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

容器的交换空间量,以MB为单位。

tags: <string>

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

template`:<boolean>(默认值=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
只有在确信设置锁定的操作不再运行时才这样做。