节点关机

在 Kubernetes 集群中,节点(node)可以以计划的优雅方式关机,也可以因停电或其它外部原因意外关机。如果在关机前未对节点执行 Drain(驱逐),节点关机可能会导致工作负载故障。节点关机可以分为优雅(graceful)关机和非优雅(non-graceful)关机。

优雅节点关机

特性状态: Kubernetes v1.21 [beta] (默认启用:true)

Kubelet 尝试检测节点系统关机并终止在该节点上运行的 Pod。

Kubelet 确保 Pod 在节点关机期间遵循正常的Pod 终止过程。在节点关机期间,Kubelet 不接受新的 Pod(即使这些 Pod 已绑定到该节点)。

优雅节点关机特性依赖于 systemd,因为它利用 systemd inhibitor locks 来按照给定的持续时间延迟节点关机。

优雅节点关机由 GracefulNodeShutdown Feature Gate 控制,该 Feature Gate 在 1.21 版本中默认启用。

请注意,默认情况下,下面描述的两个配置选项 shutdownGracePeriodshutdownGracePeriodCriticalPods 都设置为零,因此不会激活优雅节点关机功能。要激活该功能,应适当配置这两个选项并将其设置为非零值。

一旦 systemd 检测到或收到节点关机通知,kubelet 会在节点上设置 NotReady 状态,并将 reason 设置为 "node is shutting down"。kube-scheduler 会遵守此状态,不会将任何 Pod 调度到受影响的节点上;其他第三方调度器也应遵循相同的逻辑。这意味着新的 Pod 不会被调度到该节点上,因此不会启动。

如果检测到正在进行的节点关机,Kubelet 在 PodAdmission 阶段也会拒绝 Pod,以便即使是具有与 node.kubernetes.io/not-ready:NoSchedule 匹配的容忍度(toleration)的 Pod 也不会在此启动。

当 kubelet 通过 API 在其节点上设置该状态时,kubelet 也开始终止所有在本地运行的 Pod。

在优雅关机期间,kubelet 分两个阶段终止 Pod:

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

优雅节点关机功能可通过两个 KubeletConfiguration 选项进行配置:

  • shutdownGracePeriod:

    指定节点应延迟关机的总持续时间。这是常规 Pod 和关键 Pod 终止的总优雅限期。

  • shutdownGracePeriodCriticalPods:

    指定在节点关机期间用于终止关键 Pod 的持续时间。此值应小于 shutdownGracePeriod

例如,如果 shutdownGracePeriod=30sshutdownGracePeriodCriticalPods=10s,kubelet 将延迟节点关机 30 秒。在关机期间,前 20 秒 (30-10) 将用于优雅终止常规 Pod,最后 10 秒将用于终止关键 Pod

基于 Pod 优先级的优雅节点关机

特性状态: Kubernetes v1.24 [beta] (默认启用:true)

为了在优雅节点关机期间,针对 Pod 终止顺序提供更高的灵活性,优雅节点关机会遵守 Pod 的 PriorityClass(前提是你在集群中启用了此特性)。此特性允许集群管理员基于优先级类别(priority classes)明确定义优雅节点关机期间 Pod 的终止顺序。

优雅节点关机特性如上所述,分两个阶段关闭 Pod:非关键 Pod,然后是关键 Pod。如果需要更多灵活性来以更精细的方式明确定义关机期间 Pod 的顺序,可以使用基于 Pod 优先级的优雅关机。

当优雅节点关机遵守 Pod 优先级时,可以在多个阶段进行优雅节点关机,每个阶段关闭特定优先级类别的 Pod。可以为 kubelet 配置精确的阶段和每个阶段的关机时间。

假设集群中有以下自定义的 Pod 优先级类别(priority classes)

Pod 优先级类别名称Pod 优先级类别值
custom-class-a100000
custom-class-b10000
custom-class-c1000
regular/unset0

kubelet 配置中,shutdownGracePeriodByPodPriority 的设置可能如下所示:

Pod 优先级类别值关机周期
10000010 秒
10000180 秒
1000120 秒
060 秒

相应的 kubelet 配置 YAML 如下:

shutdownGracePeriodByPodPriority:
  - priority: 100000
    shutdownGracePeriodSeconds: 10
  - priority: 10000
    shutdownGracePeriodSeconds: 180
  - priority: 1000
    shutdownGracePeriodSeconds: 120
  - priority: 0
    shutdownGracePeriodSeconds: 60

上表意味着任何 priority 值 >= 100000 的 Pod 将只有 10 秒的时间关机,任何值 >= 10000 且 < 100000 的 Pod 将有 180 秒的时间关机,任何值 >= 1000 且 < 10000 的 Pod 将有 120 秒的时间关机。最后,所有其他 Pod 将有 60 秒的时间关机。

无需为所有类别指定相应的值。例如,你可以改用这些设置:

Pod 优先级类别值关机周期
100000300 秒
1000120 秒
060 秒

在上述情况下,具有 custom-class-b 的 Pod 将与 custom-class-c 一起进入同一关机分组。

如果某个范围内没有 Pod,则 kubelet 不会等待该优先级范围内的 Pod。相反,kubelet 会立即跳到下一个优先级类别值范围。

如果此特性已启用但未提供配置,则不会执行任何排序操作。

使用此特性需要启用 GracefulNodeShutdownBasedOnPodPriority Feature Gate,并在 kubelet 配置中将 ShutdownGracePeriodByPodPriority 设置为所需的配置,其中包含 Pod 优先级类别值及其相应的关机周期。

指标 graceful_shutdown_start_time_secondsgraceful_shutdown_end_time_seconds 在 kubelet 子系统下发出,用于监视节点关机。

非优雅节点关机处理

特性状态: Kubernetes v1.28 [stable] (默认启用:true)

Kubelet 的节点关机管理器可能无法检测到节点关机操作,这可能是因为该命令没有触发 kubelet 使用的 inhibitor locks 机制,也可能是由于用户错误,即 ShutdownGracePeriod 和 ShutdownGracePeriodCriticalPods 未正确配置。请参考上面关于优雅节点关机的章节了解更多详情。

当节点关机但未被 kubelet 的节点关机管理器检测到时,属于有状态集合(StatefulSet)的 Pod 将停留在关机节点上的 Terminating 状态,无法移动到新的运行节点。这是因为关机节点上的 kubelet 不可用,无法删除 Pod,因此 StatefulSet 无法创建同名的新 Pod。如果 Pod 使用了卷,VolumeAttachment 将不会从原始关机节点中删除,因此这些 Pod 使用的卷无法挂接到新的运行节点。结果是,运行在 StatefulSet 上的应用程序无法正常工作。如果原始关机节点启动,kubelet 将删除 Pod,并在不同的运行节点上创建新的 Pod。如果原始关机节点未启动,这些 Pod 将永远停留在关机节点上的 Terminating 状态。

为了缓解上述情况,用户可以手动为节点添加带有 NoExecuteNoSchedule 效果的污点 node.kubernetes.io/out-of-service,将其标记为停止服务(out-of-service)。如果节点被标记为停止服务并带有此污点,则节点上的 Pod 如果没有匹配的容忍度,将被强制删除,并且正在终止的 Pod 的卷分离(detach volume)操作将立即发生。这使得停止服务节点上的 Pod 可以在不同的节点上快速恢复。

在非优雅关机期间,Pod 分两个阶段终止:

  1. 强制删除没有匹配的 out-of-service 容忍度的 Pod。
  2. 立即为这些 Pod 执行卷分离操作。

超时时强制分离存储

在任何 Pod 删除在 6 分钟内未成功的情况下,如果节点当时处于不健康状态,kubernetes 将强制分离正在卸载的卷。任何仍在节点上运行并使用强制分离的卷的工作负载都将违反 CSI 规范,该规范规定 ControllerUnpublishVolume必须在该卷上的所有 NodeUnstageVolumeNodeUnpublishVolume 都被调用并成功后调用”。在这种情况下,相关节点上的卷可能会遇到数据损坏。

强制存储分离行为是可选的;用户可以选择使用“非优雅节点关机”特性。

可以通过在 kube-controller-manager 中设置 disable-force-detach-on-timeout 配置字段来禁用超时强制存储分离。禁用超时强制分离特性意味着,托管在不健康超过 6 分钟的节点上的卷,其关联的 VolumeAttachment 将不会被删除。

应用此设置后,仍连接到卷的不健康 Pod 必须通过上述的非优雅节点关机流程来恢复。

Windows 优雅节点关机

特性状态: Kubernetes v1.32 [alpha] (默认启用:false)

Windows 优雅节点关机特性依赖于 kubelet 作为 Windows 服务运行,然后它将拥有一个注册的 服务控制处理程序(service control handler),以给定的持续时间延迟 preshutdown 事件。

Windows 优雅节点关机由 WindowsGracefulNodeShutdown Feature Gate 控制,该 Feature Gate 在 1.32 版本中作为 Alpha 特性引入。

Windows 优雅节点关机无法取消。

如果 kubelet 未作为 Windows 服务运行,它将无法设置和监视 Preshutdown 事件,节点将不得不经历上述的非优雅节点关机流程。

在启用了 Windows 优雅节点关机特性,但 kubelet 未作为 Windows 服务运行的情况下,kubelet 将继续运行而不是失败。但是,它会记录一条错误,指示需要将其作为 Windows 服务运行。

下一步

了解更多关于以下内容的信息:

上次修改于 2025 年 2 月 24 日太平洋标准时间 11:45 AM:更新节点关机文档:单词 'administrators' 中的拼写错误 (en) (151c47470e)