lxc.container.conf 手册页 - Linux 容器

lxc.container.conf

节: (5)
更新时间: 2021-06-03
索引 返回主内容
 

名称

lxc.container.conf - LXC 容器配置文件  

描述

LXC 是一个知名且经过充分测试的低级 Linux 容器运行时。它自 2008 年以来一直在积极开发,并且已在全球范围内的关键生产环境中得到验证。它的一些核心贡献者也是那些帮助在 Linux 内核中实现各种知名容器化功能的人。

LXC 的主要目标是系统容器。也就是说,容器提供了尽可能接近虚拟机环境的环境,但没有运行单独内核和模拟所有硬件带来的开销。

这是通过内核安全功能(如命名空间、强制访问控制和控制组)的组合来实现的。

LXC 支持无特权容器。无特权容器是不带任何特权运行的容器。这需要容器运行的内核支持用户命名空间。在用户命名空间合并到主线内核之后,LXC 是第一个支持无特权容器的运行时。

本质上,用户命名空间隔离给定的 UID 和 GID 集。这是通过在主机上的一组 UID 和 GID 与容器中不同的(无特权)UID 和 GID 范围之间建立映射来实现的。内核将以这样的方式转换此映射,即在容器内部,所有 UID 和 GID 都会按预期从主机显示,而在主机上,这些 UID 和 GID 实际上是无特权的。例如,在容器内以 UID 和 GID 0 运行的进程可能在主机上显示为 UID 和 GID 100000。可以从相应的用户命名空间手册页中收集实现和工作细节。可以使用 **lxc.idmap** 键定义 UID 和 GID 映射。

Linux 容器使用简单的配置文件定义。配置文件中的每个选项都具有 **key = value** 的形式,适合放在一行。"#" 字符表示该行是注释。列表选项(如功能和 cgroups 选项)可以使用不带值的选项来清除该选项之前定义的任何值。

LXC 命名空间配置键使用单个点。这意味着诸如 **lxc.net.0** 之类的复杂配置键会公开各种子键,例如 **lxc.net.0.type**、**lxc.net.0.link**、**lxc.net.0.ipv6.address** 以及其他子键,以实现更细粒度的配置。  

配置

为了简化多个相关容器的管理,可以使容器配置文件导致加载另一个文件。例如,网络配置可以在一个公共文件中定义,该文件被多个容器包含。然后,如果将容器移动到另一个主机,则可能只需要更新一个文件。
lxc.include
指定要包含的文件。包含的文件必须采用相同的有效 lxc 配置文件格式。
 

架构

允许为容器设置架构。例如,为在 64 位主机上运行 32 位二进制文件的容器设置 32 位架构。这修复了依赖于架构来完成某些工作的容器脚本,例如下载软件包。
lxc.arch
指定容器的架构。

一些有效的选项是 **x86**、**i686**、**x86_64**、**amd64**

 

主机名

utsname 部分定义了要为容器设置的主机名。这意味着容器可以设置自己的主机名,而无需更改系统的名称。这使得主机名对容器私有。
lxc.uts.name
指定容器的主机名
 

停止信号

允许指定发送到容器 init 进程以干净地关闭容器的信号名称或编号。不同的 init 系统可以使用不同的信号来执行干净的关闭序列。此选项允许以 kill(1) 方式指定信号,例如 SIGPWR、SIGRTMIN+14、SIGRTMAX-10 或普通编号。默认信号为 SIGPWR。
lxc.signal.halt
指定用于停止容器的信号
 

重启信号

允许指定信号名称或编号以重启容器。此选项允许以 kill(1) 方式指定信号,例如 SIGTERM、SIGRTMIN+14、SIGRTMAX-10 或普通编号。默认信号为 SIGINT。
lxc.signal.reboot
指定用于重启容器的信号
 

停止信号

允许指定信号名称或编号以强制关闭容器。此选项允许以 kill(1) 方式指定信号,例如 SIGKILL、SIGRTMIN+14、SIGRTMAX-10 或普通编号。默认信号为 SIGKILL。
lxc.signal.stop
指定用于停止容器的信号
 

INIT 命令

设置用作容器 init 系统的命令。
lxc.execute.cmd
来自容器 rootfs 的绝对路径,指向默认情况下要运行的二进制文件。这主要对 **lxc-execute** 有意义。
lxc.init.cmd
来自容器 rootfs 的绝对路径,指向用作 init 的二进制文件。这主要对 **lxc-start** 有意义。默认值为 **/sbin/init**。
 

INIT 工作目录

设置容器内的绝对路径作为容器的工作目录。LXC 将在执行 init 之前切换到此目录。
lxc.init.cwd
容器内用作工作目录的绝对路径。
 

INIT ID

设置用于 init 系统和后续命令的 UID/GID。请注意,在启动系统容器时使用非 root UID 可能会失败,因为缺少权限。设置 UID/GID 主要在运行应用程序容器时有用。默认为:UID(0),GID(0)
lxc.init.uid
用于 init 的 UID。
lxc.init.gid
用于 init 的 GID。
 

PROC

配置容器的 proc 文件系统。
lxc.proc.[proc 文件名]
指定要设置的 proc 文件名。可用的文件名是在 /proc/PID/ 下列出的文件名。例如

              lxc.proc.oom_score_adj = 10
            
 

短暂的

允许指定容器是否会在关闭时被销毁。
lxc.ephemeral
唯一允许的值是 0 和 1。将此设置为 1 以在关闭时销毁容器。
 

网络

网络部分定义了容器中网络的虚拟化方式。网络虚拟化在第二层进行。为了使用网络虚拟化,必须指定参数来定义容器的网络接口。即使系统只有一个物理网络接口,也可以在容器中分配和使用多个虚拟接口。
lxc.net
可以在不带值的情况下使用,以清除所有先前的网络选项。
lxc.net.[i].type
指定要用于容器的网络虚拟化类型。必须在任何其他选项之前为网络设备指定它。可以通过在所有 **lxc.net.*** 键之后使用额外的索引 **i** 来指定多个网络。例如,**lxc.net.0.type = veth** 和 **lxc.net.1.type = veth** 指定了两个不同类型但相同类型的网络。共享相同索引 **i** 的所有键都将被视为属于同一个网络。例如,**lxc.net.0.link = br0** 将属于 **lxc.net.0.type**。目前,不同的虚拟化类型可以是

**无:** 将导致容器共享主机的网络命名空间。这意味着主机网络设备可以在容器中使用。这也意味着,如果容器和主机都使用 upstart 作为 init,那么容器中的“停止”(例如)将关闭主机。请注意,由于无法挂载 sysfs,无特权容器不适用于此设置。一个不安全的解决方法是绑定挂载主机的 sysfs。

**空:** 只会创建环回接口。

**veth:** 创建一个虚拟以太网对设备,其中一端分配给容器,另一端在主机上。**lxc.net.[i].veth.mode** 指定 veth 父级将在主机上使用的模式。接受的模式是 **bridge** 和 **router**。如果未指定,则模式默认为 bridge。在 **bridge** 模式下,主机端连接到由 **lxc.net.[i].link** 选项指定的网桥。如果未指定网桥链接,则会创建 veth 对设备,但不会连接到任何网桥。否则,必须在启动容器之前在系统上创建网桥。**lxc** 不会处理容器外部的任何配置。在 **router** 模式下,主机上将创建指向容器 IP 地址的静态路由,这些路由指向主机端 veth 接口。此外,在主机端 veth 接口上添加了代理 ARP 和代理 NDP 条目,以允许容器中的网关 IP 访问主机。默认情况下,**lxc** 为属于容器外部的网络设备选择一个名称,但如果您希望自己处理此名称,您可以告诉 **lxc** 使用 **lxc.net.[i].veth.pair** 选项设置一个特定名称(无特权容器除外,此选项出于安全原因被忽略)。可以使用 **lxc.net.[i].veth.ipv4.route** 和 **lxc.net.[i].veth.ipv6.route** 选项在指向容器的 host 上添加静态路由。多行指定多个路由。路由的格式为 x.y.z.t/m,例如 192.168.1.0/24。在 **bridge** 模式下,可以使用 **lxc.net.[i].veth.vlan.id** 选项设置未标记 VLAN 成员身份。它接受一个特殊的“无”值,指示应从网桥的默认未标记 VLAN 中删除容器端口。可以多次指定 **lxc.net.[i].veth.vlan.tagged.id** 选项,以将容器的网桥端口成员身份设置为一个或多个标记的 VLAN。

