本文发表于一年多前。旧文章可能包含过时内容。请检查页面中的信息自发布以来是否已变得不正确。

Kubernetes 1.26:非平滑节点关闭功能进入 Beta 阶段

Kubernetes v1.24 引入了一个 Alpha 质量的改进实现,用于处理非平稳的节点关闭。在 Kubernetes v1.26 中,此功能进入 Beta 阶段。该功能允许有状态的工作负载在原始节点关闭或处于不可恢复状态(例如硬件故障或操作系统损坏)后,故障转移到另一个节点。

Kubernetes 中的节点关闭是什么?

在 Kubernetes 集群中,节点可能会关闭。这可能是有计划地发生,也可能是意外发生。你可能计划进行安全补丁或内核升级而需要重启节点,或者它可能因为虚拟机实例被抢占而关闭。节点也可能由于硬件故障或软件问题而关闭。

要触发节点关闭,你可以在 shell 中运行 shutdownpoweroff 命令,或者物理上按下按钮来关闭机器电源。

如果节点在关闭前没有被排空(drain),节点关闭可能导致工作负载失败。

下面,我们将描述什么是平稳节点关闭和什么是非平稳节点关闭。

什么是平稳节点关闭?

kubelet 对平稳节点关闭的处理,允许 kubelet 检测到节点关闭事件,正确地终止该节点上的 Pod,并在实际关闭前释放资源。关键 Pod 在所有常规 Pod 终止后才会被终止,以确保应用程序的基本功能可以尽可能长时间地工作。

什么是非平稳节点关闭?

只有当 kubelet 的节点关闭管理器能够检测到即将发生的节点关闭操作时,节点关闭才能是平稳的。然而,在某些情况下,kubelet 无法检测到节点关闭操作。这可能是因为 shutdown 命令没有触发 kubelet 在 Linux 上使用的抑制锁(Inhibitor Locks)机制,或者因为用户错误。例如,如果该节点的 shutdownGracePeriodshutdownGracePeriodCriticalPods 详细信息配置不正确。

当一个节点关闭(或崩溃),并且该关闭没有被 kubelet 节点关闭管理器检测到时,它就成为了一次非平稳节点关闭。非平稳节点关闭对于有状态应用来说是个问题。如果一个包含 StatefulSet 一部分 Pod 的节点以非平稳方式关闭,该 Pod 将无限期地卡在 Terminating 状态,并且控制平面无法在健康的节点上为该 StatefulSet 创建一个替代 Pod。你可以手动删除失败的 Pod,但这对于一个自我修复的集群来说并不理想。同样,由 Deployment 创建的 ReplicaSet 的 Pod 也会卡在 Terminating 状态,并且那些绑定到已关闭节点的 Pod 会无限期地保持 Terminating 状态。如果你设置了水平扩展限制,即使是那些正在终止的 Pod 也会计入限制,因此如果你的工作负载已经达到最大规模,它可能会难以自我修复。(顺便说一句:如果那个非平稳关闭的节点重新启动,kubelet 会删除旧的 Pod,控制平面可以创建一个替代的。)

Beta 版本有什么新功能?

对于 Kubernetes v1.26,非平稳节点关闭功能是 Beta 版,并默认启用。NodeOutOfServiceVolumeDetach 特性门控kube-controller-manager 上默认启用,而不再是可选加入;如果需要,你仍然可以禁用它(也请提交一个 issue 来说明问题)。

在监控方面,kube-controller-manager 报告了两个新的度量指标。

force_delete_pods_total
被强制删除的 pod 数量(Pod 垃圾回收控制器重启时重置)
force_delete_pod_errors_total
尝试强制删除 Pod 时遇到的错误数量(Pod 垃圾回收控制器重启时也重置)

它是如何工作的?

在节点关闭的情况下,如果平稳关闭不起作用或由于硬件故障或操作系统损坏,节点处于不可恢复状态,你可以手动在节点上添加一个 out-of-service 污点。例如,这可以是 node.kubernetes.io/out-of-service=nodeshutdown:NoExecutenode.kubernetes.io/out-of-service=nodeshutdown:NoSchedule。如果 pod 上没有匹配的容忍度,这个污点会触发节点上的 pod 被强制删除。附加到关闭节点的持久卷将被分离,新的 pod 将在另一个运行中的节点上成功创建。

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

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

一旦所有链接到 out-of-service 节点的工作负载 pod 都移动到了一个新的运行节点,并且关闭的节点已经恢复,你应该在节点恢复后移除该受影响节点上的污点。

下一步是什么?

根据反馈和采用情况,Kubernetes 团队计划在 1.27 或 1.28 版本中将非平稳节点关闭的实现推向 GA(正式发布)。

此功能要求用户手动向节点添加污点以触发工作负载的故障转移,并在节点恢复后移除污点。

集群操作员可以通过自动应用 out-of-service 污点来自动化这个过程,前提是有一种程序化的方式来确定节点确实已经关闭,并且节点与存储之间没有 IO。然后,集群操作员可以在工作负载成功故障转移到另一个运行节点并且关闭的节点已经恢复后,自动移除该污点。

在未来,我们计划寻找方法来自动检测和隔离已关闭或处于不可恢复状态的节点,并将其工作负载故障转移到另一个节点。

我如何了解更多信息?

要了解更多信息,请阅读 Kubernetes 文档中的非平稳节点关闭

如何参与?

我们非常感谢所有帮助设计、实现和审查此功能的贡献者

在整个过程中,有很多人帮助审查了设计和实现。我们要感谢所有为这项工作做出贡献的人,包括在过去几年里审查了KEP和实现的大约 30 人。

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