Dynamic Workload Scheduler を使用してバッチ ワークロード用の GPU をデプロイする


このページでは、Dynamic Workload Scheduler と ProvisioningRequest を使用して、GPU を利用する大規模なバッチ ワークロードでの GPU の取得を最適化する方法について説明します。

Dynamic Workload Scheduler は、定義された GPU 容量管理条件を使用してオフピーク時に実行できる大規模なバッチ ワークロードにおすすめします。そのようなワークロードには、ディープ ラーニング モデルのトレーニングや、アトミック プロビジョニング モデルで大量の GPU を必要とする(つまりすべてのリソースが同時に作成される)シミュレーションなどがあります。

Google Kubernetes Engine(GKE)で Dynamic Workload Scheduler を使用せずに GPU ワークロードを実行するには、GKE Standard ノードプールで GPU を実行するをご覧ください。

Dynamic Workload Scheduler を使用する場合

ワークロードが次のすべての条件を満たしている場合は、Dynamic Workload Scheduler を使用することをおすすめします。

  • ワークロードを実行するために GPU をリクエストする。
  • 予約済みの GPU 容量が限られているかゼロであり、GPU リソースの入手可能性を改善したい。
  • ワークロードに時間的な制約がなく、リクエストしたすべての容量を取得するまで待つことが可能なユースケースである。たとえば、ピーク時以外に GPU リソースを GKE が割り当てる場合などです。
  • ワークロードに複数のノードが必要であり、すべての GPU ノードがプロビジョニングされて同時に準備が整うまでワークロードの実行を開始できない(分散 ML トレーニングなど)。

始める前に

始める前に、次の作業が完了していることを確認してください。

  • Google Kubernetes Engine API を有効にする。
  • Google Kubernetes Engine API の有効化
  • このタスクに Google Cloud CLI を使用する場合は、gcloud CLI をインストールして初期化する。すでに gcloud CLI をインストールしている場合は、gcloud components update を実行して最新のバージョンを取得する。

Dynamic Workload Scheduler でノードプールを使用する

次の 3 つの方法のいずれかを使用して、Dynamic Workload Scheduler がクラスタ内の特定のノードプールで動作するように指定できます。

ノードプールを作成する

gcloud CLI を使用して、Dynamic Workload Scheduler が有効なノードプールを作成します。

gcloud beta container node-pools create NODEPOOL_NAME \
    --cluster=CLUSTER_NAME \
    --location=LOCATION \
     --enable-queued-provisioning \
    --accelerator type=GPU_TYPE,count=AMOUNT,gpu-driver-version=DRIVER_VERSION \
    --machine-type=MACHINE_TYPE \
    --enable-autoscaling  \
    --num-nodes=0   \
    --total-max-nodes TOTAL_MAX_NODES  \
    --location-policy=ANY  \
    --reservation-affinity=none  \
    --no-enable-autorepair

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

  • NODEPOOL_NAME: ノードプールに付ける名前。
  • CLUSTER_NAME: クラスタの名前。
  • LOCATION: クラスタの Compute Engine リージョン(us-central1 など)。
  • GPU_TYPE: GPU タイプ
  • AMOUNT: ノードプール内のノードに接続する GPU の数。
  • DRIVER_VERSION: インストールする NVIDIA ドライバのバージョン。次のいずれか 1 つを指定できます。
    • default: GKE バージョンに対応するデフォルトのドライバ バージョンをインストールします。
    • latest: GKE バージョンに対応する最新のドライバ バージョンをインストールします。Container-Optimized OS を使用するノードでのみ指定できます。
  • TOTAL_MAX_NODES: ノードプール全体における、ノードが自動スケーリングする最大数。
  • MACHINE_TYPE: ノードの Compute Engine マシンタイプ。アクセラレータ最適化マシンタイプを選択することをおすすめします。

必要に応じて、次のフラグを使用できます。

  • --no-enable-autoupgrade: 推奨。ノードの自動アップグレードを無効にします。リリース チャンネルに登録されていない GKE クラスタでのみサポートされます。詳細については、既存のノードプールのノードの自動アップグレードを無効にするをご覧ください。
  • --node-locations=COMPUTE_ZONES: GKE が GPU ノードを作成する 1 つ以上のゾーンのカンマ区切りリスト。このゾーンはクラスタと同じリージョンに存在する必要があります。使用可能な GPU があるゾーンを選択します。
  • --enable-gvnic: このフラグにより、GPU ノードプールの gVNIC が有効になり、ネットワーク トラフィック速度が向上します。

