Todos os produtos
Search
Central de documentação

Container Service for Kubernetes:Use Gang scheduling

Última atualização: Sep 21, 2026

Evite deadlocks em jobs distribuídos garantindo que todos os pods necessários iniciem juntos ou que nenhum inicie.

Como funciona

O ACK implementa o gang scheduling por meio de um recurso PodGroup. O ACK associa cada pod a um PodGroup com uma contagem mínima de pods (min-available). O agendador mantém o grupo no estado Pending até atingir o mínimo e, em seguida, despacha todos os pods juntos.

O ACK oferece suporte a três métodos para que defina um PodGroup:

Método

Forma de agrupamento dos pods

Mais indicado para

Rótulos

O kube-scheduler cria automaticamente um PodGroup

Jobs simples, sem necessidade de um objeto PodGroup separado

PodGroup CRD

Recurso PodGroup explícito com controle de tempo limite

Jobs que precisam de scheduleTimeoutSeconds

Anotações do Koordinator

Agrupamento baseado em anotações

Clusters com a pilha de agendamento do Koordinator

Todos os métodos exigem que os pods e seus respectivos PodGroups estejam no mesmo namespace. Todos os pods de um PodGroup devem compartilhar a mesma prioridade.

Pré-requisitos

Antes de começar, certifique-se de ter:

  • Um ACK managed Pro cluster com o Kubernetes 1.16 ou posterior. Upgrade the cluster caso necessário.

  • Para configurações avançadas (GangGroup e política de correspondência): um cluster com o Kubernetes 1.22 ou posterior e versão do kube-scheduler superior a 1.xx.xx-aliyun-4.0.

Certifique-se de que o pool de nós elástico tenha capacidade máxima de recursos suficiente e rótulos de nó compatíveis para o agendamento de pods. Caso contrário, pode ocorrer falha no uso dos nós expandidos pelo pool de nós elástico.

Ative o gang scheduling

Método 1: Rótulos (recomendado)

Adicione dois rótulos a cada pod. O kube-scheduler cria automaticamente um PodGroup nomeado de acordo com o valor de pod-group.scheduling.sigs.k8s.io/name.

labels:
  pod-group.scheduling.sigs.k8s.io/name: tf-smoke-gpu       # PodGroup name (must be a valid DNS subdomain)
  pod-group.scheduling.sigs.k8s.io/min-available: "3"       # Minimum pods required to start the job

O valor de pod-group.scheduling.sigs.k8s.io/name deve ser um nome de subdomínio DNS válido.

Método 2: PodGroup CRD

Crie um recurso PodGroup e, em seguida, referencie-o em cada pod por meio de um rótulo.

Importante

A partir do ACK 1.31, há suporte apenas para scheduling.x-k8s.io/v1alpha1. O scheduling.sigs.k8s.io/v1alpha1 não tem mais suporte.

# PodGroup resource
apiVersion: scheduling.x-k8s.io/v1alpha1
kind: PodGroup
metadata:
  name: nginx
spec:
  scheduleTimeoutSeconds: 10   # Seconds to wait before rejecting the group if min-available is not met
  minMember: 3                 # Minimum number of pods required to start the job
---
# Pod label — must match the PodGroup name and namespace
labels:
  pod-group.scheduling.sigs.k8s.io/name: nginx

Método 3: Anotações do Koordinator

Adicione anotações a cada pod. Este método não oferece suporte aos parâmetros total-number ou mode da api do Koordinator.

annotations:
  gang.scheduling.koordinator.sh/name: "gang-example"
  gang.scheduling.koordinator.sh/min-available: "2"

Configurações avançadas

Agrupar vários gangs (GangGroup)

Alguns jobs possuem funções com diferentes requisitos de min-available — por exemplo, jobs do PyTorch com um servidor de parâmetros e workers. Um único PodGroup não expressa mínimos por função, e PodGroups separados não se coordenam entre as funções.

O GangGroup vincula vários PodGroups. O job inicia somente quando cada gang atinge seu próprio min-available. Adicione o seguinte rótulo a cada pod ou PodGroup (use a chave de anotação para o método do Koordinator):

Método

Recurso

Chave

Rótulos

Pod

pod-group.scheduling.sigs.k8s.io/groups

PodGroup CRD

PodGroup

pod-group.scheduling.sigs.k8s.io/groups

Anotações do Koordinator

Pod

gang.scheduling.koordinator.sh/groups

