管理 GPU 和 TPU 的 GKE 节点中断


在长时间运行的 GKE 集群的生命周期内,由于Google Cloud 导致的基础设施中断,工作负载会定期中断。这些自动事件可能会因调度决策(抢占事件)、控制平面或节点更新(包括 GKE 节点自动升级 [维护事件])或检测到的问题修复(终止事件)而发生。

本页可帮助您了解节点中断在 GKE 中的含义,监控维护通知,并最大限度地减少中断在挂接了 GPU 和 TPU 的 GKE 节点中的影响。

本文档适用于管理底层技术基础设施生命周期的平台管理员和操作员。如需详细了解我们在 Google Cloud 内容中提及的常见角色和示例任务,请参阅常见的 GKE 用户角色和任务

GKE 中的基础设施中断意味着什么?

GKE 集群会管理 GKE 节点的生命周期。这些节点预配在 Compute Engine 虚拟机上,而 Compute Engine 虚拟机会定期遇到以下中断:

  • 检测到的问题的补救措施 (TerminationEvent):这些事件的发生是因为 Google Cloud 检测到问题并中断了集群基础架构。TerminationEvent 事件不支持正常关停。 以下问题会触发 TerminationEvent 事件:

    • 当 GKE 在节点多次健康检查失败后修复该节点时,会发生自动修复
    • 当物理机上的硬件或软件错误导致虚拟机停止时,会发生 HostError
  • 维护或升级事件 (MaintenanceEvent):当 Google Cloud 需要中断虚拟机以执行维护时,会发生这些事件。MaintenanceEvent 事件由以下维护任务触发:

    • 当 Google Cloud 升级底层主机时,会发生维护事件
    • 节点更新(包括节点自动升级)是指 GKE 更新节点上运行的 Kubernetes 版本。

    如需详细了解您和 GKE 如何在集群生命周期内管理更改,请参阅更改类型

  • 对调度决策的响应 (PreemptionEvent):当Google Cloud 需要抢占虚拟机以使容量可用于更高优先级的资源时发生。PreemptionEvent 事件可以是以下任何一种:

    • 逐出:当抢占式Spot 基础架构被抢占以容纳优先级更高的虚拟机时,会发生逐出。
    • 碎片整理:当 GKE 抢占较小的 TPU 切片以容纳较大的 TPU 切片时,会发生碎片整理。碎片整理仅在 TPU 切片上进行。

在长时间运行的 GKE 集群的生命周期内,节点可能会遇到训练或服务工作负载定期中断。当这些中断影响运行 AI/机器学习工作负载的 GKE 节点时,GKE 需要重启正在运行的工作负载和底层节点。

为何 GPU 和 TPU 需要中断管理

大多数 Compute Engine 虚拟机(但有一些例外情况)的主机维护政策设置为实时迁移,这意味着正在运行的工作负载通常不会中断,或者几乎不会中断。不过,某些类别的虚拟机不支持实时迁移,包括挂接了 GPUTPU 的虚拟机。当 TPU 切片中的虚拟机发生主机事件时,整个切片会中断,然后重新计划,因为所有维护事件都是在切片级别协调的。因此,如果您创建的 TPU 切片包含数百个虚拟机,那么所有这些虚拟机都会收到相同的维护事件时间表。

发生主机事件时,GKE 会终止节点及其 Pod。如果 Pod 是作为更大的工作负载(例如作业部署)的一部分部署的,GKE 会在受影响的节点上重启 Pod。

由您或是您使用的框架决定如何处理工作负载配置以适当响应维护事件。例如,您可以保存 AI 训练作业的状态,以减少数据丢失。

如需管理 AI/机器学习工作负载中出现的中断,您可以执行以下操作:

监控节点中断

以下 GKE 系统指标会报告自上次采样以来 GKE 节点的中断次数(该指标每 60 秒采样一次):

  • kubernetes.io/node/interruption_count