このコマンドを実行すると、次の構成のノードプールが作成されます。

  • キューに格納されたプロビジョニングとクラスタの自動スケーリングが有効です。
  • ノードプールの初期ノード数はゼロです。
  • --enable-queued-provisioning フラグにより、Dynamic Workload Scheduler が有効になり、ノードプールに cloud.google.com/gke-queued taint が追加されます。
  • --no-enable-autorepair フラグと --no-enable-autoupgrade フラグにより、ノードの自動修復と自動アップグレード(修復 / アップグレード対象のノードで実行中のワークロードが中断される可能性がある)が無効になります。ノードの自動アップグレードは、リリース チャンネルに登録されていないクラスタでのみ無効にできます。

既存のノードプールを更新して Dynamic Workload Scheduler を有効にする

既存のノードプールで Dynamic Workload Scheduler を有効にするノードプールを正しく構成するための前提条件を確認します。

前提条件

  • --reservation-affinity=none フラグを指定してノードプールを作成します。ノードプールの作成後に予約のアフィニティを変更できないため、このフラグは後で Dynamic Workload Scheduler を有効にするために必要です。

  • クラスタが正常に機能するように、Dynamic Workload Scheduler 処理を有効にしていないノードプールを少なくとも 1 つ維持するようにしてください。

  • ノードプールが空であることを確認します。ノードプールのサイズを変更して、ノード数を 0 に設定できます。

  • 自動スケーリングが有効になっており、正しく構成されていることを確認します。

  • 自動修復が無効になっていることを確認します。

既存のノードプールで Dynamic Workload Scheduler を有効にする

既存のノードプールに対して Dynamic Workload Scheduler を有効にするには、gcloud CLI を使用します。

gcloud beta container node-pools update NODEPOOL_NAME \
    --cluster=CLUSTER_NAME \
    --location=LOCATION \
     --enable-queued-provisioning

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

  • NODEPOOL_NAME: 選択したノードプールの名前。
  • CLUSTER_NAME: クラスタの名前。
  • LOCATION: クラスタの Compute Engine リージョン(us-central1 など)。

このノードプールの更新コマンドを実行すると、次の構成が変更されます。

  • --enable-queued-provisioning フラグにより、Dynamic Workload Scheduler が有効になり、ノードプールに cloud.google.com/gke-queued taint が追加されます。

必要に応じて、次のノードプール設定を更新することもできます。

  • ノードの自動アップグレードを無効にする: Dynamic Workload Scheduler を使用する場合、ノードプールのアップグレードはサポートされていないため、ノードの自動アップグレードを無効にすることをおすすめします。ノードの自動アップグレードを無効にする場合は、GKE クラスタがリリース チャンネルに登録されていないことを確認してください。
  • GPU ノードプールの gVNIC を有効にする: Google Virtual NIC(gVNIC)により、GPU ノードのネットワーク トラフィック速度が向上します。

ノードの自動プロビジョニングを有効にして、Dynamic Workload Scheduler のノードプールを作成する

ノードの自動プロビジョニングを使用すると、バージョン 1.29.2-gke.1553000 以降で稼働しているクラスタで Dynamic Workload Scheduler に対応するノードプールを管理できます。ノードの自動プロビジョニングを有効にして Dynamic Workload Scheduler を有効にすると、GKE により、関連するワークロードに必要なリソースを含むノードプールが作成されます。

ノードの自動プロビジョニングを有効にするには、次の設定を考慮したうえで、GPU の上限を構成するの手順に沿って操作します。

Dynamic Workload Scheduler でバッチ ワークロードを実行する

Dynamic Workload Scheduler を使用する場合は、Kueue を使用することをおすすめします。Kueue は Job キューイングを実装しており、チーム間で公平にリソースを共有するための割り当てや階層に基づいて Job を待機するタイミングや開始するタイミングを決定します。これにより、キューに登録された VM を使用するために必要な設定が簡単になります。

独自の内部バッチ スケジューリング ツールまたはプラットフォームを使用する場合は、Kueue なしで Dynamic Workload Scheduler を使用できます。Kueue を使用しない Job の Dynamic Workload Scheduler を構成するには、Kueue を使用しない Job の Dynamic Workload Scheduler をご覧ください。

