Otimização de Custos no Kubernetes: Guia Prático com Kubecost, Autoscaling e FinOps em 2026

Aprenda a cortar até 60% da fatura do Kubernetes com right-sizing, autoscaling (HPA, VPA, Karpenter), Kubecost, OpenCost e Spot Instances. Guia prático com exemplos de código prontos para aplicar no seu cluster.

Por Que os Custos do Kubernetes Saem do Controle?

O Kubernetes mudou completamente a forma como a gente implanta e escala aplicações — nisso não há dúvida. Mas ele trouxe junto um problema que pega muita gente de surpresa: a falta de visibilidade sobre custos. Sabe aquela fatura mensal de R$ 250.000 em instâncias EC2? Ela não diz absolutamente nada sobre quanto custa cada microsserviço, qual equipe está consumindo mais, ou onde está o desperdício de verdade.

E os números assustam. Estudos recentes de 2026 mostram que 40–60% da capacidade provisionada em clusters Kubernetes é puro desperdício. Isso mesmo — metade dos containers usa menos de um terço dos recursos de CPU e memória que foram reservados.

O que acontece na prática é o seguinte: desenvolvedores inflam os resource requests por medo do temido OOMKill (e honestamente, eu entendo — ninguém quer ser acordado às 3 da manhã por causa disso). Só que essas pequenas decisões individuais se multiplicam em centenas de pods, criando um desperdício sistêmico massivo que ninguém percebe até chegar a conta.

Neste guia, vou mostrar como implementar uma estratégia completa de otimização de custos no Kubernetes — desde a configuração correta de resources até ferramentas de monitoramento e autoscaling inteligente. Tudo com exemplos de código que você pode aplicar hoje no seu cluster.

Configurando Resource Requests e Limits Corretamente

Vamos direto ao ponto: a raiz do desperdício no Kubernetes está na forma como os resource requests funcionam. Eles não são estimativas ou sugestões — são reservas fixas. Quando um pod solicita 500m de CPU e 512Mi de memória, o scheduler reserva essa capacidade inteira, mesmo que a aplicação use só uma fração durante a operação normal.

Regras Práticas para Dimensionamento

Depois de otimizar dezenas de clusters, cheguei nessas regras que funcionam bem na maioria dos cenários:

  • CPU requests: Use o percentil 50 (P50) do uso real. Se sua aplicação normalmente consome 150m, configure algo como 200m.
  • Memory requests: Use o percentil 99 (P99) do uso real. Memória precisa ter folga — um OOMKill é muito mais disruptivo do que throttling de CPU.
  • Memory limits: Configure entre 1,5x e 2x o valor do request para absorver picos sem desperdício excessivo.
  • CPU limits: Considere não definir CPU limits em muitos cenários. Sério. O throttling de CPU pode degradar a performance desnecessariamente, e o scheduler já garante os recursos via requests.

Exemplo: Deployment com Resources Bem Dimensionados

apiVersion: apps/v1
kind: Deployment
metadata:
  name: api-pagamentos
  labels:
    app: api-pagamentos
    team: squad-financeiro
    cost-center: cc-1234
spec:
  replicas: 3
  selector:
    matchLabels:
      app: api-pagamentos
  template:
    metadata:
      labels:
        app: api-pagamentos
        team: squad-financeiro
    spec:
      containers:
      - name: api
        image: api-pagamentos:v2.8.1
        resources:
          requests:
            cpu: "200m"       # P50 do uso real
            memory: "256Mi"   # P99 do uso real
          limits:
            memory: "512Mi"   # 2x o request para absorver picos
            # CPU limit omitido intencionalmente

Repare que o CPU limit está omitido de propósito. Essa é uma decisão consciente que evita o throttling desnecessário.

Aplicando ResourceQuotas por Namespace

Agora, pra evitar que uma equipe acabe consumindo recursos de forma desproporcional (já vi isso acontecer mais vezes do que gostaria), use ResourceQuota para impor limites por namespace:

