容器OOM崩溃本质是进程实际内存超容器上限,触发OOM Killer终止;排查核心是比对三组数字:容器限制值、实际峰值用量、应用真实需求。

容器因内存溢出(OOM)崩溃,本质是进程实际内存用量超出了容器被允许使用的上限,触发内核 OOM Killer 强制终止。排查关键不在“找错误”,而在“比对三组数字”:容器限制值、实际峰值用量、应用真实需求。下面分四步直击问题核心。
确认确实是 OOM 导致退出
别猜,先验证:
- 查容器状态:
docker inspect <container-name>,看State.OOMKilled是否为true,State.ExitCode是否为137(128 + 9,即收到 SIGKILL) - 查系统日志:
dmesg -T | grep -i "killed process",会明确写出被杀进程名、PID、内存占用(如anon-rss:480000kB)和限制(如memory.limit_in_bytes:524288000,即 500MiB) - 查容器日志:
docker logs --tail 100 <container-name>,搜OutOfMemory、java.lang.OutOfMemoryError或cannot allocate memory等关键词
检查容器内存限制与实际用量是否匹配
限制设低了,再健康的程序也会被杀:
- 看当前限制:
docker inspect <container-name> | grep -A 5 "Memory",重点关注HostConfig.Memory(字节)和MemoryReservation - 看历史峰值用量:
docker stats --no-stream <container-name>,输出中的MEM USAGE / LIMIT里,斜杠前的数值就是该容器运行以来用过的最高内存 - 对比:如果峰值用量持续接近或超过 LIMIT,说明限制过紧;如果峰值只到 LIMIT 的 30% 却仍 OOM,那大概率是瞬时尖峰或 JVM 堆配置冲突(比如 Java 容器没配
-XX:MaxRAMPercentage,JVM 自己按宿主机内存算堆大小,远超容器 limit)
分析容器内应用的内存行为
限制合理但还是崩?说明应用自身有问题:
- 进容器看进程:
docker exec -it <container-name> top -o %MEM,观察哪个进程吃内存最多,是否持续增长 - Java 应用必做:加 JVM 参数
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/,OOM 后 dump 文件会自动生成,用 MAT 工具打开看 Dominator Tree,找长期持有大量对象的集合或缓存 - 通用排查点:静态 Map/Cache 是否无限增长;数据库连接、文件流、网络连接是否用完未 close;定时任务是否重复创建大对象;是否有大文件一次性读入内存(如 Excel、JSON 全量解析)
检查节点级干扰因素
有时问题不在容器本身,而在它所处的环境:
- 查宿主机内存压力:
free -h和cat /proc/meminfo | grep -E "MemAvailable|MemFree",若可用内存极低,可能多个容器争抢导致误杀 - 查其他进程干扰:
top或htop,看是否有非容器进程(如日志收集 agent、监控插件)突然吃光内存 - K8s 场景额外注意:
kubectl describe node <node-name>查 Events,看是否有Evicted或NodeLowResource事件;kubectl top node看节点整体内存使用率是否长期 >90%


