interruption_type(例如 TerminationEventMaintenanceEventPreemptionEvent)和 interruption_reason(例如 HostErrorEvictionAutoRepair)字段有助于您了解节点中断的原因。

如需获取项目集群中 TPU 节点中断及其原因的细分信息,请使用以下 PromQL 查询:

  sum by (interruption_type,interruption_reason)(
    sum_over_time(
      kubernetes_io:node_interruption_count{monitored_resource="k8s_node"}[${__interval}]))

如需仅查看主机维护事件,请更新查询以在 interruption_reason 中过滤出 HW/SW Maintenance 值。请使用以下 PromQL 查询:

  sum by (interruption_type,interruption_reason)(
    sum_over_time(
      kubernetes_io:node_interruption_count{monitored_resource="k8s_node", interruption_reason="HW/SW Maintenance"}[${__interval}]))

如需查看按节点池汇总的中断次数,请使用以下 PromQL 查询:

  sum by (node_pool_name,interruption_type,interruption_reason)(
    sum_over_time(
      kubernetes_io:node_pool_interruption_count{monitored_resource="k8s_node_pool", interruption_reason="HW/SW Maintenance", node_pool_name=NODE_POOL_NAME }[${__interval}]))

监控维护通知

当已为节点及其底层虚拟机计划中断性主机事件时,以及当这些事件开始时,Compute Engine 会发出通知。通知包含计划的开始时间、事件类型以及其他详细信息。

在 GKE 1.31.1-gke.2008000 版本及更高版本中,您可以监控即将发生的维护事件,包括本部分中所述的事件。

即将进行的维护已计划,但尚未开始

在挂接了 GPU 或 TPU 的虚拟机发生计划的维护事件之前,Compute Engine 会向其所有虚拟机推送通知。这些通知会报告维护窗口的开始时间。如果虚拟机已计划即将进行的维护,但该维护尚未开始,GKE 会向节点标签添加 scheduled-maintenance-time

如需在节点级别查询这些通知,请运行以下命令:

kubectl get nodes -l cloud.google.com/scheduled-maintenance-time \
    -L cloud.google.com/scheduled-maintenance-time

输出类似于以下内容:

NAME                         STATUS    SCHEDULED-MAINTENANCE-TIME
<gke-accelerator-node-name>  Ready     1733083200
<gke-accelerator-node-name>  Ready     1733083200
[...]

SCHEDULED-MAINTENANCE-TIME 列表示秒数,以 Unix 纪元时间格式显示。

如需在节点元数据级别查询这些通知,请检查实例是否存在维护事件通知

对于支持高级维护的加速器优化机器家族,您可以访问 upcoming-maintenance 端点,该端点会提供有关已计划和已开始的维护事件的信息。

尽量减少中断的影响

Compute Engine 会针对即将进行的维护事件发出通知,并安排维护窗口。 在收到通知的时间与维护窗口开始时间之间,您可以选择:

  • 手动启动主机维护事件。
  • 让 Compute Engine 按计划启动维护事件。

手动启动主机维护事件

当 Compute Engine 发出有关计划维护事件的通知时,您可以根据您的操作时间表(例如在活动减少的时间段)手动启动维护。

在节点池中的节点上,将节点标签 cloud.google.com/perform-maintenance 设置为 true。例如:

kubectl label nodes <node-name> cloud.google.com/perform-maintenance=true

如果您启动维护事件,GKE 会执行以下操作:

  1. 为节点添加污点。
  2. 正常逐出 Pod。
  3. 请求 Compute Engine 立即开始维护事件,而不是等待安排的时间。

Compute Engine 按计划启动维护事件

如果您启动主机维护事件,Compute Engine 会自行启动计划的维护事件。从 GKE 1.33 版开始,维护窗口开始时,节点不会被污染,Pod 也不会被逐出。

维护事件开始后,节点可能会关停一次或多次,并且在即将终止之前会发出简短的通知。在这些情况下,GKE 会尽最大努力终止工作负载并正常逐出 Pod