apiVersion: v1
kind: ResourceQuota
metadata:
  name: quota-squad-financeiro
  namespace: squad-financeiro
spec:
  hard:
    requests.cpu: "8"
    requests.memory: "16Gi"
    limits.memory: "32Gi"
    pods: "50"

Autoscaling Inteligente: HPA, VPA e Karpenter

Se tem uma ferramenta que realmente faz diferença na conta, é o autoscaling bem configurado. Em 2026, o ecossistema Kubernetes oferece três mecanismos principais que, combinados da forma certa, podem reduzir custos entre 40% e 70%.

Vamos ver cada um deles.

Horizontal Pod Autoscaler (HPA)

O HPA ajusta o número de réplicas de um deployment com base em métricas como CPU, memória ou métricas customizadas. É a escolha natural para APIs, frontends e microsserviços stateless.

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: hpa-api-pagamentos
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: api-pagamentos
  minReplicas: 2
  maxReplicas: 20
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
  behavior:
    scaleDown:
      stabilizationWindowSeconds: 300
      policies:
      - type: Percent
        value: 25
        periodSeconds: 60

Dois detalhes importantes aqui: o stabilizationWindowSeconds de 300 segundos evita aquele efeito de flapping (ficar subindo e descendo sem parar), e o limite de 25% por minuto garante um scale-down gradual. Sem isso, já vi clusters ficarem instáveis durante picos de tráfego.

Vertical Pod Autoscaler (VPA)

O VPA faz algo diferente — ele ajusta os resource requests e limits de cada pod individualmente. Funciona muito bem para workloads stateful, bancos de dados e workers de background.

Um aviso importante: usar HPA e VPA ao mesmo tempo no mesmo workload pode criar um loop de feedback que desestabiliza tudo. A recomendação atual é usar o VPA em modo Off ou Initial para obter recomendações, aplicando-as manualmente, enquanto o HPA cuida do scaling automático.

apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: vpa-worker-processamento
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: worker-processamento
  updatePolicy:
    updateMode: "Off"  # Apenas recomendações, sem alterações automáticas
  resourcePolicy:
    containerPolicies:
    - containerName: worker
      minAllowed:
        cpu: "100m"
        memory: "128Mi"
      maxAllowed:
        cpu: "2"
        memory: "4Gi"

Para consultar as recomendações geradas pelo VPA, basta rodar:

kubectl describe vpa vpa-worker-processamento

Karpenter: O Substituto Moderno do Cluster Autoscaler

Aqui é onde as coisas ficam realmente interessantes. O Karpenter é um provisionador de nós de nova geração que substituiu o Cluster Autoscaler com vantagens significativas: provisiona nós em menos de um minuto, seleciona o tipo de instância dinamicamente e tem suporte nativo a Spot Instances.

Em 2026, a combinação HPA + Karpenter se tornou basicamente o padrão para clusters EKS em produção. Se você ainda está usando o Cluster Autoscaler antigo, vale muito a pena considerar a migração.

apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
  name: default
spec:
  template:
    spec:
      requirements:
      - key: kubernetes.io/arch
        operator: In
        values: ["amd64"]
      - key: karpenter.sh/capacity-type
        operator: In
        values: ["spot", "on-demand"]  # Prioriza Spot automaticamente
      - key: node.kubernetes.io/instance-type
        operator: In
        values:
        - m6i.large
        - m6i.xlarge
        - m7i.large
        - m7i.xlarge
        - c6i.large
        - c6i.xlarge
  limits:
    cpu: "100"
    memory: "400Gi"
  disruption:
    consolidationPolicy: WhenEmptyOrUnderutilized
    consolidateAfter: 60s

A política WhenEmptyOrUnderutilized é o que faz a mágica acontecer — o Karpenter consolida nós subutilizados automaticamente, eliminando capacidade ociosa em até 60 segundos. Na prática, isso significa que seu cluster se ajusta continuamente ao tamanho real da demanda.

