土法炼钢兴趣小组的算法知识备份

【操作系统百科】cgroup v2:资源控制的统一模型

文章导航

分类入口
os
标签入口
#cgroup-v2#psi#systemd-slice#resource-control#io-weight#memory-max

目录

namespace 让进程”看到啥”,cgroup 让进程”用多少”。Linux 4.5 引入的 cgroup v2(现在各大发行版已是默认)把 v1 混乱的多 hierarchy 统一成一棵树,把资源控制器(controller)统一到一套语义。本文讲 v2 的核心概念、关键 knob、PSI 压力指标、和 systemd 的整合。

一、总览

flowchart TB
    R[/sys/fs/cgroup]-->SLICE[system.slice]
    R-->USLICE[user.slice]
    R-->INIT[init.scope]
    SLICE-->A[nginx.service]
    SLICE-->B[postgresql.service]
    SLICE-->C[docker-XXX.scope]
    USLICE-->U1000[user-1000.slice]
    U1000-->S1[session-1.scope]
    A-. cpu.weight=100 .->R
    A-. memory.max=2G .->R
    B-. io.weight=200 .->R
    classDef sys fill:#388bfd22,stroke:#388bfd,color:#adbac7;
    classDef u fill:#f0883e22,stroke:#f0883e,color:#adbac7;
    classDef svc fill:#3fb95022,stroke:#3fb950,color:#adbac7;
    class R,SLICE,INIT sys
    class USLICE,U1000 u
    class A,B,C,S1 svc

关键设计:

二、controller 清单(v2)

三、key knobs 深入

3.1 cpu.weight vs cpu.max

生产建议:优先 weight;需要严控(SLA / billing)用 max。

3.2 memory.max vs memory.high

Kubernetes 的 “memory.high” 用法:limits 对齐 memory.max,保 hard-bound;requests 对齐 memory.min,保最低。

3.3 io.weight 的历史包袱

v1 的 blkio 子系统只在 CFQ 下有效;移到 v2 后 io.weight 依赖 BFQ 或 mq-deadline(有限支持)。云厂商常用 NVMe + none scheduler,weight 就失效——容器 I/O 隔离经常是”看起来设了其实没效”。真限流用 io.max 绝对 IOPS/MBps。

四、PSI:Pressure Stall Information

v2 独有,4.20+。提供 “some” / “full” 两种指标:

/sys/fs/cgroup/foo/cpu.pressure
some avg10=0.12 avg60=0.05 avg300=0.01 total=12345678
full avg10=0.00 ...

含义:some=30% 表示这个 cgroup 里过去 10 秒有 30% 时间”有人在等 CPU”。比 load average 准确得多——load 混合了 R+D 且是全局。

应用:

五、systemd 与 cgroup 的协作

systemd 是 cgroup v2 管理器的事实标准。它把系统组织成三类单元:

systemctl set-property nginx.service CPUQuota=200% 会写到 system.slice/nginx.service/cpu.max

systemd-cgls 看树;systemd-cgtop 看实时。

六、delegation:把子树交给 rootless

user ns + cgroup delegation 让非特权用户管理自己的 cgroup:

systemctl --user status
# 在 user-1000.slice 下创建、调整自己的 cgroup

systemd.unit(5)Delegate=yes 开启。rootless podman、flatpak 都用这个。

七、cgroup v2 的常见使用姿势

7.1 让服务受 OOM 保护

[Service]
MemoryMin=256M         # 保护下限
MemoryHigh=1G          # 软上限
MemoryMax=1500M        # 硬上限

7.2 IO 绝对限流

[Service]
IOReadBandwidthMax=/dev/nvme0n1 100M
IOWriteBandwidthMax=/dev/nvme0n1 100M

7.3 CPU 亲和与配额

[Service]
CPUAffinity=4-7
CPUQuota=200%          # 最多用 2 个核的时间
CPUWeight=1000

7.4 限制 fork

[Service]
TasksMax=512

八、诊断

cat /sys/fs/cgroup/foo/cpu.stat
# usage_usec, user_usec, system_usec, nr_periods, nr_throttled, throttled_usec

cat /sys/fs/cgroup/foo/memory.events
# low high max oom oom_kill

cat /sys/fs/cgroup/foo/io.stat
# rbytes wbytes rios wios ...

观察 throttled 比例判断是否打到 quota;memory.events 里 oom_kill 递增说明被杀;io.stat 结合 PSI 看磁盘瓶颈。

bpftrace 有 tracepoint:cgroup:cgroup_rmdir 等。

九、v1 → v2 迁移的坑

容器运行时会自动按发行版选 v1/v2;应用一般无感,但监控系统(cAdvisor、node_exporter)要分别处理路径。

十、常见 bug

bug A:CPU quota 设了但延迟还是抖 原因:100ms period 默认;短 quota 频繁被 throttle 解决:增大 period 或放宽 quota;或 pinning + weight

bug B:memory.high 压力大但不 OOM 现象:进程卡顿、page fault 暴涨 原因:内核持续 reclaim;交换开启时尤甚 解决:调整 memory.max、memory.swap.max、或引入 PSI 监控

bug C:io.max 限流不生效 原因:调度器是 none,v2 限流依赖 BFQ 或特定路径 解决cat /sys/block/nvme0n1/queue/scheduler;换调度器;或 NVMe 原生 I/O priority

bug D:容器里 nproc 和 cgroup TasksMax 冲突 原因:RLIMIT_NPROC 是 per-uid;TasksMax 是 per-cgroup 解决:同时设置合理值

十一、小结


至此子系列 B 完结。下一篇将进入子系列 C:调度器深度(C-19 起)——从调度理论到 CFS/EEVDF 内部、实时与 deadline、多核负载均衡、big.LITTLE、调度延迟诊断。


参考文献

工具


上一篇namespace:容器的内核根基 下一篇调度理论:从 FCFS 到 MLFQ 到 CBS

同主题继续阅读

把当前热点继续串成多页阅读,而不是停在单篇消费。

2026-04-19 · os

【操作系统百科】调度延迟分析:是不是调度器的锅?

用户抱怨「慢」时第一问题:是 CPU 本身跑得慢,还是调度器让你等?本文讲 runq latency、wakeup latency、block time 三线拆分;perf sched、bpftrace runqlat、schedviz 工具链;生产案例:CFS quota throttle、NUMA 迁移、PSI 告警。

2026-04-27 · os

【操作系统百科】内存回收

Linux 内存回收是 VM 最复杂的子系统之一。本文讲 active/inactive LRU、kswapd 与 direct reclaim、watermark 三线、swappiness 的真实含义、MGLRU 改造、memcg 回收与 PSI。

2026-04-28 · os

【操作系统百科】交换

swap 还值得开吗?本文讲 swap area 基础、swap cache、zram 压缩内存、zswap 前端压缩池、swappiness 的真实含义、容器里的 swap 策略,以及为什么现代 Android 全靠 zram 不靠磁盘。

2026-05-03 · os

【操作系统百科】Slab/SLUB 分配器

buddy 只管页粒度(4K+),内核大多数对象只有几十到几百字节。slab/SLUB 在 buddy 之上做对象级缓存。本文讲 slab 历史、SLUB 接手、SLOB 退场、kmem_cache、per-CPU cache、KASAN 集成。


By .