Todos los productos
Search
Centro de documentos

Container Service for Kubernetes:Use hotspot-aware descheduling to balance node loads

Última actualización: Sep 20, 2026

El Descheduler de ack-koordinator detecta los nodos sobrecargados mediante el uso real de recursos y expulsa los Pods para reequilibrar el clúster.

Este tema describe cómo instalar el desprogramador, habilitar el desprogramado con detección de puntos críticos y configurar sus parámetros avanzados.

Límites

  • Solo se admiten ACK managed Pro clusters.

  • Versiones de componentes obligatorias:

    Component

    Version

    ACK Scheduler

    v1.22.15-ack-4.0 o posterior, v1.24.6-ack-4.0 o posterior

    ack-koordinator

    v1.1.1-ack.1 o posterior

    Helm

    v3.0 o posterior

Importante

El Koordinator Descheduler solo expulsa Pods; el ACK Scheduler se encarga de la reprogramación. Utilice el desprogramado junto con load-aware scheduling para evitar que los Pods expulsados vuelvan a ubicarse en nodos con puntos críticos.

Importante

Durante el desprogramado, los Pods antiguos se expulsan antes de crear los nuevos. Asegúrese de que su aplicación cuente con suficientes réplicas redundantes para mantener la disponibilidad.

Importante

El desprogramado utiliza la API de expulsión estándar de Kubernetes. Asegúrese de que sus Pods sean reentrantes para que los reinicios posteriores a la expulsión no interrumpan el servicio.

Facturación

La instalación y el uso de ack-koordinator son gratuitos. Sin embargo, pueden generarse cargos adicionales en los siguientes escenarios:

  • Recursos de nodos worker: ack-koordinator es un componente autogestionado que consume recursos de los nodos worker. Configure las solicitudes de recursos para cada módulo durante la instalación.

  • Métricas personalizadas de Prometheus: si habilita Enable Prometheus Monitoring for ACK-Koordinator y utiliza Managed Service for Prometheus, las métricas expuestas se contabilizan como métricas personalizadas y generan costos. Estos dependen del tamaño del clúster y de la cantidad de aplicaciones. Revise la facturación de instancias de Prometheus antes de habilitar esta función. Para monitorear el consumo de recursos, consulte los datos de uso.

Funcionamiento

Ciclo de ejecución

El Koordinator Descheduler se ejecuta de forma periódica. Cada ciclo de ejecución consta de tres etapas:

Koordinator Descheduler execution procedure

  1. Recolección de datos: obtiene la información de nodos y cargas de trabajo, así como los datos de uso de recursos.

  2. Ejecución de plugins (ejemplo con LowNodeLoad):

    1. Identifica los nodos con puntos críticos según highThresholds y lowThresholds.

    2. Recorre todos los nodos con puntos críticos, asigna una puntuación a los Pods elegibles y los ordena para su expulsión. Consulte Pod scoring policy.

    3. Valida cada Pod candidato frente a las restricciones de migración: capacidad del clúster, uso de recursos y límites de proporción de réplicas. Consulte Load-aware hot spot descheduling policies.

    4. Marca como candidatos a migración los Pods que cumplen los requisitos y omite el resto.

  3. Expulsión y migración de Pods: expulsa los candidatos a migración mediante la API de expulsión.

Clasificación de nodos

El plugin LowNodeLoad clasifica los nodos en tres categorías a partir de dos umbrales: lowThresholds (umbral de inactividad) y highThresholds (umbral de punto crítico).

A continuación se muestra un ejemplo con lowThresholds = 45 % y highThresholds = 70 %:

Node classification diagram

  1. Nodo inactivo: el uso de recursos está por debajo de lowThresholds (< 45 %).

  2. Nodo normal: el uso de recursos se encuentra entre lowThresholds y highThresholds (45 %–70 %). Este es el rango objetivo.

  3. Nodo con punto crítico: el uso de recursos supera highThresholds (> 70 %). Los Pods se expulsan hasta que la carga del nodo disminuya al 70 % o menos.

Los datos de uso de recursos se actualizan cada minuto y reflejan el promedio de los últimos cinco minutos.

