Autoscaling é a promessa de escalar automaticamente baseado em demanda. Na prática, configurações inadequadas resultam em escalamento tardio, oscilação constante, ou custos descontrolados. Este artigo explora como configurar autoscaling de forma previsível.
Autoscaling não é "configure e esqueça". É "configure, teste, ajuste, monitore".
Como Autoscaling Funciona
O loop básico
1. Métricas coletadas
2. Comparadas com threshold
3. Decisão: scale up, down, ou nada
4. Ação executada
5. Cooldown
6. Repete
Tempo de reação
Evento (pico) → Detecção → Decisão → Provisionamento → Ready
Timeline típica:
0s: Pico começa
15s: Métrica reflete pico
30s: HPA decide escalar
60s: Pod scheduled
90s: Container pulled
120s: App ready
Total: ~2 minutos até nova capacidade
Problema: Se seu pico dura 1 minuto, autoscaling não ajuda.
Horizontal Pod Autoscaler (HPA)
Configuração básica
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: app-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: my-app
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
Problemas comuns
1. Threshold muito alto:
# ❌ 90% utilização
# Escala só quando já está saturado
averageUtilization: 90
2. Threshold muito baixo:
# ❌ 30% utilização
# Escala com qualquer variação normal
averageUtilization: 30
3. Cooldown inadequado:
# ❌ Sem configurar behavior
# Scale up/down muito rápido = thrashing
Configuração otimizada
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: app-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: my-app
minReplicas: 2
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 65 # Margem para reagir
behavior:
scaleUp:
stabilizationWindowSeconds: 0 # Escala imediatamente
policies:
- type: Percent
value: 100 # Pode dobrar
periodSeconds: 15
- type: Pods
value: 4 # Ou +4 pods
periodSeconds: 15
selectPolicy: Max # Usa o maior
scaleDown:
stabilizationWindowSeconds: 300 # Espera 5 min estável
policies:
- type: Percent
value: 10 # Reduz 10% por vez
periodSeconds: 60
Métricas customizadas
CPU nem sempre é o melhor indicador:
metrics:
# Baseado em requests por segundo
- type: Pods
pods:
metric:
name: http_requests_per_second
target:
type: AverageValue
averageValue: 1000
# Baseado em fila
- type: External
external:
metric:
name: queue_messages_ready
selector:
matchLabels:
queue: orders
target:
type: Value
value: 100
Vertical Pod Autoscaler (VPA)
Quando usar
HPA: Adiciona mais pods (horizontal)
VPA: Aumenta recursos de pods existentes (vertical)
HPA: Bom para stateless
VPA: Bom para databases, caches, stateful
Configuração
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: app-vpa
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: my-app
updatePolicy:
updateMode: "Auto" # Recreate pods when needed
resourcePolicy:
containerPolicies:
- containerName: app
minAllowed:
cpu: 100m
memory: 128Mi
maxAllowed:
cpu: 4
memory: 8Gi
VPA + HPA
# ❌ VPA e HPA no mesmo recurso (CPU)
# Conflito: ambos tentam ajustar
# ✅ VPA para memória, HPA para CPU
# VPA
resourcePolicy:
containerPolicies:
- containerName: app
controlledResources: ["memory"]
# HPA
metrics:
- type: Resource
resource:
name: cpu
Cluster Autoscaler
Como funciona
Pod pending (sem node disponível)
→ Cluster Autoscaler detecta
→ Provisiona novo node
→ Pod scheduled no novo node
Configuração
# Configuração de node pools (GKE exemplo)
gcloud container node-pools create scaling-pool \
--cluster=my-cluster \
--enable-autoscaling \
--min-nodes=1 \
--max-nodes=10 \
--machine-type=e2-standard-4
Tempo de provisionamento
AWS: 2-5 minutos
GCP: 1-3 minutos
Azure: 2-4 minutos
→ Para picos rápidos, Cluster Autoscaler é lento demais
Previsibilidade: A Chave do Autoscaling
Problema 1: Thrashing
Carga varia: 60% → 75% → 65% → 80% → 70%
Com threshold 70%:
- Scale up (75%)
- Scale down (65%)
- Scale up (80%)
- Scale down (70%)
= Pods sendo criados e destruídos constantemente
Solução: Stabilization window
behavior:
scaleDown:
stabilizationWindowSeconds: 300
Problema 2: Escalamento tardio
Pico às 9:00
HPA detecta às 9:00:30
Novos pods ready às 9:02:00
= 2 minutos de degradação
Solução: Scaling preditivo ou pré-aquecimento
# Scheduled scaling (AWS)
aws autoscaling put-scheduled-action \
--scheduled-action-name "morning-scale" \
--auto-scaling-group-name "app-asg" \
--recurrence "0 8 * * MON-FRI" \
--min-size 10
Problema 3: Cold start
Novo pod:
- Container start: 5s
- App initialization: 30s
- Warm-up: 60s
Total: ~95s até performance ideal
Solução: Readiness probe adequado + warm-up
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 60 # Tempo para warm-up
periodSeconds: 5
Problema 4: Custos descontrolados
Autoscaling sem limite:
- Pico anômalo ou ataque
- Escala para 100 pods
- Custo: $10,000/dia
→ "Autoscaling funcionou perfeitamente... e faliu a empresa"
Solução: Limites + alertas
maxReplicas: 20 # Limite hard
# Alerta quando próximo do limite
- alert: HPA_NearMaxReplicas
expr: |
kube_hpa_status_current_replicas / kube_hpa_spec_max_replicas > 0.8
for: 5m
Estratégias de Autoscaling
1. Reativo puro
Detecta aumento → Escala → Estabiliza
Prós: Simples, responde a qualquer padrão Contras: Sempre atrasado
2. Preditivo
Analisa histórico → Prevê pico → Escala antes
# AWS Predictive Scaling
aws autoscaling put-scaling-policy \
--policy-name "predictive" \
--policy-type "PredictiveScaling" \
--predictive-scaling-configuration '{
"MetricSpecifications": [...],
"Mode": "ForecastAndScale"
}'
Prós: Escala antes do pico Contras: Só funciona com padrões previsíveis
3. Scheduled
Escala em horários fixos baseado em padrão conhecido
# Kubernetes CronJob para ajustar HPA
apiVersion: batch/v1
kind: CronJob
metadata:
name: scale-up-morning
spec:
schedule: "0 8 * * MON-FRI"
jobTemplate:
spec:
template:
spec:
containers:
- name: kubectl
image: bitnami/kubectl
command:
- kubectl
- patch
- hpa/app-hpa
- --patch
- '{"spec":{"minReplicas":10}}'
Prós: Previsível, custos controlados Contras: Não responde a anomalias
4. Híbrido (recomendado)
Base: scheduled scaling para padrões conhecidos
+
Reativo: HPA para variações inesperadas
+
Limites: max replicas + alertas
Testando Autoscaling
Validação obrigatória
# 1. Teste de scale up
# Gera carga gradual, observa scaling
# 2. Teste de scale down
# Remove carga, observa cooldown
# 3. Teste de limite
# Atinge max replicas, observa comportamento
# 4. Teste de cold start
# Mede tempo até pod estar performático
Métricas para validar
1. Tempo para scale up (target < 2 min)
2. Frequência de thrashing (target = 0)
3. % de requests durante scaling (target > 99% success)
4. Custo durante picos (target dentro do budget)
Conclusão
Autoscaling previsível requer:
- Thresholds adequados: nem muito alto, nem muito baixo
- Behavior configurado: stabilization windows para evitar thrashing
- Métricas corretas: CPU nem sempre é o melhor indicador
- Limites definidos: max replicas + alertas de custo
- Testes validados: nunca confie em autoscaling não testado
Antes de confiar no autoscaling:
- Meça tempo de scale up
- Simule picos realistas
- Valide comportamento em limites
- Monitore custos ativamente
Autoscaling é como piloto automático: ótimo quando funciona, desastroso quando falha. Sempre tenha plano B.