キューに格納されたプロビジョニングでの Flex Start で大規模なワークロードを実行する


このページでは、Dynamic Workload Scheduler を活用したキューに格納されたプロビジョニングで Flex Start を使用し、GPU を使用する大規模なバッチ ワークロードと AI ワークロードの GPU の取得を最適化する方法について説明します。

このページを読む前に、次のことをよく理解しておいてください。

このガイドは、バッチ ワークロードの実行に Kubernetes コンテナ オーケストレーション機能を使用することを検討している ML エンジニア、プラットフォーム管理者、オペレーター、データおよび AI のスペシャリストを対象としています。 Google Cloud のコンテンツで使用されている一般的なロールとタスクの例の詳細については、一般的な GKE Enterprise ユーザーロールとタスクをご覧ください。

キューに格納されたプロビジョニングでの Flex Start の仕組み

キューに格納されたプロビジョニングでの Flex Start では、GKE はリクエストされたすべてのリソースを同時に割り振ります。キューに格納されたプロビジョニングの Flex Start では、次のツールが使用されます。

  • キューに格納されたプロビジョニングでの Flex Start は、Dynamic Workload Schedulerプロビジョニング リクエストのカスタム リソース定義(CRD)を組み合わせたものです。これらのツールは、利用可能なリソースとワークロードの要件に基づいて割り振られた容量を管理します。
  • (省略可)Kueue は、キューに格納されたプロビジョニング リクエストを使用して、Flex Start のライフサイクルを自動化します。Kueue はジョブ キューイングを実装し、プロビジョニング リクエストのライフサイクルを自動的に処理します。

キューに格納されたプロビジョニングで Flex Start を使用するには、ノードプールの作成時に --flex-start フラグと --enable-queued-provisioning フラグを追加する必要があります。

ベスト プラクティス:

ワークロードが次の条件を満たしている場合は、大規模なバッチ ワークロードと AI ワークロードにキューに格納されたプロビジョニングの Flex Start を使用します。

  • ワークロードの開始時間が柔軟である。
  • ワークロードを複数のノードで同時に実行する必要がある。

単一ノードで実行できる小規模なワークロードの場合は、Flex Start プロビジョニング モードを使用します。GKE での GPU プロビジョニングの詳細については、AI ワークロード用アクセラレータを取得するをご覧ください。

始める前に

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

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

キューに格納されたプロビジョニングでの Flex Start を使用するノードプール

このセクションの内容は、Standard クラスタにのみ適用されます。

キューに格納されたプロビジョニングで Flex Start がクラスタ内の特定のノードプールで動作するようにするには、次のいずれかの方法を使用します。

ノードプールを作成する

gcloud CLI を使用して、キューに格納されたプロビジョニングが有効な Flex Start のノードプールを作成します。

gcloud 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 \
    --flex-start \
    --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 マシンタイプ。

    ベスト プラクティス:

    アクセラレータ最適化マシンタイプを使用して、AI / ML ワークロードのパフォーマンスと効率を向上させます。

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

  • --node-locations=COMPUTE_ZONES: GKE が GPU ノードを作成する 1 つ以上のゾーンのカンマ区切りリスト。このゾーンはクラスタと同じリージョンに存在する必要があります。使用可能な GPU があるゾーンを選択します。
  • --enable-gvnic: このフラグにより、GPU ノードプールの gVNIC が有効になり、ネットワーク トラフィック速度が向上します。

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

  • --flex-start フラグと --enable-queued-provisioning フラグを組み合わせると、キューに格納されたプロビジョニングが有効な Flex Start ノードプールを作成し、cloud.google.com/gke-queued taint をノードプールに追加するように GKE に指示します。
  • キューに格納されたプロビジョニングとクラスタの自動スケーリングが有効です。
  • ノードプールの初期ノード数はゼロです。
  • --no-enable-autorepair フラグは自動修復を無効にします。これにより、修復されたノードで実行されているワークロードが中断される可能性があります。

ノードの自動プロビジョニングを有効にして、キューに格納されたプロビジョニングでの Flex Start 用にノードプールを作成する

ノードの自動プロビジョニングを使用すると、バージョン 1.29.2-gke.1553000 以降を実行しているクラスタで、キューに格納されたプロビジョニングを使用して Flex Start のノードプールを管理できます。ノードの自動プロビジョニングを有効にすると、GKE は関連するワークロードに必要なリソースを含むノードプールを作成します。

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

  • この機能を有効にするときに、キューに格納されたプロビジョニングで Flex Start に必要なリソースを指定します。使用可能な resourceTypes を一覧表示するには、gcloud compute accelerator-types list コマンドを実行します。
  • --no-enable-autoprovisioning-autorepair フラグを使用して、ノードの自動修復を無効にします。
  • 自動プロビジョニングされた GPU ノードに GPU ドライバを自動的にインストールします。詳細については、GPU を使用するノードの自動プロビジョニングによるドライバのインストールをご覧ください。

キューに格納されたプロビジョニングでの Flex Start を使用してバッチ ワークロードと AI ワークロードを実行する

