1.0 为什么要安全驱逐Pod?

就像搬家前要把家具打包好再搬运一样,在Kubernetes中下线节点时,必须确保容器应用平稳迁移。直接关闭节点就像突然抽掉承重墙——正在运行的容器会被强制终止,可能引发数据丢失或服务中断。本周我在处理生产环境的GPU节点升级时,就经历了完整的节点维护流程。


2.0 标准驱逐流程的技术原理

2.1 驱逐与删除的本质区别

kubectl delete node gpu-node-01

# 正确操作:排空节点资源(会触发优雅终止流程)
kubectl drain gpu-node-01 --ignore-daemonsets --delete-emptydir-data

注释:通过对比可以看到,drain命令比直接删除多了前置准备阶段,给Pod申请者响应终止信号的时间

2.2 驱逐触发的事件链条

  1. API Server将节点标记为不可调度
  2. kubelet发送TERM信号给容器进程
  3. 等待terminationGracePeriodSeconds(默认30秒)
  4. 强制终止未响应的进程

3.0 全流程操作演练(基于Kubernetes 1.26版本)

3.1 预检清单实施

# 检查待下线节点状态
kubectl get node gpu-node-01 -o wide
kubectl describe node gpu-node-01 | grep -i taint

# 定位需特殊处理的Pod
kubectl get pods -o wide --field-selector spec.nodeName=gpu-node-01

注释:这组命令帮助我们快速确认节点是否已打污点,以及要处理的Pod总数

3.2 实战驱逐命令分解

# 完整驱逐命令(含详细参数说明)
kubectl drain gpu-node-01 \
  --force \
  --ignore-daemonsets \
  --delete-emptydir-data \
  --timeout=120s \
  --pod-selector='app notin (system-critical)'

注释解析:

  • --force:突破PDB限制(慎用)
  • --ignore-daemonsets:允许驱逐守护进程Pod
  • --delete-emptydir-data:清理临时卷
  • --pod-selector:选择性驱逐特定标签Pod

4.0 防御性编程:利用PDB保平安

4.1 创建预算策略模板

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: web-server-pdb
spec:
  minAvailable: 2  # 任何时候至少保留2个实例
  selector:
    matchLabels:
      app: web-server

4.2 预算策略冲突处理

当驱逐请求导致PDB被突破时,会出现如下典型报错:

Cannot evict pod because it would violate the pod's disruption budget

此时需要评估是否调整PDB阈值或协调业务窗口期。


5.0 维护后的关键操作

5.1 节点回池验证步骤

# 解除节点不可调度状态
kubectl uncordon gpu-node-01

# 确认节点健康状况
kubectl get node gpu-node-01 -o jsonpath='{.status.conditions[?(@.type=="Ready")].status}'

5.2 自动回迁策略配置

结合反亲和性策略实现Pod均衡分布:

affinity:
  nodeAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: NotIn
          values: [gpu-node-01]

6.0 应用场景深度分析

6.1 典型维护场景

  • 硬件升级:当需要更换物理机SSD时
  • 内核更新:涉及kubelet版本升级时
  • 资源回收:缩容集群前的节点腾空
  • 故障隔离:发生硬件故障后的紧急下线

6.2 特殊场景处理技巧

对于有状态服务(如数据库)的处置方案:

# 分批次手动驱逐
for pod in $(kubectl get pods -l app=mysql -o name); do
  kubectl delete $pod --wait=false
  sleep 60  # 等待主从同步完成
done

7.0 技术方案优劣势对比

方法 优点 缺点
直接关机 操作快速 可能导致数据损坏
kubectl drain 完整的生命周期管理 复杂参数需要理解
手动删除Pod 精确控制过程 易遗漏隐藏依赖
第三方工具(如cluster-autoscaler) 自动化程度高 需要额外部署和配置

8.0 血泪教训:五大避坑指南

  1. 临时存储卷陷阱:使用emptyDir的Pod需要确认数据已持久化
  2. 优雅终止期超时:Java应用可能需要调整terminationGracePeriodSeconds
  3. 守护进程死角:KubeProxy等系统组件要特殊处理
  4. 标签选择器遗漏:未正确过滤会导致关键服务被驱逐
  5. 节点状态回滚:uncordon后需验证kubelet服务状态