Horizontal Pod Autoscaler

1. Introdução ao Horizontal Pod Autoscaler

O Horizontal Pod Autoscaler (HPA) é um recurso nativo do Kubernetes que ajusta automaticamente o número de réplicas de um Deployment, ReplicaSet ou StatefulSet com base em métricas observadas em tempo real. Diferente do escalonamento vertical (VPA), que aumenta ou diminui os recursos alocados a um único Pod, o HPA replica horizontalmente os Pods para distribuir a carga de trabalho.

Em ambientes de produção, o HPA é essencial para garantir alta disponibilidade e eficiência de custos. Por exemplo, durante picos de tráfego em uma aplicação web, o HPA pode aumentar o número de Pods de 3 para 15, e durante períodos de baixa demanda, reduzir para apenas 2. Isso evita tanto o desperdício de recursos quanto a degradação do serviço.

2. Métricas e Gatilhos de Escalonamento

O HPA suporta três categorias de métricas:

Resource Metrics: Métricas padrão como CPU e memória, fornecidas pelo Metrics Server. São as mais simples de configurar e adequadas para a maioria dos casos.

Custom Metrics: Métricas definidas pelo usuário, expostas através da Custom Metrics API. Exemplos incluem requisições por segundo, fila de mensagens ou latência.

External Metrics: Métricas de sistemas externos ao cluster, como CloudWatch ou Azure Monitor.

Os thresholds definem quando o escalonamento é acionado. Por exemplo, targetCPUUtilizationPercentage: 70 significa que o HPA tentará manter a utilização média de CPU em 70%. Períodos de estabilização (stabilizationWindowSeconds) previnem mudanças bruscas ao exigir que a métrica permaneça fora do threshold por um tempo específico.

3. Configuração Prática do HPA

Abaixo está um exemplo completo de um Deployment com um HPA associado. Primeiro, o Deployment da aplicação:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web-app
  template:
    metadata:
      labels:
        app: web-app
    spec:
      containers:
      - name: nginx
        image: nginx:1.25
        resources:
          requests:
            cpu: 200m
            memory: 256Mi
          limits:
            cpu: 500m
            memory: 512Mi

Agora, o manifesto do HPA:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: web-app-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: web-app
  minReplicas: 2
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 80

Para aplicar os manifestos:

kubectl apply -f deployment.yaml
kubectl apply -f hpa.yaml

4. Funcionamento do Algoritmo de Escalonamento

O HPA utiliza a seguinte fórmula para calcular o número desejado de réplicas:

desiredReplicas = ceil[currentReplicas * (currentMetricValue / targetMetricValue)]

Por exemplo, se temos 3 réplicas, a métrica atual de CPU é 210m (70% de 300m total) e o target é 50% (150m), o cálculo seria:

desiredReplicas = ceil[3 * (210m / 150m)] = ceil[3 * 1.4] = ceil[4.2] = 5

Para evitar flapping (oscilação constante), o HPA implementa mecanismos de cooldown. Por padrão, após um escalonamento, há um período de 3 minutos antes de permitir um novo escalonamento. Isso pode ser ajustado com behavior:

behavior:
  scaleDown:
    stabilizationWindowSeconds: 300
    policies:
    - type: Percent
      value: 100
      periodSeconds: 15
  scaleUp:
    stabilizationWindowSeconds: 0
    policies:
    - type: Percent
      value: 100
      periodSeconds: 15

Quando múltiplas métricas são usadas, o HPA calcula o número de réplicas para cada métrica e escolhe o maior valor. Isso garante que todas as métricas estejam dentro dos thresholds.

5. Integração com Resource Requests e Limits

O HPA calcula a utilização com base nos requests definidos no contêiner, não nos limites. Por exemplo, se um Pod solicita 200m de CPU e está usando 100m, a utilização é de 50%. Se o target é 70%, o HPA não escalonará.

É crucial definir requests precisos. Requests muito baixos podem causar escalonamento prematuro, enquanto requests muito altos podem impedir o escalonamento necessário. Boas práticas incluem:

  • Usar ferramentas de profiling para determinar o consumo real de recursos
  • Definir requests baseados no pico de uso normal, não no pico absoluto
  • Monitorar continuamente e ajustar conforme necessário

6. Testando e Monitorando o HPA

Comandos essenciais para monitoramento:

# Ver status do HPA
kubectl get hpa web-app-hpa

# Detalhes completos
kubectl describe hpa web-app-hpa

# Ver eventos relacionados
kubectl get events --field-selector involvedObject.name=web-app-hpa

Para simular carga e testar o escalonamento, use ferramentas como hey:

# Instalar hey
go install github.com/rakyll/hey@latest

# Gerar carga por 5 minutos
hey -z 5m -c 50 http://<service-ip>

Durante o teste, observe:

watch -n 2 kubectl get hpa web-app-hpa

Você verá o HPA aumentar gradualmente o número de réplicas até o máximo configurado, e após o término da carga, reduzir novamente.

7. Estratégias Avançadas e Considerações Finais

Para cenários complexos, o HPA pode ser combinado com o Cluster Autoscaler, que adiciona ou remove nós do cluster quando os Pods não podem ser escalonados por falta de recursos. Essa combinação permite escalonamento horizontal tanto no nível de aplicação quanto de infraestrutura.

Limitações importantes incluem:

  • Latência de métricas: O Metrics Server coleta dados a cada 15-30 segundos, causando atraso na detecção de picos
  • Dependências externas: Se a aplicação depende de serviços externos (bancos de dados, filas), o escalonamento pode não resolver problemas de desempenho
  • Custos inesperados: Em clouds públicas, escalonamento agressivo pode gerar custos elevados

Para aplicações stateful, considere usar o Kubernetes Event-driven Autoscaler (KEDA), que oferece integração com mais de 30 fontes de métricas e suporte a escalonamento para zero.

Referências