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
staticnã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 podsBurstableouBestEffort.
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:
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.
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.
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.cpusno 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.
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 |
|
Fixação 1:1 — vincula exatamente o número de núcleos definido em |
Maioria das cargas de trabalho sensíveis à latência |
|
Automática |
|
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:
Um cluster gerenciado ACK da edição Pro
Um pool de nós com
cpuManagerPolicydefinido comonone. Para mais informações, consulte Personalizar configurações do kubelet para um pool de nósack-koordinator instalado na versão 0.2.0 ou posterior. Para instruções de instalação, consulte ack-koordinator
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.
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"emmetadata.annotations.Para uma carga de trabalho como um Deployment: adicione
cpuset-scheduler: "true"emspec.template.metadata.annotations.resources.limits.cpudeve 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-3Verificar a anotação do pod
Verifique a anotação do pod:
"nginx": o contêiner chamadonginx."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 alimits.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"ecpu-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.cpudeve 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-7Verificar a anotação do pod
Verifique a anotação do pod:
"nginx": o contêiner chamadonginx."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
Edite o arquivo YAML da aplicação. Remova a anotação
cpuset-scheduler: "true"— e a anotaçãocpu-policy: "static-burst"se presente — despec.template.metadata.annotations.Aplique o arquivo YAML modificado fora do horário de pico. As alterações entram em vigor após a reinicialização do pod.
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
Agendamento com reconhecimento de topologia de GPU — selecione a combinação ideal de GPUs em um nó para maximizar a velocidade de treinamento.
Overcommitment dinâmico de recursos — recupere recursos do cluster alocados, mas não utilizados, e disponibilize-os para tarefas de baixa prioridade.