容器资源限制:CPU、内存与 OOM 的边界

Docker · 3 分钟阅读· 182 次阅读

一台小主机跑十几个容器,某个服务内存泄漏把整机拖死——这是不设限制的典型后果。

但限制设得太紧,又会出现「莫名被杀」:容器内存到 limit 就被 OOM killer 干掉,日志里什么都没有。

先说结论

内存 limit 要留出运行时开销,CPU 用 shares 做软限制。 Java/Node 必须开容器感知。

  • 内存 limit 比应用峰值高 20%-30%
  • CPU 用 --cpus 限制总量,shares 用于竞争分配
  • 开启 swap 限制(--memory-swap)
  • JVM 用 -XX:MaxRAMPercentage

先把问题说清楚

cgroups v2 下内存超限直接触发 OOM kill,容器退出码 137,日志里通常看不到原因。

CPU 的 --cpus 是硬限额(按周期分配),--cpu-shares 是相对权重,只在竞争时生效。

具体怎么做

按顺序执行,每步都验证完再进下一步:

  • 先观察一周真实峰值(docker stats / cAdvisor)
  • 按峰值 + 30% 设内存 limit
  • CPU 设 --cpus,多服务竞争时再调 shares
  • Java/Node/Python 显式设置堆上限,识别 cgroup 限制
  • 监控 OOM 事件(dmesg 与容器退出码 137)

参数与成本对照

把关键数值摊开,方便判断该选哪条路:

资源 参数 行为
内存 --memory 超限触发 OOM kill
swap --memory-swap 控制可换出量
CPU --cpus 按周期硬限
CPU --cpu-shares 竞争时按权重分配

容器资源限制

几个容易踩的坑

下面这些是最常见的错误做法:

  • 只看平均内存不看峰值:突发流量直接 OOM
  • JVM 不设 MaxRAMPercentage:堆按宿主机内存算,必超
  • 限制 CPU 到 0.1 核:启动都困难
  • 忽略页缓存:文件读写多的容器内存统计偏高

最后补两句

资源限制的前提是「知道正常水位」。先观察,再设限,最后加告警。

工具是手段,理解机制才是能力。命令记不住没关系,知道「该看什么」就够了。

评论 (3)

阿
阿哲

照着做了一遍,确实少走弯路。第二步最容易漏,建议顺手加个检查清单。

南
南风

比「一键脚本」有用多了,知道为什么比知道怎么做重要。

K
Kevin

补充一句:不同版本行为会变,动手前先确认自己的版本号。

发表评论

验证码

提交后需站长审核,通过后才会显示。