Todos os produtos
Search
Central de documentação

Container Service for Kubernetes:CPU topology-aware scheduling

Última atualização: Jun 27, 2026

Quando várias aplicações são executadas no mesmo nó, a contenção de recursos de CPU e a troca de contexto degradam cargas de trabalho sensíveis à latência. O agendamento com reconhecimento de topologia de CPU fixa os processos da aplicação em núcleos de CPU específicos, eliminando a variação de desempenho causada pela migração entre núcleos e pelo acesso à memória entre nós Non-Uniform Memory Access (NUMA).

Como funciona

Por padrão, o Kubernetes utiliza o Completely Fair Scheduler (CFS) do kernel para distribuir fatias de tempo de CPU entre todos os núcleos. O CFS ignora a topologia física da CPU, o que pode causar latência imprevisível em aplicações sensíveis ao desempenho.

O CPU Manager do Kubernetes (com a política static) consegue vincular pods a núcleos de CPU exclusivos, mas apresenta três limitações:

  • Falta de reconhecimento de topologia no nível do cluster: O kube-scheduler nativo opera apenas no nível do nó e não tem visibilidade da topologia de CPU de todo o cluster.

  • Ausência de suporte a NUMA: A política static não considera a arquitetura NUMA ao alocar núcleos. Isso pode forçar o acesso à memória entre nós NUMA distintos e introduzir latência adicional.

  • Guaranteed QoS only: Esta política se aplica somente a pods com classe de QoS Guaranteed. Não é compatível com pods Burstable ou BestEffort.

O ACK resolve essas limitações por meio da colaboração entre o kube-scheduler do ACK e o ack-koordinator, desenvolvidos sobre o Kubernetes Scheduling Framework:

  1. Relatório de topologia do nó: O ack-koordinator detecta continuamente a topologia física local da CPU — incluindo soquetes, nós NUMA e caches — e envia esses dados ao centro de agendamento.

  2. Agendamento global com reconhecimento de topologia: O kube-scheduler utiliza os dados de topologia de todo o cluster para selecionar o nó ideal para cada pod e planejar o esquema de alocação de núcleos. Por padrão, o agendador escolhe o núcleo com o menor número de aplicações vinculadas. O esquema de alocação resultante é gravado na anotação do pod.

  3. Fixação local de núcleos: Após o pod ser criado no nó de destino, o ack-koordinator lê a anotação do pod e modifica o arquivo cpuset.cpus no cgroup do pod para vinculá-lo aos núcleos físicos atribuídos.

Casos de uso

O agendamento com reconhecimento de topologia de CPU é mais adequado para as seguintes cargas de trabalho:

  • Aplicações sensíveis à latência: Sistemas de negociação de alta frequência e pipelines de processamento de dados em tempo real não toleram atrasos causados pela troca de contexto da CPU. Sem a fixação de CPU, o agendador CFS pode migrar seu processo entre núcleos durante a execução — algo inofensivo em ambiente de teste, mas mensurável em produção sob carga.

  • Aplicações sensíveis a NUMA: Cargas de trabalho em servidores multi-soquete (como Instâncias Bare Metal Elásticas AMD ou Intel) sofrem latência mensurável quando os acessos à memória cruzam limites NUMA. Fixar núcleos dentro de um único nó NUMA elimina essa sobrecarga.

  • Computação determinística: Tarefas de computação científica e análise de big data exigem throughput de CPU estável e previsível. A fixação elimina a variabilidade introduzida pelo compartilhamento de núcleos com outras cargas de trabalho.

  • Aplicações legadas sem suporte a limites de CPU de contêiner: Aplicações que criam threads com base na contagem total de núcleos físicos do host, em vez do limite de CPU do contêiner, beneficiam-se da fixação, que vincula o processo a um conjunto específico de núcleos.

Importante

Não ative o agendamento com reconhecimento de topologia de CPU nos seguintes cenários:

  • Ambientes com overcommitment de CPU: A fixação de núcleos reserva-os exclusivamente, o que é incompatível com o modelo de compartilhamento de recursos do overcommitment e causa desperdício de recursos.

  • Aplicações de uso geral ou intensivas em I/O: Serviços web, middleware e a maioria das cargas de trabalho limitadas por I/O não são sensíveis à troca de núcleos de CPU e não obtêm ganhos com a fixação.

Escolha uma política de fixação

O ACK oferece duas políticas de fixação:

