トレーニングと推論のワークロードを実行しているノードのホスト メンテナンスを行う

このドキュメントでは、Google Kubernetes Engine(GKE)クラスタ内のノードの基盤となる Compute Engine インスタンスのホスト メンテナンスを行う方法について説明します。このメンテナンスを積極的に管理する必要があるのは、GPU や TPU を搭載したインスタンスなど、ライブ マイグレーションを行わない特定のタイプの Compute Engine インスタンスのみです。このドキュメントで説明する戦略は、トレーニング ワークロードと推論ワークロードに適しています。個々のノードに対してホスト メンテナンスを手動で実行する必要がある場合や、ワークロードが自動ホスト メンテナンスを許容できる場合は、GKE でホスト メンテナンスを行う方法をご覧ください

これらの戦略では、ノードのグループに対してホスト メンテナンスを実行し、必要に応じて GKE クラスタのアップグレードを開始します。

トレーニング ワークロードのノードなど、1 回のダウンタイムで済むワークロードのノードには、並列戦略を使用します。推論ワークロードのノードなど、リソースの大部分の可用性を維持しながらダウンタイムをバッチ処理できるワークロードのノードには、ローリング戦略を使用します。

並列戦略を使用してトレーニング ワークロードのノードを更新する

この戦略では、アクセラレータを使用するノードのグループに対して同時に変更を行います。この戦略は、トレーニング ワークロードに使用できます。また、グループ内のすべてのノードと、それらのノードで実行されるワークロードに対して、完全なダウンタイムを 1 回だけ設けることで、変更による中断を最小限に抑えることができる他のタイプのワークロードにも使用できます。

この戦略の手順の概要は次のとおりです。

  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 以上である必要があります。
  • 特定のワークロード タイプを確認する: 構成タイプごとに次の点を考慮してください:
    • Mixture of Experts(MOE): バッチ処理戦略 で、各モデルに必要な最小数のレプリカが維持されるようにします。
    • 分離されたサービング: バッチを計画する際に、分離された設定に関与するすべてのレプリカを追跡します。
    • マルチホスト ノードプール(TPU、MNNVL): これらの構成では、通常、ノードプール全体を一度に停止します。複数のノードプールにまたがる障害ドメインを適切に計画します。

ローリング アップデートをバッチで実行する

ローリング ホスト メンテナンスの更新を行うには、グループ化されたメンテナンス スケジューリングを使用する予約の容量を 1 つ以上のサブブロックのバッチで更新するか、独立したメンテナンス スケジューリングを使用してクラスタ内の特定のノードセットを名前で更新します。

リソースに適した戦略を選択します。

サブブロックのバッチで予約を更新する

サブブロックのバッチで容量予約のローリング ホスト メンテナンスを行う手順は次のとおりです。

  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. 予約をバッチに分割する: 特定した容量予約サブブロックを均等なバッチに分割します。バッチサイズは、前の始める前の検討事項セクションの時間制約を計算する のリスト項目で説明した式を使用して決定します。各バッチは 1 つ以上の予約サブブロックに対応し、各バッチはサブブロックのサイズ以上である必要があります。

  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 設定を使用して、ノードプール内のゾーンごとに同時に使用できないノードの数を決定します。たとえば、ノードプールの 1 つのゾーンに 18 個のノードがある場合は、maxUnavailable フィールドの値を 18 に設定します。

    この設定は、余分な容量がない予約の容量を使用する場合に最適です。この 設定を使用する理由について詳しくは、リソースが制限された 環境でのアップグレードをご覧ください

  2. 次のコマンドを実行してノードプールをアップグレードします。複数のノードプールをアップグレードする場合は、ノードプールごとにこのコマンドを実行します。

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

    次のように置き換えます。

ノードを削除して再作成する

ノードプールを削除し、新しいバージョンを使用して再作成します。

  1. ノードプールを削除します。

    gcloud container node-pools delete NODE_POOL_NAME \
        --cluster CLUSTER_NAME \
        --location CONTROL_PLANE_LOCATION
    
  2. --cluster-version フラグを使用して、新しいバージョンを渡してノードプールを再作成します。ノードプールに推奨される自動アップグレード ターゲットを渡します。詳細については、 Standard クラスタのノード プールのアップグレード情報を取得するをご覧ください。 クラスタに推奨される自動アップグレード ターゲットがない場合は、 GKE リリースノートの最新の「バージョン アップデート」エントリを確認してください。