对运行训练和推理工作负载的节点执行主机维护

本文档介绍了如何对 Google Kubernetes Engine (GKE) 集群中节点的底层 Compute Engine 实例执行主机维护。您只需针对某些类型的 Compute Engine 实例(包括具有 GPU 和 TPU 的实例)主动管理此维护,这些实例不会实时迁移。本文档中介绍的策略非常适合训练和推理工作负载。如果您只需要手动对单个节点执行主机维护,或者您的工作负载可以容忍自动主机维护,请参阅了解如何在 GKE 上执行主机维护。

这些策略会为节点组执行主机维护,并可选择启动 GKE 集群升级。

对于可以有一个停机时间段的工作负载节点(例如训练工作负载的节点),请使用并行策略。对于可以分批停机同时保持大多数资源可用性的工作负载节点(例如推理工作负载节点),请使用滚动策略。

使用并行策略更新训练工作负载的节点

此策略会同时对一组使用加速器的节点执行更改。您可以将此策略用于训练工作负载。或者,您也可以将其用于其他类型的工作负载,其中执行更改的最不具破坏性的方法是为组中的所有节点以及在这些节点上运行的工作负载提供一个完全停机的窗口。

该策略遵循以下简要步骤:

  1. 停止工作负载:选择节点池,然后停止在其上运行的工作负载,或将工作负载移至其他仍可用的节点。
  2. 触发主机维护:同时将维护标签应用于所有选定节点,并等待所有节点上的进程完成。
  3. 升级 GKE 版本:更改节点的 GKE 版本。
  4. 重启工作负载:在所有主机维护和升级完成后,重启工作负载。

提供的说明会针对单个节点池执行更改。不过,您可以调整这些步骤,以便同时对多个节点池进行更改。在开始这些步骤之前,请确保您有至少几个小时的时间,在此期间此工作负载不需要在这些节点上运行。

为了在接收底层 Compute Engine 实例和 GKE 节点的关键更改时最大限度地减少中断,请利用这段停机时间执行主机维护和 GKE 版本升级。但是,如果您不想升级 GKE 节点的版本,则只能执行主机维护。

开始使用之前的注意事项

在开始之前,请查看以下注意事项:

  • 避免重新部署工作负载:为避免因 PodDisruptionBudgets 造成不必要的延迟,请在完成所有步骤之前不要重新部署任何工作负载。
  • 为中断做好准备:确保您的工作负载可以中断一段时间。这些步骤需要数小时才能完成,主要是因为主机维护需要时间。

同时对所有节点执行更新

如需执行主机维护和(可选)GKE 版本升级,请完成以下步骤:

  1. 准备工作负载:停止工作负载,或确保它们最近创建了快照或检查点。
  2. 启动和监控主机维护:

    • 使用分组维护调度的预留中的子块:使用相应的 gcloud compute reservations 子命令触发跨预留、预留块或预留子块的维护。例如,以下命令会启动子块的维护:

      gcloud compute reservations sub-blocks perform-maintenance RESERVATION_NAME \
          --block-name=BLOCK_NAME \
          --sub-block-name=SUB_BLOCK_NAME \
          --zone=ZONE
      

      替换以下内容:

      • RESERVATION_NAME:预留的名称。
      • BLOCK_NAME:预留块的名称。
      • SUB_BLOCK_NAME:预留子块的名称。
      • ZONE:预留所在的可用区。

      Compute Engine 会同时开始排空和更新子块中的所有实例。此过程可能需要几个小时。

      如需进行监控,请通过检查预留资源中的 upcomingGroupMaintenance 元数据字段来查看维护状态。如需了解详情,请参阅查看维护状态。

    • 使用独立维护安排的实例:通过将 cloud.google.com/perform-maintenance=true 标签应用于节点池中的节点,为按需实例或不使用子块的预留触发维护:

      kubectl label nodes -l cloud.google.com/gke-nodepool=NODE_POOL_NAME cloud.google.com/perform-maintenance=true --overwrite
      

      Compute Engine 会同时开始排空和更新底层实例。此过程可能需要几个小时。如需了解详情,请参阅正常终止过程。

      如需监控维护状态,请检查节点。维护完成后,GKE 会移除维护标签(如果已应用)。维护完成后,您可以在 Cloud Logging 中找到包含以下消息的日志:

      Maintenance window has completed for this instance. All maintenance
      notifications on the instance have been removed.
      
  3. 可选:升级 GKE 节点的版本:按照说明升级节点的 GKE 版本。