キューに格納されたプロビジョニングで Flex Start を使用してバッチ ワークロードを実行するには、次のいずれかの構成を使用します。

ベスト プラクティス:

Kueue を使用して、キューに格納されたプロビジョニングの Flex Start でバッチ ワークロードと AI ワークロードを実行します。

Kueue を使用した Job のキューに格納されたプロビジョニングでの Flex Start

以降のセクションでは、Kueue を使用して Job のキューに格納されたプロビジョニングで Flex Start を構成する方法について説明します。

  • キューに格納されたプロビジョニングのノードプールの設定を使用した Flex Start。
  • キューに格納されたプロビジョニング ノードプールの設定での予約と Flex Start。

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

Kueue をインストールするには、管理者権限が必要です。これらの権限を取得する場合は、IAM ロール roles/container.admin が付与されていることを確認します。GKE IAM ロールの詳細については、IAM 許可ポリシーを作成するガイドをご覧ください。

環境を準備する

  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=KUEUE_VERSION
    kubectl apply --server-side -f https://github.com/kubernetes-sigs/kueue/releases/download/$VERSION/manifests.yaml
    

    KUEUE_VERSION は、最新バージョンの Kueue に置き換えます。

0.7.0 より前のバージョンの Kueue を使用する場合は、ProvisioningACC フィーチャー ゲートを true に設定して、Kueue フィーチャー ゲートの構成を変更します。詳細な説明とデフォルトのゲートの値については、Kueue のフィーチャー ゲートをご覧ください。Kueue のインストールの詳細については、インストールをご覧ください。

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

次のマニフェストを使用して、dws-cluster-queue という名前のクラスタレベルのキューdws-local-queue という名前の LocalQueue Namespace を作成します。この Namespace の dws-cluster-queue キューを参照する Job は、キューに格納されたプロビジョニングで Flex Start を使用して 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", "ephemeral-storage"]
    flavors:
    - name: "default-flavor"
      resources:
      - name: "cpu"
        nominalQuota: 1000000000    # "Infinite" quota
      - name: "memory"
        nominalQuota: 1000000000Gi  # "Infinite" quota
      - name: "nvidia.com/gpu"
        nominalQuota: 1000000000    # "Infinite" quota
      - name: "ephemeral-storage"
        nominalQuota: 1000000000Ti  # "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"
---

このクラスタのキューの割り当て上限は高く、キューに格納されたプロビジョニングとの統合による Flex Start のみが有効になります。Kueue API の詳細と上限の設定方法については、Kueue のコンセプトをご覧ください。

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

キューに格納されたプロビジョニングで Flex Start を使用する Job を他の Namespace で実行する場合は、上記のテンプレートを使用して追加の LocalQueues を作成できます。

Job を実行する

次のマニフェストのサンプルの Job は、キューに格納されたプロビジョニングで Flex Start を使用します。

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

このマニフェストには、キューに格納されたプロビジョニング構成の Flex Start に関連する次のフィールドが含まれます。

  • 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
    

Kueue 統合によるキューに格納されたプロビジョニングの Flex Start は、オープンソース エコシステムで利用可能な次のような他のワークロード タイプもサポートしています。

  • 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: 1000000000    # "Infinite" quota
      - name: "memory"
        nominalQuota: 1000000000Gi  # "Infinite" quota
      - name: "nvidia.com/gpu"
        nominalQuota: 1000000000    # "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

このクラスタのキューの割り当て上限は高く、キューに格納されたプロビジョニングとの統合による Flex Start のみが有効になります。Kueue API の詳細と上限の設定方法については、Kueue のコンセプトをご覧ください。

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

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 のキューに格納されたプロビジョニングでの Flex Start

ProvisioningRequest オブジェクトを定義する

