memory.high 不会触发 oom 杀进程,仅在内存压力下尽力回收页面;真正触发 oom killer 的是 memory.max 硬限制。

memory.high 触发后进程真的会被 OOM 杀掉吗?
不会,memory.high 是软限制,内核只会在内存压力下尽力回收该 cgroup 的页面,不满足时会先踢出 page cache、swap out 匿名页,甚至延迟分配——但不会直接 kill 进程。真要杀,得靠 memory.max(硬上限)触发 OOM killer。
-
memory.max设为0表示无限制;设为1G之类具体值后,一旦实际使用超限,内核立刻选一个进程干掉 -
memory.high推荐设为略高于预期峰值(比如峰值 800M,设900M),给回收留缓冲,避免抖动 - 查看是否被压:读
/sys/fs/cgroup/mygroup/memory.events,关注high字段计数增长,不是oom才说明你在用对路子
cgroup v2 下 cpu.weight 和 cpu.max 怎么配才不冲突?
cpu.weight(默认 100)管的是「相对份额」,cpu.max(如 50000 100000)管的是「绝对带宽上限」,两者同时生效,但优先级不同:先按 cpu.max 切总带宽,再在剩余带宽里按 cpu.weight 分。
-
cpu.max第一个值是微秒(us),第二个是周期(us),50000 100000= 50% CPU;设成max表示不限制 - 如果只设
cpu.weight不设cpu.max,cgroup 可能吃满所有空闲 CPU,其他组没机会抢到 - 常见错误:把
cpu.max设太小(比如1000 100000= 1%),又把cpu.weight调很高,结果既抢不到资源,又没弹性空间
io.weight 对不同 I/O 类型(sync/async, buffered/direct)有效吗?
只对基于 bfq 调度器的 同步 buffered I/O 有效;对 direct I/O、异步 I/O(libaio/io_uring)、以及 noop/deadline 调度器下的 I/O 基本无效。
- 确认调度器:
cat /sys/block/nvme0n1/queue/scheduler,输出含[bfq]才行 -
io.weight范围是 1–1000,默认 100;设为 10 表示该组只拿约 1% 的 IO 带宽(相比 weight=1000 的组) - 容易踩坑:在容器里跑 PostgreSQL 或 Redis(常开
O_DIRECT),这时io.weight形同虚设,得靠io.max(bps/iops 限速)来控
统一 hierarchy 下如何让 memory + cpu + io 控制器真正协同生效?
必须确保所有控制器都在同一 cgroup 路径下启用,且挂载时没漏掉 memory、cpu、io —— v2 要求「全有或全无」,哪怕只缺一个,整个路径都进不了 unified 模式。
- 挂载命令必须带完整 controller list:
mount -t cgroup2 none /sys/fs/cgroup -o clone_children(注意不是cgroupv1) - 创建子 cgroup 后,往
cgroup.controllers写入要启用的控制器:echo "+memory +cpu +io" > cgroup.controllers - 若写入失败(报
Device or resource busy),说明有进程已在这个 cgroup 下运行,得先移出再操作 - 最容易被忽略的一点:systemd 默认把服务塞进
/sys/fs/cgroup/system.slice/xxx.service,但那里默认只启了cpu和memory,io得手动加进去,否则 IO 控制永远不生效