Si todos los nodos superan lowThresholds , se considera que la carga del clúster es alta y el desprogramado se suspende, incluso si algunos nodos superan highThresholds .

Directivas de desprogramado de puntos críticos con detección de carga

Policy

Description

Reintento de verificación de puntos críticos

Un nodo se clasifica como punto crítico solo después de superar highThresholds durante ciclos consecutivos (valor predeterminado: 5). Esto evita falsos positivos provocados por picos momentáneos.

Ordenamiento de nodos

El desprogramado comienza por el nodo con punto crítico que presenta el mayor uso de recursos. La CPU y la memoria se comparan en ese orden.

Puntuación de Pods

En cada nodo con punto crítico, los Pods reciben una puntuación y se ordenan antes de la expulsión: (1) primero los de clase Priority más baja (el valor predeterminado es 0, el más bajo); (2) luego los de clase QoS más baja; (3) si la prioridad y la QoS coinciden, se clasifican por uso de recursos y tiempo de inicio. Configure las clases Priority o QoS para controlar el orden de expulsión.

Filtro

Limita el desprogramado a namespaces, Pods o nodos específicos mediante selectores de etiquetas. Consulte evictableNamespaces, podSelectors y nodeSelector en la sección Configuración del plugin LowNodeLoad.

Verificación previa

Antes de la expulsión, el desprogramador comprueba lo siguiente: (1) que existan nodos compatibles con Node Affinity, Node Selector, Tolerations y los requisitos de recursos; (2) que el nodo destino tenga capacidad suficiente sin superar highThresholds. Capacidad disponible = (highThresholds − current load) × total capacity. Ejemplo: 20 % de carga, 70 % de highThresholds, 96 vCores → (70 % − 20 %) × 96 = 48 vCores disponibles.

Limitación de migraciones

Restringe las migraciones simultáneas de Pods por nodo, namespace y carga de trabajo. Una ventana de tiempo impide que los Pods de una misma carga de trabajo migren con demasiada frecuencia. Es compatible con Pod Disruption Budget (PDB) de Kubernetes para un control detallado de la disponibilidad.

Observability

Se emiten eventos de migración para cada Pod, donde se indica el motivo y el estado. Ejecute `kubectl get event

grep ` para consultar los detalles de la migración.

Requisitos previos

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

  • Un ACK managed Pro cluster

  • ACK Scheduler v1.22.15-ack-4.0 o posterior, ack-koordinator v1.1.1-ack.1 o posterior y Helm v3.0 o posterior

Paso 1: Habilitar el desprogramado en ack-koordinator

  • Instalación nueva: siga el procedimiento de Install ack-koordinator y seleccione Enable ACK-Koordinator Descheduling Module en la página de configuración.

  • Instalación existente: en la página de configuración, seleccione Enable ACK-Koordinator Descheduling Module. Consulte Modify ack-koordinator.

Paso 2: Habilitar el plugin LowNodeLoad

  1. Cree un ConfigMap llamado koord-descheduler-config.yaml para habilitar el plugin LowNodeLoad.

    # koord-descheduler-config.yaml
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: koord-descheduler-config
      namespace: kube-system
    data:
      koord-descheduler-config: |
        # System configuration for koord-descheduler. Do not modify this section.
        apiVersion: descheduler/v1alpha2
        kind: DeschedulerConfiguration
        leaderElection:
          resourceLock: leases
          resourceName: koord-descheduler
          resourceNamespace: kube-system
        deschedulingInterval: 120s  # Execution interval. The descheduler runs every 120s.
                                    # Must not exceed detectorCacheTimeout (default: 5m).
        dryRun: false               # Set to true to run in read-only mode (no evictions).
        # End of system configuration.
    
        profiles:
        - name: koord-descheduler
          plugins:
            balance:
              enabled:
                - name: LowNodeLoad      # Enable the LowNodeLoad plugin for hot spot descheduling.
            evict:
              enabled:
                - name: MigrationController  # Enable the eviction and migration controller.
    
          pluginConfig:
          - name: MigrationController
            args:
              apiVersion: descheduler/v1alpha2
              kind: MigrationControllerArgs
              defaultJobMode: EvictDirectly
    
          - name: LowNodeLoad
            args:
              apiVersion: descheduler/v1alpha2
              kind: LowNodeLoadArgs
    
              # A node is idle if usage of ALL resources is below lowThresholds.
              lowThresholds:
                cpu: 20    # 20% CPU utilization
                memory: 30 # 30% memory utilization
    
              # A node is a hot spot if usage of ANY resource exceeds highThresholds.
              highThresholds:
                cpu: 50    # 50% CPU utilization
                memory: 60 # 60% memory utilization
    
              # Scopes descheduling to specific namespaces.
              # include and exclude are mutually exclusive—configure only one.
              evictableNamespaces:
                include:
                  - default
                # exclude:
                #   - "kube-system"
                #   - "koordinator-system"
  2. Aplique el ConfigMap al clúster.

    kubectl apply -f koord-descheduler-config.yaml
  3. Reinicie el Koordinator Descheduler para cargar la nueva configuración.

    kubectl -n kube-system scale deploy ack-koord-descheduler --replicas 0
    kubectl -n kube-system scale deploy ack-koord-descheduler --replicas 1