Visibilidade de Custos com Kubecost e OpenCost

Você não pode otimizar o que não consegue medir. Parece clichê, mas é a pura verdade no mundo Kubernetes. As ferramentas de visibilidade de custos traduzem métricas de infraestrutura em valores financeiros reais, atribuindo custos a namespaces, deployments, pods e até labels individuais.

Instalando o Kubecost via Helm

# Adicionar repositório e instalar
helm repo add kubecost https://kubecost.github.io/cost-analyzer/
helm repo update

helm install kubecost kubecost/cost-analyzer \
  --namespace kubecost \
  --create-namespace \
  --set kubecostToken="SEU_TOKEN_AQUI"

# Acessar o dashboard via port-forward
kubectl port-forward -n kubecost svc/kubecost-cost-analyzer 9090:9090

Depois da instalação, o Kubecost leva uns 15 minutos para coletar dados suficientes e mostrar os primeiros relatórios. Tenha paciência — quando os dados começarem a aparecer, vai valer cada segundo de espera.

Instalando o OpenCost (Alternativa Open-Source)

Se o orçamento está apertado (e se você está lendo este artigo, provavelmente está), o OpenCost é a alternativa 100% open-source com licença Apache 2.0:

helm repo add opencost https://opencost.github.io/opencost-helm-chart
helm repo update

helm install opencost opencost/opencost \
  --namespace opencost \
  --create-namespace

# Acessar a API de custos
kubectl port-forward -n opencost svc/opencost 9003:9003

Kubecost vs OpenCost: Quando Usar Cada Um

A escolha depende bastante do estágio da sua organização:

  • OpenCost: Ideal para startups e equipes menores que precisam de visibilidade básica. Ele cobre alocação por namespace, deployment e label, mas não inclui previsão de custos, detecção de anomalias ou reconciliação com descontos (Spot, RI).
  • Kubecost: Faz mais sentido para organizações maiores com múltiplos clusters e necessidade de chargeback formal. Traz previsão de custos com IA, alertas de anomalia, suporte multi-cluster e reconciliação completa com a fatura do provedor cloud.

Labels e Namespaces para Alocação de Custos

Toda essa visibilidade de custos só funciona de verdade se seus workloads estiverem devidamente rotulados. Sem labels consistentes, as ferramentas de monitoramento simplesmente não conseguem atribuir custos a equipes ou projetos específicos — e você volta à estaca zero.

Estratégia de Labels Recomendada

# Aplicar labels por namespace
kubectl label namespace squad-backend team=backend
kubectl label namespace squad-backend cost-center=cc-2001
kubectl label namespace squad-backend environment=production

kubectl label namespace squad-frontend team=frontend
kubectl label namespace squad-frontend cost-center=cc-2002
kubectl label namespace squad-frontend environment=production

kubectl label namespace staging environment=staging
kubectl label namespace staging cost-center=cc-shared

Enforcement com Kyverno

Mas vamos ser realistas: pedir pros devs colocarem labels manualmente não funciona a longo prazo. A solução é usar um policy engine como o Kyverno para garantir que nenhum workload seja implantado sem as labels obrigatórias:

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: require-cost-labels
spec:
  validationFailureAction: Enforce
  rules:
  - name: check-required-labels
    match:
      any:
      - resources:
          kinds:
          - Deployment
          - StatefulSet
          - DaemonSet
    validate:
      message: "Labels 'team' e 'cost-center' são obrigatórias."
      pattern:
        metadata:
          labels:
            team: "?*"
            cost-center: "?*"

Com essa política ativa, qualquer tentativa de criar um Deployment sem as labels team e cost-center é automaticamente barrada pelo admission controller. Problema resolvido.

Spot Instances no Kubernetes: Economia de 70–90%

Essa é, de longe, a estratégia de maior impacto financeiro. As Spot Instances oferecem descontos de 70–90% em relação ao preço on-demand, e em 2026 elas estão mais estáveis e previsíveis do que nunca.

