使用 Kueue 部署批次系統


本教學課程說明如何使用 Kueue 在 Google Kubernetes Engine (GKE) 上排定 Job,藉此最佳化可用資源。在本教學課程中,您將瞭解如何使用 Kueue 有效管理及排定批次作業、提升資源使用率,以及簡化工作負載管理作業。您為兩個租戶團隊設定共用叢集,每個團隊都有自己的命名空間,且每個團隊建立的工作都會共用全域資源。您也可以設定 Kueue,根據您定義的資源配額排定 Job 的時間。

本教學課程的適用對象為有興趣使用 GKE 實作批次系統的雲端架構師和平台工程師。如要進一步瞭解內容中提及的常見角色和範例工作,請參閱「常見的 GKE Enterprise 使用者角色和工作」。 Google Cloud

閱讀本頁面之前,請先熟悉下列概念:

背景

作業是指會執行完畢的應用程式,例如機器學習、算繪、模擬、分析、CI/CD 和類似工作負載。

Kueue 是雲端原生的工作排程器,可與預設的 Kubernetes 排程器、工作控制器和叢集自動調度器搭配運作,提供端對端批次系統。Kueue 會實作工作佇列,並根據配額和資源共用階層,決定工作應等待或啟動的時間,確保各團隊能公平地使用資源。

Kueue 具有下列特徵:

  • 這項服務專為雲端架構設計,可處理異質、可互換及可擴充的資源。
  • 這項服務提供一組 API,可管理彈性配額和工作排隊。
  • 不會重新實作現有功能,例如自動調度資源、Pod 排程或 Job 生命週期管理。
  • Kueue 內建 Kubernetesbatch/v1.Job API 支援功能。
  • 可與其他工作 API 整合。

為避免與特定 Kubernetes Job API 混淆,Kueue 會將以任何 API 定義的工作稱為「工作負載」。

目標

  1. 建立 GKE 叢集
  2. 建立 ResourceFlavor
  3. 建立 ClusterQueue
  4. 建立 LocalQueue
  5. 建立工作並觀察允許的工作負載

費用

本教學課程使用下列 Google Cloud的計費元件:

使用 Pricing Calculator 可根據您的預測使用量來產生費用預估。

完成本教學課程後,請刪除您建立的資源,以免系統繼續計費。詳情請參閱「清除」。

事前準備

設定專案

  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

  8. 設定 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
      

      STATUSkueue-autopilotRUNNING

    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 的新命名空間:

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

建立 ResourceFlavor

ResourceFlavor 物件代表叢集中可用節點的變化,方法是將節點與節點標籤和汙點建立關聯。舉例來說,您可以使用 ResourceFlavors 代表具有不同佈建保證的 VM (例如 Spot 與隨選)、架構 (例如 x86 與 ARM CPU)、品牌和型號 (例如 Nvidia A100 與 T4 GPU)。

在本教學課程中,kueue-autopilot 叢集具有同質資源。因此,請為 CPU、記憶體、暫時性儲存空間和 GPU 建立單一 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 等資源集區。這項服務會管理 ResourceFlavor,限制用量,並決定工作負載的允許順序。

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,其中有兩項設定:

  • BestEffortFIFO

    • 預設的佇列策略設定。
    • 工作負載會依先進先出 (FIFO) 規則加入佇列,但如果配額不足以允許佇列最前端的工作負載,系統會嘗試加入下一個工作負載。
  • StrictFIFO

    • 保證 FIFO 語意。
    • 佇列開頭的工作負載可能會封鎖佇列,直到工作負載可接受為止。

cluster-queue.yaml 中,您會建立名為 cluster-queue 的新 ClusterQueue。這個 ClusterQueue 會管理四項資源:cpumemorynvidia.com/gpuephemeral-storage,並使用 flavors.yaml 中建立的風味。工作負載 Pod 規格中的要求會耗用配額。

每個變種版本都有用量限制,以 .spec.resourceGroups[].flavors[].resources[].nominalQuota 表示。在本例中,只有在下列情況下,ClusterQueue 才會允許工作負載:

  • CPU 要求總和小於或等於 10
  • 記憶體要求總和小於或等於 10Gi
  • GPU 要求總和小於或等於 10
  • 使用的儲存空間總和必須小於或等於 10 Gi

建立 LocalQueue

LocalQueue 是命名空間物件,可接受命名空間中使用者提供的工作負載。不同命名空間的 LocalQueue 可以指向同一個 ClusterQueue,共用資源配額。在本例中,命名空間 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

每個團隊都會將工作負載傳送至各自命名空間中的 LocalQueue。然後由 ClusterQueue 分配資源。

部署 LocalQueues:

kubectl apply -f local-queue.yaml

建立工作並觀察允許的工作負載

在本節中,您將在 team-a 命名空間中建立 Kubernetes Job。Kubernetes 中的 Job 控制器會建立一或多個 Pod,並確保這些 Pod 成功執行特定工作。

命名空間 team-a 中的 Job 具有下列屬性:

  • 它會指向 lq-team-a LocalQueue。
  • 方法是將 nodeSelector 欄位設為 nvidia-tesla-t4,要求 GPU 資源。
  • 這三個 Pod 會平行休眠 10 秒。系統會根據 ttlSecondsAfterFinished 欄位中定義的值,在 60 秒後清除工作。
  • 由於有三個 Pod,因此需要 1,500 milliCPU、1536 Mi 的記憶體、1,536 Mi 的臨時儲存空間和三個 GPU。
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-team-b.yaml 下建立工作,其命名空間屬於 team-b,並根據不同團隊的需求提出要求。

詳情請參閱在 Autopilot 中部署 GPU 工作負載

  1. 在新的終端機中,觀察每兩秒重新整理一次的 ClusterQueue 狀態:

    watch -n 2 kubectl get clusterqueue cluster-queue -o wide
    
  2. 在新的終端機中,觀察節點的狀態:

    watch -n 2 kubectl get nodes -o wide
    
  3. 在新的終端機中,每 10 秒從命名空間 team-ateam-b 建立 Jobs to LocalQueue:

    ./create_jobs.sh job-team-a.yaml job-team-b.yaml 10
    
  4. 觀察排入佇列的 Job、ClusterQueue 中允許的 Job,以及透過 GKE Autopilot 啟動的節點。

  5. 從命名空間 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. 當待處理工作開始從 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
    

後續步驟