作者:Xing Yang 和 Yassine Tijani(VMware)
Kubernetes v1.24 引入了对非优雅节点关闭[1](Non-Graceful Node Shutdown)的 alpha 支持。此特性允许有状态工作负载,在原节点关闭或处于不可恢复状态(如硬件故障或操作系统损坏)后,故障转移到不同的节点。
你可能听说过 Kubernetes 的优雅节点关闭[2](Graceful Node Shutdown)特性,并且想知道非优雅节点关闭特性与此有何不同。优雅节点关闭允许 Kubernetes 检测节点何时完全关闭,并适当地处理这种情况。只有当 kubelet 在实际关闭之前检测到节点关闭动作时,节点关闭才是“优雅(graceful)”的。但是,在某些情况下,kubelet 可能检测不到节点关闭操作。这可能是因为 shutdown 命令没有触发 kubelet 所依赖的 systemd 抑制锁机制,或者是因为配置错误(ShutdownGracePeriod 和 ShutdownGracePeriodCriticalPods 配置不正确)。
优雅节点关闭依赖于特定于 Linux 的支持。kubelet 不监视 Windows 节点上即将到来的关闭(这在未来的 Kubernetes 版本中可能会有所改变)。
当一个节点被关闭但 kubelet 没有检测到时,该节点上的 pod 也会不优雅地关闭。对于无状态应用程序,这通常不是问题(一旦集群检测到受影响的节点或 pod 出现故障,ReplicaSet 就会添加一个新的 pod)。对于有状态的应用程序,情况更复杂。如果你使用一个 StatefulSet,并且该 StatefulSet 中的一个 pod 在某个节点上发生了非优雅故障,则该受影响的 pod 将被标记为终止(Terminating);StatefulSet 无法创建替换 pod,因为该 pod 仍存在于群集中。因此,在 StatefulSet 上运行的应用程序可能会降级甚至离线。如果关闭的原节点再次出现,该原节点上的 kubelet 会报告,删除现有的 pod,并且控制平面会在不同的运行节点上为该状态集制作一个替换 pod。如果原节点出现故障并且没有恢复,这些有状态的 pod 将无限期地停留在该故障节点上的终止状态。
$ 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特性门[3]。
在节点关闭的情况下,你可以手动将该节点标记污点为停止服务。在添加污点之前,你应该确保节点确实关闭了(不是在重启过程中)。你可以在 kubelet 没有提前检测和处理的关闭之后添加污点;你可以使用污点的另一种情况是,由于硬件故障或操作系统损坏,节点处于不可恢复状态。你为该污点设置的值可以是 node.kubernetes.io/out-of-service=nodeshutdown: "NoExecute"或 node.kubernetes.io/out-of-service=nodeshutdown:" NoSchedule"。假设你已经启用了前面提到的特性门,在节点上设置停止服务污点意味着节点上的 pod 将被删除,除非 pod 上有匹配的容差。连接到关闭节点的持久性卷(Persistent volume)将被分离,对于状态集(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>
注意:在应用停止服务污点之前,你必须验证节点是否已经处于关闭或断电状态(不是在重新启动过程中),这可以是因为用户有意将其关闭,也可以是因为节点由于硬件故障、操作系统问题等而关闭。
一旦链接到停止服务节点的所有工作负载单元都被移动到一个新的正在运行的节点,并且关闭的节点已给恢复,你应该在节点恢复后删除受影响节点上的污点。如果你知道该节点不会恢复服务,你可以从集群中删除该节点。
根据反馈和采用情况,Kubernetes 团队计划在 1.25 或 1.26,把非优雅节点关闭实现进入 Beta。
此特性要求用户手动向节点添加污点,以触发工作负载故障转移,并在节点恢复后删除污点。未来,我们计划寻找自动检测和隔离关闭/故障节点的方法,并将工作负载自动故障转移到另一个节点。
查看非优雅节点关闭的文档[4]。
这个特性有个很长故事。两年多前,Yassine Tijani(yastij)启动了 KEP。Xing Yang(xing-yang)继续推动这项工作。SIG Storage、SIG Node 和 API 评审人员进行了多次讨论,以确定设计细节。Ashutosh Kumar(sonasingh46)完成了大部分实现,并在 Kubernetes 1.24 中将其引进为 Alpha。
我们要感谢以下人员的评审:Ti Hockin(thockin)对设计的指导;来自 Sig Storage 的 Jing Xu(jingxu97),Hemant Kumar(gnufied)和 Michelle Au(msau42);以及来自 Sig Node 的 Mrunal Patel(mrunalp),David Porter(bobbypage),Derek Carr(derekwaynecarr)和 Danielle Endocrimes(Endocrimes)。
一路上有许多人帮助审查了设计和实现。我们要感谢所有为此做出贡献的人,包括在过去几年中审核KEP[5]和实施的大约 30 人。
此特性是 SIG Storage 和 SIG Node 之间的协作。对于那些有兴趣参与 Kubernetes Storage 系统任何部分的设计和开发的人,请加入Kubernetes Storage SIG[6](特别兴趣小组)。对于那些有兴趣参与支持 pod 和主机资源之间受控交互的组件的设计和开发的人,请加入Kubernetes Node SIG[7]。
[1]
非优雅节点关闭: https://github.com/kubernetes/enhancements/tree/master/keps/sig-storage/2268-non-graceful-shutdown
[2]
优雅节点关闭: https://kubernetes.io/docs/concepts/architecture/nodes/#graceful-node-shutdown
[3]
特性门: https://kubernetes.io/docs/reference/command-line-tools-reference/feature-gates/
[4]
文档: https://kubernetes.io/docs/concepts/architecture/nodes/#non-graceful-node-shutdown
[5]
KEP: https://github.com/kubernetes/enhancements/pull/1116
[6]
Kubernetes Storage SIG: https://github.com/kubernetes/community/tree/master/sig-storage
[7]
Kubernetes Node SIG: https://github.com/kubernetes/community/tree/master/sig-node
CNCF (Cloud Native Computing Foundation)成立于2015年12月,隶属于Linux Foundation,是非营利性组织。
CNCF(云原生计算基金会)致力于培育和维护一个厂商中立的开源生态系统,来推广云原生技术。我们通过将最前沿的模式民主化,让这些创新为大众所用。