O segredo? Usar Spot para workloads tolerantes a interrupção e manter os workloads críticos em instâncias on-demand. Simples assim.

Arquitetura Híbrida com Karpenter

# NodePool para workloads críticos (on-demand)
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
  name: critical-workloads
spec:
  template:
    spec:
      requirements:
      - key: karpenter.sh/capacity-type
        operator: In
        values: ["on-demand"]
      taints:
      - key: workload-type
        value: critical
        effect: NoSchedule
  limits:
    cpu: "32"
---
# NodePool para workloads tolerantes (spot)
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
  name: batch-workloads
spec:
  template:
    spec:
      requirements:
      - key: karpenter.sh/capacity-type
        operator: In
        values: ["spot"]
      - key: node.kubernetes.io/instance-type
        operator: In
        values:
        - m6i.large
        - m6i.xlarge
        - m7i.large
        - c6i.large
        - c6i.xlarge
        - r6i.large
  limits:
    cpu: "200"
  disruption:
    consolidationPolicy: WhenEmptyOrUnderutilized

Uma dica importante: diversifique ao máximo os tipos de instância no NodePool de Spot. Quanto mais opções o Karpenter tiver disponíveis, maior a probabilidade de conseguir capacidade e menor o risco de interrupção simultânea de vários nós.

Desligamento Automático de Ambientes Dev/Staging

Essa é daquelas otimizações que parece óbvia, mas quase ninguém implementa. Ambientes de desenvolvimento e staging frequentemente rodam 24 horas por dia, 7 dias por semana, mesmo sendo usados apenas no horário comercial. Agendar o desligamento automático pode gerar uma economia imediata de 65–70% nesses ambientes.

CronJob para Scale-Down Noturno

apiVersion: batch/v1
kind: CronJob
metadata:
  name: scale-down-staging
  namespace: staging
spec:
  schedule: "0 22 * * 1-5"  # 22h de segunda a sexta (UTC)
  jobTemplate:
    spec:
      template:
        spec:
          serviceAccountName: scaler-sa
          containers:
          - name: scaler
            image: bitnami/kubectl:latest
            command:
            - /bin/sh
            - -c
            - |
              kubectl scale deployment --all --replicas=0 -n staging
              kubectl scale statefulset --all --replicas=0 -n staging
          restartPolicy: OnFailure
---
apiVersion: batch/v1
kind: CronJob
metadata:
  name: scale-up-staging
  namespace: staging
spec:
  schedule: "0 8 * * 1-5"  # 8h de segunda a sexta (UTC)
  jobTemplate:
    spec:
      template:
        spec:
          serviceAccountName: scaler-sa
          containers:
          - name: scaler
            image: bitnami/kubectl:latest
            command:
            - /bin/sh
            - -c
            - |
              kubectl scale deployment api-staging --replicas=2 -n staging
              kubectl scale deployment frontend-staging --replicas=1 -n staging
          restartPolicy: OnFailure

Basicamente, você desliga tudo às 22h e liga de volta às 8h, de segunda a sexta. São 10 horas por dia (mais fins de semana inteiros) de economia pura. Ajuste os horários conforme o fuso horário da sua equipe.

Monitoramento Contínuo e Alertas de Budget

Vou ser direto: otimização de custos não é um projeto com início e fim. É uma prática contínua. Se você fizer tudo que está neste guia e depois parar de monitorar, em seis meses estará de volta ao ponto de partida.

Configure alertas para pegar anomalias antes que elas virem faturas surpresa.

Alerta de Budget com Kubecost via Prometheus

# Regra de alerta no Prometheus para namespace com custo acima do budget
groups:
- name: kubecost-alerts
  rules:
  - alert: NamespaceBudgetExceeded
    expr: |
      kubecost_namespace_monthly_cost
        > on(namespace) kubecost_namespace_budget
    for: 1h
    labels:
      severity: warning
    annotations:
      summary: "Namespace {{ $labels.namespace }} excedeu o budget mensal"
      description: "Custo atual: ${{ $value }}. Investigue imediatamente."

