GKE Standard ノードプールのトラブルシューティング


このページでは、GKE Standard モードのノードプールに関する問題を解決する方法について説明します。

さらにサポートが必要な場合は、Cloud カスタマーケアにお問い合わせください。

ノードプールの作成に関する問題

このセクションでは、Standard クラスタで新しいノードプールを作成するときに発生する可能性のある問題と、その修正方法について説明します。

問題: リソース不足が原因でノードプールの作成が失敗する

要件を満たす十分なハードウェアを利用できない Google Cloud ゾーンに、特定のハードウェアを含むノードプールを作成すると、次の問題が発生します。

ゾーンに十分なリソースがないためにノードプールの作成に失敗したことを確認するには、ログで関連するエラー メッセージを確認します。

  1. Google Cloud コンソールの [ログ エクスプローラ] に移動します。

    [ログ エクスプローラ] に移動

  2. [クエリ] フィールドに次のクエリを規定します。

    log_id(cloudaudit.googleapis.com/activity)
    resource.labels.cluster_name="CLUSTER_NAME"
    protoPayload.status.message:("ZONE_RESOURCE_POOL_EXHAUSTED" OR "does not have enough resources available to fulfill the request" OR "resource pool exhausted" OR "does not exist in zone")
    

    CLUSTER_NAME を GKE クラスタの名前に置き換えます。

  3. [クエリを実行] をクリックします。

以下のエラー メッセージのいずれかが表示される場合があります。

  • resource pool exhausted
  • The zone does not have enough resources available to fulfill the request. Try a different zone, or try again later.
  • ZONE_RESOURCE_POOL_EXHAUSTED
  • ZONE_RESOURCE_POOL_EXHAUSTED_WITH_DETAILS
  • Machine type with name 'MACHINE_NAME' does not exist in zone 'ZONE_NAME'

この問題を解決するには、次のことを試してください。

  • 選択した Google Cloud のリージョンまたはゾーンに必要とする特定のハードウェアがあることを確認します。特定のゾーンが特定のハードウェアをサポートしているかどうかを確認するには、Compute Engine の可用性の表を使用します。必要なハードウェアの可用性が高くなる可能性があるノードとして、別の Google Cloud のリージョンまたはゾーンを選択してください。
  • より小規模なマシンタイプでノードプールを作成します。コンピューティング容量の合計が変化しないように、ノードプール内のノード数を増やします。
  • 事前にリソースを予約するには、Compute Engine の容量の予約を使用します。
  • 要求された数のうち少なくとも指定された最小数のノードをプロビジョニングできる場合は、次のセクションで説明するベストエフォート型のプロビジョニングを使用して、ノードプールを正常に作成します。

ベスト エフォート型のプロビジョニング

特定のハードウェアでは、ベスト エフォート型のプロビジョニングを使用できます。これにより、少なくとも指定された数のノードをプロビジョニングできる場合に、ノードプールを正常に作成するよう GKE に指示します。GKE は、元のリクエストを満たすために、残りのノードのプロビジョニングを徐々に試みます。ベスト エフォート型のプロビジョニングを使用するように GKE に指示するには、次のコマンドを使用します。

gcloud container node-pools create NODE_POOL_NAME \
    --cluster=CLUSTER_NAME \
    --node-locations=ZONE1,ZONE2,... \
    --machine-type=MACHINE_TYPE
    --best-effort-provision \
    --min-provision-nodes=MINIMUM_NODES

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

  • NODE_POOL_NAME: 新しいノードプールの名前。
  • ZONE1,ZONE2,...: ノードの Compute Engine ゾーン。これらのゾーンは、選択したハードウェアをサポートしている必要があります。
  • MACHINE_TYPE: ノードの Compute Engine のマシンタイプ。例: a2-highgpu-1g
  • MINIMUM_NODES: GKE がノードプールをプロビジョニングして正常に作成するために必要なノードの最小数。省略した場合、デフォルトは 1 です。

たとえば、us-central1-c に NVIDIA A100 40 GB GPU が接続された 10 個のノードが必要な場合について考えてみましょう。GPU のリージョンとゾーンの可用性の表によると、このゾーンは A100 GPU をサポートしています。10 台の GPU マシンが使用できない場合にノードプールの作成が失敗することを回避するには、ベスト エフォート型のプロビジョニングを使用します。

gcloud container node-pools create a100-nodes \
    --cluster=ml-cluster \
    --node-locations=us-central1-c \
    --num-nodes=10 \
    --machine-type=a2-highgpu-1g \
    --accelerator=type=nvidia-tesla-a100,count=1 \
    --best-effort-provision \
    --min-provision-nodes=5

us-central1-c で使用可能な GPU が 5 つのみである場合でも、GKE はノードプールを作成します。GKE は、ノードプール内のノードが 10 ノードになるまで、時間の経過とともにノードをプロビジョニングしようとします。

エラー: インスタンスに「instance-template」メタデータが含まれていません

アップグレード、スケーリング、ノードの自動修復に失敗したノードプールのステータスとして、次のエラーが表示される場合があります。

Instance INSTANCE_NAME does not contain 'instance-template' metadata

このエラーは、GKE によって割り当てられた VM インスタンスのメタデータが破損したことを示します。これは通常、カスタム作成の自動化またはスクリプトが新しいインスタンス メタデータ(block-project-ssh-keys など)を追加しようとしたときに、値を追加または更新するだけでなく、既存のメタデータも削除した場合に発生します。VM インスタンスのメタデータについては、カスタム メタデータの設定をご覧ください。

