将 Kubernetes 节点进入维护模式是一项非常常见的运维操作,其目的是为了安全地对节点进行维护(如升级内核、更换硬件等),同时确保运行在其上的工作负载能够平滑地迁移到其他节点,服务不中断。
这个操作的核心是使用 kubectl drain 命令。
什么是维护模式?
当节点进入维护模式时,会发生以下事情:
- 被标记为不可调度:Kubernetes 调度器会停止向该节点分配任何新的 Pod。
- 驱逐现有 Pod:该节点上正在运行的 Pod 会被安全地终止。
- Pod 重建:如果这些 Pod 是由
Deployment,StatefulSet等控制器管理的,控制器会在其他健康的节点上重新创建它们。 - 服务不中断:通过
readinessProbe和Service机制,在旧 Pod 终止前,新 Pod 会启动并准备就绪,从而实现流量的平滑切换。
操作步骤:如何进入和退出维护模式
假设你要维护的节点名为 worker-node-01。
第 1 步:将节点标记为不可调度并驱逐 Pod
这是进入维护模式的核心命令。
kubectl drain <node-name> --ignore-daemonsets --delete-emptydir-data
参数解释:
kubectl drain <node-name>:这是主命令,它会执行标记不可调度和驱逐的操作。--ignore-daemonsets:这是一个非常重要的参数。DaemonSet管理的 Pod(如网络插件calico-node、存储插件csi-node等)通常需要运行在每个节点上,包括正在维护的节点。这个参数告诉kubectl不要驱逐这些 Pod。--delete-emptydir-data:如果有些 Pod 使用了emptyDir类型的卷,drain默认不会驱逐它们,因为emptyDir的数据会随着 Pod 的删除而丢失。加上这个参数,表示你确认可以丢弃这些数据,并允许drain删除这些 Pod。
示例:
kubectl drain worker-node-01 --ignore-daemonsets --delete-emptydir-data
执行后,你会看到该节点上的 Pod 逐一被终止,并在其他节点上重新创建。
第 2 步:执行维护操作
此时,节点已经处于“干净”状态(除了 DaemonSet Pod),你可以安全地:
- SSH 登录到该节点。
- 执行系统更新、重启、软件安装等任何维护操作。
第 3 步:维护完成后,将节点重新上线
维护操作完成后,你需要将节点重新加入集群调度。
kubectl uncordon <node-name>
示例:
kubectl uncordon worker-node-01
执行后,该节点的状态会从 SchedulingDisabled 变回 Ready,调度器就可以开始向它分配新的 Pod 了。
完整的运维流程示例
# 1. 查看节点状态
kubectl get nodes
# 2. 对 worker-node-01 执行 drain,进入维护模式
kubectl drain worker-node-01 --ignore-daemonsets --delete-emptydir-data
# 3. 确认节点状态变为 SchedulingDisabled
kubectl get nodes
# 4. 登录节点,执行维护(例如重启)
ssh ubuntu@worker-node-01
sudo reboot
# 5. 等待节点重启并恢复网络连接,确认 kubelet 服务正常
kubectl get nodes
# 你会看到节点状态先是 NotReady,然后恢复为 Ready,但 SchedulingDisabled 依然存在
# 6. 维护完成,将节点重新上线,退出维护模式
kubectl uncordon worker-node-01
# 7. 再次确认节点状态
kubectl get nodes
# 此时,节点状态应该为 Ready,并且没有 SchedulingDisabled 的污点
重要提示和故障排查
-
如果
drain卡住怎么办?
drain可能会因为某个 Pod 无法正常终止而卡住。你可以使用--force标志来强制驱逐,但这可能导致服务中断,应谨慎使用。kubectl drain <node-name> --ignore-daemonsets --delete-emptydir-data --force -
如果节点永久下线怎么办?
如果你打算永久移除这个节点,在drain之后,还需要执行kubectl delete node来从集群的 API Server 中彻底删除它。kubectl drain <node-name> --ignore-daemonsets --delete-emptydir-data --force kubectl delete node <node-name> -
cordon和drain的区别kubectl cordon <node-name>:只将节点标记为不可调度,但不会驱逐现有的 Pod。kubectl drain <node-name>:既会标记为不可调度,也会驱逐现有 Pod。drain实际上包含了cordon的动作。
通过正确地使用 drain 和 uncordon,你可以安全、平滑地对 Kubernetes 集群进行节点维护。
2622

被折叠的 条评论
为什么被折叠?