Kueue を使用する Job の Dynamic Workload Scheduler

以降のセクションでは、Kueue を使用して Job の Dynamic Workload Scheduler を構成する方法について説明します。次の一般的なノードプールの設定を構成できます。

  • Dynamic Workload Scheduler ノードプールの設定。
  • 予約ノードプールと Dynamic Workload Scheduler ノードプールの設定。

このセクションでは、ai-on-gke リポジトリの dws-examples ディレクトリのサンプルを使用します。サンプルは、Apache2 ライセンスで dws-examples ディレクトリに公開されています。

環境を準備する

  1. Cloud Shell で、次のコマンドを実行します。

    git clone https://github.com/GoogleCloudPlatform/ai-on-gke
    cd ai-on-gke/tutorials-and-examples/workflow-orchestration/dws-examples
    
  2. クラスタに最新の Kueue バージョンをインストールします。

    VERSION=v0.7.0
    kubectl apply --server-side -f https://github.com/kubernetes-sigs/kueue/releases/download/$VERSION/manifests.yaml
    

Kueue のインストールの詳細については、インストールをご覧ください。

Dynamic Workload Scheduler ノードプールのみの設定用の Kueue リソースを作成する

次のマニフェストを使用して、dws-cluster-queue という名前のクラスタレベルのキューdws-local-queue という名前の LocalQueue Namespace を作成します。この Namespace の dws-cluster-queue キューを参照する Job は、Dynamic Workload Scheduler を使用して GPU リソースを取得します。

apiVersion: kueue.x-k8s.io/v1beta1
kind: ResourceFlavor
metadata:
  name: "default-flavor"
---
apiVersion: kueue.x-k8s.io/v1beta1
kind: AdmissionCheck
metadata:
  name: dws-prov
spec:
  controllerName: kueue.x-k8s.io/provisioning-request
  parameters:
    apiGroup: kueue.x-k8s.io
    kind: ProvisioningRequestConfig
    name: dws-config
---
apiVersion: kueue.x-k8s.io/v1beta1
kind: ProvisioningRequestConfig
metadata:
  name: dws-config
spec:
  provisioningClassName: queued-provisioning.gke.io
  managedResources:
  - nvidia.com/gpu
---
apiVersion: kueue.x-k8s.io/v1beta1
kind: ClusterQueue
metadata:
  name: "dws-cluster-queue"
spec:
  namespaceSelector: {} 
  resourceGroups:
  - coveredResources: ["cpu", "memory", "nvidia.com/gpu"]
    flavors:
    - name: "default-flavor"
      resources:
      - name: "cpu"
        nominalQuota: 10000  # Infinite quota.
      - name: "memory"
        nominalQuota: 10000Gi # Infinite quota.
      - name: "nvidia.com/gpu"
        nominalQuota: 10000  # Infinite quota.
  admissionChecks:
  - dws-prov
---
apiVersion: kueue.x-k8s.io/v1beta1
kind: LocalQueue
metadata:
  namespace: "default"
  name: "dws-local-queue"
spec:
  clusterQueue: "dws-cluster-queue"
---

LocalQueue をデプロイします。

kubectl create -f ./dws-queues.yaml

出力は次のようになります。

resourceflavor.kueue.x-k8s.io/default-flavor created
admissioncheck.kueue.x-k8s.io/dws-prov created
provisioningrequestconfig.kueue.x-k8s.io/dws-config created
clusterqueue.kueue.x-k8s.io/dws-cluster-queue created
localqueue.kueue.x-k8s.io/dws-local-queue created

Dynamic Workload Scheduler を使用する Job を他の Namespace で実行する場合は、上記のテンプレートを使用して追加の LocalQueues を作成できます。

Job を実行する

次のマニフェストのサンプルの Job は Dynamic Workload Scheduler を使用します。

apiVersion: batch/v1
kind: Job
metadata:
  name: sample-job
  namespace: default
  labels:
    kueue.x-k8s.io/queue-name: dws-local-queue
  annotations:
    provreq.kueue.x-k8s.io/maxRunDurationSeconds: "600"
