Todos os produtos
Search
Central de documentação

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

Última atualização: Sep 20, 2026

O Descheduler do ack-koordinator detecta nós sobrecarregados com base na utilização real de recursos e evicta Pods para rebalancear o cluster.

Este tópico descreve como instale o descheduler, ative o desagendamento com detecção de hotspots e configure seus parâmetros avançados.

Limitações

  • Há suporte apenas para os ACK managed Pro clusters.

  • Versões necessárias dos componentes:

    Componente

    Versão

    ACK Scheduler

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

    ack-koordinator

    v1.1.1-ack.1 ou posterior

    Helm

    v3.0 ou posterior

Importante

O Koordinator Descheduler apenas evicta Pods; o ACK Scheduler é responsável pelo reagendamento. Use o desagendamento com o agendamento com base na carga para evitar que os Pods evictados retornem a nós com hotspots.

Importante

Durante o desagendamento, o sistema evicta os Pods antigos antes de criar novos Pods. Certifique-se de que sua aplicação tenha réplicas redundantes suficientes para manter a disponibilidade.

Importante

O desagendamento usa a API REST de eviction (ou rest API) padrão do Kubernetes. Certifique-se de que seus Pods sejam reentrantes, para que as reinicializações após a evicção não interrompam seu service.

Faturamento

O ack-koordinator é gratuito para instalação e uso. Contudo, podem ser aplicadas cobranças adicionais nos seguintes cenários:

  • Recursos de nós workers: o ack-koordinator é um componente autogerenciado que consome recursos dos nós workers. Durante a instalação, configure as solicitações de recursos para cada módulo.

  • Métricas personalizadas do Prometheus: se você ativar Enable Prometheus Monitoring for ACK-Koordinator e usar o Managed service for Prometheus, o sistema contabiliza as métricas expostas como métricas personalizadas e gera cobrança. As taxas dependem do tamanho do cluster e da quantidade de aplicações. Revise o faturamento de instâncias do Prometheus antes de ativar este recurso. Consulte os dados de uso para monitorar o consumo de recursos.

Como funciona

Ciclo de execução

O Koordinator Descheduler é executado periodicamente. Cada ciclo de execução possui três etapas:

Koordinator Descheduler execution procedure

  1. Coleta de dados: busca informações de nós e workloads, além de dados de utilização de recursos.

  2. Execução de plugins (exemplo do LowNodeLoad):

    1. Identifica nós com hotspots com base em highThresholds e lowThresholds.

    2. Percorre todos os nós com hotspots, pontua os Pods elegíveis e os ordena para evicção. Consulte a Política de pontuação de Pods.

    3. Verifica cada Pod candidato em relação às restrições de migração (capacidade do cluster, utilização de recursos e limites de proporção de réplicas). Consulte as Políticas de desagendamento de hotspots com base na carga.

    4. Marca os Pods aprovados como candidatos à migração e ignora os demais.

  3. Evicção e migração de Pods: evicta os candidatos à migração por meio da API de eviction.

Classificação de nós

O plugin LowNodeLoad classifica os nós em três categorias com base em dois limiares: lowThresholds (limiar de ociosidade) e highThresholds (limiar de hotspot).

Exemplo com lowThresholds = 45% e highThresholds = 70%:

Node classification diagram

  1. Nó ocioso: a utilização de recursos está abaixo de lowThresholds (< 45%).

  2. Nó normal: a utilização de recursos está entre lowThresholds e highThresholds (45%–70%). Esta é a faixa ideal.

  3. Nó com hotspot: a utilização de recursos excede highThresholds (> 70%). O sistema evicta os Pods até que a carga do nó caia para 70% ou menos.

Os dados de utilização de recursos são atualizados a cada minuto e refletem a média de 5 minutos.

Se todos os nós excederem lowThresholds , o sistema considera a carga do cluster alta e suspende o desagendamento, mesmo que alguns nós excedam highThresholds .

Políticas de desagendamento de hotspots com base na carga

Política

Descrição

Repetição da verificação de hotspot