Job ごとに ProvisioningRequest を使用してリクエストを作成します。キューに格納されたプロビジョニングを使用する Flex Start は、Pod を起動するのではなく、ノードのプロビジョニングのみを行います。

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

    Standard

    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
          cloud.google.com/gke-flex-start: "true"
        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/API_VERSION
    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
    

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

    • API_VERSION: API のバージョン(v1 または v1beta1)。GKE バージョン 1.31.1-gke.1678000 以降では、安定性と最新機能へのアクセスのために v1 を使用することをおすすめします。
    • NAMESPACE_NAME: Kubernetes Namespace の名前。この Namespace は Pod の Namespace と同じにする必要があります。
    • PROVISIONING_REQUEST_NAME: ProvisioningRequest の名前。この名前は Pod のアノテーションで参照します。
    • MAX_RUN_DURATION_SECONDS: ノードの最大実行時間(秒)。最大実行時間はデフォルトの 7 日間です(省略可)。詳細については、キューに格納されたプロビジョニングでの Flex Start の仕組みをご覧ください。この値は、リクエストの作成後は変更できません。このフィールドは、GKE バージョン 1.28.5-gke.1355000 以降で使用できます。
    • COUNT: リクエストする Pod 数。ノードは 1 つのゾーンでアトミックにスケジュールされます。
    • POD_TEMPLATE_NAME: PodTemplate の名前。
    • NODEPOOL_NAME: ノードプールに付ける名前。自動プロビジョニングされたノードプールを使用する場合は削除します。

    GKE では、Pod の作成時に検証とミューテーションが Pod に適用されることがあります。cloud.google.com/apply-warden-policies ラベルを使用すると、同じ検証とミューテーションを PodTemplate オブジェクトに適用できます。このラベルは、GKE が Pod のノードリソース要件を計算するために必要です。キューに格納されたプロビジョニングと Flex Start の統合では、1 つの PodSet 仕様のみがサポートされます。異なる Pod テンプレートを混在させる場合は、リソースを最も多くリクエストするテンプレートを使用してください。異なるマシンタイプ(GPU タイプが異なる VM など)を混在させることはできません。

    ノードの自動プロビジョニング

    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-accelerator: GPU_TYPE
          cloud.google.com/gke-flex-start: "true"
        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/API_VERSION
    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
    

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

    • API_VERSION: API のバージョン(v1 または v1beta1)。GKE バージョン 1.31.1-gke.1678000 以降では、安定性と最新機能へのアクセスのために v1 を使用することをおすすめします。
    • NAMESPACE_NAME: Kubernetes Namespace の名前。この Namespace は Pod の Namespace と同じにする必要があります。
    • PROVISIONING_REQUEST_NAME: ProvisioningRequest の名前。この名前は Pod のアノテーションで参照します。
    • MAX_RUN_DURATION_SECONDS: ノードの最大実行時間(秒)。最大実行時間はデフォルトの 7 日間です(省略可)。詳細については、キューに格納されたプロビジョニングでの Flex Start の仕組みをご覧ください。この値は、リクエストの作成後は変更できません。このフィールドは、GKE バージョン 1.28.5-gke.1355000 以降で使用できます。
    • COUNT: リクエストする Pod 数。ノードは 1 つのゾーンでアトミックにスケジュールされます。
    • POD_TEMPLATE_NAME: PodTemplate の名前。
    • GPU_TYPE: GPU ハードウェアのタイプ。

    GKE では、Pod の作成時に検証とミューテーションが Pod に適用されることがあります。cloud.google.com/apply-warden-policies ラベルを使用すると、同じ検証とミューテーションを PodTemplate オブジェクトに適用できます。このラベルは、GKE が Pod のノードリソース要件を計算するために必要です。

  2. 次のようにマニフェストを適用します。

    kubectl apply -f provisioning-request.yaml
    

Pod を構成する

このセクションでは、Kubernetes Job を使用して Pod を構成します。ただし、Kubernetes JobSet や Kubeflow、Ray、カスタム コントローラなどの他のフレームワークを使用することもできます。Job 仕様で、次のアノテーションを使用して Pod を ProvisioningRequest にリンクします。

apiVersion: batch/v1
kind: Job
spec:
  template:
    metadata:
      annotations:
        autoscaling.x-k8s.io/consume-provisioning-request: PROVISIONING_REQUEST_NAME
        autoscaling.x-k8s.io/provisioning-class-name: "queued-provisioning.gke.io"
    spec:
      ...

GKE バージョン 1.30.3-gke.1854000 より前の場合は、次の以前のアノテーションを使用する必要があります。

      annotations:
        cluster-autoscaler.kubernetes.io/consume-provisioning-request: PROVISIONING_REQUEST_NAME
        cluster-autoscaler.kubernetes.io/provisioning-class-name: "queued-provisioning.gke.io"

GKE バージョン 1.31.1-gke.1678000 から、cluster-autoscaler.kubernetes.io/consume-provisioning-request アノテーションと cluster-autoscaler.kubernetes.io/provisioning-class-name アノテーションは非推奨になりました。

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

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

ProvisioningRequest のステータスを確認する

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

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

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

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

Reason=ResourcePoolExhausted で、MessageExpected time is indefinite が含まれている場合は、別のゾーンまたはリージョンを選択するか、リクエストされたリソースを調整します。

Pod を起動する

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

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

ProvisioningRequest リクエストをキャンセルする

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

kubectl delete provreq PROVISIONING_REQUEST_NAME -n NAMESPACE

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

割り当てに関する問題のトラブルシューティング

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

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

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

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

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

    [割り当て] に移動

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

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

ProvisioningRequest リクエストが割り当てによって制限されているかどうかを確認する

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

バージョン 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 はノードをデプロイできません。

キューに格納されたプロビジョニング モードから Flex Start プロビジョニング モードにノードプールを移行する

--enable-queued-provisioning フラグを使用して作成された既存のノードプールの場合は、次のコマンドを実行して、これらのノードプールを新しい Flex Start プロビジョニング モードに移行します。

  gcloud container node-pools update NODEPOOL_NAME \
    --cluster=CLUSTER_NAME --flex-start

このオペレーションは次の処理を行います。

  • ノードプールを Flex Start プロビジョニング モードのノードプールに更新します。
  • Flex Start プロビジョニング モードのノードの料金を適用します。

1.32.2-gke.1652000 以降(Flex Start プロビジョニング モード ノードの最小バージョン)で実行されているクラスタのすべてのノードは、短時間のアップグレードを使用します。

次のステップ