spec:
  parallelism: 1
  completions: 1
  suspend: true
  template:
    spec:
      nodeSelector:
        cloud.google.com/gke-nodepool: NODEPOOL_NAME
      tolerations:
      - key: "nvidia.com/gpu"
        operator: "Exists"
        effect: "NoSchedule"
      containers:
      - name: dummy-job
        image: gcr.io/k8s-staging-perf-tests/sleep:v0.0.3
        args: ["120s"]
        resources:
          requests:
            cpu: "100m"
            memory: "100Mi"
            nvidia.com/gpu: 1
          limits:
            cpu: "100m"
            memory: "100Mi"
            nvidia.com/gpu: 1
      restartPolicy: Never

このマニフェストには、Dynamic Workload Scheduler の構成に関連する次のフィールドが含まれます。

  • kueue.x-k8s.io/queue-name: dws-local-queue ラベルは、Kueue がその Job のオーケストレーションを担当していることを GKE に示します。このラベルは、Job が追加されるキューも定義します。
  • suspend: true フラグを指定すると、GKE は Job リソースを作成しますが、Pod はまだスケジュールされません。ノードで Job の実行準備が整うと、Kueue はこのフラグを false に変更します。
  • nodeSelector は、指定されたノードプールでのみジョブをスケジュールするように GKE に指示します。この値は、NODEPOOL_NAME(キューに格納されたプロビジョニングを有効にするノードプールの名前)と一致している必要があります。
  1. Job を実行します。

    kubectl create -f ./job.yaml
    

    出力は次のようになります。

    job.batch/sample-job created
    
  2. Job のステータスを確認します。

    kubectl describe job sample-job
    

    出力は次のようになります。

    Events:
      Type    Reason            Age    From                        Message
      ----    ------            ----   ----                        -------
      Normal  Suspended         5m17s  job-controller              Job suspended
      Normal  CreatedWorkload   5m17s  batch/job-kueue-controller  Created Workload: default/job-sample-job-7f173
      Normal  Started           3m27s  batch/job-kueue-controller  Admitted by clusterQueue dws-cluster-queue
      Normal  SuccessfulCreate  3m27s  job-controller              Created pod: sample-job-9qsfd
      Normal  Resumed           3m27s  job-controller              Job resumed
      Normal  Completed         12s    job-controller              Job completed
    

Dynamic Workload Scheduler と Kueue のインテグレーションは、オープンソース エコシステムで利用可能な次のような他のワークロード タイプもサポートしています。

  • RayJob
  • JobSet v0.5.2 以降
  • Kubeflow MPIJob、TFJob、PyTorchJob
  • ワークフロー オーケストレーターで頻繁に使用される Kubernetes Pod
  • Flux ミニクラスタ

このサポートの詳細については、Kueue のバッチユーザーをご覧ください。

予約ノードプールと Dynamic Workload Scheduler ノードプールの設定用の Kueue リソースを作成する

次のマニフェストでは、2 つの異なるノードプール(reservation-nodepooldws-nodepool)に関連付けられた 2 つの ResourceFlavors を作成します。これらのノードプールの名前は例示的な名前にすぎません。これらの名前は、ノードプールの構成に応じて変更してください。また、ClusterQueue 構成では、受信 Job は reservation-nodepool を使用しようとします。容量がない場合、これらの Job は Dynamic Workload Scheduler を使用して GPU リソースを取得します。

apiVersion: kueue.x-k8s.io/v1beta1
kind: ResourceFlavor
metadata:
  name: "reservation"
spec:
  nodeLabels:
    cloud.google.com/gke-nodepool: "reservation-nodepool" # placeholder value
---
apiVersion: kueue.x-k8s.io/v1beta1
kind: ResourceFlavor
metadata:
  name: "dws"
spec:
  nodeLabels:
    cloud.google.com/gke-nodepool: "dws-nodepool" # placeholder value
---
apiVersion: kueue.x-k8s.io/v1beta1
kind: ClusterQueue
metadata:
  name: "cluster-queue"
spec:
  namespaceSelector: {} # match all.
  resourceGroups:
  - coveredResources: ["cpu", "memory", "nvidia.com/gpu"]
    flavors:
    - name: "reservation" # first we try reservation
      resources:
      - name: "cpu"
        nominalQuota: 9
      - name: "memory"
        nominalQuota: 36Gi
      - name: "nvidia.com/gpu"
        nominalQuota: 9
    - name: "dws"         # if reservation is saturated we try dws
      resources:
      - name: "cpu"
        nominalQuota: 10000   # Infinite quota.
      - name: "memory"
        nominalQuota: 10000Gi # Infinite quota.
      - name: "nvidia.com/gpu"
        nominalQuota: 10000   # Infinite quota.
  admissionChecksStrategy:
    admissionChecks:
      - name: "dws-prov"
        onFlavors: [dws]