**vlan:** vlan 接口链接到由 **lxc.net.[i].link** 指定的接口,并分配给容器。vlan 标识符由选项 **lxc.net.[i].vlan.id** 指定。

macvlan: macvlan 接口与由 lxc.net.[i].link 指定的接口链接,并分配给容器。lxc.net.[i].macvlan.mode 指定 macvlan 用于在同一上层设备上的不同 macvlan 之间通信的模式。可接受的模式有 privatevepabridgepassthru。在 private 模式下,设备永远不会与同一 upper_dev 上的任何其他设备通信(默认)。在 vepa 模式下,新的虚拟以太网端口聚合器 (VEPA) 模式,它假设相邻网桥会返回所有源和目标都在 macvlan 端口本地的帧,即网桥被设置为反射中继。从 upper_dev 传入的广播帧在 VEPA 模式下会泛洪到所有 macvlan 接口,本地帧不会在本地传递。在 bridge 模式下,它提供了同一端口上不同 macvlan 接口之间的简单网桥行为。从一个接口到另一个接口的帧会直接传递,不会被发送到外部。广播帧会泛洪到所有其他网桥端口和外部接口,但当它们从反射中继返回时,我们不会再次传递它们。由于我们知道所有 MAC 地址,因此 macvlan 桥接模式不需要像桥接模块那样学习或 STP。在 passthru 模式下,物理接口接收的所有帧都将转发到 macvlan 接口。一个物理接口只能有一个 passthru 模式的 macvlan 接口。

ipvlan: ipvlan 接口与由 lxc.net.[i].link 指定的接口链接,并分配给容器。lxc.net.[i].ipvlan.mode 指定 ipvlan 用于在同一上层设备上的不同 ipvlan 之间通信的模式。可接受的模式有 l3l3sl2。它默认为 l3 模式。在 l3 模式下,直到 L3 的 TX 处理发生在附加到从属设备的堆栈实例上,数据包切换到父设备的堆栈实例以进行 L2 处理,并且来自该实例的路由将在数据包排队到出站设备之前使用。在此模式下,从属设备不会接收也不会发送多播/广播流量。在 l3s 模式下,TX 处理与 L3 模式非常相似,除了 iptables(连接跟踪)在此模式下工作,因此它是 L3 对称的 (L3s)。这将具有略微较低的性能,但由于您选择此模式而不是普通 L3 模式以使连接跟踪工作,因此应该没有问题。在 l2 模式下,TX 处理发生在附加到从属设备的堆栈实例上,数据包切换并排队到父设备以发送设备出去。在此模式下,从属设备也会 RX/TX 多播和广播(如果适用)。lxc.net.[i].ipvlan.isolation 指定隔离模式。可接受的隔离值有 bridgeprivatevepa。它默认为 bridge。在 bridge 隔离模式下,从属设备除了通过父设备通信外,还可以相互通话。在 private 隔离模式下,端口设置为私有模式。即端口不允许从属设备之间的交叉通信。在 vepa 隔离模式下,端口设置为 VEPA 模式。即端口将卸载切换功能到外部实体,如 802.1Qbg 中所述。

phys:lxc.net.[i].link 指定的已存在的接口将分配给容器。

lxc.net.[i].flags
指定对网络执行的操作。

up: 激活接口。

lxc.net.[i].link
指定用于真实网络流量的接口。
lxc.net.[i].l2proxy
控制是否为容器的 IP 地址将 L2 IP 邻居代理条目添加到 lxc.net.[i].link 接口。可以设置为 0 或 1。默认为 0。与 IPv4 地址一起使用时,需要设置以下 sysctl 值:net.ipv4.conf.[link].forwarding=1 与 IPv6 地址一起使用时,需要设置以下 sysctl 值:net.ipv6.conf.[link].proxy_ndp=1 net.ipv6.conf.[link].forwarding=1
lxc.net.[i].mtu
指定此接口的最大传输单元。
lxc.net.[i].name
接口名称是动态分配的,但如果由于容器使用的配置文件使用通用名称(例如 eth0)而需要另一个名称,则此选项将在容器中重命名接口。
lxc.net.[i].hwaddr
默认情况下,接口 MAC 地址由虚拟接口动态分配,但在某些情况下,这需要解决 MAC 地址冲突或始终具有相同的链接本地 IPv6 地址。地址中的任何“x”都将被随机值替换,这允许设置 hwaddr 模板。
lxc.net.[i].ipv4.address
指定要分配给虚拟化接口的 IPv4 地址。多行指定多个 IPv4 地址。地址格式为 x.y.z.t/m,例如 192.168.1.123/24。
lxc.net.[i].ipv4.gateway
指定要在容器内用作网关的 IPv4 地址。地址格式为 x.y.z.t,例如 192.168.1.123。还可以具有特殊值 auto,这意味着从桥接接口(由 lxc.net.[i].link 选项指定)获取主地址并将其用作网关。auto 仅在使用 vethmacvlanipvlan 网络类型时可用。还可以具有特殊值 dev,这意味着将默认网关设置为设备路由。这主要用于 L3 网络模式,例如 IPVLAN。
lxc.net.[i].ipv6.address
指定要分配给虚拟化接口的 IPv6 地址。多行指定多个 IPv6 地址。地址格式为 x::y/m,例如 2003:db8:1:0:214:1234:fe0b:3596/64
lxc.net.[i].ipv6.gateway
指定要在容器内用作网关的 IPv6 地址。地址格式为 x::y,例如 2003:db8:1:0::1 还可以具有特殊值 auto,这意味着从桥接接口(由 lxc.net.[i].link 选项指定)获取主地址并将其用作网关。auto 仅在使用 vethmacvlanipvlan 网络类型时可用。还可以具有特殊值 dev,这意味着将默认网关设置为设备路由。这主要用于 L3 网络模式,例如 IPVLAN。
lxc.net.[i].script.up
添加一个配置选项以指定在创建和配置从主机端使用的网络后要执行的脚本。

除了所有钩子可用的信息之外。以下信息将提供给脚本

LXC_HOOK_TYPE: 钩子类型。这可能是“up”或“down”。
LXC_HOOK_SECTION: 节点类型“net”。
LXC_NET_TYPE: 网络类型。这是此处列出的有效网络类型之一(例如,“vlan”、“macvlan”、“ipvlan”、“veth”)。
LXC_NET_PARENT: 主机上的父设备。这仅在网络类型“mavclan”、“veth”、“phys”上设置。
LXC_NET_PEER: 主机上对等设备的名称。这仅在“veth”网络类型上设置。请注意,此信息仅在 lxc.hook.version 设置为 1 时可用。

此信息是以环境变量形式提供还是作为脚本参数提供取决于 lxc.hook.version 的值。如果设置为 1,则信息以环境变量形式提供。如果设置为 0,则信息作为脚本参数提供。

脚本的标准输出将在调试级别记录。标准错误不会记录,但可以通过将标准错误重定向到标准输出的钩子来捕获。

lxc.net.[i].script.down
添加一个配置选项以指定在销毁从主机端使用的网络之前要执行的脚本。

除了所有钩子可用的信息之外。以下信息将提供给脚本

LXC_HOOK_TYPE: 钩子类型。这可能是“up”或“down”。
LXC_HOOK_SECTION: 节点类型“net”。
LXC_NET_TYPE: 网络类型。这是此处列出的有效网络类型之一(例如,“vlan”、“macvlan”、“ipvlan”、“veth”)。
LXC_NET_PARENT: 主机上的父设备。这仅在网络类型“mavclan”、“veth”、“phys”上设置。
LXC_NET_PEER: 主机上对等设备的名称。这仅在“veth”网络类型上设置。请注意,此信息仅在 lxc.hook.version 设置为 1 时可用。

此信息是以环境变量形式提供还是作为脚本参数提供取决于 lxc.hook.version 的值。如果设置为 1,则信息以环境变量形式提供。如果设置为 0,则信息作为脚本参数提供。

脚本的标准输出将在调试级别记录。标准错误不会记录,但可以通过将标准错误重定向到标准输出的钩子来捕获。

 

新的伪终端实例 (DEVPTS)

为了更严格的隔离,容器可以拥有自己的私有伪终端实例。
lxc.pty.max
如果设置,容器将拥有一个新的伪终端实例,使其对容器私有。该值指定了允许用于伪终端实例的伪终端的最大数量(此限制尚未实现)。
 

