Tous les produits
Search
Centre de documentation

Container Service for Kubernetes:Multi-cluster PyTorchJob scheduling with priority queuing

Dernière mise à jour :Aug 11, 2026

Les jobs d'entraînement distribué PyTorch nécessitent que tous les pods d'un job s'exécutent simultanément. Un démarrage partiel gaspille des ressources et peut bloquer le job indéfiniment. Le gang scheduling garantit une approche « tout ou rien » : soit tous les pods d'un job sont ordonnancés ensemble, soit aucun ne l'est. Cela permet d'éviter les interblocages de ressources dans les scénarios d'entraînement multi-GPU et multi-machines.

Cette rubrique explique comment configurer Kube Queue sur une instance ACK Fleet pour mettre en file d'attente les PyTorchJobs, et comment appliquer le gang scheduling afin que tous les pods soient déployés de manière atomique sur le même cluster membre.

Fonctionnement

L'instance Fleet coordonne l'ordonnancement des PyTorchJobs entre les clusters membres à l'aide de deux composants :

  • Kube Queue gère les files d'attente des jobs et applique des limites de quota élastiques, en maintenant les jobs en attente jusqu'à ce que suffisamment de ressources soient disponibles dans un cluster membre.

  • ACK Scheduler applique la sémantique du gang scheduling lorsque l'instance Fleet distribue les pods vers un cluster membre, garantissant que toutes les répliques (Master et Workers) sont placées de manière atomique.

image

Le flux d'ordonnancement fonctionne comme suit :

  1. Un PyTorchJob est soumis à l'instance Fleet avec une PropagationPolicy spécifiant customSchedulingType: Gang.

  2. Si la gestion des files d'attente est activée (suspension.scheduling: true), le job entre dans Kube Queue et attend qu'un emplacement de quota soit disponible.

  3. L'instance Fleet évalue les ressources disponibles sur les clusters membres et sélectionne un cluster cible.

  4. ACK Scheduler place tous les pods de manière atomique sur le cluster sélectionné, en respectant la sémantique du gang scheduling.

  5. L'instance Fleet surveille le job et synchronise le statut en retour.

Prérequis

Avant de commencer, assurez-vous d'avoir :

  • La suite AI cloud-native installée dans les clusters membres — déployez uniquement le composant Arena

  • La stratégie RAM (Resource Access Management) AliyunAdcpFullAccess attachée à votre utilisateur RAM. Pour plus de détails, consultez la section Accorder des autorisations aux utilisateurs RAM

  • L'outil de ligne de commande AMC installé. Pour plus de détails, consultez la section Utiliser AMC

  • (Facultatif) La réservation de ressources activée si vous souhaitez que l'instance Fleet garantisse la cohérence de l'ordonnancement avec le cluster membre. La réservation de ressources nécessite Kubernetes 1.28 ou version ultérieure et ACK Scheduler 6.8.0 ou version ultérieure.

(Facultatif) Activer la réservation de ressources

Sans réservation de ressources, l'instance Fleet estime la capacité disponible en additionnant les ressources restantes sur tous les nœuds d'un cluster membre. Avec la réservation de ressources activée, l'instance Fleet réserve la capacité réelle sur le cluster cible avant de valider, de sorte que la décision d'ordonnancement au niveau de Fleet corresponde au résultat du cluster membre.

  1. Connectez-vous à la console ACK et cliquez sur Clusters dans le volet de navigation de gauche.

  2. Cliquez sur le nom de votre cluster. Dans le volet de navigation de gauche, cliquez sur Add-ons.

  3. Sur la page Add-ons, recherchez Kube Scheduler et cliquez sur Configuration.

  4. Dans la boîte de dialogue Kube Scheduler Parameters, définissez enableReservation sur true et cliquez sur OK.

Choisir un mode d'ordonnancement

Deux modes sont disponibles :

Mode Quand l'utiliser Configuration clé
Gang scheduling uniquement Vous souhaitez que les pods soient placés de manière atomique sans gérer les files d'attente Définissez customSchedulingType: Gang dans PropagationPolicy
Gang scheduling + gestion des files d'attente Vous avez de nombreux jobs en concurrence pour des ressources limitées et besoin d'une mise en file d'attente ordonnée avec application des quotas Définissez customSchedulingType: Gang et suspension.scheduling: true

Suivez l'étape 1 si vous avez besoin de la gestion des files d'attente ; passez directement à l'étape 2 si vous n'avez besoin que du gang scheduling.

Étape 1 (facultative) : Configurer les files d'attente des jobs avec Kube Queue

