Kueue を使用してバッチシステムをデプロイする


このチュートリアルでは、クラウドネイティブのジョブ スケジューラである Kueue を使用して、Google Kubernetes Engine(GKE)でジョブ キューイングを実行するバッチシステムをデプロイする方法について説明します。このチュートリアルを完了すると、先入れ先出し(FIFO)順でジョブを実行するように GKE と Kueue を設定できるようになります。

背景

ジョブは、ML、レンダリング、シミュレーション、分析、CI / CD、その他の同様のワークロードなど、最後まで実行されるアプリケーションです。

Kueue は、デフォルトの Kubernetes スケジューラ、ジョブ コントローラ、クラスタ オートスケーラーと連携して、エンドツーエンドのバッチシステムを提供する、クラウド ネイティブなジョブ スケジューラです。Kueue は Job キューイングを実装しており、チーム間で公平にリソースを共有するための割り当てや階層に基づいて Job を待機するタイミングや開始するタイミングを決定します。

Kueue には次の特長があります。

  • リソースが異種で交換可能でスケーラブルであるクラウド アーキテクチャに最適化されています。
  • 弾力的な割り当てを管理し、ジョブ キューイングを管理するための一連の API を提供します。
  • 自動スケーリング、Pod スケジューリング、ジョブのライフサイクル管理などの既存の機能は再実装されません。
  • Kueue には、Kubernetesbatch/v1.Job API の組み込みサポートがあります。
  • 他のジョブ API と統合できます。

Kueue は、特定の Kubernetes Job API との混乱を避けるため、任意の API で定義されたジョブをワークロードと呼びます。

目標

このチュートリアルは、Kubernetes でバッチシステムを実装するクラスタ オペレータとその他のユーザーを対象としています。このチュートリアルでは、2 つのテナントチーム用に共有クラスタを設定します。チームごとに独自の Namespace があり、そこで Job を作成し、対応する割り当てで制御される同じグローバル リソースを共有します。

このチュートリアルでは、次の手順について説明します。

  1. GKE クラスタを作成する
  2. ResourceFlavor を作成する
  3. ClusterQueue を作成する
  4. LocalQueue を作成する
  5. Job を作成して許可されたワークロードをモニタリングする

費用

このチュートリアルでは、課金対象である次の Google Cloud コンポーネントを使用します。

料金計算ツールを使うと、予想使用量に基づいて費用の見積もりを出すことができます。

このチュートリアルの終了後に、作成したリソースを削除すれば、それ以上の支払いは発生しません。詳細については、クリーンアップをご覧ください。

始める前に

プロジェクトを設定する

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. In the Google Cloud console, on the project selector page, click Create project to begin creating a new Google Cloud project.

    Go to project selector

  3. Make sure that billing is enabled for your Google Cloud project.

  4. Enable the GKE API.

    Enable the API

  5. In the Google Cloud console, on the project selector page, click Create project to begin creating a new Google Cloud project.

    Go to project selector

  6. Make sure that billing is enabled for your Google Cloud project.

  7. Enable the GKE API.

    Enable the API

Google Cloud CLI のデフォルト値を設定する

  1. Google Cloud コンソールで、Cloud Shell インスタンスを起動します。
    Cloud Shell を開く

  2. このサンプルアプリのソースコードをダウンロードします。

    git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
    cd kubernetes-engine-samples/batch/kueue-intro
    
  3. デフォルトの環境変数を設定します。

    gcloud config set project PROJECT_ID
    gcloud config set compute/region COMPUTE_REGION
    

    次の値を置き換えます。

GKE クラスタを作成する

  1. kueue-autopilot という名前の GKE Autopilot クラスタを作成します。

    gcloud container clusters create-auto kueue-autopilot \
      --release-channel "rapid" --region COMPUTE_REGION
    

    Autopilot クラスタはフルマネージドで、自動スケーリングが組み込まれています。GKE Autopilot の詳細

    Kueue はまた、ノードの自動プロビジョニングと通常の自動スケーリング ノードプールを備えた Standard GKE もサポートしています。

    クラスタが作成されると、結果は次のようになります。

      NAME: kueue-autopilot
      LOCATION: us-central1
      MASTER_VERSION: 1.26.2-gke.1000
      MASTER_IP: 35.193.173.228
      MACHINE_TYPE: e2-medium
      NODE_VERSION: 1.26.2-gke.1000
      NUM_NODES: 3
      STATUS: RUNNING
    

    ここで、kueue-autopilotSTATUSRUNNING です。

  2. クラスタの認証情報を取得する

    gcloud container clusters get-credentials kueue-autopilot
    
  3. クラスタに Kueue をインストールします。

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

    VERSION は、最新バージョンの Kueue に置き換えます。Kueue バージョンの詳細については、Kueue リリースをご覧ください。

  4. Kueue Pod の準備が整うまで待ちます。

    watch kubectl -n kueue-system get pods
    

    出力が次のようになると続行できます。

    NAME                                        READY   STATUS    RESTARTS   AGE
    kueue-controller-manager-66d8bb946b-wr2l2   2/2     Running   0          3m36s
    
  5. team-ateam-b という 2 つの新しい Namespace を作成します。

    kubectl create namespace team-a
    kubectl create namespace team-b
    

