本文发表于一年多前。旧文章可能包含过时内容。请检查页面中的信息自发布以来是否已变得不正确。
Kubernetes 1.24:介绍非平滑节点关闭 Alpha
Kubernetes v1.24 引入了对非体面节点关闭的 Alpha 支持。此功能允许有状态工作负载在原始节点关闭或处于不可恢复状态(例如硬件故障或操作系统损坏)后,故障转移到另一个节点。
这与体面节点关闭有何不同
你可能听说过 Kubernetes 的体面节点关闭功能,并且想知道非体面节点关闭功能与它有何不同。体面节点关闭允许 Kubernetes 检测到节点何时被干净地关闭,并适当地处理这种情况。节点关闭只有在 kubelet 能够在实际关闭之前检测到节点关闭操作时,才能是“体面”的。然而,在某些情况下,节点关闭操作可能无法被 kubelet 检测到。这可能是因为关闭命令没有触发 kubelet 所依赖的 systemd 抑制锁机制,或者是因为配置错误(ShutdownGracePeriod
和 ShutdownGracePeriodCriticalPods
未正确配置)。
体面节点关闭依赖于 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
特性门控。
在节点关闭的情况下,你可以手动将该节点标记为停止服务。在添加该污点之前,你应该确保该节点确实已经关闭(而不是正在重启中)。你可以在 kubelet 未能提前检测和处理的关闭之后添加该污点;另一个可以使用该污点的情况是节点由于硬件故障或操作系统损坏而处于不可恢复状态。你可以为该污点设置的值是 node.kubernetes.io/out-of-service=nodeshutdown:"NoExecute"
或 node.kubernetes.io/out-of-service=nodeshutdown:"NoSchedule"
。只要你启用了前面提到的特性门控,在节点上设置停止服务污点意味着该节点上的 Pod 将被删除,除非 Pod 上有匹配的容忍度。附加到已关闭节点的持久卷将被分离,对于 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>
注意:在应用停止服务污点之前,你必须验证一个节点已经处于关闭或断电状态(而不是正在重启中),这可能是因为用户有意关闭它,或者节点由于硬件故障、操作系统问题等而宕机。
一旦与停止服务节点相关的所有工作负载 Pod 都移动到了一个新的正在运行的节点上,并且关闭的节点已经恢复,你应该在节点恢复后移除受影响节点上的那个污点。如果你知道该节点不会再恢复服务,你可以从集群中删除该节点。
下一步是什么?
根据反馈和采用情况,Kubernetes 团队计划在 1.25 或 1.26 版本中将非体面节点关闭的实现推向 Beta 阶段。
此功能需要用户手动向节点添加污点以触发工作负载故障转移,并在节点恢复后移除该污点。未来,我们计划寻找方法来自动检测和隔离已关闭/故障的节点,并自动将工作负载故障转移到另一个节点。
我如何了解更多信息?
请查看非体面节点关闭的文档。
如何参与?
这个特性有着悠久的历史。Yassine Tijani (yastij) 在两年多前开始了 KEP 的工作。Xing Yang (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 存储特别兴趣小组 (SIG)。对于有兴趣参与支持 Pod 和主机资源之间受控交互的组件的设计和开发的人,请加入 Kubernetes Node SIG。