直接回答:两个层级:cgroup OOM——容器内存超 limits.memory,内核直接 SIGKILL,kubectl describe 的 lastState.reason: OOMKilled 与退出码 137;节点级 OOM——节点整体内存耗尽触发系统 oom-killer 按 oom_score 挑进程杀。区分看 describe:OOMKilled 标记明确指向 cgroup 限额;节点级则看宿主机 dmesg 的 oom-killer 记录,容器退出码未必 137。

展开解析:分析流程:确认是 cgroup OOM 后查三根线——limits 是否合理(压测基线 + 30% 余量起步)、应用真实内存曲线(Prometheus 的 container_memory_working_set_bytes,注意 working_set 含活跃 page cache 才是 cgroup 计费口径)、是否存在泄漏(曲线只涨不回落)。语言运行时经典坑:JVM 堆默认按物理内存 1/4,容器限 512Mi 它按宿主机 64G 算——必须 -XX:MaxRAMPercentage 或 -Xmx 显式限制(JDK 8u191+/10+ 才感知 cgroup);Node 的 --max-old-space-size 同理;Go 的 GOMEMLIMIT(1.19+)把 GC 目标锚在限额 80%~90%。治理手段:requests=limits 的 Guaranteed QoS 减少被驱逐与调度漂移;VPA 推荐 requests 基线;memory limit 命中前的缓冲方案——应用侧限流降级。节点级 OOM 的治理不同:根源是 requests 设置失真(超卖严重),kubelet 的 eviction-hard 阈值(默认 memory.available<100Mi)先行软驱逐,治本靠准的 requests 与节点预留(system-reserved/kube-reserved)。排障命令备忘:dmesg -T | grep -i oom、/var/log/messages、container 的 /sys/fs/cgroup/memory.events(oom_kill 计数)。

追问方向:QoS 等级(Guaranteed/Burstable/BestEffort)如何影响驱逐顺序?为什么 RSS 与 working_set 差距大?

(约 500 字)