Cost optimization: right-sizing e spot instances no K8s

1. Introdução à Otimização de Custos em Kubernetes

Um dos maiores desafios em ambientes Kubernetes é o controle de custos. Estudos mostram que a maioria dos clusters opera com menos de 40% de utilização de recursos, resultando em desperdício financeiro significativo. O overprovisioning — prática de alocar mais recursos do que o necessário — é a principal causa, impulsionada pelo medo de indisponibilidade e pela falta de visibilidade sobre o consumo real das workloads.

Duas estratégias se destacam como pilares da otimização de custos: right-sizing (ajuste preciso de recursos) e spot instances (instâncias de computação com desconto). Juntas, podem reduzir custos em até 60-80% sem comprometer a performance.

As métricas-chave para acompanhar são:
- CPU/memory utilization: percentual de uso em relação ao solicitado
- Cluster efficiency: relação entre recursos utilizados e recursos provisionados
- Waste ratio: percentual de recursos alocados mas não utilizados

2. Right-Sizing de Workloads: Fundamentos e Estratégias

No Kubernetes, todo pod define requests (recursos garantidos) e limits (recursos máximos permitidos). O scheduler usa requests para alocar pods em nós; limits evitam que um pod consuma recursos excessivos. Quando requests são superdimensionados, o cluster fica com capacidade ociosa paga, mas não utilizada.

O Vertical Pod Autoscaler (VPA) é a ferramenta nativa para right-sizing. Ele analisa o histórico de uso dos pods e recomenda (ou aplica automaticamente) novos valores de requests e limits. O VPA opera em três modos:
- Off: apenas recomenda, sem alterar os pods
- Initial: aplica recomendações apenas na criação do pod
- Auto: atualiza pods em execução (requer reinicialização)

Ferramentas externas como Kubecost e Goldilocks complementam o VPA com dashboards de custo e recomendações visuais por namespace.

3. Implementando Right-Sizing na Prática

Vamos configurar o VPA no modo "Auto" para um deployment de API. Primeiro, instale o VPA no cluster:

git clone https://github.com/kubernetes/autoscaler.git
cd autoscaler/vertical-pod-autoscaler
./hack/vpa-up.sh

Agora, crie um manifesto VPA para o deployment api-gateway:

apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: api-gateway-vpa
  namespace: production
spec:
  targetRef:
    apiVersion: "apps/v1"
    kind: Deployment
    name: api-gateway
  updatePolicy:
    updateMode: "Auto"
  resourcePolicy:
    containerPolicies:
    - containerName: "*"
      minAllowed:
        cpu: 50m
        memory: 100Mi
      maxAllowed:
        cpu: 1000m
        memory: 1Gi
      controlledResources: ["cpu", "memory"]

Após aplicar (kubectl apply -f vpa.yaml), o VPA observará o consumo por 24-48 horas e começará a ajustar os recursos. Para ver recomendações em tempo real:

kubectl describe vpa api-gateway-vpa -n production

O Goldilocks oferece uma interface web que mostra recomendações por namespace. Instale com:

helm repo add fairwinds-stable https://charts.fairwinds.com/stable
helm install goldilocks fairwinds-stable/goldilocks --namespace goldilocks --create-namespace
kubectl label namespace production goldilocks.fairwinds.com/enabled=true

Acesse o dashboard via port-forward e veja sugestões de CPU/memory para cada deployment.

4. Spot Instances no Kubernetes: Conceitos e Riscos

Spot instances (ou preemptible VMs) são recursos de computação ociosos que provedores de nuvem oferecem com descontos de 60-90% em relação ao preço on-demand. Em troca, podem ser interrompidas a qualquer momento com aviso de 30 segundos a 2 minutos.

Como funciona no Kubernetes:
- O nó spot é adicionado ao cluster via node pool
- Quando a instância é interrompida, o nó recebe um taint node.kubernetes.io/unschedulable e os pods são removidos
- O control plane reagenda os pods em nós disponíveis

Riscos:
- Perda de pods em execução (especialmente problemático para stateful workloads)
- Atraso na reagendação se não houver nós on-demand disponíveis
- Picos de latência durante interrupções em massa

Para mitigar, use PodDisruptionBudget (PDB) para garantir um número mínimo de réplicas disponíveis:

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: api-pdb
spec:
  minAvailable: 2
  selector:
    matchLabels:
      app: api-gateway

