如何将一个节点设置为不可调度(Cordon)?如何驱逐节点上的 Pod(Drain)?
在 Kubernetes 中,对节点进行维护(如升级内核、硬件维修)时,通常需要两个步骤:首先停止向该节点调度新 Pod(Cordon),然后安全地将现有 Pod 迁移走(Drain)。
以下是具体的操作命令和详细说明:
1. 将节点设置为不可调度 (Cordon)
作用:标记该节点为 Unschedulable。Kubernetes 调度器将不再把新的 Pod 分配到该节点上,但节点上现有的 Pod 不受影响,继续正常运行。
命令:
bash
kubectl cordon <节点名称>
验证:
执行 kubectl get nodes,你会看到该节点的状态包含 SchedulingDisabled。
bash
NAME STATUS ROLES AGE VERSION
node-01 Ready,SchedulingDisabled <none> 30d v1.26.0
2. 驱逐节点上的 Pod (Drain)
作用:安全地驱逐节点上的 Pod。
- 它会自动先执行
cordon命令。 - 它会删除节点上的 Pod(静态 Pod 和 DaemonSet 除外),并让控制器(如 Deployment)在集群中的其他可用节点上重新创建这些 Pod。
- 它会遵守
PodDisruptionBudget(PDB) 策略,确保服务高可用。
基本命令:
bash
kubectl drain <节点名称>
常用参数(重要):
在实际生产环境中,直接运行 drain 通常会报错,因为节点上可能包含 DaemonSet 或使用本地存储的 Pod。通常需要加上以下参数:
--ignore-daemonsets:忽略 DaemonSet 管理的 Pod(如 kube-proxy, CNI 插件)。如果不加此参数,drain 会失败,因为 DaemonSet 会立即在同节点重建 Pod。--delete-emptydir-data:如果 Pod 使用了emptyDir(本地临时存储),驱逐会导致数据丢失。必须显式添加此参数确认你接受删除本地数据。--force:强制驱逐不由控制器(Deployment, ReplicaSet, Job 等)管理的“裸 Pod”。
推荐的生产环境组合命令:
bash
kubectl drain <节点名称> --ignore-daemonsets --delete-emptydir-data
3. 恢复节点 (Uncordon)
作用:当维护结束,节点重新上线后,需要解除不可调度状态,允许新的 Pod 调度上来。
命令:
bash
kubectl uncordon <节点名称>
总结与对比
| 操作 | 命令 (kubectl) |
对新 Pod 的影响 | 对现有 Pod 的影响 | 适用场景 |
|---|---|---|---|---|
| Cordon | cordon <node> |
禁止调度 | 无影响 (继续运行) | 排查问题,准备下线但暂不迁移业务 |
| Drain | drain <node> |
禁止调度 | 驱逐/删除 (在别处重建) | 节点维护、升级、下架节点 |
| Uncordon | uncordon <node> |
允许调度 | 无影响 | 维护结束,节点恢复正常 |
典型维护流程
kubectl cordon node-1(可选,drain 会自动做,但先 cordon 更稳妥)kubectl drain node-1 --ignore-daemonsets --delete-emptydir-data- [进行物理维护/重启/升级]
kubectl uncordon node-1