Pod驱逐的底层机制与触发条件
Kubernetes中的Pod驱逐(Eviction)是节点压力管理的核心机制。当节点资源耗尽时,kubelet会主动终止低优先级Pod,释放资源保障节点稳定性。理解驱逐逻辑是K8s运维的基础——生产环境中Pod无故消失,大概率就是驱逐导致的。
触发驱逐的三类资源压力:
内存压力:节点可用内存低于阈值(默认100MiB),或内核OOM Killer已经介入。kubelet按Pod QoS等级排序驱逐:BestEffort → Burstable → Guaranteed,同等级内按内存使用量占比排序。
磁盘压力:节点磁盘使用率超过阈值(默认85%驱逐,95%变为NodeOutOfDisk),或inode耗尽。kubelet会驱逐占用磁盘最多的Pod。
PID压力:节点进程数接近内核上限(pid_max),kubelet按Pod的PID使用量排序驱逐。
驱逐与OOM Kill的区别:驱逐是kubelet主动行为,Pod会收到SIGTERM信号,有优雅终止窗口(默认30秒);OOM Kill是内核行为,进程直接被SIGKILL,无优雅终止。
资源请求与限制配置的最佳实践
Pod被驱逐的根本原因往往是资源配额配置不当。requests和limits是K8s资源管理的基石:
resources:
requests: # 调度依据,保证最低资源
memory: "512Mi"
cpu: "500m"
limits: # 硬上限,超出会被OOM Kill或CPU throttle
memory: "1Gi"
cpu: "1000m"
三个关键原则:
1. requests必须真实反映稳态资源消耗。requests设得太低,调度器会将过多Pod分配到同一节点,导致内存超卖和驱逐。用kubectl top pod观察稳态资源消耗,requests设为稳态P95值。
2. limits不要设得远大于requests。内存limits与requests差距过大意味着允许Pod突发大量内存,一旦多个Pod同时突发,节点内存瞬间耗尽。生产环境中,内存limits建议不超过requests的2倍。
3. 关键服务必须设置Guaranteed QoS。当requests等于limits时,Pod获得Guaranteed QoS等级,被驱逐的优先级最低:
# Guaranteed QoS:核心数据库、支付服务等
resources:
requests:
memory: "2Gi"
cpu: "2000m"
limits:
memory: "2Gi" # requests == limits
cpu: "2000m"
节点驱逐阈值配置与调优
kubelet的驱逐阈值通过–eviction-hard和–eviction-soft参数配置:
# /var/lib/kubelet/config.yaml
# 硬驱逐阈值:立即触发
evictionHard:
memory.available: "500Mi" # 可用内存低于500Mi时立即驱逐
nodefs.available: "10%" # 节点根文件系统可用低于10%
nodefs.inodesFree: "5%" # inode可用低于5%
imagefs.available: "15%" # 镜像存储可用低于15%
# 软驱逐阈值:宽限期后触发
evictionSoft:
memory.available: "1Gi" # 可用内存低于1Gi
nodefs.available: "15%"
evictionSoftGracePeriod:
memory.available: "60s" # 宽限期60秒
nodefs.available: "120s"
# 驱逐前最大Pod优雅终止时间
evictionMaxPodGracePeriodSeconds: 60
# 驱逐信号稳定窗口,避免抖动
evictionMinimumReclaim:
memory.available: "256Mi"
调优建议:生产节点内存32GB以上时,硬驱逐阈值设为500Mi-1Gi,软驱逐阈值设为1-2Gi。不要把阈值设得太低,否则内存耗尽触发内核OOM Kill时,kubelet的驱逐逻辑来不及介入,整个节点会不可用。
Pod驱逐故障排查流程
发现Pod消失时,按以下步骤排查:
# 1. 查看Pod事件,确认是否被驱逐
kubectl get event --field-selector reason=Evicted -n <namespace>
# 2. 查看节点状态和资源压力
kubectl describe node <node-name> | grep -A 20 "Conditions"
kubectl describe node <node-name> | grep -A 10 "Allocated resources"
# 3. 查看节点内存压力历史
journalctl -u kubelet | grep -i eviction | tail -20
# 4. 查看Pod的QoS等级和资源配置
kubectl get pod <pod-name> -o jsonpath='{.status.qosClass}'
kubectl get pod <pod-name> -o jsonpath='{.spec.containers[*].resources}'
常见驱逐场景与对策:
| 场景 | 原因 | 对策 |
|---|---|---|
| BestEffort Pod频繁被驱逐 | 未设置requests/limits | 至少设置requests |
| 节点内存充足但Pod仍被驱逐 | 磁盘/inode压力 | 检查df -i,清理日志或临时文件 |
| 批量Pod同时被驱逐 | 节点资源严重超卖 | 审查requests总和与节点容量比 |
| Pod驱逐后无法重新调度 | 集群整体资源不足 | 扩容节点或优化Pod资源配额 |
资源配额与LimitRange的集群级管控
单靠开发者自觉配置resources不现实,集群级管控策略必须到位。
ResourceQuota:限制命名空间的总资源消耗:
apiVersion: v1
kind: ResourceQuota
metadata:
name: mem-cpu-quota
namespace: production
spec:
hard:
requests.memory: "64Gi" # 命名空间总内存请求上限
requests.cpu: "32"
limits.memory: "128Gi"
limits.cpu: "64"
pods: "50" # 最大Pod数量
LimitRange:为未设置resources的Pod设置默认值,并限制单个Pod的资源范围:
apiVersion: v1
kind: LimitRange
metadata:
name: default-limits
namespace: production
spec:
limits:
- type: Container
default: # 默认limits
memory: "512Mi"
cpu: "500m"
defaultRequest: # 默认requests
memory: "256Mi"
cpu: "250m"
max: # 单容器最大资源
memory: "8Gi"
cpu: "4"
min: # 单容器最小资源
memory: "64Mi"
cpu: "50m"
监控告警体系与容量规划
基于Prometheus的驱逐监控指标:
# 驱逐事件计数
rate(kube_pod_container_status_terminated_reason{reason="Evicted"}[5m]) > 0
# 节点内存压力
100 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes * 100) > 85
# 资源超卖率(已调度requests / 节点容量)
sum(kube_pod_container_resource_requests_memory_bytes) by (node)
/
sum(kube_node_status_allocatable_memory_bytes) by (node) > 1.0
容量规划的核心指标是集群资源超卖率。内存超卖率(已调度Pod的requests总和/节点可用内存)超过0.8时就应该考虑扩容。CPU超卖率可以到1.5-2.0(因为CPU是可压缩资源),但内存超卖率超过1.0意味着存在OOM风险。
每月审查一次各命名空间的ResourceQuota使用率,增长趋势明显的业务提前沟通扩容需求。容量规划做到前头,才能避免凌晨三点被驱逐告警叫醒。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/kubernetespod-qu-zhu-wen-ti-zhen-duan-yu-zi-yuan-pei-e-gui/