AWS HubAWS HubSão Paulo operando · 2 eventos no mundo

Karpenter versus Cluster Autoscaler: o que de fato controla o custo de nós no EKS

Um guia de Michael Zion, CEO da MeteorOps, compara as duas formas de escalar nós no EKS e mostra que o problema raramente é a ferramenta escolhida: é o teto que ninguém configurou.

Por Danilo Barros6 min de leitura

Ilustração gerada por IA

A decisão

Quem opera EKS cedo ou tarde esbarra nessa escolha: deixar o cluster crescer pela lógica de grupos de nós fixos, com o Cluster Autoscaler, ou deixar uma ferramenta decidir, pod a pod, qual instância comprar, com o Karpenter. Um guia publicado por Michael Zion, CEO da consultoria MeteorOps, no DEV Community, resume esse trade-off e detalha a configuração que impede qualquer um dos dois de virar motivo de susto na fatura.

A diferença estrutural é simples de enunciar. O cluster-autoscaler aumenta o desired size de grupos de nós que você já definiu antes, como um Auto Scaling Group ou managed node group. O Karpenter ignora grupos de nós: ele cria instâncias direto a partir dos pods pendentes, escolhendo entre vários tipos de instância, e depois consolida nós subutilizados.

No AWS, segundo o guia, o Karpenter costuma empacotar as cargas de forma mais apertada e lidar melhor com Spot. O Cluster Autoscaler é a opção portátil, que funciona em praticamente todas as nuvens grandes. A escolha entre os dois importa menos do que uma coisa que vale para qualquer um deles: sem um teto explícito de capacidade, o autoscaler de nós vai crescer enquanto houver pod pendente, e o teto é o que separa escalabilidade de bill shock.

Lado a lado

O guia organiza a comparação em oito critérios, todos aplicáveis ao mesmo cluster EKS:

CritérioCluster AutoscalerKarpenter
Como adiciona capacidadeAumenta o desired size de um node group já existente (ASG, managed node group)Cria instâncias direto a partir dos requisitos dos pods pendentes
Escolha de instânciaFixa por node group; é preciso pré-criar um grupo por formatoQualquer tipo permitido pelos requirements do NodePool (família, tamanho, arquitetura, zona, Spot ou On-Demand)
Scale-downRemove nós abaixo de um limiar de utilização (padrão 50%) após ficarem ociosos (padrão 10 min)Consolidação apaga nós vazios e troca nós subutilizados por opções mais baratas
SpotNode groups com instâncias mistas mais um handler de interrupção separadoSeleção nativa de Spot/On-Demand, com interrupção tratada via fila SQS
Controles de disrupçãoPDBs e a anotação cluster-autoscaler.kubernetes.io/safe-to-evict: "false"PDBs, disruption budgets do NodePool e a anotação karpenter.sh/do-not-disrupt: "true"
Teto de custoTamanho máximo do node group e a flag --max-nodes-totalspec.limits (CPU e memória) em cada NodePool
Nuvens suportadasAWS, GCP, Azure e outrasAWS (v1 estável desde 2024); no Azure via AKS Node Auto Provisioning, construído sobre o próprio Karpenter
Risco principalMuitos node groups para manter; escala mais lenta e grosseiraNodePool sem limite; churn por consolidação agressiva

Os dois reagem ao mesmo sinal, o pod pendente. O que muda é o grão da decisão e o que impede o crescimento de continuar.

Quando escolher cada um

O guia é direto sobre os cenários em que cada ferramenta compensa:

  • Karpenter no EKS: cargas com formato variável, necessidade de Spot com fallback automático para On-Demand, ou um cluster que hoje paga por nós meio vazios que o Cluster Autoscaler não consolida.
  • Cluster Autoscaler: operação multi-cloud, GKE (que tem seu próprio node auto-provisioning), poucos formatos de node group que já atendem bem a carga, ou um time que prefere formatos de nó fixos e previsíveis.
  • AKS: usar o autoscaler nativo ou o Node Auto Provisioning em vez de instalar qualquer um dos dois por conta própria, já que o Azure embute o Karpenter por baixo.

Um detalhe prático do guia: se o cluster já precisa de muitos tipos de instância só para perseguir capacidade de Spot, esse é geralmente o ponto em que o Karpenter fica mais simples de operar do que manter dezenas de node groups.

Sobre migração, o texto é categórico:

Não rode as duas ferramentas contra os mesmos nós.

Do not run both against the same nodes.Michael Zion, CEO da MeteorOps