Política

Anotação

Comportamento de fixação

Recomendada para

Geral

cpuset-scheduler: "true"

Fixação 1:1 — vincula exatamente o número de núcleos definido em resources.limits.cpu, preferindo núcleos dentro do mesmo nó NUMA

Maioria das cargas de trabalho sensíveis à latência

Automática

cpuset-scheduler: "true" e cpu-policy: "static-burst"

Analisa a topologia e o uso de recursos em tempo real; pode fixar mais núcleos do que o solicitado, priorizando um cluster completo de núcleos físicos (CCX/CCD em CPUs AMD)

Máquinas AMD de grande porte com 32 ou mais núcleos

Pré-requisitos

Antes de começar, verifique se você possui:

Etapa 1: Implantar uma aplicação de exemplo

Este guia utiliza um Deployment do Nginx para demonstrar o agendamento com reconhecimento de topologia de CPU.

  1. Crie um arquivo chamado nginx-app.yaml com o seguinte conteúdo:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx-deployment
      namespace: default
      labels:
        app: nginx
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: nginx
      template:
        metadata:
          labels:
            app: nginx
        spec:
          containers:
          - name: nginx
            image: alibaba-cloud-linux-3-registry.cn-hangzhou.cr.aliyuncs.com/alinux3/nginx_optimized:20240221-1.20.1-2.3.0
            ports:
            - containerPort: 80
            command:
            - "sleep"
            - "infinity"
            resources:
              requests:
                cpu: 4
                memory: 8Gi
              limits:
                # CPU limit must be an integer to enable pinning
                cpu: 4
                memory: 8Gi
  2. Implante a aplicação:

    kubectl apply -f nginx-app.yaml
  3. Faça logon no nó onde o pod está em execução e colete o UID do pod e o ID do contêiner.

    1. Obtenha o nome do pod:

      kubectl get pods -n default

      O nome do pod será semelhante a nginx-deployment-6f5899*****.

    2. Obtenha o UID do pod:

      # Replace <your-pod-name> with the actual pod name
      kubectl get pod <your-pod-name> -n default -o jsonpath='{.metadata.uid}{"\n"}'

      Saída esperada:

      a78a02b5-c87f-4e74-9ddd-254c163*****
    3. Obtenha o ID do contêiner:

      # Replace <your-pod-name> with the actual pod name
      kubectl describe pod <your-pod-name> -n default

      Na saída, localize Container ID em Containers. Remova o prefixo containerd:// para obter o ID bruto:

      Containers:
        nginx:
          Container ID:   containerd://b8b88a70096aabb0aea197dd2aba78d15bcbe9145198ef46a0474b31*****
  4. Verifique a versão do cgroup do nó:

    • cgroup_root — o nó usa cgroup v1

    • cgroup2fs — o nó usa cgroup v2

    stat -fc %T /sys/fs/cgroup/
  5. Verifique o status atual de fixação da CPU usando o comando apropriado para sua versão do cgroup. Antes de ativar a fixação, a saída mostra o intervalo completo de núcleos, indicando que o contêiner pode usar todos os núcleos do nó:

    • cgroup v1: ``shell # Replace <POD_UID> and <CONTAINER_ID> with the actual values cat /sys/fs/cgroup/cpuset/kubepods.slice/kubepods-pod<POD_UID>.slice/cri-containerd-<CONTAINER_ID>.scope/cpuset.cpus ``

    • cgroup v2: ``shell # Replace <POD_UID> and <CONTAINER_ID> with the actual values cat /sys/fs/cgroup/kubepods.slice/kubepods-pod<POD_UID>.slice/cri-containerd-<CONTAINER_ID>.scope/cpuset.cpus.effective ``

    No caminho do cgroup, substitua os hifens ( - ) no UID do pod por underscores ( _ ). Por exemplo, a78a02b5-c87f-4e74-9ddd-254c163 torna-se a78a02b5_c87f_4e74_9ddd_254c163 .
    0-31

Etapa 2: Ativar o agendamento com reconhecimento de topologia de CPU

Ative o agendamento com reconhecimento de topologia de CPU adicionando anotações à especificação do pod.

Importante

Não especifique nodeName diretamente em um pod ao usar este recurso. O kube-scheduler não participa do agendamento de pods com nodeName definido, portanto, a seleção de núcleos com reconhecimento de topologia não se aplica. Use nodeSelector ou afinidade de nó como alternativa.