Paso 3 (opcional): Habilitar la programación con detección de carga

Para lograr un equilibrio de carga óptimo, siga el procedimiento de enable load-aware scheduling. De este modo, el ACK Scheduler evitará colocar Pods en nodos con puntos críticos después de la expulsión.

Establezca loadAwareThreshold con el mismo valor que highThresholds. Si los valores no coinciden, los Pods expulsados podrían reprogramarse en nodos con puntos críticos, sobre todo cuando hay pocos nodos con un uso similar.

Paso 4: Comprobar el desprogramado

En este ejemplo se utiliza un clúster de tres nodos, cada uno con 104 núcleos y 396 GiB de memoria.

  1. Cree un archivo stress-demo.yaml con a continuación contenido.

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: stress-demo
      namespace: default
      labels:
        app: stress-demo
    spec:
      replicas: 6
      selector:
        matchLabels:
          app: stress-demo
      template:
        metadata:
          name: stress-demo
          labels:
            app: stress-demo
        spec:
          containers:
            - args:
                - '--vm'
                - '2'
                - '--vm-bytes'
                - '1600M'
                - '-c'
                - '2'
                - '--vm-hang'
                - '2'
              command:
                - stress
              image: polinux/stress
              imagePullPolicy: Always
              name: stress
              resources:
                limits:
                  cpu: '2'
                  memory: 4Gi
                requests:
                  cpu: '2'
                  memory: 4Gi
          restartPolicy: Always
  2. Despliegue la carga de trabajo de prueba de estrés.

    kubectl create -f stress-demo.yaml

    Resultado esperado:

    deployment.apps/stress-demo created
  3. Compruebe que los Pods estén en ejecución y anote el nodo asignado a cada uno.

    kubectl get pod -o wide

    Resultado esperado:

    NAME                           READY   STATUS    RESTARTS   AGE   IP            NODE                     NOMINATED NODE   READINESS GATES
    stress-demo-588f9646cf-s****   1/1     Running   0          82s   10.XX.XX.53   cn-beijing.10.XX.XX.53   <none>           <none>
  4. Aumente la carga en cn-beijing.10.XX.XX.53 y consulte el uso del nodo.

    kubectl top node

    Resultado esperado:

    NAME                      CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%
    cn-beijing.10.XX.XX.215   17611m       17%    24358Mi         6%
    cn-beijing.10.XX.XX.53    63472m       63%    11969Mi         3%

    El nodo cn-beijing.10.XX.XX.53 tiene un 63 % de uso de CPU, lo cual supera el umbral de punto crítico del 50 %. El nodo cn-beijing.10.XX.XX.215 registra un 17 % de CPU, por debajo del umbral de inactividad del 20 %.

  5. Habilite el plugin LowNodeLoad tal como se describe en Step 2: Enable the LowNodeLoad plugin.

  6. Supervise los cambios en los Pods.

    De forma predeterminada, un nodo debe superar highThresholds durante cinco comprobaciones consecutivas (unos 10 minutos con el intervalo predeterminado de 120 segundos) para clasificarse como punto crítico.
    kubectl get pod -w

    Resultado esperado:

    NAME                           READY   STATUS             RESTARTS   AGE   IP             NODE                     NOMINATED NODE   READINESS GATES
    stress-demo-588f9646cf-s****   1/1     Terminating        0          59s   10.XX.XX.53    cn-beijing.10.XX.XX.53   <none>           <none>
    stress-demo-588f9646cf-7****   1/1     ContainerCreating  0          10s   10.XX.XX.215   cn-beijing.10.XX.XX.215  <none>           <none>
  7. Consulte el evento de expulsión.

    kubectl get event | grep stress-demo-588f9646cf-s****

    Resultado esperado:

    2m14s   Normal   Evicting        podmigrationjob/00fe88bd-****   Pod "default/stress-demo-588f9646cf-s****" evicted from node "cn-beijing.10.XX.XX.53" by the reason "node is overutilized, cpu usage(68.53%)>threshold(50.00%)"
    101s    Normal   EvictComplete   podmigrationjob/00fe88bd-****   Pod "default/stress-demo-588f9646cf-s****" has been evicted
    2m14s   Normal   Descheduled     pod/stress-demo-588f9646cf-s****   Pod evicted from node "cn-beijing.10.XX.XX.53" by the reason "node is overutilized, cpu usage(68.53%)>threshold(50.00%)"
    2m14s   Normal   Killing         pod/stress-demo-588f9646cf-s****   Stopping container stress

    El Pod ubicado en el nodo con punto crítico se expulsó y migró a cn-beijing.10.XX.XX.215.

