简介
在生产环境的 Kubernetes 集群中,节点经常需要维护。关键是完成维护的同时,避免对工作负载造成不必要的中断。
你可以把节点想象成一间酒店客房,把 Pod 想象成住客。如果你需要翻修房间(执行维护),就不能在住客熟睡时直接闯进去。你需要遵循礼貌且安全的流程。
在本实验中,你将学习节点维护的标准流程:
- Cordon(请勿打扰):在房门上挂出「不再接待新住客」的牌子。酒店(调度器)会停止把新住客安排到这个房间。
- Drain(驱逐):礼貌地请现有住客离开,并将他们安排到其他可用房间。
- 维护:执行必要的工作(翻修)。
- Uncordon(重新开放):移除牌子,重新允许调度。
你将在本地 Minikube 集群中模拟这一过程。
将节点设置为不可调度
执行维护前,必须确保 Kubernetes 调度器不会将任何新 Pod 放置到即将维护的节点上。这个过程称为「cordon」,类似于在酒店房门上挂出「请勿打扰」或「暂停服务」的牌子。
这是调度决策,并不代表关闭节点。设置为 cordon 的节点仍然可以保持健康,并继续运行已有的 Pod。Kubernetes 只是将它标记为不接受新的 Pod,以便你能够有序地开始维护。
首先,确认节点名称。运行以下命令:
kubectl get nodes
你应该会看到一个节点(例如 minikube),其状态为 Ready。
要将节点标记为不可调度,请使用 cordon 命令。下面使用命令替换 $() 自动获取节点名称:
kubectl cordon $(kubectl get nodes -o jsonpath='{.items[0].metadata.name}')
再次检查节点状态:
kubectl get nodes
状态应该变为 Ready,SchedulingDisabled。这表示节点已经设置为 cordon。新的 Pod 不会被调度到这里,但已有的 Pod 仍会继续运行。
驱逐节点上的工作负载
Cordon 只会阻止调度新的 Pod。房间中仍有正在运行的应用程序(住客)。要安全地移除它们,请使用 drain 命令。
该命令会驱逐 Pod。随后,Kubernetes 会发现期望的副本数(2 个)没有满足,并尝试在其他可用节点上创建新的 Pod 作为替代。
这里的 evict(驱逐) 非常重要。Drain 并不是强制终止 Pod,而是以 Kubernetes 能够识别的方式请求工作负载离开,以便控制器替换它们,并遵守终止规则。因此,使用 drain 比手动删除节点上的随机进程更安全。
执行 drain 命令。在当前环境中,需要添加几个选项来强制执行驱逐:
--ignore-daemonsets:某些系统 Pod(DaemonSet)固定在节点上,无法移动。使用此选项忽略它们。--delete-emptydir-data:如果 Pod 使用本地临时存储,drain 会删除这些数据。此选项表示你已确认这一行为。--force:如果 Pod 不由 ReplicationController、ReplicaSet、Job、DaemonSet 或 StatefulSet 管理,则必须使用此选项才能删除。例如 Minikube 中的storage-provisioner就属于这种情况。
kubectl drain $(kubectl get nodes -o jsonpath='{.items[0].metadata.name}') --ignore-daemonsets --delete-emptydir-data --force
你会看到表示 Pod 正在被驱逐的输出。
注意:在这个单节点 Minikube 实验中,drain 的是唯一节点,因此 Pod 会被驱逐,但随后会变为 Pending。这是因为「酒店里没有其他房间」可供它们迁移。在真实的多节点集群中,它们会立即迁移到健康的节点。
验证状态
节点完成 drain 后,必须检查应用程序的状态变化。
这一步体现了集群管理中的一个重要习惯:执行维护命令后不要立即结束。始终从工作负载的角度检查调度结果。只有当应用程序被调度到预期位置时,维护操作才算成功。
检查 Pod 的状态:
kubectl get pods
如前所述,你很可能会看到 Pod 处于 Pending 状态。
要了解 Pod 为什么处于 Pending 状态,请让 Kubernetes 给出详细信息。描述其中一个 Pod:
kubectl describe pod $(kubectl get pods -o jsonpath='{.items[0].metadata.name}')
查看输出底部的 Events 部分。你应该会看到类似以下内容的消息:「0/1 nodes are available: 1 node(s) are unschedulable.」
这表示 drain 已成功。调度器希望运行该 Pod,但它遵守了我们在唯一可用节点上设置的「请勿打扰」标记。
恢复节点调度
现在假设你已经完成了「翻修」(操作系统升级或维护)。接下来需要重新开放房间,让节点恢复服务。
uncordon 只会移除调度限制,不会立即强制将 Pod 放置到该节点上。它会告诉调度器:该节点再次具备接受新工作负载的资格。之后,调度器会按照正常的协调流程处理 Pod。
使用 uncordon 命令移除「请勿打扰」标记:
kubectl uncordon $(kubectl get nodes -o jsonpath='{.items[0].metadata.name}')
现在,检查节点状态:
kubectl get nodes
状态应该恢复为 Ready,并且不再显示 SchedulingDisabled 标记。
最后,再次检查 Pod。由于节点已经重新开放,Kubernetes 调度器现在应该会将处于 Pending 状态的 Pod 放回该节点。
kubectl get pods
你应该会看到这些 Pod 依次从 Pending 变为 ContainerCreating,最后变为 Running。
总结
在本实验中,你练习了 Kubernetes 节点维护的安全生命周期。你学习了如何:
- Cordon 节点,将其标记为不可调度(请勿打扰)。
- Drain 节点,安全地驱逐正在运行的工作负载。
- Uncordon 节点,使其恢复服务。
对于系统管理员来说,这些命令对于确保高可用至关重要。它们可以帮助你修复基础设施,同时避免应用程序停机(当然,这需要使用多节点集群!)。


