确认 pod 因 oom 被杀需检查退出原因是否为 oomkilled、退出码是否为 137;通过 kubectl get/describe/logs 命令定位证据、日志和资源限制;java 应用须启用容器内存感知并避免硬编码堆大小。

确认 Pod 确实因 OOM 被杀,是排查的第一步。关键不是看它“有没有重启”,而是看退出原因是否为 OOMKilled,以及退出码是否为 137(128 + 9,即 SIGKILL)。
看状态和事件,锁定 OOM 证据
运行以下命令快速定位:
-
kubectl get pods -A | grep -i "OOMKilled"—— 找出所有被 OOM 杀死的 Pod -
kubectl describe pod <pod-name> -n <namespace></namespace></pod-name>—— 在 Container Statuses → Last State → Reason 中确认是否为 OOMKilled;在 Events 区域查找类似 Container exceeded memory limit 或 OOM killed 的日志,并注意其中标注的 used: XGi 和 limit: YGi -
kubectl get pod <pod-name> -n <namespace> -o yaml | yq '.status.containerStatuses[].state.terminated'</namespace></pod-name>(或用grep -A5 "terminated")—— 直接提取退出码与原因
查上一次日志,捕捉崩溃前线索
OOM 发生时容器已终止,必须加 --previous 才能读到真正有用的日志:
kubectl logs <pod-name> -c <container-name> -n <namespace> --previous</namespace></container-name></pod-name>- 重点搜索:
OutOfMemoryError、GC overhead limit exceeded、unable to allocate memory、java.lang.OutOfMemoryError(Java)、std::bad_alloc(C++)等关键词 - 配合
grep -C 20 "OutOfMemory"查看上下文,常能发现触发 OOM 的请求路径、数据量或定时任务
核对资源限制配置是否合理
很多 OOM 并非应用问题,而是 limits 设置失当,尤其 Java 类应用极易踩坑:
-
kubectl get pod <pod-name> -n <namespace> -o yaml | grep -A 10 "resources:"</namespace></pod-name>—— 检查limits.memory是否设置,值是否过低(如设了512Mi,但实际峰值达1.2Gi) - 若未设
limits.memory,容器可能被 kubelet 按 QoS 等级驱逐,且无法预测何时被杀 - Java 应用需额外注意:JDK8u131+ 后应启用容器内存感知,否则 JVM 默认按宿主机内存估算堆大小。务必添加 JVM 参数:
-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap
并避免同时硬编码-Xmx,否则会覆盖 cgroup 限制
观察内存使用趋势,区分泄漏与尖峰
仅看单次快照容易误判,要关注变化规律:
-
kubectl top pod <pod-name> -n <namespace></namespace></pod-name>—— 查看当前内存用量(需 metrics-server) -
kubectl top pod <pod-name> -n <namespace> --containers</namespace></pod-name>—— 定位具体哪个容器占内存高 - 结合 Prometheus + Grafana 查看
container_memory_working_set_bytes{pod="xxx"}曲线,识别是缓慢上涨(内存泄漏)、周期性冲高(定时任务)、还是突发流量导致瞬时超限 - 对 Java 应用,可在启动参数中加入:
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/heap.hprof,OOM 后自动生成堆转储供离线分析