Utilisez ElasticQuotaTree pour définir les limites de quota et contrôler le nombre de jobs pouvant s'exécuter simultanément entre les namespaces.

  1. Soumettez un ElasticQuotaTree à l'instance Fleet. L'exemple suivant configure un quota pour le namespace default qui permet l'exécution d'un seul job à la fois, avec un maximum de 10 000 CPU, 10 000 GiB de mémoire et 10 000 GPU.

    apiVersion: scheduling.sigs.k8s.io/v1beta1
    kind: ElasticQuotaTree
    metadata:
      name: elasticquotatree  # Only a single ElasticQuotaTree is supported.
      namespace: kube-system   # Must be created in the kube-system namespace.
    spec:
      root:
        name: root
        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  # Only one job can be dequeued at a time.
            cpu: 10000
            nvidia.com/gpu: 10000
            memory: 10000Gi
          namespaces:
            - default
  2. Vérifiez que Kube Queue a créé les files d'attente correspondantes :

    kubectl get queue -n kube-queue

    Résultat attendu :

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

Étape 2 : Soumettre un PyTorchJob pour l'ordonnancement multi-cluster

Soumettre une PropagationPolicy

Une PropagationPolicy indique à l'instance Fleet comment distribuer le PyTorchJob entre les clusters membres et quel mode d'ordonnancement appliquer.

Gang scheduling uniquement

Définissez customSchedulingType: Gang pour activer le placement atomique des pods sans mise en file d'attente.

apiVersion: policy.one.alibabacloud.com/v1alpha1
kind: PropagationPolicy
metadata:
  name: example-policy
  namespace: default
spec:
  propagateDeps: true
  failover:
    application:
      decisionConditions:
        tolerationSeconds: 30
      purgeMode: Immediately
  placement:
    replicaScheduling:
      replicaSchedulingType: Divided
      customSchedulingType: Gang
  resourceSelectors:
    - apiVersion: kubeflow.org/v1
      kind: PyTorchJob

Gang scheduling avec gestion des files d'attente

Ajoutez suspension.scheduling: true afin que l'instance Fleet maintienne le job dans Kube Queue jusqu'à ce qu'un emplacement de quota soit disponible, puis place tous les pods de manière atomique.

apiVersion: policy.one.alibabacloud.com/v1alpha1
kind: PropagationPolicy
metadata:
  name: example-policy
  namespace: default
spec:
  suspension:
    scheduling: true
  propagateDeps: true
  failover:
    application:
      decisionConditions:
        tolerationSeconds: 30
      purgeMode: Immediately
  placement:
    replicaScheduling:
      replicaSchedulingType: Divided
      customSchedulingType: Gang
  resourceSelectors:
    - apiVersion: kubeflow.org/v1
      kind: PyTorchJob

Soumettre un PyTorchJob

Soumettez le PyTorchJob suivant à l'instance Fleet. Il définit un pod Master et deux pods Worker.

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
      template:
        metadata:
          labels:
            app: pytorchjob
          name: pytorch-test
        spec:
          containers:
          - command:
            - bash
            - -c
            - |
              echo "$WORKER_INDEX"
              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

Étape 3 : Vérifier le statut du job

Exécutez ces commandes sur l'instance Fleet pour confirmer que le job a été ordonnancé et que tous les pods sont en cours d'exécution.

  1. Vérifiez l'état du PyTorchJob sur l'instance Fleet :

    kubectl get pytorchjob

    Résultat attendu :

    NAME           STATE     AGE
    pytorch-test   Created   3m44s
  2. Vérifiez vers quel cluster membre le job a été ordonnancé :

    kubectl describe pytorchjob pytorch-test

    Recherchez ScheduleBindingSucceed dans les événements. Le champ result indique le cluster cible et le nombre de répliques :

    Normal   ScheduleBindingSucceed  4m59s   default-scheduler   Binding has been scheduled successfully. Result: {cfxxxxxx:0,[{master 1} {worker 2}]}

    cfxxxxxx est l'ID du cluster membre où tous les pods s'exécuteront.

  3. Confirmez que le job est en cours d'exécution dans le cluster membre :

    kubectl amc get pytorchjob -M

    Résultat attendu :

    NAME           CLUSTER    STATE     AGE     ADOPTION
    pytorch-test   cfxxxxxx   Running   6m23s   Y

    ADOPTION: Y signifie que l'instance Fleet a pris en charge l'ordonnancement de ce job.

  4. Confirmez que tous les pods sont en cours d'exécution :

    kubectl amc get pod -M

    Résultat attendu :

    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

    Les trois pods (un Master et deux Workers) sont en cours d'exécution sur le même cluster, confirmant que le gang scheduling les a placés de manière atomique.

  5. Pour inspecter le YAML complet du PyTorchJob dans le cluster membre, exécutez :

    kubectl amc get pytorchjob pytorch-test -m ${member clusterid} -oyaml