Checklist de Monitoramento Semanal

Eu recomendo reservar 30 minutos toda semana para passar por esta lista:

  1. Revise o dashboard de custos por namespace e compare com o mês anterior
  2. Procure workloads abandonados (deployments com 0 réplicas mas com PVCs ou LoadBalancers ainda ativos — isso é mais comum do que parece)
  3. Analise as recomendações do VPA e aplique ajustes nos top 10 workloads mais caros
  4. Confira se a taxa de utilização de Spot está acima de 60% nos NodePools tolerantes
  5. Valide que a política de labels está sendo cumprida — recursos sem tags são dinheiro invisível

Resultados Esperados: Quanto Você Pode Economizar

Ok, a pergunta que todo mundo quer saber: quanto dá pra economizar de verdade? Com a implementação completa das estratégias deste guia, os resultados típicos observados em 2026 são:

  • Right-sizing de requests/limits: Redução de 25–40% no desperdício de capacidade
  • Autoscaling com HPA + Karpenter: Redução de 30–50% em custos de computação
  • Spot Instances para workloads tolerantes: Economia de 70–90% nas instâncias afetadas
  • Desligamento de ambientes dev/staging: Economia de 65–70% nesses ambientes
  • Consolidação de nós com Karpenter: Redução de 15–25% em nós ociosos

Na prática, cases reais reportam reduções totais de 35–60% na fatura de Kubernetes após implementar uma estratégia FinOps completa. Não é exagero — já vi empresas cortando centenas de milhares de reais por mês com essas mesmas técnicas.

Perguntas Frequentes

Qual a diferença entre Kubecost e OpenCost?

De forma simples: o OpenCost é o projeto open-source (Apache 2.0) que fornece a base de monitoramento de custos. O Kubecost é construído em cima dele e adiciona funcionalidades enterprise — suporte a múltiplos clusters, previsão de custos com IA, detecção de anomalias e reconciliação com descontos do provedor cloud (Spot, Reserved Instances, Savings Plans). Se sua equipe é pequena, o OpenCost resolve. Organizações maiores geralmente precisam do Kubecost.

Posso usar HPA e VPA ao mesmo tempo no mesmo workload?

Tecnicamente dá, mas eu não recomendo para o mesmo recurso (CPU/memória). Eles podem criar um loop de feedback que desestabiliza o workload inteiro. A prática que funciona melhor é usar o VPA em modo Off para obter recomendações de dimensionamento, aplicar manualmente, e deixar o HPA gerenciar o número de réplicas.

Karpenter funciona apenas com AWS EKS?

Historicamente sim, mas isso está mudando. Em 2026 o Karpenter está expandindo suporte para outros provedores. Se você usa Azure (AKS) ou GCP (GKE), as alternativas nativas são o AKS Node Autoprovisioning e o GKE Autopilot, que oferecem funcionalidades parecidas de provisionamento dinâmico de nós.

Qual a primeira ação mais impactante para reduzir custos?

Sem dúvida nenhuma: instalar uma ferramenta de visibilidade de custos. Kubecost ou OpenCost, tanto faz. Sem medir, você simplesmente não sabe onde está o desperdício. A maioria das organizações leva um susto quando descobre que está gastando 40–60% mais do que o necessário — e isso fica claro logo na primeira análise. Com dados concretos em mãos, as próximas otimizações praticamente se priorizam sozinhas.

Spot Instances são seguras para produção?

Sim, com uma condição: a arquitetura precisa estar preparada para interrupções. Use Spot para workloads stateless com múltiplas réplicas, diversifique os tipos de instância no NodePool, e mantenha workloads críticos (bancos de dados, serviços singleton) em on-demand. Com o Karpenter, a migração automática de pods em caso de interrupção é praticamente transparente e leva menos de um minuto.

Sobre o Autor Editorial Team

Our team of expert writers and editors.