5. Arquitetura para Uso Seguro de Spot Instances

A estratégia recomendada é usar nodepools híbridos: spot para workloads stateless (APIs, workers, batch jobs) e on-demand para stateful (bancos de dados, filas, sistemas críticos).

Configure dois nodepools no cluster:

# Nodepool spot (AWS EKS)
eksctl create nodegroup \
  --cluster meu-cluster \
  --name spot-pool \
  --instance-types m5.large,m5a.large,m6i.large \
  --spot \
  --nodes-min 2 \
  --nodes-max 10

# Nodepool on-demand
eksctl create nodegroup \
  --cluster meu-cluster \
  --name ondemand-pool \
  --instance-type m5.large \
  --nodes-min 1 \
  --nodes-max 5

Para direcionar pods para spot, use node affinity e tolerations no deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: worker-spot
spec:
  replicas: 3
  template:
    spec:
      affinity:
        nodeAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            preference:
              matchExpressions:
              - key: eks.amazonaws.com/capacityType
                operator: In
                values:
                - SPOT
      tolerations:
      - key: "spot"
        operator: "Exists"
        effect: "NoSchedule"
      containers:
      - name: worker
        image: myapp/worker:latest
        resources:
          requests:
            cpu: 200m
            memory: 256Mi
          limits:
            cpu: 500m
            memory: 512Mi

6. Ferramentas e Automação para Gerenciamento de Custos

Kubecost é a ferramenta mais completa para monitoramento de gastos. Instale com:

helm repo add kubecost https://kubecost.github.io/cost-analyzer/
helm install kubecost kubecost/cost-analyzer --namespace kubecost --create-namespace

Ele mostra custos por namespace, deployment, label e até por pod individual, além de recomendar right-sizing.

Para automação de nodepools, o Karpenter (AWS) gerencia dinamicamente a criação de nós spot, diversificando tipos de instância para evitar falta de capacidade:

apiVersion: karpenter.sh/v1beta1
kind: NodePool
metadata:
  name: spot-pool
spec:
  template:
    spec:
      requirements:
      - key: "karpenter.sh/capacity-type"
        operator: In
        values: ["spot"]
      - key: "node.kubernetes.io/instance-type"
        operator: In
        values: ["m5.large", "m5a.large", "m6i.large", "c5.large"]
  limits:
    cpu: 100
  disruption:
    consolidationPolicy: WhenUnderutilized
    expireAfter: 720h

7. Monitoramento e Ajuste Contínuo

Configure dashboards com Prometheus + Grafana para visualizar utilização de recursos e custos:

# Exemplo de alerta no Prometheus para baixa utilização
- alert: LowCPUUtilization
  expr: |
    sum(rate(container_cpu_usage_seconds_total{container!=""}[5m])) 
    / sum(kube_pod_container_resource_requests{resource="cpu"}) < 0.3
  for: 7d
  labels:
    severity: warning
  annotations:
    summary: "Cluster com utilização de CPU abaixo de 30% por 7 dias"

Estabeleça um ciclo de revisão trimestral para:
1. Revisar recomendações do VPA e aplicar ajustes
2. Analisar relatórios do Kubecost para identificar waste
3. Ajustar nodepools spot conforme padrões de interrupção
4. Testar cenários de eviction com PDBs

8. Casos de Uso e Boas Práticas Finais

Em um caso real de migração de um cluster EKS com 50 nodes, a combinação de VPA + spot instances resultou em:
- Redução de 35% com right-sizing (requests mais precisos)
- Redução adicional de 50% com spot (vs. on-demand)
- Economia total: ~40% sobre o custo original

Checklist de implementação:
1. Priorize workloads stateless para spot (APIs, workers, jobs)
2. Use PDBs com minAvailable adequado para cada serviço
3. Teste eviction simulando interrupção de nó spot
4. Configure Velero para backup de volumes em cenários stateful
5. Implemente Fluent Bit para logs centralizados (pods spot são efêmeros)
6. Monitore o cluster efficiency semanalmente

A otimização de custos em Kubernetes não é um projeto único, mas um processo contínuo. Right-sizing e spot instances são as ferramentas mais poderosas disponíveis, mas exigem monitoramento constante e ajustes periódicos para maximizar os benefícios sem comprometer a confiabilidade.

Referências