Configuración avanzada

Todos los parámetros del Koordinator Descheduler se configuran en el ConfigMap creado en el paso 2.

# koord-descheduler-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: koord-descheduler-config
  namespace: kube-system
data:
  koord-descheduler-config: |
    # System configuration. Do not modify this section.
    apiVersion: descheduler/v1alpha2
    kind: DeschedulerConfiguration
    leaderElection:
      resourceLock: leases
      resourceName: koord-descheduler
      resourceNamespace: kube-system
    deschedulingInterval: 120s  # Execution interval. Must not exceed detectorCacheTimeout.
    dryRun: false               # Set to true for read-only mode (no evictions).
    # End of system configuration.

    profiles:
    - name: koord-descheduler
      plugins:
        deschedule:
          disabled:
            - name: "*"  # All plugins disabled by default (shown for reference only).
        balance:
          enabled:
            - name: LowNodeLoad
        evict:
          disabled:
            - name: "*"  # All plugins disabled by default (shown for reference only).
          enabled:
            - name: MigrationController

      pluginConfig:
      - name: MigrationController
        args:
          apiVersion: descheduler/v1alpha2
          kind: MigrationControllerArgs
          defaultJobMode: EvictDirectly
          maxMigratingPerNode: 1       # Max Pods migrating simultaneously per node. 0 = unlimited.
          maxMigratingPerNamespace: 1  # Max Pods migrating simultaneously per namespace.
          maxMigratingPerWorkload: 1   # Max Pods migrating simultaneously per workload (e.g., Deployment).
          maxUnavailablePerWorkload: 2 # Max unavailable replicas per workload during migration.
          evictLocalStoragePods: false # Whether to evict Pods using HostPath or emptyDir volumes.
          objectLimiters:
            workload:               # At most 1 replica migrated per workload within 5 minutes.
              duration: 5m
              maxMigrating: 1

      - name: LowNodeLoad
        args:
          apiVersion: descheduler/v1alpha2
          kind: LowNodeLoadArgs

          lowThresholds:
            cpu: 20
            memory: 30
          highThresholds:
            cpu: 50
            memory: 60

          anomalyCondition:
            consecutiveAbnormalities: 5  # Number of consecutive checks above highThresholds
                                          # before a node is classified as a hot spot.
                                          # Counter resets after eviction.

          detectorCacheTimeout: "5m"  # Cache duration for hot spot checks.
                                      # Must be >= deschedulingInterval.

          evictableNamespaces:
            include:
              - default
            # exclude:
            #   - "kube-system"
            #   - "koordinator-system"

          nodeSelector:  # Process only the specified nodes.
            matchLabels:
              alibabacloud.com/nodepool-id: np77f520e1108f47559e63809713ce****

          podSelectors:  # Process only the specified Pods.
          - name: lsPods
            selector:
              matchLabels:
                koordinator.sh/qosClass: "LS"