ResourceFlavor を作成する

ResourceFlavor は、ノードラベルと taint に関連付けることで、クラスタで使用可能なノードのバリエーションを表すオブジェクトです。たとえば、ResourceFlavors を使用して、異なるプロビジョニングの保証(例えば、Spot とオンデマンド)、アーキテクチャ(例えば、x86 と ARM の CPU)、ブランド、モデル(例えば、Nvidia A100 と T4 GPU)を持つ VM を表すことができます。

このチュートリアルでは、kueue-autopilot クラスタに均質なリソースがあります。その結果、CPU、メモリ、エフェメラル ストレージ、GPU 用に、ラベルや taint のない単一の ResourceFlavor を作成します。

apiVersion: kueue.x-k8s.io/v1beta1
kind: ResourceFlavor
metadata:
  name: default-flavor # This ResourceFlavor will be used for all the resources
ResourceFlavor をデプロイします。

kubectl apply -f flavors.yaml

ClusterQueue を作成する

ClusterQueue は、CPU、メモリ、GPU などのリソースのプールを管理するクラスタ スコープド オブジェクトです。ResourceFlavors を管理して使用量を制限し、ワークロードが許可される順序を指定します。

apiVersion: kueue.x-k8s.io/v1beta1
kind: ClusterQueue
metadata:
  name: cluster-queue
spec:
  namespaceSelector: {} # Available to all namespaces
  queueingStrategy: BestEffortFIFO # Default queueing strategy
  resourceGroups:
  - coveredResources: ["cpu", "memory", "nvidia.com/gpu", "ephemeral-storage"]
    flavors:
    - name: "default-flavor"
      resources:
      - name: "cpu"
        nominalQuota: 10
      - name: "memory"
        nominalQuota: 10Gi
      - name: "nvidia.com/gpu"
        nominalQuota: 10
      - name: "ephemeral-storage"
        nominalQuota: 10Gi

ClusterQueue をデプロイするには:

kubectl apply -f cluster-queue.yaml

使用順序は .spec.queueingStrategy によって決定されます。ここで、次の 2 つの構成があります。

  • BestEffortFIFO

    • デフォルトのキューイング戦略構成。
    • ワークロードの承諾は、先入れ先出し(FIFO)ルールに従いますが、キューの先頭にワークロードを承諾できるだけの十分な割り当てがない場合は、その次の行が試行されます。
  • StrictFIFO

    • FIFO のセマンティクスを保証します。
    • キューの先頭のワークロードは、ワークロードが承諾されるまでキューをブロックできます。

cluster-queue.yaml で、cluster-queue という新しい ClusterQueue を作成します。この ClusterQueue は、flavors.yaml で作成されたフレーバーを使用して、cpumemorynvidia.com/gpuephemeral-storage の 4 つのリソースを管理します。割り当ては、ワークロード Pod 仕様のリクエストによって消費されます。

各フレーバーには、.spec.resourceGroups[].flavors[].resources[].nominalQuota で表される使用制限が含まれています。この場合、ClusterQueue は、次の場合にのみワークロードを承諾します。

  • CPU リクエストの合計が 10 以下
  • メモリ リクエストの合計が 10 Gi 以下
  • GPU リクエストの合計が 10 以下
  • ストレージ; 保存容量の合計が 10Gi 以下

LocalQueue を作成する

LocalQueue は、Namespace 内のユーザーからのワークロードを受け入れる Namespace オブジェクトです。異なる Namespace の LocalQueue は、リソースの割り当てを共有できる同じ ClusterQueue を指すことができます。この場合、Namespace team-ateam-b の LocalQueue は、.spec.clusterQueue の下の同じ ClusterQueue cluster-queue を指します。

apiVersion: kueue.x-k8s.io/v1beta1
kind: LocalQueue
metadata:
  namespace: team-a # LocalQueue under team-a namespace
  name: lq-team-a
spec:
  clusterQueue: cluster-queue # Point to the ClusterQueue
---
apiVersion: kueue.x-k8s.io/v1beta1
kind: LocalQueue
metadata:
  namespace: team-b # LocalQueue under team-b namespace
  name: lq-team-b
spec:
  clusterQueue: cluster-queue # Point to the ClusterQueue

各チームは、ワークロードを独自の Namespace 内の LocalQueue に送信します。ClusterQueue によってリソースが割り当てられます。

LocalQueues をデプロイします。

kubectl apply -f local-queue.yaml