重要なメタデータ値(instance-templatekube-labelskubelet-configkubeconfigcluster-nameconfigure-shcluster-uid)が削除されると、これらの値は GKE のオペレーションに不可欠であるため、ノードまたはノードプール全体が不安定な状態になる可能性があります。

インスタンス メタデータが破損した場合は、破損した VM インスタンスを含むノードプールを再作成してメタデータを復元することをおすすめします。クラスタにノードプールを追加して新しいノードプールのノード数を増やすと同時に、別のノードプールでノードの閉鎖と削除を行う必要があります。ノードプール間でワークロードを移行する手順をご覧ください。

インスタンス メタデータを編集したユーザーと日時を確認するには、Compute Engine 監査ロギング情報を確認するか、次のようなクエリを使用してログ エクスプローラでログを検索します。

resource.type="gce_instance_group_manager"
protoPayload.methodName="v1.compute.instanceGroupManagers.setInstanceTemplate"

ログには、リクエスト送信元の IP アドレスとユーザー エージェントが記録されています。次に例を示します。

requestMetadata: {
  callerIp: "REDACTED"
  callerSuppliedUserAgent: "google-api-go-client/0.5 GoogleContainerEngine/v1"
}

ノードプール間でワークロードを移行する

ワークロードをあるノードプールから別のノードプールに移行するには、次の操作を行います。ノードプール内のノードのマシン属性を変更する場合は、ノードマシン属性を変更して垂直方向にスケーリングするをご覧ください。

Pod を新しいノードプールに移行する方法

Pod を新しいノードプールに移行するには、次のことを行う必要があります。

  1. 既存のノードプール内のノードを閉鎖する: これにより、既存のノードプール内のノードがスケジュール不可に設定されます。スケジュール不可に設定されると、Kubernetes はこれらのノードに新しい Pod をスケジュールしなくなります。

  2. 既存のノードプールのノードをドレインする: これにより、既存のノードプールのノードで実行されているワークロードが正常に強制排除されます。

これらの手順はノードごとに個別に行われ、既存のノードプールで実行されている Pod が正常に終了します。Kubernetes は、これらのノードを他の使用可能なノードに再スケジュールします。

Kubernetes がアプリケーションを正常に終了するには、コンテナで SIGTERM 信号を処理する必要があります。このアプローチを使用して、クライアントへのアクティブな接続を閉じ、データベース トランザクションをクリーンな方法で commit またはロールバックします。Pod 内のコンテナを停止するまでに Kubernetes が待機する時間を Pod マニフェストの spec.terminationGracePeriodSeconds フィールドに指定できます。デフォルトは 30 秒です。詳細については、Kubernetes のドキュメントで Pod の終了に関する説明をご覧ください。

ノードの閉鎖とドレインを行うには、kubectl cordon コマンドと kubectl drain コマンドを使用します。

ノードプールを作成してワークロードを移行する

ワークロードを新しいノードプールに移行するには、新しいノードプールを作成し、既存のノードプール内のノードを閉鎖してドレインします。

  1. クラスタにノードプールを追加します。

    次のコマンドを実行して、新しいノードプールが作成されたことを確認します。

    gcloud container node-pools list --cluster CLUSTER_NAME
    
  2. 次のコマンドを実行して、Pod が実行されているノードを確認します(NODE 列を参照)。

    kubectl get pods -o=wide
    
  3. 既存のノードプール内のノードのリストを取得します。EXISTING_NODE_POOL_NAME は、名前に置き換えます。

    kubectl get nodes -l cloud.google.com/gke-nodepool=EXISTING_NODE_POOL_NAME
    
  4. 次に、kubectl cordon NODE コマンドを実行します(NODE は前のコマンドで確認した名前で置き換えます)。次のシェルコマンドは、既存のノードプール内の各ノードを繰り返し処理し、スケジュール不可としてマークします。

    for node in $(kubectl get nodes -l cloud.google.com/gke-nodepool=EXISTING_NODE_POOL_NAME -o=name); do
      kubectl cordon "$node";
    done
    
  5. 必要に応じて、既存のノードプールで実行されているワークロードを更新して、ラベル cloud.google.com/gke-nodepool:NEW_NODE_POOL_NAME の nodeSelector を追加します。ここで、NEW_NODE_POOL_NAME は新しいノードプールの名前です。これにより、GKE はこれらのワークロードを新しいノードプールのノードに配置します。

  6. 割り当てられた猶予期間が 10 秒間の Pod は強制排除し、各ノードをドレインします。

    for node in $(kubectl get nodes -l cloud.google.com/gke-nodepool=EXISTING_NODE_POOL_NAME -o=name); do
      kubectl drain --force --ignore-daemonsets --delete-emptydir-data --grace-period=GRACEFUL_TERMINATION_SECONDS  "$node";
    done
    

    GRACEFUL_TERMINATION_PERIOD_SECONDS は、正常に終了するために必要な時間に置き換えます。

  7. 次のコマンドを実行して、既存のノードプール内のノードのステータスが SchedulingDisabled であることをノードリストで確認します。

    kubectl get nodes
    

    また、新しいノードプールのノードで Pod が実行されています。

    kubectl get pods -o=wide
    
  8. 既存のノードプールが不要になった場合は削除します。

    gcloud container node-pools delete default-pool --cluster CLUSTER_NAME
    

次のステップ

さらにサポートが必要な場合は、Cloud カスタマーケアにお問い合わせください。