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

优雅节点关闭进入 Beta 版

在 1.21 中处于 Beta 阶段的优雅节点关闭功能,使 kubelet 能够在节点关闭期间优雅地驱逐 Pod。

Kubernetes 是一个分布式系统,因此我们需要为不可避免的故障做好准备 - 节点会发生故障,容器可能会崩溃或重新启动,并且 - 理想情况下 - 您的工作负载将能够承受这些灾难性事件。

常见的问题之一是节点关闭或重新启动时的工作负载故障。在关闭节点之前,最佳实践是安全地排空和隔离您的节点。这将确保在此节点上运行的所有 Pod 都可以安全地被驱逐。驱逐将确保您的 Pod 可以遵循预期的Pod 终止生命周期,这意味着在您的容器中接收 SIGTERM 和/或运行 preStopHooks

在 Kubernetes 1.20(引入优雅节点关闭作为 alpha 功能)之前,安全节点排空并不容易:它要求用户手动采取操作并事先排空节点。如果有人或某些东西在没有排空的情况下关闭了您的节点,则您的 Pod 很可能不会从您的节点中安全地被驱逐,并且会突然关闭。与这些 Pod 通信的其他服务可能会因 Pod 突然退出而出现错误。这种情况的一些示例可能是由于安全补丁导致的重新启动或短暂的云计算实例的抢占而引起的。

Kubernetes 1.21 将优雅节点关闭带到 Beta 阶段。优雅节点关闭使您可以更好地控制一些意外的关闭情况。通过优雅节点关闭,kubelet 知道底层系统的关闭事件,并将这些事件传播到 Pod,确保容器可以尽可能优雅地关闭。这使容器有机会检查点其状态或释放其持有的任何资源。

请注意,为了获得最佳可用性,即使使用优雅节点关闭,您仍然应该将部署设计为能够抵御节点故障。

它是如何工作的?

在 Linux 上,您的系统可以在许多不同的情况下关闭。例如

  • 用户或脚本运行 shutdown -h nowsystemctl poweroffsystemctl reboot
  • 物理按下机器上的电源按钮。
  • 在云提供商上停止 VM 实例,例如 GCP 上的 gcloud compute instances stop
  • 云提供商可以意外终止的抢占式 VM 或竞价实例,但会发出简短的警告。

这些情况中的许多情况可能是意外的,并且无法保证群集管理员在这些事件发生之前排空了节点。通过优雅节点关闭功能,kubelet 使用名为“Inhibitor Locks”的 systemd 机制,允许在大多数情况下进行排空。使用 Inhibitor Locks,kubelet 指示 systemd 将系统关闭推迟指定的持续时间,从而有机会排空节点并驱逐系统上的 Pod。

Kubelet 利用此机制来确保您的 Pod 将被干净地终止。当 kubelet 启动时,它会获取一个 systemd 延迟类型抑制器锁。当系统即将关闭时,kubelet 可以利用它之前获取的延迟类型抑制器锁将关闭延迟一段可配置的短时间。这给了您的 Pod 额外的终止时间。因此,即使在意外关闭期间,您的应用程序也会收到 SIGTERM,preStop 钩子将执行,并且 kubelet 将正确更新 Ready 节点条件和各自的 Pod 状态到 api-server。

例如,在启用了优雅节点关闭的节点上,您可以看到 kubelet 获取了抑制器锁

kubelet-node ~ # systemd-inhibit --list
    Who: kubelet (UID 0/root, PID 1515/kubelet)
    What: shutdown
    Why: Kubelet needs time to handle node shutdown
    Mode: delay

1 inhibitors listed.

我们在设计此功能时考虑的一个重要因素是并非所有 Pod 都是平等的。例如,在节点上运行的某些 Pod(例如与日志记录相关的 daemonset)应尽可能长时间运行,以便在关闭期间捕获重要的日志。因此,Pod 分为两类:“常规”和“关键”。关键 Pod 是指将 priorityClassName 设置为 system-cluster-criticalsystem-node-critical 的 Pod;所有其他 Pod 都被认为是常规的。

在我们的示例中,日志记录 DaemonSet 将作为关键 Pod 运行。在优雅节点关闭期间,先终止常规 Pod,然后终止关键 Pod。例如,这将允许与日志记录 daemonset 关联的关键 Pod 继续运行,并在终止常规 Pod 期间收集日志。

我们将在 Beta 阶段评估是否需要为不同的 Pod 优先级类提供更多的灵活性,并在需要时添加支持,如果您有任何想法,请告诉我们。

我该如何使用它?

优雅节点关闭由 GracefulNodeShutdown 功能门控制,并且在 Kubernetes 1.21 中默认启用。

您可以使用两个 kubelet 配置选项来配置优雅节点关闭行为:ShutdownGracePeriodShutdownGracePeriodCriticalPods。要配置这些选项,请编辑通过 --config 标志传递给 kubelet 的 kubelet 配置文件;有关更多详细信息,请参阅通过配置文件设置 kubelet 参数

在关闭期间,kubelet 分两个阶段终止 Pod。您可以配置每个阶段的持续时间。

  1. 终止在节点上运行的常规 Pod。
  2. 终止在节点上运行的关键 Pod。

控制关闭持续时间的设置是

  • ShutdownGracePeriod
    • 指定节点应延迟关闭的总持续时间。这是常规 Pod 和关键 Pod 的 Pod 终止的总宽限期。
  • ShutdownGracePeriodCriticalPods
    • 指定在节点关闭期间终止关键 Pod 所用的持续时间。这应小于 ShutdownGracePeriod

例如,如果 ShutdownGracePeriod=30sShutdownGracePeriodCriticalPods=10s,则 kubelet 会将节点关闭延迟 30 秒。在此期间,前 20 秒 (30-10) 将保留用于优雅地终止正常 Pod,最后 10 秒将保留用于终止关键 Pod。

请注意,默认情况下,上述两个配置选项 ShutdownGracePeriodShutdownGracePeriodCriticalPods 都设置为零,因此您需要根据您的环境配置它们才能激活优雅节点关闭功能。

我如何了解更多信息?

我如何参与?

欢迎您随时提供反馈!SIG Node 定期召开会议,可以通过 Slack(频道 #sig-node)或 SIG 的 邮件列表联系。