使用滚动策略更新推理工作负载的节点

此策略概述了对运行推理工作负载的 GKE 节点执行维护的手动方法。它涉及批量更新节点,以维持服务可用性。此方法最适合可以容忍一定比例的副本暂时离线的工作负载。

该策略遵循以下简要步骤:

  1. 识别节点并进行批处理:选择要更新的节点池。根据工作负载的容错能力,将节点分组为不同大小的批次。
  2. 遍历批次:对于每个批次,应用维护标签并监控该批次的节点,直到标签被移除。
  3. 升级 GKE 版本:在所有批次完成主机维护后,更改 GKE 节点的版本。

开始使用之前的注意事项

在开始之前,请查看以下注意事项:

  • 了解您的部署:若要成功,您需要详细了解工作负载分布、副本放置和故障域。确保您在整个过程中保持足够的服务容量。
  • 规划批次大小:分批更新节点。每个批次的大小由工作负载的容错能力决定。要考虑的因素包括:
    • 每个服务模型的副本数量。
    • 副本在节点和故障域之间的分布。
    • PodDisruptionBudgets 有助于强制执行同时关停的 Pod 数量上限。
    • 建议:为简化管理,请考虑将不同的节点池专用于不同的副本集,这样您就可以在节点池级别隔离故障域。
  • 计算时间限制:考虑以下时间因素:
    • 每个批次可能需要几个小时才能完成主机维护步骤。
    • 计算最小批次大小,以帮助确保所有维护工作在要求的截止日期之前完成:
      1. MAINTENANCE_BLOCKS = floor(HOURS_TO_MAINTENANCE / 4)(其中 HOURS_TO_MAINTENANCE 是总可用时间)。
      2. MIN_PER_BATCH = TOTAL_NODE_COUNT / MAINTENANCE_BLOCKS
    • 您选择的批次大小必须等于或大于 MIN_PER_BATCH。
  • 查看特定工作负载类型:请考虑以下各项配置类型:
    • 混合专家 (MoE):确保您的批处理策略为每个模型保留所需的副本数下限。
    • 解耦式服务:在规划批次时,请确保跟踪解耦式设置中涉及的所有副本。
    • 多主机节点池(TPU、MNNVL):对于这些配置,您可能需要一次性关闭整个节点池。相应地规划跨多个节点池的故障域。

分批执行滚动更新

如需执行滚动主机维护更新,您可以按一个或多个子块的批次,从使用分组维护安排的预留中更新容量,也可以通过独立维护安排按名称更新集群中的特定节点集。

为您的资源选择合适的策略:

批量更新预留中的子块

