Autoscaling de nós no EKS: CAS e Karpenter para otimizar custo
Seu cluster AWS EKS mantém nós meio vazios ou demora minutos para escalar? Neste artigo, você vai comparar o Cluster Autoscaler e o Karpenter no EKS, entender como a consolidação remove e troca nós ociosos, configurar NodePools e disruption budgets e desligar ambientes fora do horário. Inclui exemplos em YAML, casos de clientes e um checklist.
Series: Otimização de custos com AWS EKS (5 articles)
- …
- 5Autoscaling de nós no EKS: CAS e Karpenter para otimizar custo This article
No post sobre autoscaling de pods no AWS EKS , vimos como o HPA e o KEDA ajustam o número de réplicas à demanda. Só que cada pod novo precisa de um nó para rodar, e cada pod removido pode deixar um nó AWS EC2 meio vazio. Se a capacidade de nós não acompanha os pods, o resultado é pod pendente no pico e nó ocioso — pelo qual você continua pagando — quando a demanda cai. Neste post, vamos comparar o Cluster Autoscaler e o Karpenter no EKS e ver como a consolidação de nós ataca exatamente esse desperdício.
Um post da série "Otimização de custos com AWS EKS".
Você vai entender como cada autoscaler de nós funciona e como configurar o Karpenter na API v1. Em seguida, vai ver como usar consolidação e disruption budgets com segurança e, por fim, como desligar ambientes fora do horário.
Dois jeitos de escalar nós
O EKS suporta dois autoscalers de nós principais, descritos na documentação de autoscaling do EKS . Os dois reagem a pods pendentes, mas trabalham de formas diferentes.
Cluster Autoscaler: escala grupos de nós
O Cluster Autoscaler (CAS) é um projeto da comunidade Kubernetes. Ele trabalha com node groups — conjuntos de nós EC2 gerenciados juntos, cada um apoiado por um Auto Scaling group do AWS EC2 Auto Scaling . Quando há pods pendentes, o CAS aumenta o número de nós de um grupo; quando há nós subutilizados, ele reduz.
No EKS, um node group pode ser de dois tipos:
- Managed node groups : a AWS cuida do ciclo de vida dos nós — provisionamento, atualização da AMI e drenagem dos nós durante a atualização. É o caminho mais comum e com menos trabalho operacional.
- Self-managed node groups : você mesmo cria e administra o Auto Scaling group dos nós. Dá mais controle sobre a configuração (AMI customizada, parâmetros do kubelet, bootstrap próprio) e, em troca, mais responsabilidade de manutenção.
Por isso, o CAS depende de um planejamento prévio:
- Cada node group deve ter instâncias com o mesmo perfil de CPU e memória, porque o CAS assume que todos os nós do grupo são iguais ao simular o escalonamento. Isso não quer dizer um único tipo de instância: o grupo pode misturar famílias diferentes (por exemplo,
m5,m5aem5n), desde que todas tenham a mesma capacidade de CPU e memória. - Workloads diferentes (Spot, GPU, Graviton) costumam exigir node groups separados, e o número de grupos cresce rápido.
- O CAS respeita o mínimo e o máximo de cada grupo e escolhe qual grupo escalar por meio de expanders. O EKS Best Practices Guide sobre o Cluster Autoscaler sugere o
least-wastecomo bom padrão.
Karpenter: provisiona o nó certo para os pods pendentes
O Karpenter é um projeto open source criado pela AWS que dispensa node groups. Ele parte dos pods pendentes e das restrições de agendamento (arquitetura, zona, tipo de capacidade) e provisiona a instância com a melhor relação custo-benefício para atendê-los — não um nó qualquer que caiba, mas o mais barato que caiba.
Segundo o FAQ do Karpenter , o processo tem três etapas:
- Agrupa os pods pendentes e faz o bin packing por CPU, memória e GPU, já descontando o overhead do nó, os recursos reservados pelo VPC CNI e os DaemonSets.
- Encontra o tipo mais eficiente — a menor instância em que o lote cabe — e reúne a ela outras 59 opções maiores, formando 60 tipos candidatos.
- Entrega os 60 tipos ao EC2 Fleet em modo instantâneo , que provisiona pela estratégia Price Capacity Optimized: para On-Demand, equivale ao menor preço; para Spot, o menor preço combinado com a menor chance de interrupção.
A diferença fica clara num exemplo. Imagine dois pods pendentes de tamanhos diferentes:
- Com o CAS, cada node group só cria instâncias do seu próprio tipo. O resultado pode ser dois nós, um para cada pod.
- Com o Karpenter, a decisão considera os dois pods juntos e escolhe o tipo mais barato que acomoda ambos. O resultado tende a ser um único nó do tamanho certo.
Além de escalar, o Karpenter também remove e troca nós continuamente, o que chamamos de consolidação. É aí que o Karpenter no EKS elimina boa parte da capacidade ociosa.