O sistema classifica um nó como hotspot somente após ele exceder highThresholds por ciclos consecutivos (padrão: 5), o que evita falsos positivos causados por picos momentâneos.

Ordenação de nós

O desagendamento começa pelo nó com hotspot de maior utilização. O sistema compara CPU e memória em ordem.

Pontuação de Pods

Para cada nó com hotspot, o sistema pontua e ordena os Pods antes da evicção: (1) prioridade (Priority class) mais baixa primeiro (o padrão é 0, a mais baixa); (2) classe de QoS mais baixa; (3) para prioridade e QoS iguais, os Pods são classificados por utilização de recursos e tempo de inicialização. Configure as classes de Priority ou QoS para controlar a ordem de evicção.

Filtro

Restringe o desagendamento a namespaces, Pods ou nós específicos usando seletores de rótulos. Consulte evictableNamespaces, podSelectors e nodeSelector na configuração do plugin LowNodeLoad.

Pré-verificação

Antes da evicção, o descheduler verifica: (1) se existem nós correspondentes a Node Affinity, Node Selector, Tolerations e requisitos de recursos; (2) se o nó de destino tem capacidade suficiente sem exceder highThresholds. Capacidade disponível = (highThresholds − current load) × total capacity. Exemplo: 20% de carga, 70% de highThresholds, 96 vCores → (70% − 20%) × 96 = 48 vCores disponíveis.

Limitação de migração

Limita as migrações simultâneas de Pods por nó, namespace e workload. Uma janela de tempo impede que os Pods do mesmo workload migrem com muita frequência. Compatível com o Pod Disruption Budget (PDB) do Kubernetes para um controle de disponibilidade mais refinado.

Observabilidade

O sistema emite eventos de migração para cada Pod, mostrando o motivo e o status. Para monitorar, execute `kubectl get event

grep ` e visualize os detalhes da migração.

Pré-requisitos

Antes de começar, certifique-se de que você tem:

  • Um ACK managed Pro cluster

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

Etapa 1: Ativar o desagendamento no ack-koordinator

  • Nova instalação: instale o ack-koordinator e selecione Enable ACK-Koordinator Descheduling Module na página de configuração.

  • Instalação existente: na página de configuração, selecione Enable ACK-Koordinator Descheduling Module. Consulte modifique o ack-koordinator.

Etapa 2: Ativar o plugin LowNodeLoad

  1. Para começar, crie um ConfigMap koord-descheduler-config.yaml para ativar o 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 o ConfigMap no cluster.

    kubectl apply -f koord-descheduler-config.yaml
  3. Reinicie o Koordinator Descheduler para carregar a nova configuração.

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

Etapa 3 (opcional): Ativar o agendamento com base na carga

Para um balanceamento de carga ideal, ative o agendamento com base na carga para que o ACK Scheduler evite colocar Pods em nós com hotspots após a evicção.

Para isso, defina loadAwareThreshold para corresponder a highThresholds. Valores incompatíveis podem fazer com que os Pods evictados sejam reagendados em nós com hotspots, especialmente quando há poucos nós com utilização semelhante.

Etapa 4: Verificar o desagendamento

Este exemplo utiliza um cluster de três nós, em que cada nó possui 104 núcleos e 396 GiB de memória.

  1. Primeiro, crie um arquivo stress-demo.yaml com o seguinte conteúdo.

    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. Implante o workload de teste de estresse.

    kubectl create -f stress-demo.yaml

    Saída esperada:

    deployment.apps/stress-demo created
  3. Em seguida, verifique se os Pods estão em execução e anote o nó atribuído a eles.

    kubectl get pod -o wide

    Saída esperada:

    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 a carga em cn-beijing.10.XX.XX.53 e verifique a utilização do nó.

    kubectl top node

    Saída esperada:

    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%

    O nó cn-beijing.10.XX.XX.53 está com 63% de CPU, excedendo o limiar de hotspot de 50%. O nó cn-beijing.10.XX.XX.215 está com 17% de CPU, abaixo do limiar de ociosidade de 20%.

  5. Em seguida, ative o plugin LowNodeLoad conforme descrito na Etapa 2: Ativar o plugin LowNodeLoad.

  6. Monitore as alterações nos Pods.

    Por padrão, um nó deve exceder highThresholds por cinco verificações consecutivas (cerca de 10 minutos no intervalo padrão de 120 segundos) para ser classificado como um hotspot.
    kubectl get pod -w

    Saída esperada:

    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. Por fim, verifique o evento de evicção.

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

    Saída esperada:

    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

    O descheduler evictou o Pod no nó com hotspot e o migrou para cn-beijing.10.XX.XX.215.