---
apiVersion: kueue.x-k8s.io/v1beta1
kind: LocalQueue
metadata:
  namespace: "default"
  name: "user-queue"
spec:
  clusterQueue: "cluster-queue"
---
apiVersion: kueue.x-k8s.io/v1beta1
kind: AdmissionCheck
metadata:
  name: dws-prov
spec:
  controllerName: kueue.x-k8s.io/provisioning-request
  parameters:
    apiGroup: kueue.x-k8s.io
    kind: ProvisioningRequestConfig
    name: dws-config
---
apiVersion: kueue.x-k8s.io/v1beta1
kind: ProvisioningRequestConfig
metadata:
  name: dws-config
spec:
  provisioningClassName: queued-provisioning.gke.io
  managedResources:
  - nvidia.com/gpu

次のコマンドを使用してマニフェストをデプロイします。

kubectl create -f ./dws_and_reservation.yaml

出力は次のようになります。

resourceflavor.kueue.x-k8s.io/reservation created
resourceflavor.kueue.x-k8s.io/dws created
clusterqueue.kueue.x-k8s.io/cluster-queue created
localqueue.kueue.x-k8s.io/user-queue created
admissioncheck.kueue.x-k8s.io/dws-prov created
provisioningrequestconfig.kueue.x-k8s.io/dws-config created

Job を実行する

前の設定とは異なり、このマニフェストには nodeSelector フィールドが含まれていません。これは、ClusterQueue の空き容量に応じて Kueue によって入力されるためです。

apiVersion: batch/v1
kind: Job
metadata:
  generateName: sample-job-
  namespace: default
  labels:
    kueue.x-k8s.io/queue-name: user-queue
  annotations:
    provreq.kueue.x-k8s.io/maxRunDurationSeconds: "600"
spec:
  parallelism: 1
  completions: 1
  suspend: true
  template:
    spec:
      tolerations:
      - key: "nvidia.com/gpu"
        operator: "Exists"
        effect: "NoSchedule"
      containers:
      - name: dummy-job
        image: gcr.io/k8s-staging-perf-tests/sleep:v0.0.3
        args: ["120s"]
        resources:
          requests:
            cpu: "100m"
            memory: "100Mi"
            nvidia.com/gpu: 1
          limits:
            cpu: "100m"
            memory: "100Mi"
            nvidia.com/gpu: 1
      restartPolicy: Never
  1. Job を実行します。

    kubectl create -f ./job-without-node-selector.yaml
    

    出力は次のようになります。

    job.batch/sample-job-v8xwm created
    

Job で使用するノードプールを確認するには、Job で使用する ResourceFlavor を確認する必要があります。

トラブルシューティング

Kueue のトラブルシューティングの詳細については、Kueue でのプロビジョニング リクエストのトラブルシューティングをご覧ください。

Kueue を使用しない Job の Dynamic Workload Scheduler