容器系统控制台

如果容器配置了根文件系统并且 inittab 文件设置为使用控制台,您可能需要指定此控制台的输出位置。
lxc.console.buffer.size
设置此选项指示 liblxc 分配一个内存中环形缓冲区。容器的控制台输出将写入环形缓冲区。请注意,环形缓冲区必须至少与标准页面大小一样大。当传递的值小于单个页面大小时,liblxc 将分配一个单个页面大小的环形缓冲区。页面大小通常为 4KB。“auto”关键字将导致 liblxc 分配一个 128KB 的环形缓冲区。当手动指定环形缓冲区的大小 时,转换为字节的值应该是一个 2 的幂。有效的尺寸前缀是“KB”、“MB”、“GB”。(请注意,所有转换都是基于 1024 的倍数。这意味着“KB” == “KiB”、“MB” == “MiB”、“GB” == “GiB”。此外,后缀的大小写将被忽略,即“kB”、“KB”和“Kb”被视为相同。)
lxc.console.size
设置此选项指示 liblxc 对 lxc.console.logfile 中指定 的控制台日志文件的大小进行限制。请注意,日志文件的大小必须至少与标准页面大小一样大。当传递的值小于单个页面大小时,liblxc 将将日志文件的大小设置为单个页面大小。页面大小通常为 4KB。“auto”关键字将导致 liblxc 对日志文件的大小限制为 128KB。当手动指定日志文件的大小 时,转换为字节的值应该是一个 2 的幂。有效的尺寸前缀是“KB”、“MB”、“GB”。(请注意,所有转换都是基于 1024 的倍数。这意味着“KB” == “KiB”、“MB” == “MiB”、“GB” == “GiB”。此外,后缀的大小写将被忽略,即“kB”、“KB”和“Kb”被视为相同。)如果用户希望镜像磁盘上的控制台环形缓冲区,他们应该将 lxc.console.size 设置为等于 lxc.console.buffer.size
lxc.console.logfile
指定一个路径,该路径指向将写入控制台输出的文件。请注意,与磁盘上的环形缓冲区日志文件相反,此文件将不断增长,如果 不轮换和删除,可能会填满用户磁盘。此问题也可以通过使用内存中的环形缓冲区选项 lxc.console.buffer.sizelxc.console.buffer.logfile 来避免。
lxc.console.rotate
是否轮换 lxc.console.logfile 中指定的控制台日志文件。用户可以发送 API 请求来轮换日志文件。请注意,旧的日志文件将具有与原始文件相同的名称,并在末尾添加“.1”后缀。希望防止控制台日志文件填满磁盘的用户应该轮换日志文件,如果不需要就将其删除。此问题也可以通过使用内存中的环形缓冲区选项 lxc.console.buffer.sizelxc.console.buffer.logfile 来避免。
lxc.console.path
指定一个路径,该路径指向将连接控制台的设备。关键字“none”将简单地禁用控制台。请注意,当指定“none”并在容器中为控制台创建设备节点(在 /dev/console)或将主机的 /dev/console 绑定装载到容器中的 /dev/console 时,容器将直接访问主机的 /dev/console。当容器对设备具有写访问权限时,这很危险,因此应该谨慎使用。
 

通过 TTYS 进行控制台

如果容器配置了根文件系统,并且 inittab 文件设置为在 ttys 上启动 getty,则此选项很有用。该选项指定容器可用的 tty 数量。容器 inittab 文件中的 getty 数量不应超过此选项中指定的 tty 数量,否则多余的 getty 会话将无限期地死亡并重新生成,从而在控制台或 /var/log/messages 中显示烦人的消息。
lxc.tty.max
指定提供给容器的 tty 数量。
 

控制台设备位置

