设置 `--memory.high` 与 `--memory.max` 的实际效果区别
解读
国内 Docker 面试常把 cgroup v2 的内存子系统细节当成“过滤器”,用来区分“只会用 docker run”与“真正懂内核资源隔离”的候选人。
--memory.max 对应旧版 --memory,是硬上限,容器一旦触碰即触发 OOM Kill;--memory.high 是 cgroup v2 引入的软上限,内核会尽力回收内存、限速分配,但不杀进程。
面试官想听的是:你能否在生产环境利用这对参数做分级 QoS,既保护高优业务,又提升节点整体利用率,而不是背定义。
知识点
- cgroup v1 vs v2:Docker 20.10+ 在 Linux 5.8+ 可启用 v2,
--memory.high仅 v2 生效。 - memory.max:绝对阈值,达到后 cgroup 内进程立即被选杀,OOM Kill 不可捕获、不可恢复。
- memory.high:回收阶段阈值,内核先尝试页面回收、匿名页换出、压缩缓存,若仍不足才允许突破;突破后无杀进程风险,但会阻塞新内存分配请求,表现为 RT 升高、IOWait 增加。
- Docker CLI 映射:
--memory始终映射到 memory.max;
--memory-high需显式写,且要求宿主机已挂载 cgroup v2,否则报错“unknown flag”。 - 节点视角:设置 memory.high ≤ memory.max 可形成两级水位,实现“节点内存超卖+单容器保护”,是云厂商超卖比模型的核心手段。
- 监控差异:metrics 中 memory.high 突破仅记
memory.high_events,不会记container_oom_events,容易被漏警。
答案
“--memory.max 是容器内存的硬顶,触碰即 OOM Kill,等同于传统 --memory;--memory.high 是软限制,内核会先通过回收机制压制用量,允许短时突破,不杀进程,但会阻塞新分配。
在生产里,我把高优业务设 memory.high=4G、memory.max=6G,低优业务直接 memory.max=4G,节点总内存 8G 却能跑下 10G 需求;高优在 4–6G 区间仅性能抖动,低优一旦到 4G 立即被杀,实现分级 QoS 与超卖兼得。
前提是宿主机必须 cgroup v2,否则 Docker 不认 --memory-high 参数。”
拓展思考
- 混部场景:与 kubelet 的 QoS 类(Burstable/Guaranteed)结合时,把 Guaranteed Pod 的 memory.high 设成 request,max 设成 limit,可让节点在内存紧张时优先回收 Burstable,保证高优延迟敏感业务。
- 内存回收限速:cgroup v2 还暴露
memory.high.wmark_ratio,可调回收激进程度;在电商大促中我曾把 ratio 降到 5%,避免瞬时回收导致 P99 抖动。 - Serverless 安全:若平台允许用户自定义
--memory-high,需校验 high ≤ max,否则用户可构造“高频突破 high 却不被杀”的旁路攻击,耗尽节点内存引发系统级 OOM。 - 与 swap 联动:当
--memory-swap未禁用且开启 swap account,memory.high 回收会优先换出匿名页,若宿主机 swap 放在低速云盘,可能把内存问题转化为IO 雪崩;此时应关闭 swap 或把 swap 放在本地 NVMe,并配套memory.high告警。