这篇文章发表时间超过一年。较旧的文章可能包含过时内容。请检查页面中的信息自发布以来是否仍然准确。

Kubernetes 1.24: 引入非优雅节点关机 Alpha 功能

Kubernetes v1.24 引入了针对非正常节点关闭的 Alpha 支持。该功能允许有状态工作负载在原始节点关闭或处于不可恢复状态(如硬件故障或操作系统损坏)后故障转移到另一个节点。

这与正常节点关闭有何不同

你可能听说过 Kubernetes 的正常节点关闭功能,并且想知道非正常节点关闭功能与它的区别。正常节点关闭允许 Kubernetes 检测节点何时正在正常关闭,并适当地处理这种情况。只有当 kubelet 在实际关闭之前能够检测到节点关闭操作时,节点关闭才能称为“正常”。然而,在某些情况下,节点关闭操作可能无法被 kubelet 检测到。这可能是因为关机命令没有触发 kubelet 依赖的 systemd 抑制锁机制,或者是因为配置错误(ShutdownGracePeriodShutdownGracePeriodCriticalPods 未正确配置)。

正常节点关闭依赖于 Linux 特有的支持。kubelet 不会监视 Windows 节点上即将发生的关机(这可能会在未来的 Kubernetes 版本中改变)。

当节点关闭但未被 kubelet 检测到时,该节点上的 Pod 也会非正常关闭。对于无状态应用,这通常不是问题(一旦集群检测到受影响的节点或 Pod 出现故障,ReplicaSet 会添加一个新的 Pod)。对于有状态应用,情况就复杂得多。如果你使用 StatefulSet,并且 StatefulSet 中的某个 Pod 位于一个非正常失败的节点上,那么受影响的 Pod 将被标记为 Terminating;StatefulSet 无法创建一个替代 Pod,因为该 Pod 仍然存在于集群中。因此,运行在 StatefulSet 上的应用可能会降级甚至离线。如果原始的、已关闭的节点重新启动,该原始节点上的 kubelet 会报告状态,删除现有的 Pod,控制平面会在另一个正在运行的节点上为该 StatefulSet 创建一个替代 Pod。如果原始节点已失败且无法启动,这些有状态 Pod 将无限期地停留在该失败节点上的 Terminating 状态。

$ kubectl get pod -o wide
NAME    READY   STATUS        RESTARTS   AGE   IP           NODE                      NOMINATED NODE   READINESS GATES
web-0   1/1     Running       0          100m   10.244.2.4   k8s-node-876-1639279816   <none>           <none>
web-1   1/1     Terminating   0          100m   10.244.1.3   k8s-node-433-1639279804   <none>           <none>

试用新的非正常关机处理功能

要使用非正常节点关机处理功能,必须为 kube-controller-manager 组件启用 NodeOutOfServiceVolumeDetach Feature Gate

在节点关机的情况下,你可以手动标记该节点为 out of service。在添加该污点 (taint) 之前,应确保节点确实已关闭(而非正在重启中)。你可以在 kubelet 未能提前检测和处理的关机发生后添加该污点;另一种可以使用该污点的情况是节点因硬件故障或操作系统损坏而处于不可恢复状态。为该污点设置的值可以是 node.kubernetes.io/out-of-service=nodeshutdown: "NoExecute"node.kubernetes.io/out-of-service=nodeshutdown:" NoSchedule"。如果在之前启用了所述的 Feature Gate,那么在节点上设置 out-of-service 污点意味着该节点上的 Pod 将被删除,除非 Pod 上存在匹配的容忍度 (tolerations)。连接到已关机节点的持久卷将被分离,对于 StatefulSet,将在另一个正在运行的节点上成功创建替代 Pod。

$ kubectl taint nodes <node-name> node.kubernetes.io/out-of-service=nodeshutdown:NoExecute

$ kubectl get pod -o wide
NAME    READY   STATUS    RESTARTS   AGE    IP           NODE                      NOMINATED NODE   READINESS GATES
web-0   1/1     Running   0          150m   10.244.2.4   k8s-node-876-1639279816   <none>           <none>
web-1   1/1     Running   0          10m    10.244.1.7   k8s-node-433-1639279804   <none>           <none>

注意:在应用 out-of-service 污点之前,你必须验证节点是否已处于关机或断电状态(而非正在重启中),无论是用户有意关闭还是节点因硬件故障、操作系统问题等原因而宕机。

一旦所有关联到 out-of-service 节点的工作负载 Pod 都已转移到新的运行节点,并且已关闭的节点已恢复,应在该节点恢复后移除其上的污点。如果你知道该节点不会恢复服务,则可以直接从集群中删除该节点。

接下来的计划?

根据反馈和采用情况,Kubernetes 团队计划在 1.25 或 1.26 版本中将非正常节点关闭的实现升级到 Beta。

此功能需要用户手动向节点添加污点以触发工作负载故障转移,并在节点恢复后移除污点。未来,我们计划寻找方法自动检测并隔离已关闭/失败的节点,并自动将工作负载故障转移到另一个节点。

我如何了解更多信息?

请查阅关于非正常节点关闭的文档

如何参与进来?

这个特性有着漫长的故事。Yassine Tijani (yastij) 在两年多前启动了 KEP。邢洋 (xing-yang) 继续推动这项工作。SIG Storage、SIG Node 和 API 评审者之间进行了多次讨论,以确定设计细节。Ashutosh Kumar (sonasingh46) 完成了大部分实现,并在 Kubernetes 1.24 中将其带入了 Alpha 阶段。

我们感谢以下人员的富有洞察力的评审:Tim Hockin (thockin) 对设计的指导,以及 Jing Xu (jingxu97)、Hemant Kumar (gnufied) 和 Michelle Au (msau42) 来自 SIG Storage 的评审,以及 Mrunal Patel (mrunalp)、David Porter (bobbypage)、Derek Carr (derekwaynecarr) 和 Danielle Endocrimes (endocrimes) 来自 SIG Node 的评审。

过程中有许多人帮助评审了设计和实现。我们感谢所有为这项工作做出贡献的人,包括过去几年评审了 KEP 和实现的约 30 位人员。

此特性是 SIG Storage 和 SIG Node 之间的协作成果。对于有兴趣参与 Kubernetes 存储系统任何部分的设计和开发的人员,请加入Kubernetes Storage 特别兴趣小组 (SIG)。对于有兴趣参与支持 Pod 和宿主机资源之间受控交互的组件设计和开发的人员,请加入Kubernetes Node SIG