Job ごとに ProvisioningRequest API を使用してリクエストを作成します。 Dynamic Workload Scheduler は Pod を起動するのではなく、ノードのプロビジョニングのみを行います。

  1. 次の provisioning-request.yaml マニフェストを作成します。

    apiVersion: v1
    kind: PodTemplate
    metadata:
      name: POD_TEMPLATE_NAME
      namespace: NAMESPACE_NAME
      labels:
        cloud.google.com/apply-warden-policies: "true"
    template:
      spec:
        nodeSelector:
            cloud.google.com/gke-nodepool: NODEPOOL_NAME
        tolerations:
            - key: "nvidia.com/gpu"
              operator: "Exists"
              effect: "NoSchedule"
        containers:
            - name: pi
              image: perl
              command: ["/bin/sh"]
              resources:
                limits:
                  cpu: "700m"
                  nvidia.com/gpu: 1
                requests:
                  cpu: "700m"
                  nvidia.com/gpu: 1
        restartPolicy: Never
    ---
    apiVersion: autoscaling.x-k8s.io/v1beta1
    kind: ProvisioningRequest
    metadata:
      name: PROVISIONING_REQUEST_NAME
      namespace: NAMESPACE_NAME
    spec:
      provisioningClassName: queued-provisioning.gke.io
      parameters:
        maxRunDurationSeconds: "MAX_RUN_DURATION_SECONDS"
      podSets:
      - count: COUNT
        podTemplateRef:
          name: POD_TEMPLATE_NAME
    

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

    • NAMESPACE_NAME: Kubernetes Namespace の名前。この Namespace は Pod の Namespace と同じにする必要があります。
    • PROVISIONING_REQUEST_NAME: ProvisioningRequest の名前。この名前は Pod のアノテーションで参照します。
    • MAX_RUN_DURATION_SECONDS: ノードの最大実行時間(秒)。最大実行時間はデフォルトの 7 日間です(省略可)。詳細については、Dynamic Workload Scheduler の仕組みをご覧ください。この値は、リクエストの作成後は変更できません。このフィールドは、GKE バージョン 1.28.5-gke.1355000 以降のプレビューで使用できます。
    • COUNT: リクエストする Pod 数。ノードは 1 つのゾーンでアトミックにスケジュールされます。
    • POD_TEMPLATE_NAME: Kubernetes の標準名。GKE は Provisioning Request PodSet でこの値を参照します。
    • NODEPOOL_NAME: ノードプールに付ける名前。
  1. 次のようにマニフェストを適用します。

    kubectl apply -f provisioning-request.yaml
    

Pod を構成する

Job仕様で、次のアノテーションを使用して Pod を ProvisioningRequest にリンクします。

apiVersion: batch/v1
kind: Job
spec:
  template:
    metadata:
      annotations:
        cluster-autoscaler.kubernetes.io/consume-provisioning-request: PROVISIONING_REQUEST_NAME
        cluster-autoscaler.kubernetes.io/provisioning-class-name: "queued-provisioning.gke.io"
    spec:
      ...

Pod のアノテーション キー cluster-autoscaler.kubernetes.io/consume-provisioning-request は、消費する ProvisioningRequest を定義します。GKE は consume-provisioning-requestprovisioning-class-name のアノテーションを使用して次の処理を行います。

  • Dynamic Workload Scheduler によってプロビジョニングされたノードでのみ Pod をスケジュールする。
  • クラスタ オートスケーラーで、Pod 間と Dynamic Workload Scheduler 間でリソース リクエストが重複してカウントされるのを回避する。
  • クラスタ オートスケーラーがノード間で Pod を移動してバッチ計算を中断することを防ぐため、safe-to-evict: false アノテーションを挿入する。この動作は、Pod アノテーションで safe-to-evict: true を指定することによって変更できます。

Dynamic Workload Scheduler のステータスを確認する

Dynamic Workload Scheduler のステータスは、Pod がスケジュール可能かどうかを定義します。Kubernetes の watch を使用すると、変化を効率的に監視できます。または、Kubernetes オブジェクトのステータスのトラッキングに使っているその他のツールを利用できます。次の表に、Dynamic Workload Scheduler の各ステータスと、考えられる結果を示します。

Dynamic Workload Scheduler のステータス 説明 考えられる結果
Pending リクエストは認識されず、まだ処理されていません。 処理後、リクエストは Accepted 状態または Failed 状態に移行します。
Accepted=true リクエストは承認済みで、リソースが使用可能になるのを待機しています。 リソースが見つかってノードがプロビジョニングされた場合、リクエストは Provisioned 状態に移行し、そうでない場合は Failed 状態に移行します。
Provisioned=true ノードの準備ができています。 10 分以内に Pod を起動して、プロビジョニングされたリソースを使用できます。この期間が経過すると、ノードはクラスタ オートスケーラーによって不要ノードと見なされ、削除されます。
Failed=true エラーのため、ノードをプロビジョニングできません。Failed=true は終了状態です。 条件の Reason フィールドと Message フィールドの情報に基づいて、条件のトラブルシューティングを行ってください。新しい Dynamic Workload Scheduler リクエストを作成して再試行します。
Provisioned=false ノードがまだプロビジョニングされていません。

Reason=NotProvisioned の場合は、すべてのリソースが使用可能になる前の一時的な状態です。

