Todos los productos
Search
Centro de documentos

Container Service for Kubernetes:Using network topology-aware scheduling in an ACK Lingjun cluster, Using network topology-aware scheduling in an ACK Lingjun cluster, Using network topology-aware scheduling in an ACK Lingjun cluster

Última actualización: Sep 02, 2026

En las cargas de trabajo de entrenamiento de IA distribuida y big data, los pods se comunican con frecuencia. El programador predeterminado de Kubernetes distribuye los pods uniformemente entre los nodos, por lo que estos pueden terminar en nodos separados por múltiples saltos de switch; cada salto adicional aumenta la latencia y reduce el throughput. La programación consciente de la topología de red resuelve este problema al asignar todos los pods de un trabajo a nodos dentro del mismo dominio de reenvío de Capa 1 o Capa 2, lo que minimiza los saltos de switch y acelera la finalización del trabajo.

Funcionamiento

La programación consciente de la topología de red utiliza un algoritmo voraz para asignar trabajos a nodos Lingjun con la menor extensión topológica posible.

Los clústeres ACK Lingjun tienen una topología de red de dos niveles:

  • Access Switch (ASW): es la interfaz directa para los nodos Lingjun. Los nodos bajo el mismo ASW requieren como mínimo un salto para comunicarse.

  • Point of Delivery (Pod): es la topología de nivel superior que agrupa varios ASW. Los nodos bajo diferentes ASW en el mismo Pod requieren como mínimo dos saltos.

Cuantas menos capas de switch existan entre los nodos, menor será la latencia. El programador intenta ubicar primero todos los pods dentro del nivel topológico más bajo posible:

  • Trabajo de 2 nodos: se asigna a nodos dentro del mismo ASW (por ejemplo, par de nodos A-B o E-F).

  • Trabajo de 4 nodos: se asigna a nodos dentro del mismo Pod (por ejemplo, par de nodos A-D o E-H).

image

Las etiquetas de nodo indican a qué ASW y Pod pertenece cada nodo:

  • alibabacloud.com/asw-id: identifica el ASW.

  • alibabacloud.com/point-of-delivery: identifica el Pod.

En los clústeres ACK Lingjun, el componente lingjun-networktopology-collector recopila automáticamente esta información y aplica estas etiquetas a los nodos Lingjun. Para otros tipos de nodos o clústeres, agregue las etiquetas manualmente y asegúrese de que las claves de etiqueta coincidan con los valores de labelKey en su configuración de ClusterNetworkTopology.

Estrategias de programación

Dos estrategias controlan qué tan estrictamente se agrupan los pods dentro de un nivel topológico:

Estrategia

Comportamiento

PreferGather

Agrupa los pods dentro de la capa cuando es posible; permite la programación entre capas si los recursos son insuficientes

MustGather

Requiere que todos los pods estén dentro de la misma capa; la programación falla si ninguna capa individual puede alojar el trabajo

Requisitos previos

Antes de empezar, asegúrese de contar con lo siguiente:

  • Un clúster ACK Lingjun

  • kubectl configurado para conectarse al clúster

  • Nodos suficientes con etiquetas de topología aplicadas

Configuración y despliegue de la programación consciente de la topología de red

Configurar la programación consciente de la topología de red requiere tres archivos YAML: uno que define la estructura de topología a nivel de clúster, otro que declara las restricciones de programación para un trabajo específico y uno para el trabajo en sí.

Paso 1: Definir la topología del clúster

Cree el archivo cluster-network-topology.yaml para declarar la estructura de topología de dos niveles del clúster:

apiVersion: scheduling.koordinator.sh/v1alpha1
kind: ClusterNetworkTopology
metadata:
  # Keep unchanged.
  name: default
