安全地排空节点
此页面展示了如何安全地清空一个 节点,可以选择性地遵守您定义的 PodDisruptionBudget。
开始之前
此任务假设您已满足以下先决条件
- 您不需要在节点清空期间应用程序具有高可用性,或者
- 您已经阅读了有关 PodDisruptionBudget 概念,并且已经 为需要它们的应用程序配置了 PodDisruptionBudgets。
(可选) 配置中断预算
为了确保您的工作负载在维护期间保持可用,您可以配置 PodDisruptionBudget。
如果可用性对于您正在清空的节点上运行或可能运行的任何应用程序很重要,请先 配置 PodDisruptionBudgets,然后继续按照本指南操作。
建议将 AlwaysAllow
不健康 Pod 驱逐策略 设置为您的 PodDisruptionBudgets,以支持在节点清空期间驱逐行为不端的应用程序。默认行为是等待应用程序 Pod 变得 健康 才能继续清空。
使用 kubectl drain
从服务中移除节点
您可以使用 kubectl drain
在对节点执行维护操作(例如内核升级、硬件维护等)之前安全地将所有 Pod 从节点中驱逐出去。安全驱逐允许 Pod 的容器 优雅地终止,并将尊重您指定的 PodDisruptionBudgets。
当 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
命令。多个并行运行的 drain 命令仍然会尊重您指定的 PodDisruptionBudget。
例如,如果您有一个具有三个副本的 StatefulSet,并且为该集合设置了一个 PodDisruptionBudget,该预算指定 minAvailable: 2
,kubectl drain
只有在所有三个副本 Pod 都 健康 时才会从 StatefulSet 中驱逐一个 Pod;如果您随后并行发出多个 drain 命令,Kubernetes 会尊重 PodDisruptionBudget 并确保在任何给定时间只有一个(计算为 replicas - minAvailable
)Pod 不可用。任何会导致 健康 副本数量低于指定预算的 drain 都会被阻止。
驱逐 API
如果您不想使用 kubectl drain(例如,为了避免调用外部命令,或者为了更精细地控制 Pod 驱逐过程),您也可以使用驱逐 API 以编程方式导致驱逐。
有关更多信息,请参阅 API 发起的驱逐。
下一步
- 按照步骤通过 配置 Pod Disruption Budget 来保护您的应用程序。