Reason=QuotaExceeded の場合は、この理由と条件の Message フィールドの情報に基づいて、この状態のトラブルシューティングを行います。追加の割り当てのリクエストが必要になる場合があります。詳細については、Dynamic Workload Scheduler が割り当てによって制限されているかどうかを確認するをご覧ください。この Reason は、GKE バージョン 1.29.2-gke.1181000 以降でのみ使用できます。

Pod を起動する

Dynamic Workload Scheduler リクエストが Provisioned=true ステータスに達したら、Job を実行して Pod を起動できます。これにより、保留中のリクエストや失敗したリクエストによってスケジュール不可能な Pod が急増する(これは、kube-scheduler とクラスタ オートスケーラーのパフォーマンスに影響を与えます)のを回避できます。

また、スケジュール不可の Pod があることが特に重要ではない場合は、Dynamic Workload Scheduler と並行して Pod を作成できます。

Dynamic Workload Scheduler リクエストをキャンセルする

プロビジョニングの実行前にリクエストをキャンセルするには、ProvisioningRequest を削除します。

kubectl delete provreq PROVISIONING_REQUEST_NAME -n NAMESPACE

ほとんどの場合、ProvisioningRequest を削除すればノードは作成されなくなります。 ただし、タイミングによっては(ノードがすでにプロビジョニングされている場合など)、最終的にノードが作成されることもあります。この場合、Pod が作成されなければ、ノードは 10 分後にクラスタ オートスケーラーによって削除されます。

Dynamic Workload Scheduler の仕組み

ProvisioningRequest API を使用すると、Dynamic Workload Scheduler は次の処理を行います。

  1. 必要なすべてのノードが同時に使用可能になるまでワークロードが無期限に待機することを、ユーザーが GKE に指示します。
  2. クラスタ オートスケーラーがユーザーのリクエストを受け入れ、必要なノードの数を計算します(それらのノードは 1 つのユニットとして扱われます)。
  3. リクエストは、必要なすべてのリソースが単一のゾーンで使用可能になるまで待機します。1.29.1-gke.1708000 以降を実行しているクラスタの場合、このゾーンは利用可能な容量に関する情報を使用して選択され、待機時間が短縮されます。以前のバージョンを実行しているクラスタでは、この情報を利用することなくゾーンが選択されているため、待機時間が大幅に長いゾーンでキューイングが発生する可能性があります。
  4. 必要なノードが利用可能になった時点で、クラスタ オートスケーラーはすべてのノードを一度にプロビジョニングします。
  5. 新しくプロビジョニングされたノードで、ワークロードのすべての Pod が同時に実行可能になります。
  6. プロビジョニングされたノードの実行時間は 7 日間に制限されます。maxRunDurationSeconds パラメータを設定して、ワークロードの実行に必要な時間が短いことを指定する場合は、実行時間をこれよりも短くできます。詳細については、VM のランタイムを制限する(プレビュー)をご覧ください。この機能は、GKE バージョン 1.28.5-gke.1355000 以降で使用できます。この時間が経過すると、ノードとその上で実行中の Pod はプリエンプトされます。Pod がそれより前に終了し、ノードが使用されなければ、クラスタ オートスケーラーは自動スケーリング プロファイルに従ってノードと Pod を削除します。
  7. Dynamic Workload Scheduler 間でノードが再利用されることはありません。各 ProvisioningRequest により、新たな 7 日間を実行時間とする新しいノードの作成がリクエストされます。

割り当て

Dynamic Workload Scheduler リクエストによってプロビジョニングされるすべての VM は、プリエンプティブル割り当てを使用します。

Accepted 状態の ProvisioningRequests の数は、専用の割り当てによって制限されます。プロジェクトごとに割り当てを構成します。リージョンごとに 1 つの割り当て構成です。

Google Cloud コンソールで割り当てを確認する

Google Cloud コンソールで割り当て上限の名前と現在の使用量を確認する手順は次のとおりです。

  1. Google Cloud コンソールで [割り当て] ページに移動します。

    [割り当て] に移動

  2. [ フィルタ] ボックスで [指標] プロパティを選択し、「active_resize_requests」と入力して Enter キーを押します。

デフォルト値は 100 です。割り当てを増やすには、割り当て上限の引き上げをリクエストするの説明に従ってください。

Dynamic Workload Scheduler が割り当てによって制限されているかどうかを確認する

Dynamic Workload Scheduler リクエストの処理に予想よりも時間がかかっている場合は、リクエストが割り当てによって制限されていないことを確認してください。追加の割り当てのリクエストが必要になる場合があります。