spec:
  networkTopologySpec:
  # parentTopologyLayer declares the upper topology structure.
  - parentTopologyLayer: ASWTopologyLayer
  # The lowest level must be NodeTopologyLayer for Lingjun nodes.
    topologyLayer: NodeTopologyLayer
  # The following defines the cross-layer topology mapping. Normally, no modification is needed.
  - labelKey:
    - alibabacloud.com/point-of-delivery
    topologyLayer: PoDTopologyLayer
  - labelKey:
    - alibabacloud.com/asw-id
    parentTopologyLayer: PoDTopologyLayer
    topologyLayer: ASWTopologyLayer

Paso 2: Declarar las restricciones de topología del trabajo

Cree el archivo sample-network-topology.yaml para especificar la estrategia de programación de cada nivel topológico:

apiVersion: scheduling.koordinator.sh/v1alpha1
kind: JobNetworkTopology
metadata:
  labels:
    network-topology-permit-wait-time: "999999"
  # The job name.
  name: sample-network-topology
  # The namespace the job belongs to.
  namespace: sample-network-topology
spec:
  topologyStrategy:
  # PreferGather: allows cross-ASW scheduling when resources are insufficient.
  - layer: ASWTopologyLayer
    strategy: PreferGather
  - layer: NodeTopologyLayer
    strategy: PreferGather
  # MustGather: cross-Pod scheduling is not allowed.
  - layer: PoDTopologyLayer
    strategy: MustGather
  # Must match spec.parallelism and pod-group.scheduling.sigs.k8s.io/min-available in the Job manifest.
  workerNum: 2

Paso 3: Crear el trabajo

Cree el archivo pi.yaml para definir el trabajo y hacer referencia a las restricciones de topología:

apiVersion: batch/v1
kind: Job
metadata:
  name: pi
spec:
  # Must match workerNum in JobNetworkTopology.
  parallelism: 2
  template:
    metadata:
      labels:
        # Must match workerNum in JobNetworkTopology.
        pod-group.scheduling.sigs.k8s.io/min-available: "2"
        pod-group.scheduling.sigs.k8s.io/name: sample-gang
        # Reference the JobNetworkTopology created in Step 2.
        network-topology-job-name: sample-network-topology
        network-topology-job-namespace: sample-network-topology
    spec:
      schedulerName: default-scheduler
      containers:
      - name: pi
        image: perl:5.34.0
        command: ["perl",  "-Mbignum=bpi", "-wle", "print bpi(2000)"]
        resources:
          limits:
            # This example uses a single GPU. Adjust as needed.
            nvidia.com/gpu: 1
      restartPolicy: Never
  backoffLimit: 4

Paso 4: Desplegar la configuración

Aplique los tres archivos al clúster:

kubectl apply -f cluster-network-topology.yaml
kubectl apply -f sample-network-topology.yaml
kubectl apply -f pi.yaml

Comprobación de los resultados de programación

Verificar la topología del clúster

Obtenga las etiquetas de topología de sus nodos para confirmar la estructura topológica:

# Network topology:
#              test-pod-1                     test-pod-2
#        /          |           \                   |
#    test-1      test-2      test-3               test-4
#     /   \         |           |                   |
#   0.12  0.14     0.15        0.16                0.17

kubectl get no -l alibabacloud.com/asw-id,alibabacloud.com/point-of-delivery -ojson | jq '.items[] | {"Name":.metadata.name, "ASW":.metadata.labels."alibabacloud.com/asw-id", "POD":.metadata.labels."alibabacloud.com/point-of-delivery"}'

Salida esperada:

{
  "Name": "cn-hongkong.10.1.0.12",
  "ASW": "test-1",
  "POD": "test-pod-1"
}
{
  "Name": "cn-hongkong.10.1.0.14",
  "ASW": "test-1",
  "POD": "test-pod-1"
}
{
  "Name": "cn-hongkong.10.1.0.15",
  "ASW": "test-2",
  "POD": "test-pod-1"
}
{
  "Name": "cn-hongkong.10.1.0.16",
  "ASW": "test-3",
  "POD": "test-pod-1"
}
{
  "Name": "cn-hongkong.10.1.0.17",
  "ASW": "test-4",
  "POD": "test-pod-2"
}

