【操作系统百科】cgroup v2:资源控制的统一模型
内容提要
本文介绍Linux cgroup v2的核心概念:统一层级树结构、资源控制器(cpu.weight/max、memory.max/high、io.weight/max等)、PSI压力指标,以及与systemd的整合方式。还涵盖delegation机制、常见使用姿势、诊断方法、v1迁移注意事项和典型bug,强调PSI是资源压力的权威指标。
延伸解读
cgroup v2 与 Kubernetes 资源映射的差异
文章指出 Kubernetes 标准 spec 中,requests.memory 映射到 memory.min,而 limits.memory 映射到 memory.max;requests.cpu 映射到 cpu.weight,limits.cpu 映射到 cpu.max。但 requests.memory 并不映射到 memory.high,这意味着软节流需要额外配置或依赖节点驱逐。理解这一差异有助于避免对 Kubernetes 资源语义的误解。
io.weight 在云环境中的失效风险
文章强调 io.weight 依赖 BFQ 或 mq-deadline 调度器,而云厂商常用的 NVMe 设备常使用 none 调度器,导致 io.weight 实际不生效。因此,在云环境中依赖 io.weight 进行 I/O 隔离可能无效,应改用 io.max 进行绝对限流。这一提醒对容器 I/O 管理具有实际意义。
PSI 指标的应用与局限
PSI 提供 some 和 full 两种指标,比 load average 更精确地反映资源压力,被 oomd 和 Kubernetes 用于主动干预。但文章指出,PSI 阈值与业务 SLO 之间缺乏统一公式,需要根据 workload 进行 A/B 验证。这提示读者在利用 PSI 时需结合自身场景调整阈值。
v1 迁移到 v2 的常见陷阱
迁移时需注意所有控制器必须位于同一棵树,且部分 knob 语义变化,如 memory.limit_in_bytes 对应 memory.max,但 swap 计算方式不同。此外,监控系统如 cAdvisor 和 node_exporter 需分别处理 v1/v2 路径。这些细节对迁移规划至关重要。
Q&A
cgroup v2 相比 v1 有哪些核心改进?
cgroup v2 将 v1 中混乱的多 hierarchy 统一为一棵树,每个进程只属于一个 cgroup,资源控制器语义统一,并引入了 PSI 压力指标。
cgroup v2 中 cpu.weight 和 cpu.max 有什么区别?
cpu.weight 是比例权重,用于 CPU 竞争时按比例分配;cpu.max 是绝对配额,限制 CPU 使用上限,即使 CPU 空闲也不能超过。
memory.max 和 memory.high 在 cgroup v2 中分别有什么作用?
memory.max 是硬上限,超过会触发 OOM;memory.high 是软上限,达到后内核施加回收压力,进程不会被杀但性能下降。
PSI 指标中的 some 和 full 分别代表什么?
some 表示至少一个任务在等待资源的时间比例;full 表示所有可运行任务都在等待的时间比例。
systemd 如何与 cgroup v2 集成?
systemd 将系统组织为 slice、service、scope 三类单元,通过 systemctl set-property 可以设置资源限制,如 CPUQuota 会写入 cpu.max。
cgroup v2 的 delegation 机制有什么作用?
delegation 允许非特权用户通过 user namespace 管理自己的 cgroup 子树,是 rootless 容器(如 Podman)的基础。
在 cgroup v2 中如何限制服务的 IO 带宽?
可以使用 systemd 的 IOReadBandwidthMax 和 IOWriteBandwidthMax 属性,或者直接设置 io.max 文件来限制绝对 IOPS/带宽。
cgroup v2 中如何诊断资源限制是否生效?
可以查看 cpu.stat 中的 nr_throttled 和 throttled_usec 判断 CPU 是否被限流;memory.events 中的 oom_kill 判断是否发生 OOM;io.stat 结合 PSI 判断磁盘瓶颈。
从 cgroup v1 迁移到 v2 有哪些注意事项?
所有控制器必须挂载在同一棵树;部分 knob 语义变化,如 memory.limit_in_bytes 对应 memory.max,但 swap 计算方式不同;需注意监控系统路径差异。
cgroup v2 中 io.weight 在云环境可能失效的原因是什么?
io.weight 依赖 BFQ 或 mq-deadline 调度器,云厂商常用 NVMe + none 调度器,导致 weight 失效,应使用 io.max 进行绝对限流。