计划的维护开始

当计划的维护开始时,Compute Engine 会更新 http://metadata.google.internal/computeMetadata/v1/instance/attributes/ 目录中的元数据。Compute Engine 会按如下方式更新元数据标签:

  • maintenance-event 设置为 TERMINATE_ON_HOST_MAINTENANCE
  • upcoming-maintenance 中,将 maintenance_status 设置为 ONGOING

GKE 会处理预定的主机维护事件,具体取决于您是手动触发该事件,还是让 GKE 自动执行。

配置 GKE 以正常终止工作负载

在本部分中,您将配置 GKE 以管理应用生命周期并最大限度地减少工作负载的中断。如果您未配置宽限期,则宽限期默认为 30 秒。

GKE 会尽最大努力正常终止这些 Pod 并执行您定义的终止操作,例如保存训练状态。GKE 会在宽限期开始时向 Pod 发送 SIGTERM 信号。如果 Pod 未在宽限期结束前退出,GKE 会向仍在 Pod 中的任何容器中运行的任何进程发送跟进 SIGKILL 信号。

如需配置正常终止期,请在 Pod 清单的 spec.terminationGracePeriodSeconds 字段中设置终止宽限期(秒)。例如,如需获得 10 分钟的通知时间,请将 Pod 清单中的 spec.terminationGracePeriodSeconds 字段设置为 600 秒,如下所示:

    spec:
      terminationGracePeriodSeconds: 600

我们建议您设置的终止宽限期足够长,以便任何正在进行的任务在通知时间范围内完成。 如果您的工作负载使用机器学习框架(例如 MaxText、Pax 或带有 Orbax 的 JAX),则工作负载可以捕获关停 SIGTERM 信号并启动检查点过程。如需了解详情,请参阅 TPU 自动检查点

正常终止的过程

当手动启动的维护事件开始时,Compute Engine 会通过更新 maintenance-event 元数据键来发出即将关停机器的信号。GKE 开始正常终止。

以下工作流展示了 GKE 在即将关停节点时如何正常终止节点:

  1. 在 60 秒内会发生以下情况:
    1. 系统组件将应用设置为 ONGOINGcloud.google.com/active-node-maintenance 节点标签,以指示工作负载正在停止过程中。
    2. GKE 会应用节点污点来防止在该节点上安排新的 Pod。污点具有 cloud.google.com/impending-node-termination:NoSchedule 键。我们建议您不要修改工作负载,以容忍由于发生已知终止而导致的此污点。
  2. maintenance-handler 组件会开始逐出 Pod,首先逐出工作负载 Pod,然后逐出系统 Pod(例如 kube-system)。
  3. GKE 会向节点上正在运行的工作负载 Pod 发送 SIGTERM 关停信号,以提醒它们即将关停。Pod 可以使用此提醒来完成任何正在进行的任务。GKE 会尽最大努力正常终止这些 Pod。
  4. 驱逐完成后,GKE 会将 cloud.google.com/active-node-maintenance 标签的值更新为 terminating,以指示节点已准备好进行终止。

之后,系统会执行节点终止并分配替换节点。该过程完成后,GKE 会清除标签和污点。如需延长使用 GPU 或 TPU 的工作负载的终止时段,请完成手动启动主机维护事件部分中的步骤。

监控活跃正常终止的进度

您可以按以下正常终止事件过滤 GKE 日志:

  • 当虚拟机检测到因即将发生的节点终止(例如 Compute Engine 主机维护事件)而导致中断时,GKE 会在工作负载正在停止时将 cloud.google.com/active-node-maintenance 设置为 ONGOING,并在工作负载完成且节点准备好进行终止时将其设置为 terminating
  • 在限制安排新的工作负载时,GKE 会应用 cloud.google.com/impending-node-termination:NoSchedule 污点。

后续步骤