バージョン 1.29.2-gke.1181000 以降を実行しているクラスタでは、特定の割り当て制限が原因でリクエストの処理が妨げられているかどうかを確認します。

kubectl describe provreq PROVISIONING_REQUEST_NAME \
    --namespace NAMESPACE

出力は次のようになります。

…
Last Transition Time:  2024-01-03T13:56:08Z
    Message:               Quota 'NVIDIA_P4_GPUS' exceeded. Limit: 1.0 in region europe-west4.
    Observed Generation:   1
    Reason:                QuotaExceeded
    Status:                False
    Type:                  Provisioned
…

この例では、europe-west4 リージョンに十分な割り当てがないため、GKE はノードをデプロイできません。

Dynamic Workload Scheduler を使用するワークロードを含むノードプールの停止設定を構成する

ノードプール内のすべてのノードまたはほとんどのノードが利用可能であることを必要とするワークロードは、強制排除の影響を受けやすくなります。ProvisioningRequest API を使用してプロビジョニングされたノードの自動修復または自動アップグレードはサポートされていません。これは、これらのオペレーションでは、そのノードで実行中のすべてのワークロードが強制排除され、ワークロードをスケジュールできなくなるためです。

Dynamic Workload Scheduler を使用するワークロード実行の停止を最小限に抑えるために、次の対策を取ることをおすすめします。

  • クラスタのリリース チャンネルの登録に応じて、次のベスト プラクティスを使用して、ノードの自動アップグレードによってワークロードが中断されないようにします。
  • ノードの自動修復を無効にします
  • メンテナンスの時間枠と除外を使用して、実行中のワークロードへの影響を最小限に抑えながら、GKE が自動メンテナンスのためにノードプールを中断できる時間枠を確保します。これらのメンテナンス ツールを使用する場合は、GKE がノードプールを中断できる特定の時間枠を設定する必要があります。そのため、この時間枠を実行中のワークロードがない時間に設定することをおすすめします。
  • ノードプールを最新の状態に保つには、アクティブな Dynamic Workload Scheduler リクエストがなく、ノードプールが空であるときに、ノードプールを手動でアップグレードすることをおすすめします。

制限事項

  • Pod 間のアンチアフィニティはサポートされていません。クラスタ オートスケーラーではノードのプロビジョニング中に Pod 間のアンチアフィニティ ルールが考慮されないため、スケジュール不可能なワークロードが発生する可能性があります。これは、複数の Dynamic Workload Scheduler オブジェクト用のノードが同じノードプールでプロビジョニングされたときに発生する場合があります。
  • GPU ノードのみがサポートされています。
  • Dynamic Workload Scheduler では予約はサポートされていません。ノードプールの作成時に --reservation-affinity=none を指定する必要があります。 Dynamic Workload Scheduler では、クラスタの自動スケーリングに必要な ANY ロケーション ポリシーのみがサポートされます。
  • 1 つの Dynamic Workload Scheduler リクエストで最大 1,000 個の VM を作成できます。これは、1 つのノードプールのゾーンあたりの最大ノード数です。
  • GKE では、Compute Engine の ACTIVE_RESIZE_REQUESTS 割り当てにより、キューで保留される Dynamic Workload Scheduler リクエストの数が制御されます。デフォルトでは、この割り当ては Google Cloud プロジェクト レベルで 100 に制限されています。この割り当てを超える Dynamic Workload Scheduler リクエストを作成しようとすると、新しいリクエストは失敗します。
  • Dynamic Workload Scheduler を使用するノードプールは、ノードがまとめてプロビジョニングされるため、停止の影響を受けやすくなります。詳細については、Dynamic Workload Scheduler を使用するワークロードを含むノードプールの停止設定を構成するをご覧ください。
  • Google Cloud コンソールに、有効期間の短い追加の VM が表示される場合があります。これは、必要なすべてのマシンをプロビジョニングする容量が使用可能になるまで、Compute Engine によって VM が作成され、すぐに削除される可能性があるためです。
  • Dynamic Workload Scheduler インテグレーションでサポートされる PodSet は 1 つのみです。異なる Pod テンプレートを混在させる場合は、リクエストされるリソースが最も多いテンプレートを使用してください。異なるマシンタイプ(GPU タイプが異なる VM など)を混在させることはできません。

次のステップ