如需对容量预留执行滚动主机维护(按子块批次),请完成以下步骤:

  1. 确定要维护的预留:确定 GKE 集群使用的容量预留名称以及预留块或预留子块。为此,请使用 GKE 节点标签和 gcloud compute reservations 命令执行查找:

    1. 列出节点池中节点的预留名称以及物理块和子块拓扑 ID:

      kubectl get nodes -l cloud.google.com/gke-nodepool=NODE_POOL_NAME \
          -o custom-columns='NAME:.metadata.name,RESERVATION:.metadata.labels.cloud\.google\.com/reservation-name,BLOCK_ID:.metadata.labels.cloud\.google\.com/gce-topology-block,SUBBLOCK_ID:.metadata.labels.cloud\.google\.com/gce-topology-subblock'
      

      将 NODE_POOL_NAME 替换为节点池的名称。

      记下输出值:预留名称(例如 nvidia-gb300-m7kp2xq9vd4j1)、块 ID(例如 3f2a8c9b1d4e0756f8a2b3c1d9e4f0a5)和子块 ID(例如 e7b91f4a3c2d58069e1a4b7f3d2c8056)。

    2. 如需确定预留区块资源名称,请使用预留名称查询 Compute Engine 预留区块列表,并按区块 ID 进行过滤:

      gcloud compute reservations blocks list RESERVATION_NAME \
          --zone=ZONE \
          --project=PROJECT_ID \
          --filter="physicalTopology.block=BLOCK_ID"
      

      替换以下内容:

      • RESERVATION_NAME:预留的名称。
      • ZONE:预留所在的可用区。
      • PROJECT_ID:预留所在的项目 ID。
      • BLOCK_ID:从节点标签中检索到的块 ID。

      从输出中记录该块的名称。

    3. 如需识别预留子块资源名称,请使用预留名称和块名称查询预留子块列表,并按子块 ID 进行过滤:

      gcloud compute reservations sub-blocks list RESERVATION_NAME \
          --block-name=BLOCK_NAME \
          --zone=ZONE \
          --project=PROJECT_ID \
          --filter="physicalTopology.subBlock=SUBBLOCK_ID"
      

      替换以下内容:

      • RESERVATION_NAME:预留的名称。
      • BLOCK_NAME:预留块资源名称。
      • ZONE:预留所在的可用区。
      • PROJECT_ID:预留所在的项目 ID。
      • SUBBLOCK_ID:从节点标签中检索到的子块 ID。

      输出会显示匹配的预留子块的详细信息,包括其资源名称。

  2. 将预留划分为多个批次:将确定的容量预留子块划分为大小相等的批次。使用前面开始前的注意事项部分中计算时间限制列表项中介绍的公式确定批次大小。每个批次对应一个或多个预留子块,并且每个批次的大小必须至少为一个子块的大小。

  3. 执行主机维护:对于每个批次,请完成以下步骤:

    1. 选择一批预留子块并触发主机维护。您可以跨预留、预留块或预留子块触发维护。对于 A4X、A4X Max、TPU v6e 和 TPU7x 等机器类型,您必须以这种方式触发维护。维护作业是按子区块组执行的。使用 gcloud compute reservations sub-blocks perform-maintenance 命令:

      gcloud compute reservations sub-blocks perform-maintenance RESERVATION_NAME \
          --block-name=BLOCK_NAME \
          --sub-block-name=SUB_BLOCK_NAME \
          --zone=ZONE
      

      替换以下内容:

      • RESERVATION_NAME:预留的名称。
      • BLOCK_NAME:预留块的名称。
      • SUB_BLOCK_NAME:预留子块的名称。
      • ZONE:预留所在的可用区。

      Compute Engine 会同时开始排空和更新子块中的所有实例。此过程可能需要几个小时。

    2. 通过检查预留资源中的 upcomingGroupMaintenance 元数据字段,查看维护状态,从而监控维护状态。如需了解详情,请参阅查看预留维护状态。

    3. 对每个剩余批次重复上述步骤,直到完成所有批次的主机维护。

  4. 可选:升级 GKE 节点的版本:仅在所有预留子块的主机维护完成后执行此步骤,以避免将 GKE 节点部署在尚未完成维护的主机上。按照说明升级节点的 GKE 版本。

批量更新节点

