bigywater.tech
Docker · 42

OOM Kill:容器内谁被杀、dmesg 里怎么看

容器因为内存不足被杀,到底留下哪些证据?谁被杀、容器退不退出、怎么在 docker 和内核两边查到?这篇逐项复现:退出码、OOMKilled 标志、docker events、dmesg、cgroup 的 memory.events,以及 --oom-kill-disable 的下场。

oom → die
docker events 里 OOM 的容器,die 之前会多出一个 oom 事件
running 且 OOMKilled=True
多进程容器里只有吃内存的进程被杀,容器没退出,标志已经是 True
max 37 / oom_kill 1
memory.events:碰到上限 37 次,真正触发 OOM 杀进程 1 次

三处证据

实测 · 本机执行输出
  docker run 退出码 137;State.OOMKilled=True ExitCode=137 Error=''
  docker events:create → attach → start → oom → die
  虚拟机内核日志(dmesg)里的相关行:[13225.072532] Memory cgroup out of memory: Killed process 70745 (python) total-vm:144460kB, anon-rss:64508kB, file-rss:5472kB, shmem-rss:0kB, UID:0 pgtables:316kB oom_score_adj:0 ; [13272.476306] Memory cgroup out of memory: Killed process 74249 (python) total-vm:41996kB, anon-rss:32104kB, file-rss:5432kB, shmem-rss:0kB, UID:0 pgtables:124kB oom_score_adj:0

docker 这边:退出码 137、State.OOMKilled=True、events 里有 oom。内核这边:虚拟机的 dmesg 里有 Memory cgroup out of memory: Killed process … (python),anon-rss 约 32 MB,与容器的上限吻合。cgroup 这边:memory.events 的 oom_kill 计数。

多进程容器

实测 · 本机执行输出
  5 秒后容器 Status=running OOMKilled=True;日志:子进程 python 结束 状态 137 | Killed
  容器里还活着的进程:PID   COMMAND |     1 sleep |     7 sleep |     9 ps

内核杀的是进程,不是容器。容器里有 sleep 和吃内存的 python,只有 python 被杀,容器还在运行,但 OOMKilled 已经是 True。如果被杀的恰好是 PID 1,容器才会退出。看到 OOMKilled=True 不代表容器已经停了(我没有测被杀的是 PID 1 以外且容器继续服务的情形对应用的实际影响)。

memory.events

实测 · 本机执行输出
  memory.events:low 0;high 0;max 37;oom 1;oom_kill 1;oom_group_kill 0;sock_throttled 0;
  memory.events.local 里 oom_kill:oom_kill 1

max 是碰到上限的次数(37 次),不代表被杀;按我的理解,内核会先尝试回收内存,回收不了才 OOM,最终 oom_kill 为 1(回收的过程我没有观察)。

--oom-kill-disable

实测 · 本机执行输出
  docker run -d 退出码 0;输出:369adf5dbf7d8083935afdc7e5a7d0175d7d1e5f8e6d8c20c79017f4deda1756 | WARNING: Your kernel does not support OomKillDisable. OomKillDisable discarded.
  4 秒后 Status=exited OOMKilled=True;HostConfig.OomKillDisable=<nil>

这个环境(cgroup v2)下 --oom-kill-disable 会被丢弃,docker 打印 WARNING,容器照样被杀。cgroup v1 的行为我没有测。

分步演示

OOM 杀手
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / Docker Desktop(Engine 29.8.2,容器跑在 Docker Desktop 自带的 Linux 虚拟机里,内核与宿主机的 macOS 不同);镜像为 linux/arm64;需要看虚拟机内部时用特权容器 + nsenter;计时用 time / date +%s%N,数字每次运行会有小幅抖动。吃内存的程序是 python 的循环分配 5 MiB 并写入;内核日志取自虚拟机里的 dmesg(特权容器加 nsenter,方法见 c19),dmesg 里还有此前其它实验的 OOM 记录,文中只引用本次对应的那一行;memory.events 取自容器 cgroup;每种情形运行一次;实验后已删除容器
    • 没有验证:cgroup v1、oom_score_adj 对杀谁的影响、memory.oom.group(整组杀)、宿主机整体内存耗尽时的全局 OOM、PID 1 被杀时容器的退出、应用对 OOM 的感知与恢复
    京ICP备2026067502号-1京公网安备11010502063487号