LXC 4.0 LTS 已发布¶
2020年3月25日
简介¶
LXC 团队很高兴地宣布发布 LXC 4.0.0!
这是自 LXC 3.0.0 发布以来两年工作的成果,也是 LXC 项目的第四个 LTS 版本。此版本将得到支持,直至 2025 年 6 月。
主要变化¶
cgroups:完全支持 cgroup2¶
LXC 4.0 现在完全支持统一的 cgroup 层次结构。为了实现这一点,整个 cgroup 驱动程序必须重写。这项工作的结果是 LXC 容器的 cgroup 布局必须更改。旧版本的 LXC 使用布局
/sys/fs/cgroup/<controller>/<container-name>/
例如,在旧的 cgroup 层次结构中,cpuset
层次结构会将容器的 init 进程放置在
/sys/fs/cgroup/cpuset/c1/
监管监控进程将保留在
/sys/fs/cgroup/cpuset/
LXC 4.0 使用布局
/sys/fs/cgroup/<controller>/lxc.payload.<container-name>/
对于容器 f2
在旧的 cgroup 层次结构中的 cpuset
控制器,cgroup 将是
/sys/fs/cgroup/cpuset/lxc.payload.f2/
监控进程现在也移动到一个单独的 cgroup 中
/sys/fs/cgroup/<controller>/lxc.monitor.<container-name>/
对于我们的示例,这将是
/sys/fs/cgroup/cpuset/lxc.monitor.f2/
监控器和容器的 cgroup 将放置在相应的 cgroup 层次结构中的同一级别。
这些更改适用于旧的和统一的层次结构,并且不是任意的。新的统一 cgroup 层次结构对进程在 cgroup 层次结构中的迁移位置和方式施加了特定的限制。最重要的限制是叶节点限制。这意味着只有叶节点可以包含活动进程,即如果您有以下 cgroup 树
/sys/fs/cgroup/a/f2-monitor/f2-container/
那么只有 f2-container
可以包含活动进程,而非叶节点 a
和 f2-monitor
则不能。这导致 LXC 使用的旧 cgroup 布局(其中监控进程位于 f2-monitor
中,容器的 init 进程位于 f2-container
中)不再可能。内核不允许这种布局。相反,监控进程和容器的 init 进程需要移动到 cgroup 层次结构中同一级别的两个叶节点 cgroup 中。对于容器 f2
,这将意味着布局将是
/sys/fs/cgroup/lxc.monitor.f2/
和
/sys/fs/cgroup/lxc.payload.f2/
统一 cgroup 层次结构强制执行的限制也意味着,为了启动完全非特权容器,需要与使用管理 cgroup 的 init 系统的发行版进行合作。这适用于所有使用 systemd 作为其 init 系统的发行版。当通过 lxc-start
或其他方式从 shell 启动容器时,要么需要是 root 以允许 LXC 转义到根 cgroup,要么需要指示 init 系统委托一个空的 cgroup。在这种情况下,明智的做法是将配置键 lxc.cgroup.relative
设置为 1
以防止 LXC 转义到根 cgroup。
cgroups:CGroup2 中的冻结支持¶
作为 LXC 4.0 的 cgroup2 支持工作的一部分,我们还添加了对 cgroup2 的冻结控制器实现的支持,该控制器允许轮询直到 cgroup 被冻结或解冻,从而使冻结和解冻容器比以前更可靠。
cgroups:CGroup2 中的 eBPF 设备控制器支持¶
LXC 4.0 现在可以正确使用 cgroup2 设备控制器。它将自动创建、加载和附加 eBPF 程序到容器的 cgroup,并支持动态添加和删除规则。配置格式与旧的 cgroup 控制器相同。只需要使用 lxc.cgroup2.devices.
前缀而不是旧的 lxc.cgroup.devices
前缀。LXC 继续支持黑名单和白名单。
AppArmor:拒绝访问 /proc/acpi/**
¶
默认的 AppArmor 配置文件现在拒绝访问 /proc/acpi/
,从而提高安全性。
配置:添加 lxc.autodev.tmpfs.size
配置键¶
LXC 通过在容器的配置文件中设置 lxc.autodev = 1
来支持为容器创建一个可用的最小 /dev
目录。为此,LXC 在 /dev
上设置了一个 tmpfs
挂载。在以前的版本中,此 tmpfs
挂载无法限制。现在可以通过将 lxc.autodev.tmpfs.size
设置为 tmpfs
应限制使用的字节数来限制 tmpfs
挂载的大小。
配置:添加 lxc.selinux.context.keyring
键¶
这允许指定要用于容器使用的密钥环的 selinux
上下文。
配置:添加 lxc.keyring.session
¶
将其设置为 1
(默认值)将导致 LXC 创建一个新的会话密钥环。
文件实用程序:添加 fopen_cached()
和 fdopen_cached
¶
这些帮助程序首先读取整个文件,然后将其作为流提供,以便通过基于常规文件的 libc api 读取。这使得 LXC 对各种文件的处理更加健壮,因为基础文件在读取时可能会发生变化。
api:添加新的 init_pidfd()
成员¶
LXC 4.0 完全支持新的 pidfd 内核 api,LXC 团队已将其合并到上游 Linux 内核中。可以通过 c->init_pidfd(c)
请求容器的 init 进程的 pidfd
。
内存实用程序:添加新的清理 api¶
LXC 4.0 通过引入新的内部 api 来定义和调用复杂资源分配的清理宏,扩展了编译器的清理属性的使用。通过切换到这种新的资源清理方式,我们在减少文件描述符和内存泄漏方面的错误方面取得了非常积极的结果。
lxc-usernsexec:轻松映射自己的 uid¶
lxc-usernsexec
二进制文件现在找到 /etc/subuid
和 /etc/subgid
中指定的默认映射,并通过 newuidmap
和 newgidmap
写入它。
seccomp:添加 s390 支持¶
LXC 4.0 的 seccomp 实现现在支持 s390 作为体系结构。
系统调用:改进手动系统调用实现¶
每当给定的系统调用不受支持或未由系统的底层 C
库公开时,LXC 将为重要的系统调用或它认为非常有价值的新功能定义系统调用存根。这过去是通过检查 __NR_<syscall-name>
是否已定义来完成的。但是 __NR_<syscall-name>
是否已定义取决于为当前运行的 LXC 编译的内核安装的正确头文件,并且在 LXC 编译在运行旧内核的系统上但在使用或部署在使用新内核的系统上时会出现问题。在这种情况下,LXC 无法利用新的内核功能,即使它应该这样做。我们现在在系统尚未定义它并且它是我们支持的体系结构(基本上是任何体系结构)时引入 __NR_<syscall-name>
的定义。这样,我们更好地处理内核 <-> 头文件版本不匹配和编译 <-> 部署内核不匹配。
网络:改进的网络设备创建和删除¶
我们重新设计了网络设备的创建、跟踪、在网络命名空间之间移动以及删除方式,使低级网络管理更加可靠。
网络:允许移动无线设备¶
LXC 允许将无线网络设备(nl80211
)移动到容器中。这有一段时间坏了。在 4.0 中,移动无线网络设备的功能得到了恢复和改进。
完整变更日志¶
以下是此版本中所有更改的完整列表
完整提交列表
- cgroups:修复附加到统一 cgroup
- dir:改进 dir 后端
- dir:在 dir_mount() 中使用清理宏
- 全树:强化挂载选项解析
- lxc_init:添加缺少的 O_CLOEXEC
- lxc_init:将 main() 向下移动
- configure.ac:发布后重置 devel 标志
- make dist:添加缺少的文件
- lxc-download:兼容性的预发布版本提升
- conf:修复只读绑定挂载
- utils:允许删除不可变文件
- lxc-local:从帮助中删除 -l/--list
- lvm:不要为 ext4 快照生成 uuid
- lxc-update-config:正确处理 lxc.rootfs.backend
- lxc_copy:仅使用 tmpfs 覆盖挂载覆盖子目录
- overlay:重写和简化
- lxc-user-nic:为具有 5 位数字的 uid 启用 uid 标记的 veth 设备
- network:引入 lxc_ifname_alnum_case_sensitive()
- log:修复 cmd 日志记录
- cgroups:简化
- ringbuf:修复清理操作
- mainloop:清理
- log:添加缺少的变量并修复 CMD_SYSINFO()
- log:清理
- log:添加缺少的 \
- start:在预启动钩子之后移动读取 seccomp 配置文件
- lxc_user_nic: 重构设备创建
- nl: 改善错误上报方式
- 网络: 使用清理宏
- 网络: 使用清理属性
- 网络: 大量清理
- 网络: 在所有地方使用 is_empty_string()
- 网络: 修复 ovs 移除
- 日志: 使用全局变量捕获日志器中的语句
- cgroups: 不要从日志器调用语句
- 配置: 简化 mount_entry() 中的逻辑
- 配置: 不要意外地双重挂载
- 网络: 修复移动具有自定义名称的网络设备
- 网络: 引入并使用 is_empty_string()
- Makefile: 修复错别字
- lxc-unshare: 将 syscall_wrappers.h 添加到构建需求中
- 全树: 引入并使用系统调用编号头文件
- raw_syscalls: 如果缺少则定义 __NR_pidfd_send_signal
- 工具: 修复 lxc-execute 和 lxc-attach 的 -g -u 参数
- ISSUE_TEMPLATE: 修复 -l -o 的顺序
- lxc_user_nic: 不要依赖 MAP_FIXED
- busybox: 将 mqueue 标记为可选
- 自动创建 /dev/shm 和 /dev/mqueue
- busybox: 修复错误的 lxc.mount.entry
- 文档: 修复语法错误
- 触发 shm 文件系统的挂载
- 全树: 将 lxc_fini() 替换为 lxc_end()
- 全树: 从 lxc_{fini,abort}() 中移除 "name" 参数
- {_}lxc_start: 移除 "name" 参数
- 启动: 添加缺失的 TRACE() 调用
- 启动: 改进 __lxc_start() 中的 goto 目标命名
- 启动: 重构 __lxc_start() 中的清理代码
- 启动: 简化 lxc_init()
- 配置: 不要包装字符串
- 全树: 使用清理宏替换最后 -1 fd 初始化,改为 -EBADF
- 全树: 将 __do_close_prot_errno 替换为 __do_close
- memory_utils: 适配新的基础设施
- 全树: 将 cgroup 清理移植到 call_cleaner(cgroup_exit)
- 功能: 移植到基于 call_cleaner() 的清理
- memory_utils: 添加 call_cleaner() 助手函数
- travis: 启用所有架构
- travis: 移除 libgnutls-dev
- 实用程序: 清理
- file_utils: 清理宏和改进
- api-extensions: 使用正确的标题
- api-extensions: 文档化 "network_veth_router" api 扩展
- api-extensions: 重新格式化 "seccomp_allow_nesting" api 扩展
- api-extensions: 重新格式化 "seccomp_notify" api 扩展
- api-extensions: 重新格式化 "cgroup2_devices" 扩展
- api-extensions: 重新格式化 "cgroup2" api 扩展
- api-extensions: 添加 "pidfd" api 扩展
- lxccontainer: 在关闭容器时切换到 pidfd 轮询
- lxccontainer: 尽可能切换到 pidfds
- 启动: 添加检测内核是否支持 pidfds 的功能
- lxccontainer: 添加 init_pidfd() API 扩展
- 命令: LXC_CMD_GET_INIT_PIDFD
- lxccontainer.h: 文档化 seccomp_notify_fd()
- 命令: 在 lxc_cmd_get_cgroup2_fd_callback() 中使用 LXC_CMD_REAP_CLIENT_FD
- 命令: 添加审核 fd 连接和清理路径的功能
- 文档: 修复错别字
- 文档: 在日语 lxc.containers.conf(5) 中添加密钥环选项
- 命令: 简化 lxc_cmd_fd_cleanup()
- commands_utils: 修复命令套接字哈希
- af_unix: 修复返回值
- 启动: 清理文件描述符关闭
- 命令: 确保始终关闭客户端 fd
- 命令: 改善状态客户端清理
- 命令: 切换到 pid_t 来传递 pid
- share_ns: 改善错误处理
- share_ns: 改善错误处理
- file_utils: 处理没有 fmemopen() 的 libc
- cgroups: 清理
- cgfsng: 在所有地方使用 __do_free_string_list
- file_utils: 包含 stdio.h 用于 fmemopen()
- tests/share_ns: 始终调用 pthread_exit()
- memory_utils: 移除不必要的 mntent.h 包含
- cgroups: 修复内存泄漏并简化代码
- tests/share_ns: 错误修复
- 配置: 清理
- commands_utils: 清理
- 命令: 清理
- 全树: 更多清理宏
- lxccontainer: 增加清理宏的使用
- autotools: 修复 clang-10 下 lxc-init 的构建
- 全树: 改善日志记录
- 全树: 尽可能使文件为 cloexec
- 附加: 清理各种助手函数
- 附加: 处理没有新权限时使用日志记录助手函数
- 附加: 获取 seccomp 时使用清理宏和日志记录助手函数
- 附加: 使用 LXC_INVALID_{G,U}ID 宏
- 附加: 在 lxc_attach_getpwshell() 中使用清理宏
- 附加: 修复 fd 泄漏
- 附加: 清理
- cgroup2_devices: 修复逻辑错误
- 命令: 移除未使用的变量
- commands_utils: 添加状态客户端时修复套接字泄漏
- commands_utils: 在 lxc_add_state_client() 中指示获取 state_client_fd 的所有权
- commands_utils: 添加状态客户端时修复套接字泄漏
- commands_utils: 添加状态客户端时修复套接字泄漏
- af_unix: 清理
- 网络: 使用 netlink 进行 IP 邻居代理管理
- 实用程序: 仅在 fdopen() 成功后 move_fd()
- api-extensions: 文档化 cgroup2_devices 和 cgroup2 api 扩展
- src/lxc/raw_syscalls.c: 修复 sparc 汇编
- cgroups: 如果显式设置则遵循 lxc.cgroup.pattern II
- cgroups: 如果显式设置则遵循 lxc.cgroup.pattern
- cgroups: 移除未使用的 method 并清理 cgroup_exit()
- 全树: 改善 setgroups() 的丢弃
- lxclock: 修复一个小内存泄漏
- container.conf: 文档说明 config_jump_table 中顺序的重要性
- container.conf: 修复 config_jump_table 中的选项顺序
- 目前 lxc.selinux.context.keyring 位于之后
- container.conf: 修复选项解析中的偏移 2 错误
- 文档: 添加密钥环选项的文档
- container.conf: 添加禁用会话密钥环创建的选项
- container.conf: 添加设置密钥环 SELinux 上下文的选项
- cgroups: 修复默认的 cgroup 模式
- 启动: 修复容器终止逻辑
- 网络: 恢复固定 MTU 功能
- 测试: 增加 api 重启测试的超时时间
- cgroup.c: 修复 cgroup 初始化失败时的内存泄漏
- 网络: 重构网络设备创建
- 网络: 修复网络设备移除
- 测试: 记录 api 重启测试失败
- 网络: 修复注释中的错别字和格式
- 网络: 改善 veth 设备创建
- 启动: 处理内核头文件和内核不兼容性
- 测试: 60 秒后超时
- 主循环: 添加缺失的 \n
- 抑制无用的 udhcpc 目录
- 启动: 移除 procfs pidfd 支持
- create_run_template(): 注释中重复出现 "will mount"
- 命令: 修复 shebang
- travis: 启用 -fsanitize=undefined
- fd: 仅将有效的 fd 添加到主循环
- seccomp: 支持 s390 seccomp
- api_extensions: 公告 cgroup2 支持
- cgroups/cgfsng: 不要过早关闭文件描述符
- cgroups/cgfsng: 改善 cgroup 创建和移除
- cgroups/cgfsng: 重构 cgroup 移除
- cgroups/cgfsng: 重构旧的 cpuset 处理
- cgroupfs/cgfsng: 将 cgroup 作为 const char * 传递给 cg_legacy_handle_cpuset_hierarchy()
- cgroups: 为位字段使用显式无符号类型
- cgroups: 扁平化层次结构
- file_utils: 使用 O_NOCTTY | O_NOFOLLOW
- cgroups/devices: 为 cgroup2 设备控制器启用 devpath 语义
- cgroups/cgfsng: 替换 lxc_write_file()
- cgroups/cgfsng: cgfsng_devices_activate()
- cgroups/cgfsng: 重构 cgfsng_nrtasks()
- cgroups/cgfsng: 重构 cgfsng_mount()
- cgroups/cgfsng: 重构 cgfsng_chown()
- cgroups/cgfsng: 重构 cgfsng_attach()
- cgroups/cgfsng: 重构 cgfsng_setup_limits()
- cgroups/cgfsng: 重构 cgfsng_setup_limits_legacy()
- cgroups/cgfsng: 重构 cgfsng_{get,set}()
- cgroups/cgfsng: 重构 cgfsng_unfreeze()
- cgroups/cgfsng: 重构 cgfsng_get_hierarchies()
- cgroups/cgfsng: 重构 cgfsng_num_hierarchies()
- cgroups/cgfsng: 重构 cgfsng_escape()
- cgroups/cgfsng: 重构 cgfsng_payload_enter()
- cgroups/cgfsng: 重构 cgfsng_payload_create()
- 全树: 将 __unused 替换为 __lxc_unused
- cgroups/cgfsng: 重构 cgroup 附加
- cgroups/cgfsng: 不要解除对 NULL 指针的引用
- cgroups/cgfsng: 记录 chown_cgroup_wrapper()
- cgroups/cgfsng: 重构 cgroup2 无特权委托
- cgroups/cgfsng: 重构 cgfsng_{monitor,payload}_delegate_controllers()
- cgroups/cgfsng: 重构 cgfsng_monitor_enter()
- cgroups/cgfsng: 重构 cgfsng_monitor_create()
- cgroups/cgfsng: 重构 cgfsng_monitor_destroy()
- cgroups/cgfsng: 重构 cgfsng_payload_destroy()
- 日志: 移除未使用的编译器属性
- 启动: 替换编译器属性
- 日志: 替换编译器属性
- 附加: 替换关闭助手函数
- 编译器: 添加 __unused 属性
- {日志, 宏}: 移除未使用的日志函数
- lxccontainer: 替换日志函数
- confile_utils: 替换日志函数
- cgroups: 重构某些函数的返回值
- cgroups/cgroup2_devices: 替换日志函数
- cgroups/cgroup: 替换日志函数
- cgroups/cgfsng: 替换日志函数
- confile: 替换日志助手函数
- 网络: 替换日志助手函数
- 命令: 替换日志助手函数
- 附加: 将 minus_one_set_errno() 替换为 ret_set_errno(-1,
- af_unix: 将 minus_one_set_errno() 替换为 ret_set_errno(-1,
- 宏: 添加 ret_errno()
- 日志: 重新排列
- cgroup2: 重构控制器委托
- "busy" 字段设置为 -1 而不是 0
- "busy" 字段设置为 1 而不是 0
- 将 "busy" 字段初始化为 -1,因为 0 是有效的 fd
- 配置: 修复挂载选项的解析
- cgroups/devices: 在 cgfsng_devices_activate() 中正确验证 bpf 设备可用性
- cgroups: 改善容器 cgroup 附加
- lxc: 切换到 SPDX
- 命令: 使用日志返回助手函数
- cgfsng: 重构 cgroup2 附加
- cgroups/devices: 当 bpf 设备功能不可用时不要记录错误
- 冻结器: 清理
- cgroups/冻结器: 修复和改进 cgroup2 冻结器实现
- cgroups: 添加 DEFAULT_MOUNTPOINT #define
- cgroups/devices: 使用专用的枚举
- cgroups/devices: 引入 ebpf 设备 cgroup 全局规则类型
- cgroups/devices: 处理 NULL
- 配置: 启用 -Wunused-but-set-variable
- cgroups/cgfsng: 实现 cgroup2 设备控制器实时更新
- 配置: 以解析的格式记录 cgroup2 设备
- cgroups/cgfsng: “原子地”替换 bpf 设备程序
- 宏: 移除未使用的宏
- api_extension: 添加 cgroup2_devices api 扩展
- cgroups: 添加 cgroup2 设备控制器支持
- cgfsng: 如果容器停止则返回附加失败
- 配置: 修复设置配置根文件系统选项的内存泄漏
- 修复错误消息中 bridge/nic 的错误顺序
- 注释中的错别字
- 测试: 使用 /dev/loop-control 而不是 /dev/network_latency
- configure.ac: 修复在没有 SSP 的工具链上的构建
- 更新 cgroup.h
- 终端: 防止返回无效指针
- 终端: 将 lxc_terminal_signal_fini() 设置为静态
- lxc-usernsexec: 支持轻松映射自己的 uid
- 测试: 添加测试以确保退出代码正确。
- 终端: 在 terminal_signal_init 中错误时返回 NULL
- 终端: 防止 lxc_terminal_state 的内存泄漏
- apparmor: 防止写入 /proc/acpi/**
- syscall_wrappers: 将内部 memfd_create 重命名为 memfd_create_lxc
- lxc/tools/lxc/destroy: 恢复容器销毁时的错误消息
- 更新日语中的 lxc.containers.conf(5)
- 错误的 sgml/man 翻译
- 在日语手册中添加有关 lxc.start.order 的更多信息
- 在日语 lxc.container.conf(5) 中添加 autodev.tmpfs.size
- lxc-destroy: 将成功输出消息发送到日志信息而不是错误。
- 文档: 添加有关“lxc.start.order”的更多信息
- 更新过时的函数
- 添加 autodev.tmpfs.size 配置参数
- 启动: 处理在新的 pidns 中设置 pdeath 信号
- 启动: pidfds 显然从 0 开始,就像任何 fd 一样
- 修复 network.address 中的 lxc-update-config
- 允许用户配置选项 --enable-feature 或 --with-package,如果给定选项则运行 shell 命令操作-如果给定
- 将最小 autoconf 版本设置为 2.69 并将过时的函数 AC_HELP_STRING 更改为 AS_HELP_STRING
- 文档: 在日语 lxc.container.conf(5) 中添加 lxc.net.[i].veth.mode 选项
- 文档: 添加日语 pam_cgfs(8) 手册页
- doc: 为 pam_cgfs 添加手册页
- 确保 OpenSSL 与旧版本的 EVP API 兼容。
- utils: 复制源文件名以避免丢失信息。
- cgroups: 统一 cgfsng_{un}freeze() 函数。
- cgroups: 初始化 cgroup 根目录 - encore
- cgroups: 在冻结/解冻时检查空 cgroup。
- cgroups: 初始化 cgroup 根目录
- [aa-profile] 拒绝访问 /proc/acpi/**
- lxc-attach: 确保返回命令的退出状态。
- cgfsng: 正确挂载纯统一 cgroup 布局。
- lxc-create: 检查参数 '--dir' 的绝对路径。
- cgroups: 支持 cgroup2 freezer。
- attach: 不要关闭 getent 的标准输出。
- utils: 修复函数参数的整数类型错误。
- 尝试修复搜索用户而不是搜索子字符串。
- lxccontainer: do_lxcapi_detach_interface 支持分离 wlan 设备。
- cgroups: 正确初始化 cpuset。
- network: 恢复移动 nl80211 设备的能力。
- pidfds: 在 ENOSYS 时不要打印吓人的警告。
- tree-wide: 初始化所有自动清理变量。
- 抑制模板和 nvidia 钩子中的误报错误。
- 容器特定的文件/目录名称
- 使用 macro.h 中的文件/目录名称。
- tree-wide: 修复许可证的错误复制粘贴。
支持和升级¶
LXC 4.0.0 将支持到 2025 年 6 月,我们当前的 LTS 版本 LXC 3.0 现在将切换到较慢的维护速度,仅接收关键错误修复和安全更新。
我们强烈建议所有 LXC 用户计划升级到 4.0 分支。
下载¶
- 主要版本 tarball: lxc-4.0.0.tar.gz
- GPG 签名: lxc-4.0.0.tar.gz.asc
贡献者¶
LXC 4.0.0 版本由总共 30 位贡献者带来。