Exemplo de valor (array JSON de entradas <namespace>/<gang-name>):

pod-group.scheduling.sigs.k8s.io/groups: "[\"default/gang-example1\", \"default/gang-example2\"]"
O GangGroup requer o Kubernetes 1.22 ou posterior com a versão do kube-scheduler superior a 1.xx.xx-aliyun-4.0 .

Configure política de correspondência

Por padrão, um PodGroup conta apenas pods com pré-alocação de recursos concluída (only-waiting). Use match-policy para incluir pods em outros estados no cálculo do mínimo — por exemplo, quando pods de um ciclo anterior ainda estão em execução.

Adicione o rótulo a cada pod (método de rótulos) ou ao recurso PodGroup (método PodGroup CRD). O método de anotações do Koordinator oferece suporte apenas a once-satisfied.

Política de correspondência

Pods contados para o min-available

Quando usar

only-waiting

Pods com pré-alocação de recursos concluída

Mais restrita. Use para jobs stateless sem reaproveitamento de ciclos anteriores.

waiting-and-running

Pods no estado Running + pods com pré-alocação concluída

Use para contar pods em execução de um ciclo anterior no mínimo.

waiting-running-succeed

Pods no estado Succeeded + Running + com pré-alocação concluída

Use para jobs que toleram reinícios parciais — pods já concluídos continuam na contagem.

once-satisfied

Pods com pré-alocação de recursos concluída; o PodGroup torna-se inválido após o atendimento

Use para jobs de execução única. O PodGroup torna-se inválido assim que o agendador despacha o gang.

Exemplo baseado em rótulos:

pod-group.scheduling.sigs.k8s.io/match-policy: "waiting-and-running"

Exemplo de PodGroup CRD (adicione ao PodGroup, não ao pod):

pod-group.scheduling.sigs.k8s.io/match-policy: "waiting-and-running"
A configuração da política de correspondência requer o Kubernetes 1.22 ou posterior com a versão do kube-scheduler superior a 1.xx.xx-aliyun-4.0 .

Exemplo: job distribuído do TensorFlow

Este exemplo compara um job distribuído do TensorFlow com e sem gang scheduling. O cluster possui 4 GPUs. O job tem 1 pod PS e 4 pods worker, cada um com exigência de 2 GPUs e min-available definido como 5.

Etapa 1: Instale o Arena e prepare o cluster para jobs do TensorFlow.

O Arena é um subprojeto do Kubeflow para o gerenciamento de ciclos de vida de jobs de machine learning — incluindo configuração de ambiente, preparação de dados, desenvolvimento de modelos, treinamento e previsão — por meio de CLI ou sdk.

Etapa 2: envie o job do TensorFlow. Tanto os modelos de PS quanto de worker incluem rótulos de gang scheduling com min-available: "5".

apiVersion: "kubeflow.org/v1"
kind: "TFJob"
metadata:
  name: "tf-smoke-gpu"
spec:
  tfReplicaSpecs:
    PS:
      replicas: 1
      template:
        metadata:
          creationTimestamp: null
          labels:
            pod-group.scheduling.sigs.k8s.io/name: tf-smoke-gpu
            pod-group.scheduling.sigs.k8s.io/min-available: "5"
        spec:
          containers:
          - args:
            - python
            - tf_cnn_benchmarks.py
            - --batch_size=32
            - --model=resnet50
            - --variable_update=parameter_server
            - --flush_stdout=true
            - --num_gpus=1
            - --local_parameter_device=cpu
            - --device=cpu
            - --data_format=NHWC
            image: registry.cn-hangzhou.aliyuncs.com/kubeflow-images-public/tf-benchmarks-cpu:v20171202-bdab599-dirty-284af3
            name: tensorflow
            ports:
            - containerPort: 2222
              name: tfjob-port
            resources:
              limits:
                cpu: '1'
            workingDir: /opt/tf-benchmarks/scripts/tf_cnn_benchmarks
          restartPolicy: OnFailure
    Worker:
      replicas: 4
      template:
        metadata:
          creationTimestamp: null
          labels:
            pod-group.scheduling.sigs.k8s.io/name: tf-smoke-gpu
            pod-group.scheduling.sigs.k8s.io/min-available: "5"
        spec:
          containers:
          - args:
            - python
            - tf_cnn_benchmarks.py
            - --batch_size=32
            - --model=resnet50
            - --variable_update=parameter_server
            - --flush_stdout=true
            - --num_gpus=1
            - --local_parameter_device=cpu
            - --device=gpu
            - --data_format=NHWC
            image: registry.cn-hangzhou.aliyuncs.com/kubeflow-images-public/tf-benchmarks-gpu:v20171202-bdab599-dirty-284af3
            name: tensorflow
            ports:
            - containerPort: 2222
              name: tfjob-port
            resources:
              limits:
                nvidia.com/gpu: 2
            workingDir: /opt/tf-benchmarks/scripts/tf_cnn_benchmarks
          restartPolicy: OnFailure