Job を作成し、許可されたワークロードを監視する

apiVersion: batch/v1
kind: Job
metadata:
  namespace: team-a # Job under team-a namespace
  generateName: sample-job-team-a-
  annotations:
    kueue.x-k8s.io/queue-name: lq-team-a # Point to the LocalQueue
spec:
  ttlSecondsAfterFinished: 60 # Job will be deleted after 60 seconds
  parallelism: 3 # This Job will have 3 replicas running at the same time
  completions: 3 # This Job requires 3 completions
  suspend: true # Set to true to allow Kueue to control the Job when it starts
  template:
    spec:
      nodeSelector:
        cloud.google.com/gke-accelerator: "nvidia-tesla-t4" # Specify the GPU hardware
      containers:
      - name: dummy-job
        image: gcr.io/k8s-staging-perf-tests/sleep:latest
        args: ["10s"] # Sleep for 10 seconds
        resources:
          requests:
            cpu: "500m"
            memory: "512Mi"
            ephemeral-storage: "512Mi"
            nvidia.com/gpu: "1"
          limits:
            cpu: "500m"
            memory: "512Mi"
            ephemeral-storage: "512Mi"
            nvidia.com/gpu: "1"
      restartPolicy: Never

Job は Namespace team-a の下に作成されます。この Job は LocalQueue lq-team-a を指します。GPU リソースをリクエストする場合、nodeSelectornvidia-tesla-t4 に設定されます。

Job は、並行して 10 秒間スリープする 3 つの Pod で構成されています。Job は、ttlSecondsAfterFinished に従って 60 秒後に削除されます。

この Job には、3 つの Pod があるため、1,500 milliCPU、1,536 Mi のメモリ、1,536 Mi のエフェメラル ストレージ、3 つの GPU が必要です。

Jobs はファイル job-team-b.yaml の下に作成され、その Namespace は team-b に属し、異なるニーズが異なるチームを表すリクエストがあります。

詳細については、Autopilot での GPU ワークロードのデプロイをご覧ください。

  1. 新しいターミナルで、2 秒ごとに更新される ClusterQueue のステータスを確認します。

    watch -n 2 kubectl get clusterqueue cluster-queue -o wide
    
  2. 新しいターミナルで、ノードのステータスを確認します。

    watch -n 2 kubectl get nodes -o wide
    
  3. 新しいターミナルで、Namespace team-ateam-b から LocalQueue への Job を 10 秒ごとに作成します。

    ./create_jobs.sh job-team-a.yaml job-team-b.yaml 10
    
  4. Job がキューに格納され、ClusterQueue に承諾され、ノードが GKE Autopilot とともに起動することを確認します。

  5. Namespace team-a から Job を取得します。

    kubectl -n team-a get jobs
    

    結果は次のようになります。

    NAME                      COMPLETIONS   DURATION   AGE
    sample-job-team-b-t6jnr   3/3           21s        3m27s
    sample-job-team-a-tm7kc   0/3                      2m27s
    sample-job-team-a-vjtnw   3/3           30s        3m50s
    sample-job-team-b-vn6rp   0/3                      40s
    sample-job-team-a-z86h2   0/3                      2m15s
    sample-job-team-b-zfwj8   0/3                      28s
    sample-job-team-a-zjkbj   0/3                      4s
    sample-job-team-a-zzvjg   3/3           83s        4m50s
    
  6. 前の手順の Job 名をコピーし、Workloads API を通じて Job の承諾ステータスとイベントを確認します。

    kubectl -n team-a describe workload JOB_NAME
    
  7. 保留中の Job が ClusterQueue から増加し始めたら、実行中のスクリプトで CTRL + C を押してスクリプトを終了します。

  8. すべての Job が完了したら、ノードがスケールダウンされています。

クリーンアップ

このチュートリアルで使用したリソースについて、Google Cloud アカウントに課金されないようにするには、リソースを含むプロジェクトを削除するか、プロジェクトを維持して個々のリソースを削除します。

プロジェクトを削除する

  1. In the Google Cloud console, go to the Manage resources page.

    Go to Manage resources

  2. In the project list, select the project that you want to delete, and then click Delete.
  3. In the dialog, type the project ID, and then click Shut down to delete the project.

個々のリソースを削除する

  1. Kueue 割り当てシステムを削除します。

    kubectl delete -n team-a localqueue lq-team-a
    kubectl delete -n team-b localqueue lq-team-b
    kubectl delete clusterqueue cluster-queue
    kubectl delete resourceflavor default-flavor
    
  2. Kueue マニフェストを削除します。

    VERSION=VERSION
    kubectl delete -f \
      https://github.com/kubernetes-sigs/kueue/releases/download/$VERSION/manifests.yaml
    
  3. クラスタを削除します。

    gcloud container clusters delete kueue-autopilot --region=COMPUTE_REGION
    

次のステップ