このページでは、GKE Standard モードのノードプールに関する問題を解決する方法について説明します。
さらにサポートが必要な場合は、Cloud カスタマーケアにお問い合わせください。ノードプールの作成に関する問題
このセクションでは、Standard クラスタで新しいノードプールを作成するときに発生する可能性のある問題と、その修正方法について説明します。
問題: リソース不足が原因でノードプールの作成に失敗する
要件を満たす十分なハードウェアを利用できない Google Cloud ゾーンに、特定のハードウェアを含むノードプールを作成すると、次の問題が発生します。
ゾーンに十分なリソースがないためにノードプールの作成に失敗したことを確認するには、ログで関連するエラー メッセージを確認します。
Google Cloud コンソールの [ログ エクスプローラ] に移動します。
[クエリ] フィールドに次のクエリを規定します。
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 クラスタの名前に置き換えます。[クエリを実行] をクリックします。
以下のエラー メッセージのいずれかが表示される場合があります。
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-template
、kube-labels
、kubelet-config
、kubeconfig
、cluster-name
、configure-sh
、cluster-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 を新しいノードプールに移行するには、次のことを行う必要があります。
既存のノードプールを閉鎖する: これにより、既存のノードプール内のノードがスケジュール不可に設定されます。スケジュール不可に設定されると、Kubernetes はこれらのノードに新しい Pod をスケジュールしなくなります。
既存のノードプールをドレインする: これにより、既存のノードプールのノードで実行されているワークロードが正常に強制排除されます。
これらの手順により、既存のノードプールで実行されている Pod が正常に終了します。Kubernetes は、これらのノードを他の使用可能なノードに再スケジュールします。
Kubernetes がアプリケーションを正常に終了するには、コンテナで SIGTERM 信号を処理する必要があります。このアプローチを使用して、クライアントへのアクティブな接続を閉じ、データベース トランザクションをクリーンな方法で commit またはロールバックします。Pod 内のコンテナを停止するまでに Kubernetes が待機する時間を Pod マニフェストの spec.terminationGracePeriodSeconds
フィールドに指定できます。デフォルトは 30 秒です。詳細については、Kubernetes のドキュメントで Pod の終了に関する説明をご覧ください。
ノードの閉鎖とドレインを行うには、kubectl cordon
コマンドと kubectl drain
コマンドを使用します。
ノードプールを作成してワークロードを移行する
ワークロードを新しいノードプールに移行するには、新しいノードプールを作成し、既存のノードプール内のノードを閉鎖してドレインします。
クラスタにノードプールを追加します。
次のコマンドを実行して、新しいノードプールが作成されたことを確認します。
gcloud container node-pools list --cluster CLUSTER_NAME
次のコマンドを実行して、Pod が実行されているノードを確認します(
NODE
列を参照)。kubectl get pods -o=wide
既存のノードプール内のノードのリストを取得します。
EXISTING_NODE_POOL_NAME
は、名前に置き換えます。kubectl get nodes -l cloud.google.com/gke-nodepool=EXISTING_NODE_POOL_NAME
次に、
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
必要に応じて、既存のノードプールで実行されているワークロードを更新して、ラベル
cloud.google.com/gke-nodepool:NEW_NODE_POOL_NAME
の nodeSelector を追加します。ここで、NEW_NODE_POOL_NAME
は新しいノードプールの名前です。これにより、GKE はこれらのワークロードを新しいノードプールのノードに配置します。割り当てられた猶予期間が 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
は、正常に終了するために必要な時間に置き換えます。次のコマンドを実行して、既存のノードプール内のノードのステータスが
SchedulingDisabled
であることをノードリストで確認します。kubectl get nodes
また、新しいノードプールのノードで Pod が実行されています。
kubectl get pods -o=wide
既存のノードプールが不要になった場合は削除します。
gcloud container node-pools delete default-pool --cluster CLUSTER_NAME