← 返回技术随笔仓库

容器 OOMKilled 但宿主机内存充足

发布时间:2026-11-13容器云原生

exit 137 = SIGKILL,容器场景九成是 OOM。关键认知:容器内存限制是 cgroup 独立账本,宿主机再空闲,容器用了超过 docker run -m / K8s limits.memory 的量就杀,跟宿主机全局内存无关。确认方法:docker inspect 看 State.OOMKilled=true,或 K8s 里 kubectl describe pod 看到 Reason: OOMKilled。

JVM 是重灾区里的重灾区:老版本 JDK(8u191 之前)看不到 cgroup 限制,按宿主机总内存算默认堆大小——宿主机 64G 容器限 2G,JVM 理直气壮开 16G 堆,起来就被杀。修复:升级 JDK 认容器限制(UseContainerSupport 默认开),或显式 -XX:MaxRAMPercentage=70 按限制比例给堆。注意堆外还有元空间、线程栈、直接内存,MaxRAMPercentage 别给到 95,留余量。

另一个隐蔽点:cgroup 的内存统计包含 page cache(文件缓存)。容器大量读写文件时 cache 涨满限额触发回收,回收不动才 OOM——正常情况 cache 会被自动回收不算真占用,但 v1 cgroup 的统计口径容易造成「明明应用没用这么多内存」的困惑。K8s 里 requests/limits 设置建议:内存 requests=limits(Guaranteed QoS,避免节点压力时被优先驱逐),JVM 堆设为 limit 的 60-70%。