Cluster autoscaling: nodes que escalam com a demanda

Em ambientes Kubernetes dinâmicos, a capacidade de ajustar automaticamente a infraestrutura subjacente é fundamental para garantir desempenho e economia. O Cluster Autoscaler (CA) é o componente responsável por adicionar ou remover nós do cluster conforme a demanda de workloads, complementando o Horizontal Pod Autoscaler (HPA) que atua no nível de pods.

1. Fundamentos do Cluster Autoscaling

Escalabilidade horizontal no Kubernetes pode ocorrer em duas camadas: pods (HPA) e nós (Cluster Autoscaler). Enquanto o HPA ajusta o número de réplicas de um deployment, o CA ajusta a quantidade de máquinas no cluster.

Diferenças principais:
- HPA: escala pods dentro dos recursos existentes
- CA: escala a infraestrutura (nodes) quando não há recursos para novos pods

Cenários típicos:
- Picos de carga durante horário comercial
- Redução noturna para economizar custos
- Workloads sazonais como Black Friday ou promoções

2. Arquitetura do Cluster Autoscaler

O CA é implantado como um pod no cluster que monitora constantemente:
- Pods em estado Pending por falta de recursos
- Nós subutilizados que podem ser removidos

Fluxo de decisão:
1. Pod não consegue ser agendado → status Pending
2. CA detecta pods pendentes com mensagens de falta de CPU/memória
3. CA consulta o Cloud Provider (AWS, GCP, Azure) para solicitar novo nó
4. Nó é provisionado e registrado no cluster
5. Kubernetes agenda os pods pendentes no novo nó

Componentes:
- Pod do Cluster Autoscaler
- Cloud Provider (Auto Scaling Groups na AWS, Managed Instance Groups no GCP, Scale Sets no Azure)
- Node Groups configurados com limites mínimo e máximo

Limitações:
- Tempo de provisionamento de 2 a 5 minutos
- Limites de cota da cloud (vCPU, IPs, etc.)
- Restrições de zonas de disponibilidade

3. Configuração Prática do Cluster Autoscaler

A instalação mais comum é via Helm chart:

helm repo add autoscaler https://kubernetes.github.io/autoscaler
helm upgrade --install cluster-autoscaler autoscaler/cluster-autoscaler \
  --namespace kube-system \
  --set autoDiscovery.clusterName=meu-cluster \
  --set awsRegion=us-east-1 \
  --set rbac.create=true

Parâmetros essenciais em values.yaml para AWS:

autoDiscovery:
  clusterName: "meu-cluster-eks"
awsRegion: "us-east-1"
rbac:
  create: true
extraArgs:
  v: 4
  stderrthreshold: info
  logtostderr: true
  scale-down-delay-after-add: 10m
  scale-down-unneeded-time: 10m
  max-nodes-total: 10
  min-nodes-total: 2
  expander: "least-waste"

Para GCP (MIGs):

cloudProvider: gce
autoDiscovery:
  clusterName: "meu-cluster-gke"
gce:
  project: "meu-projeto"
  zone: "us-central1-a"
extraArgs:
  min-nodes-total: 2
  max-nodes-total: 10

4. Políticas de Escalonamento (Scale-Up)

O scale-up é acionado quando pods permanecem em estado Pending por recursos insuficientes. O CA verifica a mensagem de erro do scheduler:

0/3 nodes are available: 3 Insufficient cpu, 2 Insufficient memory.

Estratégias de expansão (expander):
- least-waste: escolhe o node group que minimiza desperdício de recursos
- random: seleção aleatória entre node groups elegíveis
- priority: baseado em prioridade definida em configuração

Priorização de tipos de instância:

expanderPriorities:
- priorities:
  - spot: 100
  - on-demand: 50

5. Políticas de Desescalonamento (Scale-Down)

O scale-down remove nós subutilizados, mas requer cuidados para não interromper workloads.

Condições para remoção:
- Nó com utilização abaixo do threshold por tempo configurado
- Todos os pods podem ser movidos para outros nós
- Nenhum pod possui anotação cluster-autoscaler.kubernetes.io/safe-to-evict=false

Parâmetros importantes:

extraArgs:
  scale-down-unneeded-time: 10m
  scale-down-utilization-threshold: 0.5
  scale-down-delay-after-add: 10m
  scale-down-delay-after-delete: 10m

Proteção de pods críticos:

apiVersion: v1
kind: Pod
metadata:
  annotations:
    cluster-autoscaler.kubernetes.io/safe-to-evict: "false"
spec:
  containers:
  - name: banco
    image: postgres:13

6. Integração com Pod Disruption Budgets (PDBs)

PDBs garantem que um número mínimo de pods permaneça ativo durante evacuações de nós.

Exemplo de PDB para aplicação crítica:

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

Este PDB garante que pelo menos 2 pods da aplicação estejam sempre rodando, mesmo durante scale-down. O CA respeita esses limites antes de drenar um nó.

7. Monitoramento e Observabilidade

Métricas essenciais expostas pelo CA via Prometheus:

# Nós atuais no cluster
cluster_autoscaler_nodes_count{node_group="workers"}

# Pods não agendáveis
cluster_autoscaler_unschedulable_pods_count

# Eventos de scale-up/down
cluster_autoscaler_scaled_up_nodes_total
cluster_autoscaler_scaled_down_nodes_total

Configuração de ServiceMonitor para Prometheus Operator:

apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: cluster-autoscaler
  namespace: monitoring
spec:
  selector:
    matchLabels:
      app: cluster-autoscaler
  endpoints:
  - port: metrics
    interval: 30s

Logs úteis para troubleshooting:

kubectl logs -n kube-system deployment/cluster-autoscaler --tail=100

# Identificar falhas por cota
"Failed to scale up: failed to increase node group: QuotaExceeded"

8. Boas Práticas e Troubleshooting

Evitando thrashing (oscilação):
- Configure scale-down-delay-after-add para pelo menos 10 minutos
- Ajuste scale-down-unneeded-time entre 5-15 minutos
- Combine com HPA para evitar que pods sejam removidos antes do scale-down

Combinação com HPA e VPA:
- HPA: ajusta réplicas de pods
- VPA: ajusta recursos solicitados por pod
- CA: ajusta número de nós

Problemas comuns e soluções:

Problema Causa Solução
Scale-up não ocorre Cota da cloud excedida Solicitar aumento de cota
Scale-down não ocorre Pods com safe-to-evict=false Revisar anotações
Nós quebrados Labels incorretos Verificar nodeSelector
Thrashing Cooldown muito curto Aumentar delays

Verificação de nós não saudáveis:

kubectl get nodes
kubectl describe node <nome-node> | grep -A5 Conditions

Conclusão

O Cluster Autoscaler é essencial para ambientes Kubernetes que precisam equilibrar performance e custo. Sua configuração adequada, combinada com HPA e PDBs, permite que clusters se adaptem automaticamente à demanda sem intervenção manual. O monitoramento contínuo das métricas e logs do CA garante que problemas sejam identificados rapidamente, mantendo a infraestrutura resiliente e econômica.

Referências