全部產品
Search
文件中心

Container Service for Kubernetes:基於優先順序排隊的多叢集PyTorchJob調度

更新時間:Dec 26, 2025

PyTorch是廣泛應用的機器學習架構,能夠協助模型開發人員實現多機多卡分布式訓練。在Kubernetes中,可以通過PyTorchJob提交PyTorch架構下的機器學習任務。本文介紹如何在艦隊叢集中使用ACK Kube Queue進行任務管理及如何在艦隊叢集下發資源時聲明Gang調度要求。

架構資訊

在實現多機多卡分布式訓練時,為確保訓練負載的Pod能夠正常運行,通常需要任務負載在調度時滿足Gang調度語義(任務的所有工作負載必須全部運行或全部不運行)。艦隊通過ACK Kube Queue以及ACK Scheduler實現了多叢集中的PyTorchJob調度,並且能夠在調度時保障PyTorchJob工作負載上聲明的Gang語義。

image

前提條件

  • 子叢集已安裝雲原生AI套件(僅需部署Arena)。

  • 已授予RAM使用者AliyunAdcpFullAccess許可權。具體操作,請參見管理RAM使用者的許可權

  • 已安裝AMC命令列工具。具體操作,請參見AMC命令列協助

  • (可選)當叢集開啟了資源預留時,艦隊將使用資源預留保障艦隊叢集的調度結果與子叢集一致。當叢集未開啟資源預留時,艦隊叢集採用比較子叢集所有節點剩餘資源之和與任務需求資源之和的方式進行資源評估以及任務調度。開啟資源預留的方式如下。

    說明

    開啟資源預留需要叢集版本不低於1.28,且調度器版本不低於6.8.0。

    1. 登入Container Service管理主控台,在左側導覽列選擇叢集列表

    2. 叢集列表頁面,單擊目的地組群名稱,然後在左側導覽列,單擊組件管理

    3. 組件管理頁面,找到Kube Scheduler組件,單擊配置進入參數配置頁面,將enableReservation設定為true,然後單擊確認

步驟一:使用Kube Queue進行任務排隊及配額管理(可選)

多叢集艦隊中通過ElasticQuotaTree進行配額管理以及隊列配置,能夠解決在多使用者情境下大量任務的排隊問題。

  1. 使用以下樣本內容,提交ElasticQuotaTree。

    叢集管理員可以在艦隊中提交ElasticQuotaTree來配置任務隊列。本樣本將在default命名空間中設定配額,總共10000CPU、10000Gi記憶體、10000GPU以及1個任務。

    apiVersion: scheduling.sigs.k8s.io/v1beta1
    kind: ElasticQuotaTree
    metadata:
      name: elasticquotatree # 只支援單個ElasticQuotaTree。
      namespace: kube-system # 只有kube-system下才會生效。
    spec:
      root:
        name: root # Root節點的Max必須等於Min。
        max:
          cpu: 999900
          memory: 400000Gi
          kube-queue/max-jobs: 10000000000
          nvidia.com/gpu: 100000
        min:
          cpu: 999900
          memory: 400000Gi
          kube-queue/max-jobs: 10000000000
          nvidia.com/gpu: 100000
        children:
        - name: child-2
          max:
            # 限制同時只能出隊一個任務。
            kube-queue/max-jobs: 1
            cpu: 10000
            nvidia.com/gpu: 10000
            memory: 10000Gi
          namespaces: # 配置對應的Namespace。
            - default
  2. 在艦隊執行個體中執行以下命令,查看ElasticQuotaTree及KubeQueue建立的隊列。

    kubectl get queue -n kube-queue

    預期輸出:

    NAME                 AGE
    root-child-2-v5zxz   15d
    root-kdzw7           15d

