Systemd中的CGroup委托机制详解

Systemd中的CGroup委托机制详解

systemd The systemd System and Service Manager systemd 项目地址: https://gitcode.com/gh_mirrors/sy/systemd

前言

在现代Linux系统中,控制组(cgroup)是资源管理的关键技术。作为系统和服务管理器,systemd对cgroup提供了深度集成支持。本文将深入解析systemd中的cgroup委托机制,帮助开发者特别是容器管理器开发者理解如何正确与systemd的cgroup管理进行交互。

CGroup基础概念

CGroup v2的核心规则

在深入systemd实现前,必须理解cgroup v2的两条核心规则:

  1. 内部节点无进程规则:一个cgroup要么是内部节点(包含子cgroup),要么是叶节点(包含进程),但不能同时具备两种特性。内核会强制实施此规则。

  2. 单一写入者规则:每个cgroup应当只有一个管理进程拥有写入权限。这避免了多个管理器之间的冲突。

CGroup v1与v2的差异

  • CGroup v1存在语义缺陷,许多功能表现与预期不符
  • CGroup v2提供了更完整的功能集,包括:
    • 可靠的cgroup空通知
    • 每个cgroup的BPF功能
    • 安全的cgroup树委托机制
  • 新内核特性仅添加到v2,v1已停止发展

Systemd的CGroup支持模式

systemd支持三种cgroup层次结构模式:

  1. 统一模式(Unified):纯cgroup v2模式,所有控制器通过/sys/fs/cgroup/单一挂载点暴露。

  2. 传统模式(Legacy)(已弃用):传统cgroup v1模式,每个控制器有独立挂载点。

  3. 混合模式(Hybrid)(已弃用):保留v1兼容性的同时提供部分v2功能。

当前推荐仅使用统一模式,其他模式已在较新版本中移除。

Systemd的单元类型与CGroup

systemd通过三种单元类型暴露cgroup功能:

  1. 服务单元(.service):封装由systemd直接启动的进程,通常是cgroup树的叶节点。

  2. 范围单元(.scope):封装由外部进程启动的进程组,只能以临时方式创建。

  3. 切片单元(.slice):构成cgroup树的内部节点,不直接包含进程。

默认切片单元

systemd默认创建四个切片单元:

  1. -.slice:根切片,对应cgroup v2的顶层目录
  2. system.slice:系统服务默认位置
  3. user.slice:用户会话位置
  4. machines.slice:虚拟机和容器位置

CGroup委托机制详解

委托的基本概念

委托允许将cgroup子树的管理权交给特定进程。在systemd中,可以通过设置服务或范围单元的Delegate=属性来启用委托。

启用委托后:

  1. systemd不再干涉该单元下的子树
  2. 若使用User=,子树会被chown给指定用户
  3. BPF过滤器会设置BPF_F_ALLOW_MULTI标志

委托的使用方法

在单元文件中:

[Service]
Delegate=yes  # 委托所有可用控制器
# 或
Delegate=cpu memory  # 仅委托指定控制器

从systemd 236开始,Delegate=可接受控制器列表,仅请求特定控制器的委托。

重要注意事项

  1. 仅限服务/范围单元:切片单元不支持委托,因为它们是内部节点。

  2. .control子cgroup:若服务有ExecStartPost等命令,systemd会在.control/子cgroup中执行它们。

  3. 线程化cgroups:如需使用线程化cgroups(Linux 4.14+),需要在主服务cgroup下两级创建。

  4. 控制器启用:委托后需手动写入cgroup.subtree_control启用控制器。

实践场景分析

场景1:深度集成(推荐)

适用:希望与系统深度集成的容器管理器

实现方式

  1. 将每个容器注册为systemd服务或范围单元
  2. 启用Delegate=属性
  3. 可选择通过systemd-machined注册以获得额外集成功能

优点

  • 管理员可使用标准systemd工具管理容器资源
  • 支持完整的系统集成功能
  • 允许容器内运行cgroup感知程序(如嵌套systemd)

场景2:独立管理

适用:希望最小化与systemd交互的简单管理器

实现方式

  1. 为主管理器服务启用Delegate=
  2. 在分配的cgroup下自主管理子树

注意:必须将主进程移出初始cgroup才能创建子cgroup。

场景3:混合管理

适用:希望保持管理器独立但统一管理工作负载

实现方式

  1. 不委托管理器自身的cgroup
  2. 为工作负载创建专用范围单元并启用委托
  3. 将所有工作进程放入该范围

最佳实践建议

  1. 优先选择统一模式:避免使用已弃用的传统/混合模式。

  2. 遵循单一写入者规则:即使技术上允许多个写入者,也应保持单一管理关系。

  3. 及时迁移进程:在创建子cgroup前,确保将主进程移出当前cgroup。

  4. 考虑使用systemd-machined:为容器管理提供更好的系统集成。

  5. 测试控制器可用性:委托时检查实际获得的控制器可能与请求不同。

通过正确理解和应用systemd的cgroup委托机制,开发者可以构建既能充分利用系统功能,又能保持必要独立性的资源管理方案。

systemd The systemd System and Service Manager systemd 项目地址: https://gitcode.com/gh_mirrors/sy/systemd

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

钟冶妙Tilda

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值