K8s OOMKilled 是什么
Pod 里的容器内存超过 limits 上限会被内核杀死,容器状态里 reason 显示 OOMKilled、退出码 137。与单机 Docker 的判断逻辑一致:先确认生效的限制值与真实用量峰值,再区分是限制设得太小还是应用内存真的在涨。差别在于 Kubernetes 里还要多看一层——节点内存压力同样会触发驱逐,根因未必在容器本身。
基本信息
| 确认方式 | 取容器状态 lastState 中的 terminated.reason 是否为 OOMKilled |
|---|---|
| 对比对象 | limits.memory 与 kubectl top 或监控里的峰值内存 |
| 节点侧因素 | 节点内存压力会触发驱逐,需查节点事件与内核记录 |
| 常见修正 | 调大 limit、修内存增长、限制并发与缓存 |
| 预防建议 | requests 与 limits 设置得接近,配合压测与内存告警 |
典型使用场景
- Pod 反复重启:确认是否每次都是内存超限被杀
- 发布回归:新版本内存占用上升,用峰值对比定位变化
- 大促前评估:按压测峰值重新设定内存上下限
- 节点驱逐排查:多个 Pod 同时异常,怀疑是节点资源不足
- 成本优化:用真实峰值下调过大的 limit,提升装箱率
排查命令
排查命令
kubectl get pod web-1 -o jsonpath='{.status.containerStatuses[0].lastState}'
# 关注 reason 是否为 OOMKilled 与 exitCode 是否为 137
kubectl top pod web-1 # 当前实际用量
kubectl describe pod web-1 | grep -i oom # 事件里的相关记录
kubectl describe node node-1 | grep -i memory | head # 节点内存压力
kubectl get pod web-1 -o jsonpath='{.spec.containers[*].resources}' # 生效限制判定与处置对照
| 现象 | 判定 | 处置方向 |
|---|---|---|
| 稳定运行后周期性被杀 | 内存随流量或时间增长 | 排查泄漏,结合长期曲线判断 |
| 一起量立即被杀 | limit 低于实际需求 | 按峰值重新设定 limit |
| 多个 Pod 同时异常 | 节点内存压力导致驱逐 | 扩容节点或调整 requests |
| 只有生产环境出现 | 数据量或并发高于测试 | 用生产负载压测后调参 |
只把 limit 调大并不能解决问题:如果应用的记忆曲线仍在上涨,早晚还会撞墙。上线前按压测峰值的一点三到一点五倍设限,比事后反复加大更稳。
完全不设 limits 风险更大:容器内存无界会先耗尽节点内存,触发节点级驱逐,波及同一节点上的所有业务,影响面远超单个容器。