Kubernetes na AWS costuma parecer “só mais containers” até a fatura mostra EKS + EC2/Fargate + NLB + NAT + logs + métricas. Este guia mapeia onde o custo se esconde e o que atacar primeiro em clusters de startup e médio porte.
O que compõe a fatura de um cluster EKS
| Componente | Cobrança típica |
|---|---|
| Control plane EKS | ~US$ 0,10/h por cluster (região) |
| Worker nodes | EC2, Fargate ou Outposts — maior fatia |
| EBS | Volumes por pod (PVC) e disco dos nós |
| Load balancers | ALB/NLB por Ingress/Service |
| NAT / data transfer | Egress de nós em subnet privada |
| Observability | CloudWatch, Prometheus, sidecars |
O control plane é previsível; o vazamento quase sempre está em nós oversized, nós ociosos e LBs órfãos.
Passo 1: visibilidade por namespace e label
Sem labels, FinOps em K8s é cego.
Mínimo:
- Labels
team,product,environmentem Deployments/Namespaces - Cost Allocation Tags nos nós EC2 e volumes EBS
- Kubecost, OpenCost ou CUR + labels (quando a conta justifica)
No Cost Explorer, filtre EC2 por tag do node group. Cruze com kubectl top nodes e kubectl top pods.
Passo 2: right-sizing de nós (node groups)
Erros clássicos:
- Node group único
m5.2xlarge“para tudo” com CPU média 15% - Over-provisioning de requests no YAML (requests altos → scheduler pede mais nós)
- Autoscaler com mínimo de nós alto demais em dev
Ações
- Instale metrics-server e olhe uso real vs requests/limits por 14 dias.
- Ajuste requests para p95 real + margem (não “10 CPU por precaução”).
- Use Cluster Autoscaler ou Karpenter com limites máximos por ambiente.
- Dev/staging:
minSize=0ou cluster desligado fora do horário (se política permitir).
Karpenter vs ASG tradicional
Karpenter provisiona instâncias certas para pods pendentes — costuma reduzir fragmentação. ASG + CA é mais familiar; ambos exigem teto máximo para não virar cheque em branco.
Passo 3: Fargate vs EC2 para workers
| Fargate | EC2 (managed node groups) | |
|---|---|---|
| Ops | Menor | Maior (patches, AMI) |
| Custo | Premium por vCPU/GB | Mais controle (Spot, RI, Graviton) |
| Ideal | Cargas pequenas, poucos pods | Produção com baseline estável |
Muitos times usam Fargate em dev e Graviton Spot em prod — padrão comum, não regra universal.
Passo 4: Spot para workloads tolerantes
Batch, filas, CI runners e alguns workers stateless funcionam em Spot node groups com:
- Multiple instance types no pool
- PodDisruptionBudgets sensatos
- Termination handler (graceful drain)
Nunca coloque banco stateful em Spot sem arquitetura que aguente perda de nó.
Leia: Spot Instances — guia prático.
Passo 5: rede e load balancers
Cada Service type=LoadBalancer pode criar ALB/NLB. Ingress mal limpo deixa LB cobrando sem tráfego.
- Audite LBs no console EC2 → Load Balancers sem targets saudáveis
- Ingress controller único (nginx, ALB controller) em vez de um LB por app
- Endpoints S3/Dynamo via VPC endpoints para reduzir NAT (NAT e data transfer)
Passo 6: storage (EBS + CSI)
PVCs esquecidos após delete do namespace (se reclaim policy errada) viram EBS available.
- Política de StorageClass com reclaim claro
- Snapshots de volumes órfãos antes de delete
- gp3 em vez de gp2 onde possível
Passo 7: observability sem explodir a fatura
Métricas, logs e traces em K8s multiplicam volume.
- Amostragem de traces em dev
- Retenção curta de logs de app (7–14 dias dev)
- Evite métrica custom em loop a cada segundo
Artigo relacionado: CloudWatch e logs.
Checklist EKS FinOps
- Requests/limits revisados com dados reais?
- Node groups com min/max adequados por ambiente?
- Spot para workloads stateless?
- LBs órfãos removidos?
- Tags em nós e namespaces para showback?
- NAT/endpoints revisados?
Quando EKS não é o problema
Às vezes o cluster é caro porque tudo roda lá — jobs batch, cron, workers e API no mesmo pool. Separar batch para Fargate/ Lambda/ fila SQS pode custar menos que otimizar só o node type.
Leitura relacionada
Por Mauricio Nascimento de Oliveira. Teste mudanças em staging; clusters em produção exigem runbook próprio.