安全地排空节点
本页面展示如何安全排空节点,并可选地遵循你所定义的 PodDisruptionBudget。
准备工作
本任务假设你已满足以下先决条件:
- 在节点排空期间,你的应用程序不需要高可用性,或者
- 你已阅读了 PodDisruptionBudget 概念,并已为需要它们的应用程序配置了 PodDisruptionBudget。
(可选)配置中断预算
为了确保你的工作负载在维护期间仍然可用,你可以配置 PodDisruptionBudget。
如果可用性对你正在排空或可能在这些节点上运行的任何应用程序都很重要,请首先配置 PodDisruptionBudget,然后继续遵循本指南。
建议将 AlwaysAllow
非健康 Pod 驱逐策略 设置到你的 PodDisruptionBudget 中,以支持在节点排空期间驱逐行为异常的应用程序。默认行为是等待应用程序 Pod 变为健康,然后才能进行排空。
使用 kubectl drain
将节点从服务中移除
你可以在对节点执行维护(例如内核升级、硬件维护等)之前,使用 kubectl drain
安全地从节点中驱逐所有 Pod。安全驱逐允许 Pod 的容器优雅终止,并将遵循你所指定的 PodDisruptionBudget。
当 kubectl drain
成功返回时,这表示所有 Pod(除了上一段中描述的被排除的 Pod)都已安全驱逐(遵循所需的优雅终止期,并遵循你所定义的 PodDisruptionBudget)。然后,通过关闭其物理机电源或(如果在云平台上运行)删除其虚拟机来关闭节点是安全的。
注意
如果任何新的 Pod 容忍 node.kubernetes.io/unschedulable
污点,那么这些 Pod 可能会被调度到你已排空的节点。除了 DaemonSet 之外,避免容忍该污点。
如果你或另一个 API 用户直接为 Pod 设置了 nodeName
字段(绕过调度器),那么 Pod 将绑定到指定的节点并在那里运行,即使你已排空该节点并将其标记为不可调度。
首先,确定你希望排空的节点的名称。你可以使用以下命令列出集群中的所有节点:
kubectl get nodes
接下来,告诉 Kubernetes 排空节点
kubectl drain --ignore-daemonsets <node name>
如果存在由 DaemonSet 管理的 Pod,你将需要使用 kubectl
指定 --ignore-daemonsets
以成功排空节点。kubectl drain
子命令本身并不会实际排空节点的 DaemonSet Pod:DaemonSet 控制器(控制平面的一部分)会立即用新的等效 Pod 替换丢失的 Pod。DaemonSet 控制器还会创建忽略不可调度污点的 Pod,这使得新的 Pod 能够在你正在排空的节点上启动。
一旦它返回(没有报错),你就可以关闭节点(或者等效地,如果是在云平台上,删除支持该节点的虚拟机)。如果你在维护操作期间将节点留在集群中,你需要运行
kubectl uncordon <node name>
之后,通知 Kubernetes 它可以恢复将新的 Pod 调度到该节点。
并行排空多个节点
kubectl drain
命令一次只能对一个节点发出。但是,你可以并行地在不同的终端或后台为不同的节点运行多个 kubectl drain
命令。多个并发运行的排空命令仍将遵循你指定的 PodDisruptionBudget。
例如,如果你有一个包含三个副本的 StatefulSet,并为该集合设置了 minAvailable: 2
的 PodDisruptionBudget,则仅当所有三个副本 Pod 都健康时,kubectl drain
才会从 StatefulSet 中驱逐 Pod;如果然后你并行发出多个排空命令,Kubernetes 会遵循 PodDisruptionBudget,并确保在任何给定时间只有一个(计算为 replicas - minAvailable
)Pod 不可用。任何会导致健康副本数量低于指定预算的排空都将被阻止。
驱逐 API
如果你不想使用 kubectl drain(例如为了避免调用外部命令,或者为了更精细地控制 Pod 驱逐过程),你也可以使用驱逐 API 以编程方式进行驱逐。
有关更多信息,请参阅 API 发起的驱逐。
下一步
- 通过配置 Pod Disruption Budget 来保护你的应用程序。