Kubernetes Pod驱逐机制详解
Kubernetes集群中的Pod驱逐(Eviction)由kubelet在节点资源不足时触发,是保障节点稳定性的核心机制。当节点内存、磁盘等资源耗尽时,kubelet按照预定义优先级主动终止Pod,避免节点进入不可用状态。理解驱逐触发条件、优先级排序和参数调优,对维护生产环境SRE稳定性工程至关重要。
驱逐信号与触发条件
kubelet监控以下节点级资源信号:memory.available、nodefs.available、nodefs.inodesFree、imagefs.available、imagefs.inodesFree。当任一信号低于对应阈值时,kubelet启动驱逐流程。
默认硬驱逐阈值:
# 默认硬驱逐阈值(不可配置,已内置于kubelet)
memory.available < 100Mi
nodefs.available < 10%
nodefs.inodesFree < 5%
imagefs.available < 15%
硬驱逐阈值触发后,kubelet立即开始终止Pod,不等待优雅终止期。软驱逐阈值可自定义,支持宽限期配置:
# kubelet配置 - /var/lib/kubelet/config.yaml
evictionHard:
memory.available: "500Mi"
nodefs.available: "10%"
nodefs.inodesFree: "5%"
imagefs.available: "15%"
evictionSoft:
memory.available: "750Mi"
nodefs.available: "15%"
evictionSoftGracePeriod:
memory.available: "1m30s"
nodefs.available: "2m0s"
evictionMaxPodGracePeriod: 30
软驱逐阈值触发后,kubelet等待宽限期(如1分30秒),若资源压力未缓解再执行驱逐。这套分级机制为短暂资源峰值预留了缓冲空间。
Pod驱逐优先级排序规则
kubelet按以下维度对Pod排序,优先驱逐排名靠前的Pod:
- 服务质量等级(QoS):BestEffort > Burstable > Guaranteed(优先驱逐BestEffort)
- 优先级类(PriorityClass):低优先级优先驱逐
- 资源使用率:超出request请求比例最高的优先驱逐
QoS等级由Pod的resources字段自动判定。三个容器全部设置requests且requests等于limits时,Pod为Guaranteed;至少一个容器未设置resources请求为BestEffort;其余均为Burstable。
# Guaranteed QoS - 最高保障
apiVersion: v1
kind: Pod
metadata:
name: Guaranteed-pod
spec:
containers:
- name: app
image: nginx
resources:
requests:
cpu: "500m"
memory: "512Mi"
limits:
cpu: "500m"
memory: "512Mi"
---
# BestEffort QoS - 最先被驱逐
apiVersion: v1
kind: Pod
metadata:
name: besteoffort-pod
spec:
containers:
- name: app
image: nginx
# 未设置resources
生产环境核心服务应配置Guaranteed QoS并绑定高PriorityClass,确保资源紧张时不会被优先驱逐。
节点压力状态与污点机制
驱逐触发后,节点会被打上对应污点(Taint),阻止新Pod调度到该节点。kubelet根据驱逐信号设置不同状态的污点:
| 节点状态 | 污点Key | 触发条件 |
|---|---|---|
| MemoryPressure | node.kubernetes.io/memory-pressure | memory.available低于阈值 |
| DiskPressure | node.kubernetes.io/disk-pressure | nodefs或imagefs低于阈值 |
| PIDPressure | node.kubernetes.io/pid-pressure | 进程数过多 |
| NetworkUnavailable | node.kubernetes.io/network-unavailable | 网络配置异常 |
查看节点污点状态:
# 查看节点Conditions和Taints
kubectl describe node worker-01
# 精确查看污点
kubectl get nodes -o custom-columns=NAME:.metadata.name,TAINTS:.spec.taints
# 查看节点Conditions
kubectl get nodes -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.conditions[-1].type}{"\t"}{.status.conditions[-1].status}{"\n"}{end}'
DaemonSet类型的Pod通常配置污点容忍(Toleration),确保在节点压力状态下仍能运行。日志采集Agent和监控Agent属于此类:
tolerations:
- key: node.kubernetes.io/memory-pressure
operator: Exists
effect: NoSchedule
- key: node.kubernetes.io/disk-pressure
operator: Exists
effect: NoSchedule
优雅终止与数据保护
Pod被驱逐时,kubelet按以下顺序执行终止流程:发送SIGTERM信号 → 等待terminationGracePeriodSeconds(默认30秒)→ 发送SIGKILL强制终止。应用需正确处理SIGTERM信号,完成数据持久化和连接关闭。
# Pod终止流程处理示例(Python)
import signal
import sys
import time
import threading
shutdown_event = threading.Event()
def handle_sigterm(signum, frame):
print("收到SIGTERM信号,开始优雅关闭")
shutdown_event.set()
signal.signal(signal.SIGTERM, handle_sigterm)
# 主循环
while not shutdown_event.is_set():
# 处理业务逻辑
time.sleep(1)
# 清理逻辑:关闭数据库连接、刷写缓存、完成进行中的请求
print("正在关闭数据库连接...")
db_pool.close()
print("正在刷写缓存...")
cache.flush()
print("优雅关闭完成")
sys.exit(0)
terminationGracePeriodSeconds需根据应用实际关闭时间调整:
spec:
terminationGracePeriodSeconds: 60 # 给予60秒优雅关闭时间
containers:
- name: app
image: myapp:v1.0
lifecycle:
preStop:
exec:
command: ["/bin/sh", "-c", "sleep 15 && nginx -s quit"]
preStop hook在SIGTERM之前执行,sleep 15秒缓冲让Service的iptables规则完成更新,避免终止过程中的流量打到即将关闭的Pod。
PDB与滚动更新保护
PodDisruptionBudget(PDB)防止驱逐操作导致过多副本同时不可用。PDB对节点维护、自动缩容等自愿性驱逐生效,对OOMKilled等非自愿驱逐无效。
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: api-server-pdb
spec:
minAvailable: 2 # 至少保持2个副本可用
# 或使用 maxUnavailable: 1
selector:
matchLabels:
app: api-server
minAvailable设为2时,若当前运行3个副本,驱逐操作一次最多终止1个Pod,确保服务连续性。搭配Deployment的滚动更新策略形成双重保障:
spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 0 # 滚动更新时不允许减少可用副本
maxSurge: 1 # 最多额外创建1个新副本
集群级资源监控与预警
主动监控节点资源使用趋势,在驱逐触发前介入处理,是SRE的标准实践。Prometheus + node-exporter可采集节点级资源指标:
# PromQL查询:节点内存可用率低于20%的节点
100 * (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) > 80
# 节点磁盘使用率高于85%
100 * (1 - (node_filesystem_avail_bytes{fstype=~"ext4|xfs"} / node_filesystem_size_bytes{fstype=~"ext4|xfs"})) > 85
# 过去5分钟内发生驱逐的节点
rate(kubelet_evicted_pods_total[5m]) > 0
告警规则建议设置两级阈值:内存可用率低于25%触发预警,低于15%触发紧急告警。磁盘使用率80%预警、90%紧急。配合Grafana看板可视化节点资源趋势,在资源压力到达驱逐阈值前完成扩容或迁移。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/kubernetespod-qu-zhu-ji-zhi-shen-du-jie-xi-qos-deng-ji-yu/