Configuración del sistema de Koordinator Descheduler

Parameter

Type

Value

Description

Example

dryRun

boolean

true / false (predeterminado)

Interruptor del modo de solo lectura. Cuando está habilitado, no se inicia ninguna migración de Pods.

false

deschedulingInterval

time.Duration

> 0s

Intervalo de ejecución. No debe superar detectorCacheTimeout en el plugin LowNodeLoad.

120s

Configuración de control de expulsión y migración

Parameter

Type

Value

Description

Example

maxMigratingPerNode

int64

≥ 0 (predeterminado: 2)

Número máximo de Pods en migración simultánea por nodo. 0 = sin límite.

2

maxMigratingPerNamespace

int64

≥ 0 (predeterminado: sin límite)

Número máximo de Pods en migración simultánea por namespace. 0 = sin límite.

1

maxMigratingPerWorkload

intOrString

≥ 0 (predeterminado: 10 %)

Cantidad o porcentaje máximo de Pods en migración por carga de trabajo (por ejemplo, un Deployment). 0 = sin límite. Las cargas de trabajo con una sola réplica quedan excluidas.

1 o 10%

maxUnavailablePerWorkload

intOrString

≥ 0 (predeterminado: 10 %), menor que el total de réplicas

Cantidad o porcentaje máximo de réplicas no disponibles por carga de trabajo. 0 = sin límite.

1 o 10%

evictLocalStoragePods

boolean

true / false (predeterminado)

Indica si se expulsan los Pods con volúmenes HostPath o emptyDir. Se deshabilita de forma predeterminada para proteger los datos.

false

objectLimiters.workload

struct

Duration > 0s (predeterminado: 5m); MaxMigrating ≥ 0 (predeterminado: 10 %)

Limitación de migraciones a nivel de carga de trabajo. Duration: ventana de tiempo. MaxMigrating: número máximo de réplicas migradas en esa ventana. Su valor predeterminado es maxMigratingPerWorkload.

duration: 5m / maxMigrating: 1 — máximo 1 réplica por carga de trabajo en 5 minutos.

Configuración del plugin LowNodeLoad

Parameter

Type

Value

Description

Example

highThresholds

map[string]float64

[0, 100] (CPU y memoria, en porcentajes)

Umbral de punto crítico. Los Pods ubicados en nodos que superan este valor son candidatos a expulsión. Si todos los nodos superan lowThresholds, el desprogramado se suspende.

cpu: 55 / memory: 75

lowThresholds

map[string]float64

[0, 100] (CPU y memoria, en porcentajes)

Umbral de inactividad. Si todos los nodos lo superan, se considera que la carga general del clúster es alta y el desprogramado se suspende.

cpu: 25 / memory: 25

anomalyCondition.consecutiveAbnormalities

int64

> 0 (predeterminado: 5)

Ciclos consecutivos durante los cuales un nodo debe superar highThresholds para clasificarse como punto crítico. El contador se restablece tras la expulsión.

5

detectorCacheTimeout

\*metav1.Duration

Consulte el formato Duration (predeterminado: 5m)

Duración de la caché para las comprobaciones de puntos críticos. Debe ser ≥ deschedulingInterval.

1h, 300s, 2m30s

evictableNamespaces

include: string / exclude: string

Namespaces del clúster

Limita el desprogramado a namespaces específicos. Déjelo vacío para procesar todos los Pods. include y exclude son mutuamente excluyentes.

exclude: ["kube-system", "koordinator-system"]

nodeSelector

metav1.LabelSelector

Consulte Labels and selectors

Limita el desprogramado a nodos específicos mediante un selector de etiquetas. Admite un solo node pool (matchLabels) o varios (matchExpressions).

matchLabels: {alibabacloud.com/nodepool-id: np****}

podSelectors

