容器 OOMKilled 是什么
容器 OOMKilled 表示容器内进程的内存用量超过了 cgroup 上限,被内核直接杀死,典型表现是退出码 137 且 State.OOMKilled 为 true。关键在于区分两类原因:一类是限制值低于业务的真实需求,属于配置问题;另一类是应用内存持续增长,属于代码或缓存问题。两者的处置方向完全不同。
基本信息
| 确认方式 | docker inspect -f 取 State.OOMKilled 得到 true |
|---|---|
| 查看限制 | HostConfig.Memory 是生效的内存上限 |
| 查看用量 | docker stats 看实时用量,历史曲线看监控系统 |
| 内核记录 | dmesg 中能看到宿主级别的 OOM 与被杀进程记录 |
| 两类原因 | 限制低于需求(配置)与内存泄漏或缓存膨胀(应用) |
典型使用场景
- 容器反复重启:确认是否每次都是内存超限被杀
- 发布后异常:新版本内存占用明显上升,怀疑引入泄漏
- 并发提升后崩溃:并发数提高导致内存线性上涨并撞上限
- 容量评估:用稳定运行时的峰值内存决定合理的上限值
- 宿主告警:容器未设限,把宿主内存吃满引发连锁故障
排查命令
排查命令
docker inspect myapp -f 'OOM={{.State.OOMKilled}} limit={{.HostConfig.Memory}}'
# 上限为 0 表示未设限,容器可一直吃到宿主内存
docker stats --no-stream myapp # 看当前内存用量与占比
dmesg -T | grep -i "oom\|killed process" | tail -10 # 内核侧记录
free -m # 先确认宿主还有多少余量原因判定对照
| 现象 | 判定 | 处置方向 |
|---|---|---|
| 运行一段时间后稳定被杀 | 内存缓慢增长 | 排查泄漏,配合监控看长期曲线 |
| 一起量就立刻被杀 | 限制值明显低于需求 | 结合峰值重新设定上限 |
| 并发升高时被杀 | 并发与内存正相关 | 限制并发或按并发估算容量 |
| 多个容器同时被杀 | 宿主内存不足 | 检查宿主整体内存与超卖情况 |
调大限制之前先看宿主余量:把容器上限调大只是把风险转移给宿主,宿主级别的 OOM 会杀掉更关键的进程,影响面反而更大。
JVM 类应用要特别注意堆外内存:堆、元空间、线程栈、直接内存加起来可能远超设定的堆上限,只按堆大小估算容器内存限制会持续踩坑。