Kubernetes集群运行中,Pod被驱逐(Evicted)或因OOMKilled重启是高频运维问题。这两类故障根因不同但表现相似,排查时容易混淆。本文从Kubelet驱逐机制入手,结合实际排障场景,梳理从现象发现到根因定位的完整流程。
Kubelet驱逐机制触发条件与流程
Kubelet持续监控节点的内存、磁盘等资源指标。当资源消耗超过软驱逐阈值(soft eviction threshold)时,Pod进入优雅终止流程;超过硬驱逐阈值(hard eviction threshold)时,Kubelet立即杀掉Pod。默认硬驱逐阈值配置:
# /var/lib/kubelet/config.yaml
evictionHard:
memory.available: "100Mi"
nodefs.available: "10%"
nodefs.inodesFree: "5%"
imagefs.available: "15%"
evictionSoft:
memory.available: "300Mi"
nodefs.available: "15%"
evictionSoftGracePeriod:
memory.available: "1m30s"
nodefs.available: "2m"
当节点可用内存低于100Mi时,Kubelet按QoS等级和优先级排序,优先驱逐BestEffort类型的Pod,其次Burstable, Guaranteed类型最后驱逐。同一QoS等级内,已使用资源占Request比例最高的Pod优先被驱逐。
Pod状态诊断:区分驱逐与OOMKilled
通过kubectl获取Pod状态,驱逐和OOM的表现不同:
# 查看Pod状态
kubectl get pods -n production
NAME READY STATUS RESTARTS AGE
api-server-7d4f-xx9a 0/1 Evicted 0 2h
worker-pod-b3c2-zz1m 1/1 OOMKilled 3 45m
# 查看驱逐详情
kubectl describe pod api-server-7d4f-xx9a -n production | grep -A5 "Reason"
# Reason: Evicted
# Message: The node was low on resource: memory.
# Container api-server was using 800Mi, which exceeds its request of 256Mi.
# 查看OOM事件
kubectl describe pod worker-pod-b3c2-zz1m -n production | grep -A5 "Last State"
# Last State: Terminated
# Reason: OOMKilled
# Exit Code: 137
# Memory: 524288KB (超过limit 512Mi)
关键区分点:Evicted状态由Kubelet在节点资源压力时触发,整个Pod被终止;OOMKilled是容器进程内存使用超过resources.limits.memory,被内核cgroup OOM killer杀掉,Pod可能自动重启。Exit Code 137(128+9=SIGKILL)是OOM的典型信号。
内存资源Request与Limit配置排查
OOM和驱逐的根因往往指向资源配置不当。查看节点资源分配情况:
# 节点资源分配概览
kubectl describe node worker-node-03 | grep -A10 "Allocated resources"
# Allocated resources:
# (Total limits may be over 100 percent, i.e., overcommitted.)
# Resource Requests Limits
# -------- -------- ------
# cpu 6500m (81%) 9000m (112%)
# memory 22Gi (78%) 30Gi (107%)
# ephemeral-storage 0 (0%) 0 (0%)
Limits超过100%意味着节点存在超售,高峰期多个Pod同时到达Limit上限时极易触发OOM。排查步骤:确认被驱逐Pod的Request是否设置过低(导致调度到已紧张节点),Limit是否设置过高(超出节点实际可用内存)。
合理的配置原则:Request设为日常平均使用量,Limit设为峰值使用量的1.2到1.5倍。使用kubectl top pod监控实际用量:
# 实时资源使用
kubectl top pod -n production --sort-by=memory
NAME CPU(cores) MEMORY(bytes)
api-server-7d4f-xx9a 120m 890Mi
worker-pod-b3c2-zz1m 340m 512Mi # 刚好到limit
cache-pod-a1b2-c3d4 50m 1800Mi
# 查看历史指标(需Metrics Server)
kubectl get --raw "/apis/metrics.k8s.io/v1beta1/nodes/worker-node-03" | jq .
节点资源压力条件分析
节点级别的资源压力通过Conditions字段反映。MemoryPressure和DiskPressure为True时,Kubelet进入驱逐模式:
# 检查节点条件
kubectl describe node worker-node-03 | grep -A15 "Conditions:"
# Conditions:
# Type Status LastHeartbeatTime
# MemoryPressure True 2026-07-23T08:30:00Z
# DiskPressure False 2026-07-23T08:30:00Z
# PIDPressure False 2026-07-23T08:30:00Z
# Ready True 2026-07-23T08:30:00Z
MemoryPressure为True时,新Pod不再调度到该节点(NoSchedule污点)。排查内存压力来源:使用crictl查看容器实际内存占用,定位异常Pod:
# SSH到节点查看容器内存
crictl ps | grep -v pause | awk '{print $1}' | xargs -I{} crictl stats {} | sort -k6 -h
# 查看内核OOM记录
dmesg | grep -i "out of memory\|oom-kill"
# [12345.678] Out of memory: Killed process 2345 (java) total-vm:4GB, anon-rss:3GB
dmesg中的OOM记录能确认是内核cgroup OOM还是系统级OOM。如果进程名出现在dmesg中,说明容器内存确实超限;如果dmesg无记录但Pod状态显示OOMKilled,检查是否为容器运行时(containerd)的内存限制触发。
PDB保护与优雅驱逐配置
PodDisruptionBudget(PDB)防止驱逐导致服务不可用。生产环境必须为核心服务配置PDB:
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: api-server-pdb
namespace: production
spec:
minAvailable: 2
selector:
matchLabels:
app: api-server
minAvailable: 2确保驱逐时至少保留2个Pod运行。但PDB只对主动驱逐(如kubectl drain)生效,节点资源压力触发的硬驱逐不受PDB约束。因此PDB是保护手段而非根治方案,核心还是在资源配置和节点容量规划上做合理预估。
长期优化方向:为关键Pod设置Guaranteed QoS(Request等于Limit),确保驱逐优先级最低;使用Vertical Pod Autoscaler(VPA)自动调优资源配置;部署Descheduler组件定期重平衡Pod分布,避免热点节点资源耗尽。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/kubernetespod-qu-zhu-ji-zhi-yu-oom-zhen-duan-jie-dian-zi/