| Cluster Autoscaler | Karpenter | |
|---|---|---|
| Unidade de escala | Node group (Auto Scaling group) | Instância individual |
| Tipos de instância | Definidos por grupo, com o mesmo perfil (CPU e Memória) | Escolhidos a cada provisionamento pelo menor preço, dentro das restrições do NodePool |
| Como lança a instância | Ajusta o desiredCapacity do ASG, que chama a API do EC2 | Chama a API do EC2 Fleet diretamente, sem ASG |
| Remoção de nós | Nós subutilizados do grupo | Consolidação: remove nós vazios, junta pods e troca nós por opções mais baratas |
| Configuração | Node groups + parâmetros do CAS | NodePools e EC2NodeClasses |
Karpenter no EKS na API v1
A API estável do Karpenter (v1) tem dois recursos principais, documentados no site do Karpenter :
- NodePool (
karpenter.sh/v1): define quais nós podem ser criados (tipos de instância, capacidade Spot ou On-Demand, arquitetura, zonas), os limites de recursos e as regras de disrupção. - EC2NodeClass (
karpenter.k8s.aws/v1): define como os nós são criados na AWS (AMI, sub-redes, security groups e a role do AWS IAM dos nós).
⚠️ Se você tem manifestos antigos comProvisioner(karpenter.sh/v1alpha5), eles não funcionam mais. O anúncio do Karpenter 1.0 , de agosto de 2024, e o guia de migração explicam o caminho paraNodePooleEC2NodeClass.
Exemplo: NodePool e EC2NodeClass
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: default
spec:
template:
spec:
nodeClassRef:
group: karpenter.k8s.aws
kind: EC2NodeClass
name: default
requirements:
- key: karpenter.sh/capacity-type
operator: In
values: ["spot", "on-demand"] # Spot quando houver, On-Demand como alternativa
- key: kubernetes.io/arch
operator: In
values: ["amd64"] # arm64 só com imagens multi-arch (veja o próximo post)
- key: karpenter.k8s.aws/instance-category
operator: In
values: ["c", "m", "r"]
- key: karpenter.k8s.aws/instance-generation
operator: Gt
values: ["5"]
expireAfter: 720h # tempo máximo de vida do nó (padrão: 30 dias)
limits: # teto de capacidade do NodePool
cpu: "1000"
memory: 1000Gi
disruption:
consolidationPolicy: WhenEmptyOrUnderutilized
consolidateAfter: 1m
apiVersion: karpenter.k8s.aws/v1
kind: EC2NodeClass
metadata:
name: default
spec:
role: KarpenterNodeRole-meu-cluster
amiSelectorTerms:
- alias: al2023@latest # em produção, fixe uma versão da AMI
subnetSelectorTerms:
- tags:
karpenter.sh/discovery: meu-cluster
securityGroupSelectorTerms:
- tags:
karpenter.sh/discovery: meu-clusterQuanto mais tipos de instância o NodePool permite, mais opções o Karpenter tem para encontrar a combinação mais barata. Por isso, prefira requisitos por categoria e geração em vez de uma lista fechada de tipos. O blog da AWS sobre EC2 Spot com Karpenter reforça esse ponto ao recomendar diversificar ao máximo os tipos — por categoria, tamanho e zona — para ampliar o leque de capacidade que o Karpenter pode escolher.
Consolidação: onde o Karpenter economiza
A consolidação é o recurso que mais diferencia o Karpenter no EKS: é o processo em que ele procura nós que podem sair do cluster. Segundo a documentação de disruption do Karpenter , ela acontece de três formas:
- Remover nós vazios, que não têm mais pods de workload.
- Remover nós subutilizados, quando os pods deles cabem na capacidade livre de outros nós.
- Substituir nós por uma opção mais barata, quando os pods cabem numa combinação de nós existentes com um nó menor.
Dois campos controlam esse comportamento:
consolidationPolicy:WhenEmptyOrUnderutilizedconsidera nós vazios e subutilizados;WhenEmptyconsidera só os vazios. Desde a versão 1.14 (julho de 2026), há tambémBalanced, que compara o ganho de cada troca com a disrupção e pula as pouco vantajosas. O padrão continuaWhenEmptyOrUnderutilized.consolidateAfter: quanto tempo o Karpenter espera, depois que um pod é adicionado ou removido do nó, antes de considerá-lo para consolidação. O padrão é0s.
Disruption budgets: consolidar sem susto
Consolidar significa drenar nós e recriar pods em outro lugar. Para controlar o ritmo, o NodePool aceita disruption budgets. Sem nenhum budget definido, o Karpenter limita a disrupção voluntária a 10% dos nós por vez. Você pode criar regras mais específicas por motivo (
Empty, Underutilized, Drifted) e por horário:1
2
3
4
5
6
7
8
9
disruption:
consolidationPolicy: WhenEmptyOrUnderutilized
consolidateAfter: 1m
budgets:
- nodes: "10%" # regra geral
- nodes: "0" # sem consolidar nós em uso no horário comercial
schedule: "0 9 * * mon-fri"
duration: 8h
reasons: ["Underutilized", "Drifted"]Os budgets não impedem a expiração de nós pelo
expireAfter. Além disso, a documentação alerta que PodDisruptionBudgets mal configurados e a anotação karpenter.sh/do-not-disrupt podem travar a drenagem. Por isso, ao usar expireAfter, defina também um terminationGracePeriod.PodDisruptionBudgets: proteja a aplicação durante a consolidação
Vale separar dois mecanismos de nomes parecidos. Os disruption budgets do NodePool, que acabamos de ver, limitam quantos nós o Karpenter mexe de uma vez — protegem o cluster. Já o PodDisruptionBudget (PDB) é um objeto do Kubernetes que a própria aplicação declara para garantir uma disponibilidade mínima de réplicas — protege o workload.
Quando o Karpenter consolida, ele drena nós, e drenar é uma disrupção voluntária. Antes de despejar um pod, o Kubernetes consulta o PDB da aplicação: nele você define quantas réplicas precisam continuar no ar (
minAvailable) ou quantas podem sair ao mesmo tempo (maxUnavailable). Se remover aquele pod violasse o mínimo declarado, a drenagem espera até que outra réplica suba e fique pronta. Assim, a consolidação acontece aos poucos, sem levar a aplicação abaixo da capacidade de que ela precisa para atender tráfego.É isso que torna o PDB essencial para usar o Karpenter com segurança: sem ele, uma consolidação poderia remover várias réplicas de uma vez e causar indisponibilidade; com ele, a economia da consolidação não custa a resiliência. O cuidado é calibrar o mínimo com folga — alto o bastante para proteger a aplicação, baixo o bastante para não travar a consolidação, como veremos a seguir. Para aprofundar, veja a documentação do Kubernetes sobre PodDisruptionBudgets e o EKS Best Practices Guide sobre Karpenter .
O que bloqueia a consolidação
Na prática, porém, a consolidação costuma falhar por causa das aplicações, e não do Karpenter:
- PodDisruptionBudgets restritivos demais. O EKS Best Practices Guide recomenda que o
minAvailablefique abaixo do número de réplicas, com folga. - Uso excessivo de
karpenter.sh/do-not-disrupt. Reserve a anotação para casos justificados e revise periodicamente quem a usa. - Topology spread constraints e anti-afinidade rígidas, que forçam pods a ficarem espalhados em mais nós do que o necessário.
- Requests inflados, assunto do post sobre application profiling e rightsizing .
Casos reais
Stone: 35% de redução de custo com ajustes no Karpenter
Um blog da AWS Brasil , publicado em abril de 2026, mostra como a Stone reduziu em 35% o custo da infraestrutura da sua plataforma interna sobre o EKS. A redução veio de ajustes no Karpenter e nas aplicações. Entre os problemas encontrados:
- O cluster criava muitos nós pequenos em vez de consolidar em nós maiores.
- Regras de anti-afinidade e topology spread com
maxSkew: 1espalhavam pods mais do que o necessário. - O
consolidateAfterque a Stone usava, de 10 minutos, era lento demais. Novos pods chegavam aos nós subutilizados antes da consolidação, e o timer recomeçava. - Sem preferência explícita por Spot, pods compatíveis com Spot ocupavam nós On-Demand e impediam a remoção deles.
💰 Preços de referência: outubro de 2026. A redução de 35% foi relatada pela Stone no blog da AWS Brasil de abril de 2026 e depende do ambiente e dos preços da época. Para estimar o impacto no seu cluster, use os valores atuais da página de preços do AWS EC2 .
Salesforce: do Cluster Autoscaler ao Karpenter em mais de mil clusters
Num blog de arquitetura de janeiro de 2026 , a AWS descreve a migração da Salesforce do Cluster Autoscaler para o Karpenter em mais de 1.000 clusters EKS. Antes, a necessidade de atender workloads diferentes tinha gerado milhares de node groups e Auto Scaling groups. Depois da migração, a latência de escala caiu de minutos para segundos. Além disso, o esforço operacional manual caiu 80%, com automação e autoatendimento para os times.
Downscaling fora do horário
Por outro lado, nem todo ambiente precisa ficar no ar o dia inteiro. Ambientes de desenvolvimento, homologação e ferramentas internas costumam ser usados só no horário comercial. Desligá-los à noite e no fim de semana é, portanto, uma das formas mais simples de cortar capacidade ociosa.
O caminho mais idiomático hoje é combinar o KEDA com o Karpenter:
- O scaler cron do KEDA mantém as réplicas no horário de trabalho e, com
minReplicaCount: 0, leva o deployment a zero fora dele. - Sem pods, os nós ficam vazios, e a consolidação do Karpenter os remove.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: app-homologacao
namespace: homologacao
spec:
scaleTargetRef:
name: app
minReplicaCount: 0 # zero réplicas fora do horário
triggers:
- type: cron
metadata:
timezone: America/Sao_Paulo
start: 0 8 * * 1-5 # 8h, de segunda a sexta
end: 0 20 * * 1-5 # 20h, de segunda a sexta
desiredReplicas: "3"Por padrão, a redução acontece cinco minutos depois do horário de fim, que é o
cooldownPeriod do ScaledObject. Como alternativa para casos simples, o kube-downscaler original não é mais mantido, mas existe um fork ativo, o py-kube-downscaler .Boas práticas de Karpenter no EKS
Estas práticas complementam o guia de compute e autoscaling do EKS Best Practices :
- Faça o rightsizing e o autoscaling de pods antes. O Karpenter provisiona pelos requests; requests inflados viram nós grandes demais.
- Dê flexibilidade ao NodePool do Karpenter. Quanto mais categorias, gerações e tamanhos de instância o NodePool permite, mais opções o Karpenter tem para empacotar os pods e escolher o nó mais barato — e, no caso de Spot, mais pools de capacidade para reduzir o risco de interrupção.
- Defina
limitsem cada NodePool, para que um erro de configuração não crie capacidade sem teto. - Use consolidação com
WhenEmptyOrUnderutilized, ouBalancedse quiser menos trocas de nós, e ajuste oconsolidateAfterao ritmo dos seus workloads. - Proteja a produção com disruption budgets, por motivo e por horário.
- Revise PDBs,
do-not-disrupte topology spread, que costumam bloquear a consolidação. - Configure
expireAftercomterminationGracePeriod, para renovar os nós sem deixá-los presos. - Separe NodePools só quando necessário, por exemplo, para GPU ou para isolar times, e use
weightpara definir prioridades.
Por onde começar
Para adotar o Karpenter no EKS com segurança:
- Instale o Karpenter seguindo o guia de primeiros passos do projeto ou o guia de migração a partir do Cluster Autoscaler .
- Crie um NodePool flexível, com limites e disruption budgets, e comece por um ambiente não produtivo.
- Mova os workloads aos poucos, reduzindo os node groups antigos e mantendo um grupo pequeno para o próprio Karpenter e os componentes críticos.
- Desligue o Cluster Autoscaler quando todos os workloads estiverem nos nós do Karpenter.
- Acompanhe a utilização dos nós e o custo ocioso na visibilidade de custos, para medir o efeito da consolidação.
Checklist do post
- Nenhum manifesto usa
Provisioneroukarpenter.sh/v1alpha5 - Os NodePools permitem vários tipos e tamanhos de instância
- Todo NodePool tem
limitsdefinidos - A consolidação está ativa, com
consolidateAfteradequado - Existem disruption budgets para a produção
- PDBs têm folga entre
minAvailablee o número de réplicas - O uso de
karpenter.sh/do-not-disruptfoi revisado expireAftereterminationGracePeriodestão configurados- Ambientes não produtivos são desligados fora do horário
Perguntas frequentes
Qual a diferença entre Cluster Autoscaler e Karpenter?
O Cluster Autoscaler aumenta ou diminui node groups com instâncias de mesmo perfil. O Karpenter cria diretamente a instância mais adequada para os pods pendentes e consolida continuamente os nós, removendo ou trocando os ociosos.
Se o Karpenter dispensa node groups, ainda preciso de algum?
Sim, de um pequeno. O Karpenter dispensa node groups para os nós de workload — as suas aplicações rodam em nós que ele provisiona diretamente. Mas o controlador do Karpenter (os pods do próprio Karpenter) precisa rodar em algum lugar que já exista antes de ele estar no ar; senão vira um problema de "ovo e galinha", em que o Karpenter teria de provisionar o nó em que ele mesmo roda. Por isso, o padrão é manter um node group de tamanho fixo (dois nós costumam bastar), sem Cluster Autoscaler — é só capacidade estática para o Karpenter e os componentes críticos, não um grupo que alguém fica escalando. Como alternativa, o Fargate roda o controlador sem nenhum nó para gerenciar. Todo o restante da capacidade fica a cargo do Karpenter.
O que é consolidação no Karpenter?
É o processo em que o Karpenter remove nós vazios, junta pods de nós subutilizados e troca nós por opções mais baratas, respeitando os disruption budgets e os PodDisruptionBudgets.
O Provisioner do Karpenter ainda funciona?
Não. Na API v1 do Karpenter, o
Provisioner foi substituído pelo NodePool, e o AWSNodeTemplate pelo EC2NodeClass.Posso usar o Cluster Autoscaler e o Karpenter ao mesmo tempo?
Durante a migração, sim, com cuidado para que os dois não disputem os mesmos pods. O guia de migração do Karpenter mostra como fazer a transição e desligar o Cluster Autoscaler no fim.
Como desligar um ambiente de homologação à noite?
Use o scaler cron do KEDA com
minReplicaCount: 0 para levar os deployments a zero fora do horário. Em seguida, a consolidação do Karpenter remove os nós vazios.Próximo post
Com o Karpenter escolhendo os nós, fica fácil trocar a arquitetura das instâncias. No próximo post da série, vamos falar de AWS Graviton no EKS: como montar clusters com arquitetura mista, criar imagens multi-arch e evitar a armadilha de subir um pod x86 num nó Arm.
Series: Otimização de custos com AWS EKS (5 articles)
- …
- 5Autoscaling de nós no EKS: CAS e Karpenter para otimizar custo This article
Enjoyed reading this content? Let the author know!
Your likes, comments, shares, and saves help creators reach more builders.
Loading recommendations
Loading article