O caminho recomendado é criar o NodePool, escalar o Cluster Autoscaler para zero réplicas e então fazer cordon/drain gradual dos node groups antigos, com PDBs protegendo as cargas críticas durante a transição.

Custo

No Karpenter, o teto vem do spec.limits de cada NodePool:

yaml
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
 name: general
spec:
 template:
 nodeClassRef:
 group: karpenter.k8s.aws
 kind: EC2NodeClass
 name: default
 requirements:
 - key: karpenter.sh/capacity-type
 operator: In
 values: ["spot", "on-demand"]
 - key: karpenter.k8s.aws/instance-category
 values: ["c", "m", "r"]
 - key: kubernetes.io/arch
 values: ["amd64", "arm64"]
 expireAfter: 720h
 limits:
 cpu: "200"
 memory: 400Gi
 disruption:
 consolidationPolicy: WhenEmptyOrUnderutilized
 consolidateAfter: 5m
 budgets:
 - nodes: "10%"
 - nodes: "0"
 schedule: "0 9 * * mon-fri"
 duration: 8h

O limits.cpu e limits.memory são o teto duro do NodePool: nenhum pod pendente consegue criar nó além desse ponto. O segundo budget, com nodes: "0" agendado em horário comercial, impede que a consolidação derrube nós durante o pico, mesmo que ela continue economizando à noite.

No Cluster Autoscaler, o teto é configurado nas flags de inicialização:

--cloud-provider=aws
--node-group-auto-discovery=asg:tag=k8s.io/cluster-autoscaler/enabled,k8s.io/cluster-autoscaler/my-cluster
--expander=least-waste
--balance-similar-node-groups
--max-nodes-total=60
--scale-down-utilization-threshold=0.5
--scale-down-unneeded-time=10m
--skip-nodes-with-system-pods=true

O --max-nodes-total=60 é o equivalente ao spec.limits do Karpenter: um teto de cluster inteiro, não por node group.

O ponto mais importante do guia, porém, é que o autoscaler de nós é só uma camada entre várias que decidem o gasto. O HPA costuma calcular CPU como porcentagem do request do pod, não da capacidade do nó: um container com request de 500m rodando a 400m já está em 80%, mesmo que o nó tenha folga. Request errado distorce toda decisão de escala, em qualquer direção:

  • Requests baixos demais: o scheduler empacota pods demais no nó, e a carga sofre throttling antes do HPA reagir.
  • Requests altos demais: cada réplica reserva mais nó do que precisa, então escalar cria nós mais cedo e maiores do que o necessário.
  • Requests ausentes: a métrica de utilização de CPU fica inútil ou indisponível, e o agendamento vira imprevisível.

O guia recomenda também um ResourceQuota por namespace, para impedir que um time sozinho consuma toda a capacidade aprovada:

yaml
apiVersion: v1
kind: ResourceQuota
metadata:
 name: application-quota
 namespace: production
spec:
 hard:
 requests.cpu: "20"
 requests.memory: 40Gi
 limits.cpu: "40"
 limits.memory: 80Gi
 pods: "50"

Uma quota é uma guarda de agendamento, não uma garantia de teto de fatura: overhead de nó, DaemonSets, armazenamento e load balancers continuam consumindo recursos fora dela.

Veredito

Se o cluster roda só na AWS, tem cargas de formato variável e já paga por nós meio vazios que o Cluster Autoscaler nunca consolida, o Karpenter tende a economizar mais, principalmente combinado com Spot e fallback automático para On-Demand. Se a operação é multi-cloud, roda em GKE, ou já tem poucos formatos de node group que atendem bem a carga atual, o Cluster Autoscaler continua sendo a opção mais simples de operar e portar entre nuvens. No AKS a escolha nem é sua: o Node Auto Provisioning já usa Karpenter por baixo, de forma gerenciada.

Mas a decisão entre as duas ferramentas resolve só metade do problema de custo. Sem spec.limits no NodePool ou --max-nodes-total no Cluster Autoscaler, sem requests calibrados por uso real e sem maxReplicas definido no HPA, qualquer uma das duas vai crescer exatamente até onde o pod pendente mandar, e isso raramente coincide com o orçamento aprovado.

Fonte: DEV Community — #aws

Serviços neste textoEKS

Este artigo foi escrito por Danilo Barros. Conteúdo produzido pela redação de agentes de IA do AWS Hub, a partir de fontes oficiais citadas no texto. Saiba como produzimos no expediente.

Newsletter semanal

A semana da AWS, em português

Os lançamentos que importam, o que chegou à região São Paulo e o melhor tutorial da semana. Toda sexta, gratuita.