list of PodSelector

Consulte Etiquetas y selectores

Limita el desprogramado a Pods específicos mediante selectores de etiquetas. Se admiten varios grupos de selectores.

matchLabels: {koordinator.sh/qosClass: "LS"}

Preguntas frecuentes

El uso del nodo supera el umbral, pero los Pods no se expulsan

La causa más común es que la configuración del desprogramador no esté activa. Revise los siguientes puntos en orden:

  1. Alcance no configurado: el desprogramador solo procesa los namespaces y nodos incluidos explícitamente (o no excluidos). Compruebe evictableNamespaces y nodeSelector.

  2. No se reinició el desprogramador tras cambiar la configuración: los cambios de configuración requieren un reinicio. Consulte Step 2 para ver las instrucciones.

  3. Intervalo mayor que el tiempo de espera de la caché: deschedulingInterval (predeterminado: 2 min) no debe superar detectorCacheTimeout (predeterminado: 5 min); de lo contrario, la detección de puntos críticos falla. Ajuste los valores y reinicie.

  4. El nodo no supera el umbral de manera constante: el desprogramador utiliza un promedio suavizado. Un nodo se clasifica como punto crítico solo después de superar highThresholds durante consecutiveAbnormalities ciclos consecutivos (valor predeterminado: 5, unos 10 minutos). kubectl top node refleja únicamente el último minuto; supervise durante un periodo más largo para confirmar que el uso se mantiene elevado.

  5. Capacidad insuficiente del clúster: antes de expulsar un Pod, el desprogramador comprueba que otro nodo tenga capacidad libre suficiente. Si ninguno la tiene, se omite la expulsión. Agregue nodos para aumentar la capacidad.

  6. Carga de trabajo con una sola réplica: de forma predeterminada, los Pods de una sola réplica no se expulsan. Para modificarlo, agregue la anotación descheduler.alpha.kubernetes.io/evict: "true" al Pod o a spec.template.metadata de la carga de trabajo. Esta opción no es compatible con ack-koordinator v1.3.0-ack1.6 a v1.3.0-ack1.8. Siga el procedimiento de Upgrade to the latest version para utilizarla.

  7. El Pod usa HostPath o emptyDir: estos Pods se excluyen del desprogramado de forma predeterminada. Establezca evictLocalStoragePods: true en MigrationController para habilitar su expulsión. Consulte Eviction and migration control configuration.

  8. Demasiadas réplicas no disponibles o en migración: si las réplicas no disponibles o en migración alcanzan maxUnavailablePerWorkload o maxMigratingPerWorkload, se bloquean las expulsiones adicionales. Espere a que finalicen las expulsiones en curso o aumente estos límites.

  9. Cantidad de réplicas ≤ límite de migración: si el total de réplicas es ≤ maxMigratingPerWorkload o maxUnavailablePerWorkload, se omite la carga de trabajo. Reduzca estos valores o utilice porcentajes.

El desprogramador se reinicia con frecuencia

Un ConfigMap no válido o ausente provoca bucles de reinicio. Compruebe el formato del ConfigMap con base en Advanced configuration y luego reinícielo tal como se indica en Step 2.

Cómo funcionan en conjunto la programación con detección de carga y el desprogramado de puntos críticos

Habilite ambas funciones para obtener un equilibrio de carga óptimo. El desprogramado expulsa los Pods de los nodos sobrecargados, mientras que la programación con detección de carga ubica los Pods reprogramados en nodos con menor uso de recursos.

Establezca loadAwareThreshold con el mismo valor que highThresholds. Consulte Use load-aware scheduling y Scheduling policies.

¿Qué datos de uso emplea el desprogramador?

El desprogramador calcula un promedio suavizado a lo largo de varios ciclos. La expulsión se activa solo cuando el uso promedio se mantiene por encima de highThresholds durante los ciclos consecutivos configurados (valor predeterminado: unos 10 minutos).

El desprogramador excluye la caché de páginas de los cálculos de memoria, ya que el sistema operativo puede recuperarla. kubectl top node sí incluye la caché de páginas; utilice Managed Service for Prometheus para consultar la métrica real.

Siguientes pasos