LXC 控制台通过在主机上创建的 Unix98 PTY 提供,并绑定安装到容器中预期的设备上。默认情况下,它们绑定安装在 /dev/console/dev/ttyN 上。这可能会阻止客户机中的软件包升级。因此,您可以指定一个目录位置(在 /dev 下,LXC 将在此目录下创建文件并绑定安装到它们上。然后,它们将符号链接到 /dev/console/dev/ttyN。然后软件包升级就可以成功,因为它能够删除和替换符号链接。
lxc.tty.dir
/dev 下指定一个目录,用于创建容器控制台设备。请注意,LXC 会将 /dev/console 的任何绑定安装或设备节点移动到此目录中。
 

/DEV 目录

默认情况下,lxc 在容器的 /dev 目录中创建一些符号链接(fd、stdin、stdout、stderr),但不会自动创建设备节点条目。这允许容器的 /dev 按照容器根文件系统中的需要进行设置。如果 lxc.autodev 设置为 1,则在挂载容器的根文件系统后,LXC 会在 /dev 下挂载一个新的 tmpfs(默认情况下限制为 500K,除非在 lxc.autodev.tmpfs.size 中定义),并填充一组最小的初始设备。这通常在启动包含基于“systemd”的“init”的容器时需要,但在其他时间可能不是必需的。容器 /dev 目录中的其他设备可以通过使用 lxc.hook.autodev 钩子创建。
lxc.autodev
将其设置为 0 以阻止 LXC 在启动容器时挂载和填充最小 /dev
lxc.autodev.tmpfs.size
将其设置为定义 /dev tmpfs 的大小。默认值为 500000(500K)。如果使用该参数但没有值,则使用默认值。
 

挂载点

挂载点部分指定了要挂载的不同位置。这些挂载点将对容器私有,并且外部运行的进程将无法看到它们。这对于挂载 /etc、/var 或 /home 非常有用。

注意 - LXC 通常会确保挂载目标和相对绑定安装源在容器根目录下受到适当的限制,以避免使用过度挂载主机目录和文件的攻击。(绝对挂载源中的符号链接将被忽略)但是,如果容器配置首先将一个目录(在容器用户的控制下,例如 /home/joe)挂载到容器中的某个 path,然后在 path 下挂载,那么 TOCTTOU 攻击就可能发生,在这种攻击中,容器用户在恰当的时间修改了他的主目录下的符号链接。

lxc.mount.fstab
指定 fstab 格式中的一个文件位置,其中包含挂载信息。挂载目标位置可以并且在大多数情况下应该是相对路径,这将成为挂载的容器根目录的相对路径。例如,

             proc proc proc nodev,noexec,nosuid 0 0
             

将在容器的 /proc 下挂载一个 proc 文件系统,无论根文件系统来自哪里。这对于块设备支持的文件系统以及容器克隆具有弹性。

请注意,从镜像文件或块设备挂载文件系统时,第三个字段(fs_vfstype)不能像 mount(8) 那样是 auto,而必须明确指定。

lxc.mount.entry
指定与 fstab 格式中的行相对应的挂载点。此外,lxc 支持挂载传播,例如 rshared 或 rprivate,并添加了三个额外的挂载选项。optional 如果挂载失败则不要失败。create=dircreate=file 在挂载该点时创建目录(或文件)。relative 源路径被认为是相对于挂载的容器根目录的。例如,

             dev/null proc/kcore none bind,relative 0 0
             

将扩展 dev/null 到 ${LXC_ROOTFS_MOUNT}/dev/null,并将其挂载到容器内的 proc/kcore。

lxc.mount.auto
指定哪些标准内核文件系统应该自动挂载。这可能会大大简化配置。文件系统是
proc:mixed(或 proc):以读写方式挂载 /proc,但以只读方式重新挂载 /proc/sys/proc/sysrq-trigger,以确保安全/容器隔离。
proc:rw:以读写方式挂载 /proc
sys:mixed(或 sys):以只读方式挂载 /sys,但 /sys/devices/virtual/net 可写。
sys:ro:以只读方式挂载 /sys,以确保安全/容器隔离。
sys:rw:以读写方式挂载 /sys
cgroup:mixed:将 tmpfs 挂载到 /sys/fs/cgroup,为容器添加的所有层次结构创建目录,在这些层次结构中创建与 cgroup 名称相同的子目录,并将容器自己的 cgroup 绑定安装到该目录中。容器将能够写入它自己的 cgroup 目录,但不能写入父目录,因为父目录将以只读方式重新挂载。
cgroup:mixed:forceforce 选项将导致 LXC 在任何情况下都对容器执行 cgroup 挂载。否则,它类似于 cgroup:mixed。这在启用了 cgroup 命名空间时主要有用,在这种情况下,LXC 通常会将挂载 cgroup 留给容器的 init 二进制文件,因为这样做是完全安全的。
cgroup:ro:类似于 cgroup:mixed,但所有内容都将以只读方式挂载。
cgroup:ro:forceforce 选项将导致 LXC 在任何情况下都对容器执行 cgroup 挂载。否则,它类似于 cgroup:ro。这在启用了 cgroup 命名空间时主要有用,在这种情况下,LXC 通常会将挂载 cgroup 留给容器的 init 二进制文件,因为这样做是完全安全的。
cgroup:rw:类似于 cgroup:mixed,但所有内容都将以读写方式挂载。请注意,通向容器自己的 cgroup 的路径将是可写的,但不会是 cgroup 文件系统,而只是 /sys/fs/cgroup 的 tmpfs 的一部分。
cgroup:rw:forceforce 选项将导致 LXC 在任何情况下都对容器执行 cgroup 挂载。否则,它类似于 cgroup:rw。这在启用了 cgroup 命名空间时主要有用,在这种情况下,LXC 通常会将挂载 cgroup 留给容器的 init 二进制文件,因为这样做是完全安全的。
cgroup(没有说明符):如果容器保留 CAP_SYS_ADMIN 功能,则默认为 cgroup:rw,否则默认为 cgroup:mixed
cgroup-full:mixed:将 tmpfs 挂载到 /sys/fs/cgroup,为容器添加的所有层次结构创建目录,将来自主机的层次结构绑定安装到容器中,并将所有内容设为只读,除了容器自己的 cgroup 之外。请注意,与 cgroup 相比,cgroup 中通向容器自己的 cgroup 的所有路径只是底层 tmpfs 中的简单目录,这里 /sys/fs/cgroup/$hierarchy 将包含主机完整的 cgroup 层次结构,尽管在容器自己的 cgroup 之外是只读的。这可能会将相当多的信息泄露到容器中。
cgroup-full:mixed:forceforce 选项将导致 LXC 在任何情况下都对容器执行 cgroup 挂载。否则,它类似于 cgroup-full:mixed。这在启用了 cgroup 命名空间时主要有用,在这种情况下,LXC 通常会将挂载 cgroup 留给容器的 init 二进制文件,因为这样做是完全安全的。
cgroup-full:ro:类似于 cgroup-full:mixed,但所有内容都将以只读方式挂载。
cgroup-full:ro:forceforce 选项将导致 LXC 在任何情况下都对容器执行 cgroup 挂载。否则,它类似于 cgroup-full:ro。这在启用了 cgroup 命名空间时主要有用,在这种情况下,LXC 通常会将挂载 cgroup 留给容器的 init 二进制文件,因为这样做是完全安全的。
cgroup-full:rw:类似于 cgroup-full:mixed,但所有内容都将以读写方式挂载。请注意,在这种情况下,容器可能会逃脱它自己的 cgroup。(另请注意,如果容器具有 CAP_SYS_ADMIN 支持,并且可以自己挂载 cgroup 文件系统,它也可能会这样做。)
cgroup-full:rw:forceforce 选项将导致 LXC 在任何情况下都对容器执行 cgroup 挂载。否则,它类似于 cgroup-full:rw。这在启用了 cgroup 命名空间时主要有用,在这种情况下,LXC 通常会将挂载 cgroup 留给容器的 init 二进制文件,因为这样做是完全安全的。
cgroup-full(没有说明符):如果容器保留 CAP_SYS_ADMIN 功能,则默认为 cgroup-full:rw,否则默认为 cgroup-full:mixed

如果启用了 cgroup 命名空间,那么任何 cgroup 自动挂载请求都将被忽略,因为容器可以自己挂载文件系统,并且自动挂载可能会使容器 init 混乱。

请注意,如果启用了 cgroup 文件系统的自动挂载,则 /sys/fs/cgroup 下的 tmpfs 将始终以读写方式挂载(但对于 :mixed:ro 情况,各个层次结构 /sys/fs/cgroup/$hierarchy 将是只读的)。这是为了解决 Ubuntu 的 mountall(8) 命令中的一个怪癖,如果 /sys/fs/cgroup 以只读方式挂载,并且由于缺乏 CAP_SYS_ADMIN,容器无法以读写方式重新挂载它,则会导致容器在启动时等待用户输入。

示例

              lxc.mount.auto = proc sys cgroup
              lxc.mount.auto = proc:rw sys:rw cgroup-full:rw
            
 

根文件系统

容器的根文件系统可以与主机系统的根文件系统不同。
lxc.rootfs.path
指定容器的根文件系统。它可以是镜像文件、目录或块设备。如果未指定,则容器将与主机共享其根文件系统。

对于目录或简单的块设备支持的容器,可以使用路径名。如果 rootfs 由 nbd 设备支持,则 nbd:file:1 指定 file 应该附加到 nbd 设备,并且分区 1 应该作为 rootfs 挂载。nbd:file 指定 nbd 设备本身应该被挂载。overlayfs:/lower:/upper 指定 rootfs 应该是一个覆盖层,/upper 以读写方式挂载在 /lower 的只读挂载上。对于 overlay,可以指定多个 /lower 目录。loop:/file 告诉 lxc 将 /file 附加到循环设备并挂载循环设备。

lxc.rootfs.mount
在旋转之前递归绑定 lxc.rootfs.path 的位置。这是为了确保 pivot_root(8) 系统调用的成功。任何目录都足够,默认值通常应该可以工作。
lxc.rootfs.options
指定在挂载根文件系统时要使用的额外挂载选项。挂载选项的格式对应于 fstab 中使用的格式。此外,LXC 支持自定义的 idmap= 挂载选项。此选项可用于告知 LXC 为容器的根文件系统创建 idmapped 挂载。当用户不希望递归地 chown 容器的根文件系统以匹配容器将要使用的用户命名空间的 idmapping 时,此选项非常有用。相反,可以使用 idmapped 挂载来处理这种情况。idmap= 的参数可以是指向用户命名空间文件的路径,LXC 将打开并使用该文件来 idmap 根文件系统,也可以是特殊值“container”,这将指示 LXC 使用容器的用户命名空间来 idmap 根文件系统。
lxc.rootfs.managed
将其设置为 0 表示 LXC 不管理容器存储,然后 LXC 不会修改容器存储。默认值为 1。
 

控制组(“CGROUPS”)

控制组部分包含不同子系统的配置。lxc 不会检查子系统名称的正确性。这具有在容器启动之前不检测配置错误的缺点,但具有允许任何未来子系统的优点。

多年来,cgroups 的内核实现发生了重大变化。随着 Linux 4.5 对新 cgroup 文件系统的支持添加,通常称为“cgroup2”或“统一层次结构”。从那时起,旧的 cgroup 文件系统通常被称为“cgroup1”或“传统层次结构”。有关两个版本之间差异的详细说明,请参阅 cgroups 手册页。

LXC 通过使用不同的配置键前缀来区分传统层次结构和统一层次结构的设置。要更改传统层次结构中控制器的设置,必须使用键前缀 lxc.cgroup.,并且为了更改统一层次结构中控制器的设置,必须使用 lxc.cgroup2. 键。请注意,LXC 将忽略仅使用统一层次结构的系统上的 lxc.cgroup. 设置。相反,它将忽略仅使用传统层次结构的系统上的 lxc.cgroup2. 选项。

从本质上讲,cgroup 层次结构是一种以分层方式组织进程的方式。通常,cgroup 层次结构将启用一个或多个“控制器”。cgroup 层次结构中的“控制器”通常负责沿层次结构分配特定类型的系统资源。控制器包括“pids”控制器、“cpu”控制器、“memory”控制器等。然而,某些控制器不属于分配系统资源的类别,而是通常被称为“实用程序”控制器。一个实用程序控制器是设备控制器。它不分配系统资源,而是允许管理设备访问。

在传统层次结构中,设备控制器与大多数其他控制器一样实现为一组可以写入的文件。这些文件名为“devices.allow”和“devices.deny”。传统设备控制器允许实现“允许列表”和“拒绝列表”。

允许列表是一个设备程序,它默认阻止对所有设备的访问。为了访问特定设备,必须为特定设备或设备类别指定“允许规则”。相反,拒绝列表是一个设备程序,它默认允许访问所有设备。为了限制对特定设备的访问,必须为特定设备或设备类别指定“拒绝规则”。

在统一 cgroup 层次结构中,设备控制器的实现已经完全改变。不再使用文件进行读写,而是可以使用 BPF_PROG_TYPE_CGROUP_DEVICE 的 eBPF 程序附加到 cgroup。即使内核实现已经完全改变,LXC 仍然尝试允许在传统设备 cgroup 和基于 eBPF 的统一设备控制器中遵循相同的语义。以下段落解释了基于 eBPF 的统一设备控制器的语义。

如上所述,为基于 eBPF 的统一设备控制器指定设备规则的格式与传统 cgroup 设备控制器相同;只有配置键前缀已更改。具体来说,传统 cgroup 设备控制器的设备规则通过 lxc.cgroup.devices.allowlxc.cgroup.devices.deny 指定,而对于 cgroup2 基于 eBPF 的设备控制器,必须使用 lxc.cgroup.devices.allowlxc.cgroup.devices.deny

允许列表设备规则

                lxc.cgroup2.devices.deny = a
              

将导致 LXC 指示内核默认阻止对所有设备的访问。要授予对设备的访问权限,必须通过 lxc.cgroup2.devices.allow 键添加允许设备规则。这被称为“允许列表”设备程序。

拒绝列表设备规则

                lxc.cgroup2.devices.allow = a
              

将导致 LXC 指示内核默认允许访问所有设备。要拒绝对设备的访问,必须通过 lxc.cgroup2.devices.deny 键添加拒绝设备规则。这被称为“拒绝列表”设备程序。

指定上述两个规则中的任何一个将导致所有以前的规则被清除,即设备列表将被重置。
当请求允许列表程序时,即默认情况下阻止对所有设备的访问,将忽略单个设备或设备类别的特定拒绝规则。
当请求拒绝列表程序时,即默认情况下允许访问所有设备,将忽略单个设备或设备类别的特定允许规则。

例如,规则集

          lxc.cgroup2.devices.deny = a
          lxc.cgroup2.devices.allow = c *:* m
          lxc.cgroup2.devices.allow = b *:* m
          lxc.cgroup2.devices.allow = c 1:3 rwm
        

实现允许列表设备程序,即内核将阻止对未在此列表中明确允许的所有设备的访问。此特定程序指出,可以创建所有字符设备和块设备,但只能读写 /dev/null。

如果我们改为切换到以下规则集

          lxc.cgroup2.devices.allow = a
          lxc.cgroup2.devices.deny = c *:* m
          lxc.cgroup2.devices.deny = b *:* m
          lxc.cgroup2.devices.deny = c 1:3 rwm
        

那么 LXC 将指示内核实现拒绝列表,即内核将允许访问未在此列表中明确拒绝的所有设备。此特定程序指出,不允许创建任何字符设备或块设备,并且不允许读写或创建 /dev/null。

现在考虑相同的程序,但紧随其后的是一个“全局规则”,它确定设备程序的类型(允许列表或拒绝列表),如上所述

          lxc.cgroup2.devices.allow = a
          lxc.cgroup2.devices.deny = c *:* m
          lxc.cgroup2.devices.deny = b *:* m
          lxc.cgroup2.devices.deny = c 1:3 rwm
          lxc.cgroup2.devices.allow = a
        

最后一行将导致 LXC 重置设备列表,而不会更改设备程序的类型。

如果我们指定

          lxc.cgroup2.devices.allow = a
          lxc.cgroup2.devices.deny = c *:* m
          lxc.cgroup2.devices.deny = b *:* m
          lxc.cgroup2.devices.deny = c 1:3 rwm
          lxc.cgroup2.devices.deny = a
        

相反,最后一行将导致 LXC 重置设备列表,并从允许列表程序切换到拒绝列表程序。

lxc.cgroup.[控制器名称].[控制器文件]
指定要在传统 cgroup 层次结构上设置的控制组值。控制器名称是控制组的字面名称。允许的名称及其值的语法不受 LXC 约束,而是取决于启动容器时运行的 Linux 内核的功能,例如 lxc.cgroup.cpuset.cpus
lxc.cgroup2.[控制器名称].[控制器文件]
指定要在统一 cgroup 层次结构上设置的控制组值。控制器名称是控制组的字面名称。允许的名称及其值的语法不受 LXC 约束,而是取决于启动容器时运行的 Linux 内核的功能,例如 lxc.cgroup2.memory.high
lxc.cgroup.dir
指定将创建容器的 cgroup 的目录或路径。例如,为名为“c1”的容器设置 lxc.cgroup.dir = my-cgroup/first 将创建容器的 cgroup 作为“my-cgroup”的子 cgroup。例如,如果用户的当前 cgroup“my-user”位于 cgroup v1 层次结构中 cpuset 控制器的根 cgroup 中,这将为容器创建 cgroup“/sys/fs/cgroup/cpuset/my-user/my-cgroup/first/c1”。LXC 将创建任何缺少的 cgroup。这预设了用户对其当前 cgroup 具有写入权限。
lxc.cgroup.dir.container
这类似于 lxc.cgroup.dir,但必须与 lxc.cgroup.dir.monitor 一起使用,并且仅影响容器的 cgroup 路径。此选项与 lxc.cgroup.dir 相互排斥。请注意,容器附加到的最终路径可能会被 lxc.cgroup.dir.container.inner 选项进一步扩展。
lxc.cgroup.dir.monitor
这是 lxc.cgroup.dir.container 的监视器进程对应项。
lxc.cgroup.dir.monitor.pivot
在容器终止时,监视器进程的 PID 将附加到此 cgroup。此路径不应是任何其他已配置 cgroup dir 的子路径,以确保在容器终止时正确删除其他 cgroup 路径。
lxc.cgroup.dir.container.inner
指定将创建 cgroup 命名空间的附加子目录。使用此选项,cgroup 限制将应用于 lxc.cgroup.dir.container 中指定的外部路径,该路径无法从容器内部访问,从而可以更好地对特权容器实施限制,以使它们无法覆盖这些限制。这仅与 lxc.cgroup.dir.containerlxc.cgroup.dir.monitor 选项一起使用,否则没有效果。
lxc.cgroup.relative
将其设置为 1 以指示 LXC 从不转义到根 cgroup。这使用户可以轻松遵守 cgroup2 和 systemd 强制执行的限制。具体来说,这使得可以将 LXC 容器作为 systemd 服务运行。
 

功能

如果此容器以 root 身份运行,则可以在容器中删除功能。
lxc.cap.drop
指定要在容器中删除的功能。允许使用一个空格分隔的定义多个功能的单行。格式是功能定义的小写,没有“CAP_”前缀,例如 CAP_SYS_MODULE 应指定为 sys_module。请参阅 capabilities(7)。如果使用没有值,lxc 将清除到目前为止指定的所有删除功能。
lxc.cap.keep
指定要在容器中保留的功能。所有其他功能都将被删除。当遇到特殊值“none”时,lxc 将清除到目前为止指定的所有保留功能。仅使用“none”值可以删除所有功能。
 

命名空间

命名空间可以克隆 (lxc.namespace.clone)、保留 (lxc.namespace.keep) 或共享 (lxc.namespace.share.[命名空间标识符])。
lxc.namespace.clone
指定应该使用容器创建的命名空间。要创建的命名空间作为空格分隔的列表指定。每个命名空间必须对应于在 /proc/PID/ns 目录中看到的标准命名空间标识符之一。当未显式设置 lxc.namespace.clone 时,将使用内核和当前配置支持的所有命名空间。

要创建一个新的挂载、网络和 ipc 命名空间,请设置 lxc.namespace.clone=mount net ipc

lxc.namespace.keep
指定容器应该从创建它的进程继承的命名空间。要保留的命名空间作为空格分隔的列表指定。每个命名空间必须对应于在 /proc/PID/ns 目录中看到的标准命名空间标识符之一。lxc.namespace.keep 是一个拒绝列表选项,即它在强制容器必须保留特定命名空间集时很有用。

要保留网络、用户和 ipc 命名空间,请设置 lxc.namespace.keep=user net ipc

请注意,与大多数 init 系统共享 pid 命名空间可能无法正常工作。

请注意,如果容器请求一个新的用户命名空间,并且容器想要继承网络命名空间,它也需要继承用户命名空间。

lxc.namespace.share.[命名空间标识符]
指定要从另一个容器或进程继承的命名空间。[命名空间标识符] 后缀需要替换为出现在 /proc/PID/ns 目录中的命名空间之一。

要从另一个进程继承命名空间,请将 lxc.namespace.share.[命名空间标识符] 设置为进程的 PID,例如 lxc.namespace.share.net=42

要从另一个容器继承命名空间,请将 lxc.namespace.share.[命名空间标识符] 设置为容器的名称,例如 lxc.namespace.share.pid=c3

要从位于与标准 liblxc 路径不同的路径中的另一个容器继承命名空间,请将 lxc.namespace.share.[命名空间标识符] 设置为容器的完整路径,例如 lxc.namespace.share.user=/opt/c3

为了继承命名空间,调用者需要对进程或容器具有足够的权限。

请注意,在系统容器之间共享 pid 命名空间可能不适用于大多数 init 系统。

请注意,如果两个进程位于不同的用户命名空间中,并且一个进程想要继承另一个进程的网络命名空间,则通常需要也继承用户命名空间。

请注意,如果没有对 LSM 进行仔细的额外配置,与任务共享用户+pid 命名空间可能会允许该任务将权限提升到调用 liblxc 的任务的权限。

lxc.time.offset.boot
指定引导时钟的正负偏移量。格式接受小时 (h)、分钟 (m)、秒 (s)、毫秒 (ms)、微秒 (us) 和纳秒 (ns)。
lxc.time.offset.monotonic
指定单调时钟的正负偏移量。格式接受小时 (h)、分钟 (m)、秒 (s)、毫秒 (ms)、微秒 (us) 和纳秒 (ns)。
 

资源限制

可以更改容器的软硬资源限制。无特权容器只能降低它们。未明确指定的资源将被继承。
lxc.prlimit.[limit name]
指定要设置的资源限制。限制指定为两个用冒号分隔的值,这些值要么是数字,要么是“unlimited”这个词。单个值可以用作快捷方式,将软限制和硬限制都设置为相同的值。允许的名称是“RLIMIT_”资源名称的小写形式,不带“RLIMIT_”前缀,例如 RLIMIT_NOFILE 应指定为“nofile”。请参阅 **setrlimit**(2)。如果使用无值,lxc 将清除到目前为止指定的资源限制。没有明确配置限制的资源将从启动容器的进程继承。
 

SYSCTL

为容器配置内核参数。
lxc.sysctl.[kernel parameters name]
指定要设置的内核参数。可用的参数是在 /proc/sys/ 下列出的那些。请注意,并非所有 sysctl 都是命名空间的。更改非命名空间 sysctl 会导致系统范围的设置被修改。**sysctl**(8)。如果使用无值,lxc 将清除到目前为止指定的参数。
 

APPARMOR 配置文件

如果 lxc 是用 apparmor 支持编译和安装的,并且主机系统启用了 apparmor,那么可以在容器配置中指定容器应该在哪个 apparmor 配置文件下运行。默认情况下,如果主机内核是 cgroup 命名空间感知的,则为 **lxc-container-default-cgns**,否则为 **lxc-container-default**。
lxc.apparmor.profile
指定容器应该在哪个 apparmor 配置文件下运行。要指定容器应该不受限制,请使用

lxc.apparmor.profile = unconfined

如果 apparmor 配置文件应该保持不变(即,如果你是嵌套容器并且已经受到限制),那么请使用

lxc.apparmor.profile = unchanged

如果你指示 LXC 生成 apparmor 配置文件,那么请使用

lxc.apparmor.profile = generated
lxc.apparmor.allow_incomplete
Apparmor 配置文件是基于路径名的。因此,许多文件限制需要挂载限制才能对确定的攻击者有效。但是,这些挂载限制尚未在 upstream 内核中实现。如果没有挂载限制,apparmor 配置文件仍然可以防止意外损坏。

如果此标志为 0(默认),那么如果内核缺少 apparmor 挂载功能,则不会启动容器,以便在内核升级后检测到回归。要启动部分 apparmor 保护下的容器,请将此标志设置为 1。

lxc.apparmor.allow_nesting
如果将其设置为 1,会导致以下更改。当使用生成的 apparmor 配置文件时,它们将包含允许创建嵌套容器的必要更改。除了通常的挂载点外,* /dev/.lxc/proc * 和 * /dev/.lxc/sys * 将包含 procfs 和 sysfs 挂载点,没有 lxcfs 覆盖,如果使用生成的 apparmor 配置文件,则不能直接读写。
lxc.apparmor.raw
要追加到配置文件的原始 AppArmor 配置文件行的列表。仅在使用生成的配置文件时有效。
 

SELINUX 上下文

如果 lxc 是用 SELinux 支持编译和安装的,并且主机系统启用了 SELinux,那么可以在容器配置中指定容器应该在哪个 SELinux 上下文下运行。默认值为 **unconfined_t**,这意味着 lxc 不会尝试更改上下文。请参阅 /usr/share/lxc/selinux/lxc.te 以获取示例策略和更多信息。
lxc.selinux.context
指定容器应该在哪个 SELinux 上下文下运行,或者 **unconfined_t**。例如

lxc.selinux.context = system_u:system_r:lxc_t:s0:c22
lxc.selinux.context.keyring
指定容器的密钥环应该在哪个 SELinux 上下文下创建。默认情况下,这与 lxc.selinux.context 相同,或者如果未设置 lxc.selinux.context,则与 lxc 执行的上下文相同。

lxc.selinux.context.keyring = system_u:system_r:lxc_t:s0:c22
 

内核密钥环

Linux 密钥环机制主要是一种方法,用于各种内核组件在内核中保留或缓存安全数据、身份验证密钥、加密密钥和其他数据。默认情况下,lxc 将为启动的应用程序创建一个新的会话密钥环。
lxc.keyring.session
禁用 lxc 创建新的会话密钥环。然后,启动的应用程序将继承当前会话密钥环。默认情况下,或者在传递值 1 时,将创建一个新的密钥环。

lxc.keyring.session = 0
 

SECCOMP 配置

可以通过在启动时加载 seccomp 配置文件,以减少可用系统调用的集来启动容器。seccomp 配置文件必须在第一行以版本号开头,在第二行以策略类型开头,然后是配置。

目前支持版本 1 和 2。在版本 1 中,策略是一个简单的允许列表。因此,第二行必须读取“allowlist”,文件其余部分每行包含一个(数字)系统调用号。每个系统调用号都被允许列入白名单,而所有未列出的号码都被列入黑名单,禁止在容器中使用。

在版本 2 中,策略可以是拒绝列表或允许列表,支持每条规则和每项策略的默认操作,并支持每种架构的文本名称系统调用解析。

以下是一个拒绝列表策略示例,其中所有系统调用都被允许,除了 mknod,它只会执行无操作并返回 0(成功):

      2
      denylist
      mknod errno 0
      ioctl notify
      

指定“errno”作为操作会导致 LXC 注册一个 seccomp 过滤器,该过滤器会导致将特定 errno 返回给调用者。errno 值可以在“errno”操作词后指定。

指定“notify”作为操作会导致 LXC 注册一个 seccomp 侦听器,并从内核中检索一个侦听器文件描述符。当执行注册为“notify”的系统调用时,内核将生成一个轮询事件,并通过文件描述符发送一条消息。调用者可以读取此消息,检查系统调用,包括其参数。根据这些信息,调用者预计会发送回一条消息,通知内核要采取的操作。在发送该消息之前,内核将阻塞调用进程。要读取和发送的消息格式在 seccomp 本身中有记录。

lxc.seccomp.profile
指定包含要在容器启动之前加载的 seccomp 配置的文件。
lxc.seccomp.allow_nesting
如果此标志设置为 1,那么无论是否已经加载了 seccomp 配置文件,seccomp 过滤器都将被堆叠。这允许嵌套容器加载它们自己的 seccomp 配置文件。默认设置为 0。
lxc.seccomp.notify.proxy
指定 LXC 将连接并转发 seccomp 事件到的 unix 套接字。路径必须采用 unix:/path/to/socket 或 unix:@socket 的形式。前者指定一个路径绑定的 unix 域套接字,而后者指定一个抽象的 unix 域套接字。
lxc.seccomp.notify.cookie
与代理的 seccomp 通知请求一起发送的附加字符串。
 

PR_SET_NO_NEW_PRIVS

在 PR_SET_NO_NEW_PRIVS 处于活动状态时,execve() 承诺不会授予权限执行在没有 execve() 调用的情况下无法执行的任何操作(例如,使 set-user-ID 和 set-group-ID 模式位以及文件功能失效)。一旦设置,该位就不能被取消设置。此位的设置由 fork() 和 clone() 创建的子进程继承,并在 execve() 中保留。请注意,PR_SET_NO_NEW_PRIVS 在容器更改为其预期的 AppArmor 配置文件或 SElinux 上下文后应用。
lxc.no_new_privs
指定是否应该为容器设置 PR_SET_NO_NEW_PRIVS 标志。设置为 1 表示激活。
 

UID 映射

容器可以在私有用户命名空间中启动,并使用用户和组 ID 映射。例如,你可以将容器中的用户 ID 0 映射到主机上的用户 ID 200000。容器中的 root 用户将在容器中具有特权,但在主机上没有特权。通常,系统容器需要一个 ID 范围,因此你将映射例如容器中的用户和组 ID 0 到 20,000 到主机上的 ID 200,000 到 220,000。
lxc.idmap
必须提供四个值。首先是一个字符,要么是“u”,要么是“g”,用于指定是用户 ID 还是组 ID 被映射。接下来是容器的用户命名空间中看到的第一用户 ID。接下来是主机上看到的用户 ID。最后,一个范围表示要映射的连续 ID 的数量。
 

容器钩子

容器钩子是在容器生命周期的不同时间可以执行的程序或脚本。

当执行容器钩子时,会传递一些额外的信息。**lxc.hook.version** 参数可以用来确定以下参数是作为命令行参数传递还是通过环境变量传递。参数是

容器名称。
部分(始终为“lxc”)。
钩子类型(即“clone”或“pre-mount”)。
其他参数。在 clone 钩子的情况下,传递的任何额外参数都将作为钩子的其他参数出现。在 stop 钩子的情况下,将传递指向每个容器的命名空间的文件描述符以及它们的类型的路径。

设置了以下环境变量

LXC_CGNS_AWARE:指示容器是否具有 cgroup 命名空间感知能力。
LXC_CONFIG_FILE:容器配置文件的路径。
LXC_HOOK_TYPE:钩子类型(例如“clone”、“mount”、“pre-mount”)。请注意,此环境变量的存在取决于 **lxc.hook.version** 的值。如果将其设置为 1,那么 LXC_HOOK_TYPE 将被设置。
LXC_HOOK_SECTION:部分类型(例如“lxc”、“net”)。请注意,此环境变量的存在取决于 **lxc.hook.version** 的值。如果将其设置为 1,那么 LXC_HOOK_SECTION 将被设置。
LXC_HOOK_VERSION:钩子的版本。此值与容器的 **lxc.hook.version** 配置项的值相同。如果将其设置为 0,则使用旧式钩子。如果将其设置为 1,则使用新式钩子。
LXC_LOG_LEVEL:容器的日志级别。
LXC_NAME:是容器的名称。
LXC_[NAMESPACE IDENTIFIER]_NS:/proc/PID/fd/ 下的路径,指向一个文件描述符,该文件描述符引用容器的命名空间。对于每个保留的命名空间类型,将有一个单独的环境变量。只有当 **lxc.hook.version** 设置为 1 时,这些环境变量才会被设置。
LXC_ROOTFS_MOUNT:已挂载的根文件系统的路径。
LXC_ROOTFS_PATH:这是容器的 lxc.rootfs.path 条目。请注意,这可能不是挂载的根文件系统所在的实际位置,请使用 LXC_ROOTFS_MOUNT 来获取该路径。
LXC_SRC_NAME:在 clone 钩子的情况下,这是原始容器的名称。

钩子的标准输出以调试级别记录。标准错误不会记录,但可以由钩子通过将其标准错误重定向到标准输出来捕获。

lxc.hook.version
通过环境变量将参数传递到新样式的钩子,如果设置值为1,则传递为环境变量,否则设置值为0,则传递为参数。此设置影响所有传统上作为参数传递给脚本的钩子参数。具体来说,它影响容器名称、部分(例如“lxc”、“net”)和钩子类型(例如“clone”、“mount”、“pre-mount”)参数。如果使用新样式钩子,则参数将作为环境变量提供。容器名称将设置为LXC_NAME。(这是独立于此配置项值设置的。)部分将设置为LXC_HOOK_SECTION,钩子类型将设置为LXC_HOOK_TYPE。它还影响如何传递引用容器命名空间的文件描述符的路径。如果设置为1,则每个命名空间将设置一个单独的环境变量LXC_[命名空间标识符]_NS。如果设置为0,则路径将作为参数传递给停止钩子。
lxc.hook.pre-start
在容器 tty、控制台或挂载启动之前,在主机命名空间中运行的钩子。
lxc.hook.pre-mount
在容器的文件系统命名空间中运行的钩子,但在根文件系统设置之前。这允许操作根文件系统,例如挂载加密文件系统。在此钩子中完成的挂载不会反映在主机上(除了挂载传播),因此它们将在容器关闭时自动清除。
lxc.hook.mount
在容器命名空间中运行的钩子,在完成挂载后,但在 pivot_root 之前。
lxc.hook.autodev
在容器命名空间中运行的钩子,在完成挂载并运行任何挂载钩子之后,但在 pivot_root 之前,如果 lxc.autodev == 1。此钩子的目的是在使用 autodev 选项为基于 systemd 的容器填充容器的 /dev 目录时提供帮助。容器的 /dev 目录相对于在运行钩子时可用的 ${LXC_ROOTFS_MOUNT} 环境变量。
lxc.hook.start-host
在容器设置完毕后,在主机命名空间中运行的钩子,并且在启动容器 init 之前立即运行。
lxc.hook.start
在容器命名空间中运行的钩子,在执行容器的 init 之前立即运行。这要求程序在容器中可用。
lxc.hook.stop
在容器关闭后,在主机命名空间中运行的钩子,并带有对容器命名空间的引用。对于每个命名空间,都会向钩子传递一个额外的参数,其中包含命名空间的类型和一个文件名,该文件名可用于获取指向相应命名空间的文件描述符,两者之间用冒号分隔。类型是在 /proc/PID/ns 目录中显示的名称。例如,对于挂载命名空间,参数通常类似于 mnt:/proc/PID/fd/12
lxc.hook.post-stop
在容器关闭后,在主机命名空间中运行的钩子。
lxc.hook.clone
在将容器克隆到新容器时运行的钩子。有关更多信息,请参阅 lxc-clone(1)。
lxc.hook.destroy
在销毁容器时运行的钩子。
 

容器钩子环境变量

一些环境变量可用于启动钩子,以提供配置信息并帮助钩子正常运行。并非所有变量在所有上下文中都有效。特别是,所有路径都相对于主机系统,因此在 lxc.hook.start 钩子期间无效。
LXC_NAME
容器的 LXC 名称。在公共日志环境中用于记录消息。[-n]
LXC_CONFIG_FILE
相对于主机的容器配置文件路径。这使容器可以引用容器的原始顶级配置文件,以便找到未提供给它的任何其他配置信息。[-f]
LXC_CONSOLE
容器控制台输出的路径(如果非 NULL)。[-c] [lxc.console.path]
LXC_CONSOLE_LOGPATH
容器控制台日志输出的路径(如果非 NULL)。[-L]
LXC_ROOTFS_MOUNT
容器最初绑定的挂载位置。这将是相对于主机的容器根文件系统路径,用于启动的容器实例,并且应该是为该实例进行更改的地方。[lxc.rootfs.mount]
LXC_ROOTFS_PATH
相对于主机的容器根路径,该路径已挂载到 rootfs.mount 位置。[lxc.rootfs.path]
LXC_SRC_NAME
仅适用于克隆钩子。设置为原始容器名称。
LXC_TARGET
仅适用于停止钩子。对于容器关闭,设置为“stop”,对于容器重启,设置为“reboot”。
LXC_CGNS_AWARE
如果未设置,则此版本的 lxc 不了解 cgroup 命名空间。如果设置,它将设置为 1,并且 lxc 了解 cgroup 命名空间。请注意,这并不能保证 cgroup 命名空间在内核中启用。lxcfs 挂载钩子使用它。
 

记录

可以针对每个容器配置记录。默认情况下,根据 lxc 包的编译方式,容器启动仅在 ERROR 级记录,并记录到一个以容器命名的文件(附加 '.log')中,该文件位于容器路径下或 /var/log/lxc 下。

默认日志级别和日志文件都可以在容器配置文件中指定,覆盖默认行为。请注意,配置文件条目可以依次被 lxc-start 的命令行选项覆盖。

lxc.log.level
记录的级别。日志级别是 0..8(含)之间的整数,其中数字越小,调试信息越详细。特别是 0 = trace,1 = debug,2 = info,3 = notice,4 = warn,5 = error,6 = critical,7 = alert,8 = fatal。如果未指定,级别默认为 5(错误),因此只记录错误及以上级别的信息。

请注意,当调用脚本(例如钩子脚本或网络接口启动或停止脚本)时,脚本的标准输出将以级别 1(调试)记录。

lxc.log.file
要写入日志信息的日志文件。
lxc.log.syslog
将日志信息发送到 syslog。它会遵守 lxc.log.level 中定义的日志级别。参数应该是要使用的 syslog 机制,有效值为:daemon、local0、local1、local2、local3、local4、local5、local5、local6、local7。
 

自动启动

自动启动选项支持标记哪些容器应自动启动以及启动顺序。这些选项可以直接由 LXC 工具使用,也可以由发行版提供的外部工具使用。
lxc.start.auto
容器是否应自动启动。有效值为 0(关闭)和 1(打开)。
lxc.start.delay
在容器启动后,启动下一个容器之前要等待多长时间(以秒为单位)。
lxc.start.order
一个整数,用于在一次自动启动一系列容器时对容器进行排序。数字越小,启动越早。
lxc.monitor.unshare
如果非零,则在初始化容器(在运行任何预启动钩子之前)之前,挂载命名空间将与主机分离。这需要在启动时具有 CAP_SYS_ADMIN 权限。默认值为 0。
lxc.monitor.signal.pdeath
设置当 lxc 监视器退出时发送给容器 init 的信号。默认情况下,它设置为 SIGKILL,当 lxc 监视器进程死亡时,这将导致所有容器进程被杀死。要确保即使 lxc 监视器死亡,容器也能保持活动状态,请将此设置为 0。
lxc.group
一个多值键(可以多次使用),用于将容器置于容器组中。然后,这些组可以用作(除其他事项外)启动一系列相关容器。
 

自动启动和系统启动

每个容器都可以属于任何数量的组,也可以不属于任何组。两个组是特殊的。一个是 NULL 组,即容器不属于任何组。另一个组是“onboot”组。

当系统在启用 LXC 服务的情况下启动时,它将首先尝试启动 lxc.start.auto == 1 且是“onboot”组成员的任何容器。启动将按照 lxc.start.order 的顺序进行。如果指定了 lxc.start.delay,则在尝试启动下一个容器之前,会遵守该延迟,以便为当前容器提供时间来开始初始化并减少对主机系统的过载。在启动“onboot”组的成员后,LXC 系统将继续启动 lxc.start.auto == 1 且不属于任何组(NULL 组)的容器,并与 onboot 组一样进行操作。  

容器环境

如果您想将环境变量传递到容器中(也就是说,init 及其所有后代可以访问的环境变量),可以使用 lxc.environment 参数来执行此操作。请务必谨慎,不要传递任何敏感信息;容器中任何没有清除其环境的进程都可以访问这些变量,并且环境变量始终可以通过 /proc/PID/environ 获取。

此配置参数可以多次指定;每次指定一个要配置的环境变量。

lxc.environment
指定一个环境变量传递到容器中。示例

              lxc.environment = APP_ENV=production
              lxc.environment = SYSLOG_SERVER=192.0.2.42
            

可以通过设置变量名称(不带“=”符号)来继承主机环境变量。例如

              lxc.environment = PATH
            
 

示例

除了以下几个示例之外,您还可以在 /usr/share/doc/lxc/examples 中找到其他一些配置文件示例  

网络

此配置设置了一个容器,使用一个 veth 对设备,其中一侧连接到桥接 br0(管理员之前已在系统上配置过该桥接)。容器中可见的虚拟网络设备被重命名为 eth0。

        lxc.uts.name = myhostname
        lxc.net.0.type = veth
        lxc.net.0.flags = up
        lxc.net.0.link = br0
        lxc.net.0.name = eth0
        lxc.net.0.hwaddr = 4a:49:43:49:79:bf
        lxc.net.0.ipv4.address = 10.2.3.5/24 10.2.3.255
        lxc.net.0.ipv6.address = 2003:db8:1:0:214:1234:fe0b:3597
      
 

UID/GID 映射

此配置将容器中 0-9999 范围内的用户 ID 和组 ID 映射到主机上的 100000-109999 范围内的 ID。

        lxc.idmap = u 0 100000 10000
        lxc.idmap = g 0 100000 10000
      
 

控制组

此配置将为应用程序设置多个控制组,cpuset.cpus 限制对定义的 CPU 的使用,cpus.share 优先级控制组,devices.allow 使指定的设备可用。

        lxc.cgroup.cpuset.cpus = 0,1
        lxc.cgroup.cpu.shares = 1234
        lxc.cgroup.devices.deny = a
        lxc.cgroup.devices.allow = c 1:3 rw
        lxc.cgroup.devices.allow = b 8:0 rw
      
 

复杂配置

此示例展示了一个复杂的配置,创建一个复杂的网络堆栈,使用控制组,设置新的主机名,挂载一些位置并更改根文件系统。

        lxc.uts.name = complex
        lxc.net.0.type = veth
        lxc.net.0.flags = up
        lxc.net.0.link = br0
        lxc.net.0.hwaddr = 4a:49:43:49:79:bf
        lxc.net.0.ipv4.address = 10.2.3.5/24 10.2.3.255
        lxc.net.0.ipv6.address = 2003:db8:1:0:214:1234:fe0b:3597
        lxc.net.0.ipv6.address = 2003:db8:1:0:214:5432:feab:3588
        lxc.net.1.type = macvlan
        lxc.net.1.flags = up
        lxc.net.1.link = eth0
        lxc.net.1.hwaddr = 4a:49:43:49:79:bd
        lxc.net.1.ipv4.address = 10.2.3.4/24
        lxc.net.1.ipv4.address = 192.168.10.125/24
        lxc.net.1.ipv6.address = 2003:db8:1:0:214:1234:fe0b:3596
        lxc.net.2.type = phys
        lxc.net.2.flags = up
        lxc.net.2.link = dummy0
        lxc.net.2.hwaddr = 4a:49:43:49:79:ff
        lxc.net.2.ipv4.address = 10.2.3.6/24
        lxc.net.2.ipv6.address = 2003:db8:1:0:214:1234:fe0b:3297
        lxc.cgroup.cpuset.cpus = 0,1
        lxc.cgroup.cpu.shares = 1234
        lxc.cgroup.devices.deny = a
        lxc.cgroup.devices.allow = c 1:3 rw
        lxc.cgroup.devices.allow = b 8:0 rw
        lxc.mount.fstab = /etc/fstab.complex
        lxc.mount.entry = /lib /root/myrootfs/lib none ro,bind 0 0
        lxc.rootfs.path = dir:/mnt/rootfs.complex
        lxc.rootfs.options = idmap=container
        lxc.cap.drop = sys_module mknod setuid net_raw
        lxc.cap.drop = mac_override
      
 

另请参阅

chroot(1), pivot_root(8), fstab(5), capabilities(7)  

另请参阅

lxc(7), lxc-create(1), lxc-copy(1), lxc-destroy(1), lxc-start(1), lxc-stop(1), lxc-execute(1), lxc-console(1), lxc-monitor(1), lxc-wait(1), lxc-cgroup(1), lxc-ls(1), lxc-info(1), lxc-freeze(1), lxc-unfreeze(1), lxc-attach(1), lxc.conf(5)  

作者

Daniel Lezcano <daniel.lezcano@free.fr>


 

索引

名称
描述
配置
架构
主机名
停止信号
重启信号
停止信号
INIT 命令
INIT 工作目录
INIT ID
PROC
短暂的
网络
新的伪终端实例 (DEVPTS)
容器系统控制台
通过 TTYS 进行控制台
控制台设备位置
/DEV 目录
挂载点
根文件系统
控制组(“CGROUPS”)
功能
命名空间
资源限制
SYSCTL
APPARMOR 配置文件
SELINUX 上下文
内核密钥环
SECCOMP 配置
PR_SET_NO_NEW_PRIVS
UID 映射
容器钩子
容器钩子环境变量
记录
自动启动
自动启动和系统启动
容器环境
示例
网络
UID/GID 映射
控制组
复杂配置
另请参阅
另请参阅
作者

此文档由 man2html 使用手册页创建。
时间:2024 年 11 月 3 日,格林尼治标准时间 04:45:10