Configuração avançada

Todos os parâmetros do Koordinator Descheduler são configurados no ConfigMap da Etapa 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"

Configuração do sistema do Koordinator Descheduler

Parâmetro

Tipo

Valor

Descrição

Exemplo

dryRun

boolean

true / false (padrão)

Alternador do modo somente leitura. Quando ativado, o sistema não inicia nenhuma migração de Pod.

false

deschedulingInterval

time.Duration

> 0s

Intervalo de execução. Não deve exceder detectorCacheTimeout no plugin LowNodeLoad.

120s

Configuração de controle de evicção e migração

Parâmetro

Tipo

Valor

Descrição

Exemplo

maxMigratingPerNode

int64

≥ 0 (padrão: 2)

Máximo de Pods migrando simultaneamente por nó. 0 = ilimitado.

2

maxMigratingPerNamespace

int64

≥ 0 (padrão: ilimitado)

Máximo de Pods migrando simultaneamente por namespace. 0 = ilimitado.

1

maxMigratingPerWorkload

intOrString

≥ 0 (padrão: 10%)

Máximo de Pods migrando ou porcentagem por workload (por exemplo, Deployment). 0 = ilimitado. Workloads de réplica única são excluídos.

1 ou 10%

maxUnavailablePerWorkload

intOrString

≥ 0 (padrão: 10%), menor que o total de réplicas

Máximo de réplicas indisponíveis ou porcentagem por workload. 0 = ilimitado.

1 ou 10%

evictLocalStoragePods

boolean

true / false (padrão)

Define se Pods com volumes HostPath ou emptyDir devem ser evictados. Desativado por padrão para segurança dos dados.

false

objectLimiters.workload

struct

Duration > 0s (padrão: 5m); MaxMigrating ≥ 0 (padrão: 10%)

Limitação de migração no nível do workload. Duration: janela de tempo. MaxMigrating: máximo de réplicas migradas nessa janela. O padrão é maxMigratingPerWorkload.

duration: 5m / maxMigrating: 1 — no máximo 1 réplica por workload em 5 minutos.

Configuração do plugin LowNodeLoad

Parâmetro

Tipo

Valor

Descrição

Exemplo

highThresholds

map[string]float64

[0, 100] (CPU e memória, em porcentagem)

Limiar de hotspot. Pods em nós acima deste valor são elegíveis para evicção. Se todos os nós excederem lowThresholds, o sistema suspende o desagendamento.

cpu: 55 / memory: 75

lowThresholds

map[string]float64

[0, 100] (CPU e memória, em porcentagem)

Limiar de ociosidade. Se todos os nós excederem este valor, o sistema considera a carga geral do cluster alta e suspende o desagendamento.

cpu: 25 / memory: 25

anomalyCondition.consecutiveAbnormalities

int64

> 0 (padrão: 5)

Ciclos consecutivos em que um nó deve exceder highThresholds para ser classificado como hotspot. Reinicia após a evicção.

5

detectorCacheTimeout

\*metav1.Duration

Consulte Formato de Duration (padrão: 5m)

Duração do cache para verificações de hotspot. Deve ser ≥ deschedulingInterval.

1h, 300s, 2m30s

evictableNamespaces

include: string / exclude: string

Namespaces no cluster

Restringe o desagendamento a namespaces específicos. Deixe em branco para processar todos os Pods. include e exclude são mutuamente exclusivos.

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

nodeSelector

metav1.LabelSelector