Escenario 1: Trabajo de 2 pods

Con workerNum: 2, ambos pods se programan en nodos dentro del mismo ASW (test-1):

kubectl get pod -owide
NAME       READY   STATUS              RESTARTS   AGE   IP               NODE                    NOMINATED NODE   READINESS GATES
pi-8p89l   1/1     Running             0          4s    172.30.240.197   cn-hongkong.10.1.0.14   <none>           <none>
pi-p8swv   0/1     ContainerCreating   0          4s    <none>           cn-hongkong.10.1.0.12   <none>           <none>

Ambos pods se ubican en test-1 (ASW) y comparten la ruta de red con el menor número de saltos.

Escenario 2: Trabajo de 4 pods

Actualice parallelism y pod-group.scheduling.sigs.k8s.io/min-available en pi.yaml, así como workerNum en sample-network-topology.yaml a 4. Vuelva a aplicar ambos archivos.

El programador asigna los 4 pods dentro de test-pod-1, ya que MustGather en PoDTopologyLayer impide la programación entre Pods. El nodo bajo test-pod-2 permanece sin programar:

NAME       READY   STATUS              RESTARTS   AGE   IP               NODE                    NOMINATED NODE   READINESS GATES
pi-2kwq9   1/1     Running             0          4s    172.30.241.123   cn-hongkong.10.1.0.12   <none>           <none>
pi-87hm5   0/1     ContainerCreating   0          4s    <none>           cn-hongkong.10.1.0.16   <none>           <none>
pi-bsvx8   1/1     Running             0          4s    172.30.240.198   cn-hongkong.10.1.0.14   <none>           <none>
pi-dvwhl   0/1     ContainerCreating   0          4s    <none>           cn-hongkong.10.1.0.15   <none>           <none>

Escenario 3: Trabajo de 5 pods (fallo de programación)

Actualice los mismos parámetros a 5. El trabajo falla porque test-pod-1 solo tiene 4 espacios disponibles y MustGather en PoDTopologyLayer prohíbe usar el único nodo en test-pod-2.

Todos los pods permanecen en estado Pending:

NAME       READY   STATUS    RESTARTS   AGE
pi-75qf5   0/1     Pending   0          2s
pi-8k4nd   0/1     Pending   0          2s
pi-b2pmc   0/1     Pending   0          2s
pi-n7c2b   0/1     Pending   0          2s
pi-wf4zn   0/1     Pending   0          2s

Inspeccione el mensaje de fallo de programación:

kubectl get pod -ojson | jq '.items[].status'

El mensaje de fallo de programación contiene:

0/6 nodes are available: 1 Insufficient nvidia.com/gpu, 1 [NetworkTopology begin] cluster total nodes:6, 5 node provide 5 freeSlot, 1 node unavailable cause Insufficient nvidia.com/gpu, job desireNum:5, all fail topology paths by MustGather reason: [path:RootNode->test-pod-1, freeSlotNum:4], [path:RootNode->DefaultTopologyName, freeSlotNum:0], [path:RootNode->test-pod-2, freeSlotNum:1] [NetworkTopology end], 4 NetworkTopology bestPlan empty. network topology job sample-network-topology/sample-network-topology gets rejected due to pod is unschedulable...

Campos clave en el mensaje:

Campo

Valor

Significado

job desireNum

5

El programador necesita 5 espacios dentro de un solo dominio de nivel Pod

path:RootNode->test-pod-1, freeSlotNum

4

test-pod-1 solo tiene 4 espacios disponibles, insuficientes para 5 pods

path:RootNode->test-pod-2, freeSlotNum

1

test-pod-2 tiene 1 espacio, pero MustGather prohíbe dividir el trabajo entre Pods

NetworkTopology bestPlan empty

—

No existe ningún plan de topología válido; la programación está bloqueada

Para resolver esto, reduzca workerNum para que quepa dentro de un solo Pod, o cambie la estrategia de PoDTopologyLayer de MustGather a PreferGather para permitir la programación entre Pods.