如需为不支持子块的按需实例或预留分批执行滚动主机维护,请完成以下步骤:

  1. 确定要维护的节点:确定要执行维护的所有节点,并保存此列表。如需识别节点,请使用以下任一方法或手动选择节点:

    • 获取集群中使用加速器(TPU 或 GPU)的所有节点:

      kubectl get nodes -o json | jq -r '.items[] | select(.spec.taints[]? | select(.key=="nvidia.com/gpu" or .key=="google.com/tpu")) | .metadata.name'
      
    • 获取特定节点池中的所有节点:

      kubectl get nodes -l cloud.google.com/gke-nodepool=NODE_POOL_NAME --no-headers -o custom-columns=":metadata.name"
      

      将 NODE_POOL_NAME 替换为节点池的名称。

    • 获取具有特定标签的所有节点:

      kubectl get nodes -l LABEL -o jsonpath='{.items[*].metadata.name}'
      

      将 LABEL 替换为节点标签。

  2. 将节点分成批次:将确定的节点分成大小相等的批次。使用前面的开始前的注意事项部分中计算时间限制列表项中介绍的公式确定批次大小。

  3. 执行主机维护:对于每个批次,请完成以下步骤:

    1. 选择一批节点,然后使用 instances API 通过应用维护标签在实例层触发维护:

      kubectl label nodes LIST_OF_NODES_IN_BATCH cloud.google.com/perform-maintenance=true --overwrite
      

      将 LIST_OF_NODES_IN_BATCH 替换为批处理中以空格分隔的节点列表。例如 node-1 node-2 node-3。

      Compute Engine 会同时开始排空和更新底层实例。此过程可能需要几个小时。如需了解详情,请参阅正常终止过程。

    2. 监控主机维护的状态。维护完成后,GKE 会移除维护标签(如果已应用)。维护完成后,您可以在 Logging 中找到包含以下消息的日志:

      Maintenance window has completed for this instance. All maintenance
      notifications on the instance have been removed.
      
    3. 对每个剩余批次重复上述步骤,直到完成所有批次的主机维护。

  4. 可选:升级 GKE 节点的版本:仅在所有节点的主机维护完成后执行此步骤,以避免在尚未完成维护的主机上部署 GKE 节点。按照说明升级节点的 GKE 版本。

升级节点的 GKE 版本

考虑您要同时升级的节点数。使用并行策略时,您需要同时对整个节点池或多个节点池执行主机维护。使用滚动策略时,您需要分批执行主机维护。根据节点组的大小确定要使用的升级方法:

  • 并行策略:如果您的节点池在每个可用区中各有 100 个或更少的节点,请使用超额配置升级。如果您的节点池在每个可用区中都有超过 100 个节点,请删除并重新创建节点池。
  • 滚动策略:如果每个可用区、每个节点池的批次包含 100 个或更少的节点,请使用超额配置升级。如果每个可用区、每个节点池的批次超过 100 个节点,请删除并重新创建节点。

使用超额配置升级

  1. 配置超额配置升级,使用 maxUnavailable 设置来确定节点池中每个可用区可以同时不可用的节点数。例如,如果节点池中的一个可用区中有 18 个节点,请将 maxUnavailable 字段的值设置为 18。

    如果您没有多余容量,则在使用预留中的容量时,此设置效果最佳。如需详细了解为何使用此设置,请参阅在资源受限的环境中升级。

  2. 运行以下命令,升级节点池。如果您要升级多个节点池,请针对每个节点池运行以下命令:

    gcloud container clusters upgrade CLUSTER_NAME \
        --node-pool NODE_POOL_NAME \
        --cluster-version VERSION \
        --location CONTROL_PLANE_LOCATION \
        --quiet
    

    替换以下内容:

    • CLUSTER_NAME:您的集群的名称。
    • NODE_POOL_NAME:节点池的名称。
    • VERSION:节点池的推荐自动升级目标。如需了解详情,请参阅获取 Standard 集群节点池的升级信息。如果您的集群没有建议的自动升级目标,请查看 GKE 版本说明中的最新版本更新条目。
    • CONTROL_PLANE_LOCATION:集群控制平面的位置。

删除并重新创建节点

删除节点池,然后使用更高版本重新创建节点池:

  1. 删除节点池:

    gcloud container node-pools delete NODE_POOL_NAME \
        --cluster CLUSTER_NAME \
        --location CONTROL_PLANE_LOCATION
    
  2. 重新创建节点池,并使用 --cluster-version 标志传递新版本。传递节点池的建议自动升级目标。如需了解详情,请参阅获取 Standard 集群节点池的升级信息。如果您的集群没有建议的自动升级目标,请查看 GKE 版本说明中的最新版本更新条目。