Consulte Rótulos e seletores

Restringe o desagendamento a nós específicos usando um seletor de rótulos. Suporta pool de nós único (matchLabels) e múltiplos pools de nós (matchExpressions).

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

podSelectors

list of PodSelector

Consulte Rótulos e seletores

Restringe o desagendamento a Pods específicos usando seletores de rótulos. Há suporte para múltiplos grupos de seletores.

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

Perguntas frequentes

A utilização do nó excede o limiar, mas os Pods não são evictados

A causa mais comum é a configuração do descheduler estar inativa. Verifique os seguintes itens na ordem:

  1. Escopo não configurado: o descheduler processa apenas namespaces e nós explicitamente incluídos (ou não excluídos). Verifique evictableNamespaces e nodeSelector.

  2. Descheduler não reiniciado após alteração de configuração: alterações de configuração exigem uma reinicialização. Consulte a Etapa 2 para obter instruções.

  3. Intervalo maior que o tempo limite do cache: deschedulingInterval (padrão: 2 min) não deve exceder detectorCacheTimeout (padrão: 5 min); caso contrário, a detecção de hotspots falhará. Ajuste e reinicie.

  4. Nó não está consistentemente acima do limiar: o descheduler usa uma média suavizada. O sistema classifica um nó como hotspot somente após ele exceder highThresholds por consecutiveAbnormalities ciclos consecutivos (padrão: 5, ~10 minutos). O comando kubectl top node reflete apenas o último minuto; monitore por um período mais longo e confirme a utilização sustentada.

  5. Capacidade insuficiente do cluster: antes de evictar um Pod, o descheduler verifica se outro nó possui capacidade livre suficiente. Se nenhum tiver, o sistema ignora a evicção. Adicione nós para aumentar a capacidade.

  6. Workload de réplica única: o sistema não evicta Pods de réplica única por padrão. Para substituir isso, adicione a anotação descheduler.alpha.kubernetes.io/evict: "true" ao Pod ou ao spec.template.metadata do workload. Não há suporte nas versões do ack-koordinator v1.3.0-ack1.6 até v1.3.0-ack1.8. Atualize para a versão mais recente para usar este recurso.

  7. Pod usa HostPath ou emptyDir: excluídos do desagendamento por padrão. Defina evictLocalStoragePods: true no MigrationController para ativar a evicção. Consulte a Configuração de controle de evicção e migração.

  8. Muitas réplicas indisponíveis ou em migração: se as réplicas indisponíveis ou em migração atingirem maxUnavailablePerWorkload ou maxMigratingPerWorkload, o sistema bloqueia novas evicções. Aguarde a conclusão das evicções em andamento ou aumente esses limites.

  9. Contagem de réplicas ≤ limite de migração: se o total de réplicas for ≤ maxMigratingPerWorkload ou maxUnavailablePerWorkload, o sistema ignora o workload. Diminua esses valores ou use porcentagens.

O descheduler reinicia com frequência

Um ConfigMap inválido ou ausente causa loops de reinicialização. Verifique o formato do ConfigMap em relação à Configuração avançada e, em seguida, reinicie conforme descrito na Etapa 2.

Como o agendamento com base na carga e o desagendamento de hotspots funcionam juntos

Ative ambos os recursos para um balanceamento de carga ideal. O desagendamento evicta Pods de nós sobrecarregados; o agendamento com base na carga coloca os Pods reagendados em nós com menor utilização.

Para isso, defina loadAwareThreshold para corresponder a highThresholds. Consulte Usar o agendamento com base na carga e Políticas de agendamento.

Quais dados de utilização o descheduler usa?

O descheduler calcula uma média suavizada ao longo de múltiplos ciclos. O sistema aciona a evicção apenas quando o uso médio permanece acima de highThresholds pelos ciclos consecutivos configurados (padrão: ~10 minutos).

O descheduler exclui o page cache dos cálculos de memória (recuperável pelo SO). O comando kubectl top node inclui o page cache; use o Managed Service for Prometheus para visualizar a métrica real.

Próximas etapas