Sem o gang scheduling ativado:

Verifique o status dos pods:

kubectl get pods

Com apenas 4 GPUs, 2 workers entram no estado Running e reivindicam todas as GPUs. Os 2 restantes permanecem no estado Pending, bloqueando o job:

NAME                    READY   STATUS    RESTARTS   AGE
tf-smoke-gpu-ps-0       1/1     Running   0          6m43s
tf-smoke-gpu-worker-0   1/1     Running   0          6m43s
tf-smoke-gpu-worker-1   1/1     Running   0          6m43s
tf-smoke-gpu-worker-2   0/1     Pending   0          6m43s
tf-smoke-gpu-worker-3   0/1     Pending   0          6m43s

Verifique os logs de um worker em execução:

kubectl logs -f tf-smoke-gpu-worker-0

Os workers aguardam parados pelos pods no estado Pending — as GPUs permanecem retidas e não há execução de treinamento:

INFO|2020-05-19T07:02:18|/opt/launcher.py|27| 2020-05-19 07:02:18.199696: I tensorflow/core/distributed_runtime/master.cc:221] CreateSession still waiting for response from worker: /job:worker/replica:0/task:3
INFO|2020-05-19T07:02:28|/opt/launcher.py|27| 2020-05-19 07:02:28.199798: I tensorflow/core/distributed_runtime/master.cc:221] CreateSession still waiting for response from worker: /job:worker/replica:0/task:2

Com o gang scheduling ativado:

Todos os 5 pods permanecem no estado Pending até o cluster dispor de recursos suficientes para atender ao min-available: 5:

NAME                    READY   STATUS    RESTARTS   AGE
tf-smoke-gpu-ps-0       0/1     Pending   0          43s
tf-smoke-gpu-worker-0   0/1     Pending   0          43s
tf-smoke-gpu-worker-1   0/1     Pending   0          43s
tf-smoke-gpu-worker-2   0/1     Pending   0          43s
tf-smoke-gpu-worker-3   0/1     Pending   0          43s

Após a adição de 4 GPUs ao cluster, o agendador despacha todos os 5 pods simultaneamente:

kubectl get pods

Saída esperada:

NAME                    READY   STATUS    RESTARTS   AGE
tf-smoke-gpu-ps-0       1/1     Running   0          3m16s
tf-smoke-gpu-worker-0   1/1     Running   0          3m16s
tf-smoke-gpu-worker-1   1/1     Running   0          3m16s
tf-smoke-gpu-worker-2   1/1     Running   0          3m16s
tf-smoke-gpu-worker-3   1/1     Running   0          3m16s

Verifique o log do worker e confirme o início do treinamento:

kubectl logs -f tf-smoke-gpu-worker-0

Saída esperada:

INFO|2020-05-19T07:15:24|/opt/launcher.py|27| Running warm up
INFO|2020-05-19T07:21:04|/opt/launcher.py|27| Done warm up
INFO|2020-05-19T07:21:04|/opt/launcher.py|27| Step  Img/sec loss
INFO|2020-05-19T07:21:05|/opt/launcher.py|27| 1 images/sec: 31.6 +/- 0.0 (jitter = 0.0) 8.318
INFO|2020-05-19T07:21:15|/opt/launcher.py|27| 10  images/sec: 31.1 +/- 0.4 (jitter = 0.7) 8.343
INFO|2020-05-19T07:21:25|/opt/launcher.py|27| 20  images/sec: 31.5 +/- 0.3 (jitter = 0.7) 8.142

Solução de problemas

Erro: "rejected by podgroup xxx"

Quando há vários PodGroups, a fila de backoff do kube-scheduler pode rejeitar pods com pré-alocação concluída em um ciclo durante o processamento de PodGroups subsequentes.

Este é um comportamento esperado. Ignore o erro se a resolução ocorrer em até 20 minutos. Se persistir, abra um ticket.

Próximos passos