Política de fixação geral

A política de fixação geral vincula ao pod exatamente o número de núcleos especificado em resources.limits.cpu, preferindo núcleos dentro do mesmo nó NUMA.

Configuração:

  • Para um pod: adicione cpuset-scheduler: "true" em metadata.annotations.

  • Para uma carga de trabalho como um Deployment: adicione cpuset-scheduler: "true" em spec.template.metadata.annotations.

  • resources.limits.cpu deve ser um número inteiro.

Exemplo:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  namespace: default
  labels:
    app: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      annotations:
        cpuset-scheduler: "true"  # Enables CPU topology-aware scheduling
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: alibaba-cloud-linux-3-registry.cn-hangzhou.cr.aliyuncs.com/alinux3/nginx_optimized:20240221-1.20.1-2.3.0
        ports:
        - containerPort: 80
        command:
        - "sleep"
        - "infinity"
        resources:
          requests:
            cpu: 4
            memory: 8Gi
          limits:
            cpu: 4       # Must be an integer
            memory: 8Gi

Verificar a fixação:

Depois que o pod estiver em execução, confirme se a fixação de núcleos está ativa usando um dos métodos a seguir.

  • Verificação:

    Visualize o status de duas maneiras.

    Verificar o arquivo Cgroup do nó

    Verifique o arquivo cgroup no nó: A saída mostra um conjunto de IDs de núcleo correspondente a limits.cpu: 4, confirmando que a fixação está ativa:

    • cgroup v1: ``shell # Replace <POD_UID> and <CONTAINER_ID> with the actual values cat /sys/fs/cgroup/cpuset/kubepods.slice/kubepods-pod<POD_UID>.slice/cri-containerd-<CONTAINER_ID>.scope/cpuset.cpus ``

    • cgroup v2: ``shell # Replace <POD_UID> and <CONTAINER_ID> with the actual values cat /sys/fs/cgroup/kubepods.slice/kubepods-pod<POD_UID>.slice/cri-containerd-<CONTAINER_ID>.scope/cpuset.cpus.effective ``

    0-3

    Verificar a anotação do pod

    Verifique a anotação do pod:

    • "nginx": o contêiner chamado nginx.

    • "0": o ID do nó NUMA. Todos os núcleos fixados estão no Nó NUMA 0, o que evita perda de desempenho por acesso à memória entre nós NUMA.

    • "elems": {"0":{},"1":{},"2":{},"3":{}}: os IDs dos núcleos físicos de CPU aos quais o contêiner está fixado (núcleos 0–3), correspondendo a limits.cpu: 4.

    # Replace <your-pod-name> with the actual pod name
    kubectl get pod <your-pod-name> -n default -o yaml | grep "cpuset:"

    Saída esperada:

    cpuset: '{"nginx":{"0":{"elems":{"0":{},"1":{},"2":{},"3":{}}}}}'

    Os campos da saída significam:

Política de fixação automática

A política de fixação automática é otimizada para hardware específico. Ela analisa a topologia da CPU do nó e o uso de recursos em tempo real, priorizando a vinculação de um cluster completo de núcleos físicos (como um CCX ou CCD em CPUs AMD) ao pod. O número de núcleos fixados pode exceder o solicitado, para maximizar a localidade da CPU e a concorrência.

Utilize esta política para tipos de máquinas AMD de grande porte com 32 ou mais núcleos.

Configuração:

  • Adicione duas anotações: cpuset-scheduler: "true" e cpu-policy: "static-burst".

    • Para um pod: adicione-as em metadata.annotations.

    • Para uma carga de trabalho como um Deployment: adicione-as em spec.template.metadata.annotations.

  • resources.limits.cpu deve ser um número inteiro.

Exemplo:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  namespace: default
  labels:
    app: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      annotations:
        cpuset-scheduler: "true"    # Enables CPU topology-aware scheduling
        cpu-policy: "static-burst"  # Enables automatic pinning and NUMA affinity
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: alibaba-cloud-linux-3-registry.cn-hangzhou.cr.aliyuncs.com/alinux3/nginx_optimized:20240221-1.20.1-2.3.0
        ports:
        - containerPort: 80
        command:
        - "sleep"
        - "infinity"
        resources:
          requests:
            cpu: 4
            memory: 8Gi
          limits:
            cpu: 4       # Must be an integer
            memory: 8Gi

Verificar a fixação:

A política automática pode fixar mais núcleos do que o solicitado. Verifique o resultado usando um dos métodos a seguir.

  • Verificação:

    A política de fixação automática analisa a topologia da CPU do nó e o uso de recursos em tempo real. O número de núcleos fixados pode ser maior do que o número de núcleos solicitados explicitamente para o pod. Verifique o status da fixação das duas maneiras a seguir.

    Verificar o arquivo Cgroup do nó

    Verifique o arquivo cgroup no nó: A saída mostra os núcleos específicos fixados (mais do que os 4 solicitados neste exemplo), confirmando que a fixação está ativa:

    • cgroup v1: ``shell # Replace <POD_UID> and <CONTAINER_ID> with the actual values cat /sys/fs/cgroup/cpuset/kubepods.slice/kubepods-pod<POD_UID>.slice/cri-containerd-<CONTAINER_ID>.scope/cpuset.cpus ``

    • cgroup v2: ``shell # Replace <POD_UID> and <CONTAINER_ID> with the actual values cat /sys/fs/cgroup/kubepods.slice/kubepods-pod<POD_UID>.slice/cri-containerd-<CONTAINER_ID>.scope/cpuset.cpus.effective ``

    0-7

    Verificar a anotação do pod

    Verifique a anotação do pod:

    • "nginx": o contêiner chamado nginx.

    • "0": o ID do nó NUMA. Todos os núcleos fixados estão no Nó NUMA 0, evitando acesso à memória entre nós NUMA.

    • "elems": os IDs dos núcleos físicos aos quais o contêiner está fixado (núcleos 0–7). A política automática pode fixar mais núcleos do que o solicitado para alinhar-se ao limite do cluster de núcleos físicos.

    # Replace <your-pod-name> with the actual pod name
    kubectl get pod <your-pod-name> -n default -o yaml | grep "cpuset:"

    Saída esperada:

    cpuset: '{"nginx":{"0":{"elems":{"0":{},"1":{},"2":{},"3":{},"4":{},"5":{},"6":{},"7":{}}}}}'

    Os campos da saída significam:

Aplicar em produção

Observabilidade

Antes e depois de ativar a fixação de núcleos, integre com o Monitoramento Prometheus da Alibaba Cloud. Monitore as seguintes métricas para observar o efeito da fixação em suas cargas de trabalho:

  • Métricas da aplicação: tempo de resposta (RT) e QPS

  • Métricas do nó: uso de CPU e throttling de CPU

Implantação gradual

Para Deployments com múltiplas réplicas, utilize canary releases ou atualizações graduais para ativar ou desativar a política de fixação progressivamente. Isso reduz o risco de uma regressão generalizada de desempenho.

Desativar o agendamento com reconhecimento de topologia de CPU

  1. Edite o arquivo YAML da aplicação. Remova a anotação cpuset-scheduler: "true" — e a anotação cpu-policy: "static-burst" se presente — de spec.template.metadata.annotations.

  2. Aplique o arquivo YAML modificado fora do horário de pico. As alterações entram em vigor após a reinicialização do pod.

Importante

Após desativar a fixação de CPU, os processos do pod deixam de estar vinculados a núcleos físicos específicos e podem ser executados em qualquer núcleo disponível no nó. Esteja ciente dos seguintes impactos potenciais:

  • O uso de CPU pode aumentar ligeiramente devido à troca de contexto entre núcleos.

  • Para aplicações intensivas em computação, a variação de desempenho causada pela contenção de recursos de CPU pode retornar.

  • Quando vários pods com alta carga compartilham o mesmo núcleo, podem ocorrer picos de carga que disparam o throttling da CPU.

Faturamento

O ack-koordinator é gratuito para instalação e uso. Cobranças adicionais podem ser aplicadas nos seguintes casos:

  • O ack-koordinator é um componente não gerenciado que consome recursos dos nós worker após a instalação. Configure as solicitações de recursos para cada módulo no momento da instalação.

  • Se você selecionar a opção Enable Prometheus monitoring for ACK-Koordinator e utilizar o Prometheus da Alibaba Cloud, as métricas de monitoramento serão contabilizadas como métricas personalizadas e incorrerão em taxas. O custo depende do tamanho do seu cluster e do número de aplicações. Antes de ativar esta opção, revise as informações de faturamento do Prometheus para entender a cota gratuita e os preços. Acompanhe seu uso consultando seus dados de utilização.

Próximos passos