步驟二:提交PyTorchJob進行多叢集調度

  1. 在艦隊執行個體中提交PropagationPolicy,並指定自訂策略為Gang。

    僅使用Gang調度策略

    在使用Gang調度能力時,需要在提交的PropagationPolicy中使用customSchedulingType=Gang的自訂調度策略。

    apiVersion: policy.one.alibabacloud.com/v1alpha1
    kind: PropagationPolicy
    metadata:
      name: example-policy # The default namespace is `default`.
    spec:
      propagateDeps: true
      # 申明任務運行失敗時重新調度。
      failover:
        application:
          decisionConditions:
            tolerationSeconds: 30
          purgeMode: Immediately
      placement:
        replicaScheduling:
          replicaSchedulingType: Divided
          # 聲明使用Gang調度。
          customSchedulingType: Gang
      resourceSelectors:
        - apiVersion: kubeflow.org/v1
          kind: PyTorchJob

    使用ElasticQuotaTree及Gang調度策略

    需要在提交的PropagationPolicy中使用customSchedulingType=Gang的自訂調度策略,並將.Spec.Suspension.Scheduling設定為true,表明需要進入Queue隊列進行排隊。

    apiVersion: policy.one.alibabacloud.com/v1alpha1
    kind: PropagationPolicy
    metadata:
      name: example-policy # The default namespace is `default`.
    spec:  
      suspension:
        scheduling: true
      propagateDeps: true
      # 申明任務運行失敗時重新調度。
      failover:
        application:
          decisionConditions:
            tolerationSeconds: 30
          purgeMode: Immediately
      placement:
        replicaScheduling:
          replicaSchedulingType: Divided
          # 聲明使用Gang調度。
          customSchedulingType: Gang
      resourceSelectors:
        - apiVersion: kubeflow.org/v1
          kind: PyTorchJob
  2. 在艦隊執行個體中使用以下樣本內容,提交PyTorchJob。

    展開查看PyTorchJob樣本YAML

    apiVersion: kubeflow.org/v1
    kind: PyTorchJob
    metadata:
      labels:
        app: pytorchjob
      name: pytorch-test
      namespace: default
    spec:
      cleanPodPolicy: None
      pytorchReplicaSpecs:
        Master:
          replicas: 1
          restartPolicy: Never
          template:
            metadata:
              labels:
                app: pytorchjob
              name: pytorch-test
            spec:
              schedulerName: default-scheduler
              containers:
              - command:
                - sh
                - -c
                - sleep 1h
                env:
                - name: NVIDIA_VISIBLE_DEVICES
                  value: void
                - name: gpus
                  value: "0"
                - name: workers
                  value: "8"
                image: registry-cn-hangzhou.ack.aliyuncs.com/acs/nginx
                imagePullPolicy: Always
                name: pytorch
                resources:
                  limits:
                    cpu: "3"
                  requests:
                    cpu: "10m"
                volumeMounts:
                - mountPath: /dev/shm
                  name: dshm
                workingDir: /root
              volumes:
              - emptyDir:
                  medium: Memory
                  sizeLimit: 2Gi
                name: dshm
        Worker:
          replicas: 2
          restartPolicy: OnFailure
          # restartPolicy: Never
          template:
            metadata:
              labels:
                app: pytorchjob
              name: pytorch-test
            spec:
              containers:
              - command:
                - bash
                - -c
                - |
                  #!/bin/bash
                  #sleep 180
                  echo "$WORKER_INDEX"
                  #if [[ "$WORKER_INDEX" == "0" ]]
                  #then
                  #  exit -1
                  #fi
                  sleep 1h
                env:
                - name: WORKER_INDEX
                  valueFrom:
                    fieldRef:
                      fieldPath: metadata.labels['pytorch-replica-index']
                - name: NVIDIA_VISIBLE_DEVICES
                  value: void
                - name: gpus
                  value: "0"
                - name: workers
                  value: "8"
                image: registry-cn-hangzhou.ack.aliyuncs.com/acs/nginx
                imagePullPolicy: Always
                name: pytorch
                resources:
                  limits:
                    cpu: "2"
                  requests:
                    cpu: "2"
                    memory: "2Gi"
                volumeMounts:
                - mountPath: /dev/shm
                  name: dshm
                workingDir: /root
              volumes:
              - emptyDir:
                  medium: Memory
                  sizeLimit: 2Gi
                name: dshm

步驟三:查看任務狀態

  1. 在艦隊執行個體中執行以下命令,查看PyTorchJob任務的狀態。

    kubectl get pytorchjob

    預期輸出:

    NAME           STATE     AGE
    pytorch-test   Created   3m44s
  2. 在艦隊中執行以下命令,在事件中查看PyTorchJob任務調度至哪個關聯集群。

    kubectl describe pytorchjob pytorch-test

    預期輸出:

     Normal   ScheduleBindingSucceed  4m59s                   default-scheduler                   Binding has been scheduled successfully. Result: {cfxxxxxx:0,[{master 1} {worker 2}]}
  3. 在艦隊中執行以下命令,查看關聯集群中的PyTorchJob任務的狀態。

    kubectl amc get pytorchjob -M

    預期輸出:

    NAME           CLUSTER    STATE     AGE     ADOPTION
    pytorch-test   cfxxxxxx   Running   6m23s   Y
  4. 在艦隊中執行以下命令,查看Pod狀態。

    kubectl amc get pod -M   

    預期輸出:

    NAME                    CLUSTER    READY   STATUS      RESTARTS   AGE
    pytorch-test-master-0   cfxxxxxx   1/1     Running     0          7m16s
    pytorch-test-worker-0   cfxxxxxx   1/1     Running     0          7m16s
    pytorch-test-worker-1   cfxxxxxx   1/1     Running     0          7m16s
  5. 在艦隊中執行以下命令,查看關聯集群中PyTorchJob任務的詳情。

    kubectl amc get pytorchjob pytorch-test -m ${member_cluster_id} -o yaml