Estratégias de escalonamento com HPA e VPA no Kubernetes

1. Fundamentos do escalonamento automático no Kubernetes

1.1. Conceitos de escalonamento horizontal (HPA) vs. vertical (VPA)

O escalonamento automático no Kubernetes permite adaptar dinamicamente os recursos dos workloads às demandas reais. O Horizontal Pod Autoscaler (HPA) ajusta o número de réplicas de um deployment, enquanto o Vertical Pod Autoscaler (VPA) ajusta os limites de CPU e memória dos contêineres individuais.

Enquanto o HPA adiciona ou remove pods para distribuir a carga, o VPA modifica os recursos solicitados por cada pod, otimizando a utilização de recursos sem alterar a quantidade de réplicas. A escolha entre eles depende do perfil da aplicação e das métricas monitoradas.

1.2. Métricas base para decisão de escala

As métricas mais comuns para decisão de escala incluem:

  • CPU: Utilização percentual em relação ao request definido
  • Memória: Consumo absoluto ou percentual
  • Métricas customizadas: QPS (queries por segundo), latência, tamanho de fila

O Metrics Server coleta essas métricas dos nós e as expõe via API de métricas, que é consumida pelos controladores HPA e VPA.

1.3. Componentes do ecossistema

Os principais componentes são:

  • Metrics Server: Coleta métricas de recursos (CPU/memória) dos nós e pods
  • API de métricas: Endpoint /apis/metrics.k8s.io/ que expõe dados em tempo real
  • Controlador HPA: Loop de reconciliação que calcula o número desejado de réplicas
  • Controlador VPA: Recomenda e aplica ajustes de recursos nos contêineres

2. Configurando o Horizontal Pod Autoscaler (HPA) na prática

2.1. Sintaxe e parâmetros essenciais do manifesto HPA

Um manifesto HPA básico utiliza os seguintes parâmetros:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: web-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

2.2. Estratégias de comportamento avançado

Para evitar oscilações (thrashing), o HPA permite configurar políticas de estabilização:

behavior:
  scaleDown:
    stabilizationWindowSeconds: 300
    policies:
    - type: Percent
      value: 10
      periodSeconds: 60
  scaleUp:
    stabilizationWindowSeconds: 0
    policies:
    - type: Pods
      value: 4
      periodSeconds: 60

A janela de estabilização (stabilizationWindowSeconds) impede que o HPA reduza réplicas imediatamente após uma queda momentânea de carga.

2.3. Exemplo completo: HPA para um deployment web com base em CPU e requisições HTTP

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: web-app-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: web-app
  minReplicas: 3
  maxReplicas: 20
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 60
  - type: Pods
    pods:
      metric:
        name: http_requests_per_second
      target:
        type: AverageValue
        averageValue: 100
  behavior:
    scaleDown:
      stabilizationWindowSeconds: 180
      policies:
      - type: Percent
        value: 20
        periodSeconds: 120

3. Vertical Pod Autoscaler (VPA): quando e como usar

3.1. Modos de operação do VPA

O VPA oferece quatro modos de operação:

  • Off: Apenas recomendações, sem aplicar mudanças
  • Auto: Aplica recomendações automaticamente, reiniciando pods quando necessário
  • Recreate: Similar ao Auto, mas sempre recria o pod (não usa atualização in-place)
  • Initial: Aplica recomendações apenas na criação do pod
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: app-vpa
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: app
  updatePolicy:
    updateMode: "Auto"
  resourcePolicy:
    containerPolicies:
    - containerName: "*"
      minAllowed:
        cpu: 100m
        memory: 50Mi
      maxAllowed:
        cpu: 1
        memory: 500Mi

3.2. Limitações do VPA

O VPA apresenta limitações importantes:

  • Reinicialização de pods: No modo Auto, o VPA precisa recriar o pod para aplicar novas recomendações
  • Conflitos com HPA: Nunca use VPA e HPA baseados na mesma métrica (CPU/memória)
  • Workloads stateful: Podem sofrer interrupções durante a reinicialização

3.3. Casos de uso ideais

O VPA é ideal para:

  • Workloads stateful com picos imprevisíveis de memória
  • Bancos de dados que precisam de ajuste fino de recursos
  • Aplicações com perfis de consumo variáveis ao longo do dia
  • Ambientes onde o custo de recursos é crítico e precisa ser otimizado

4. Estratégias combinadas: HPA + VPA em harmonia

4.1. Regra de ouro

A regra fundamental é: nunca usar VPA e HPA baseados na mesma métrica. Se o HPA escala por CPU e o VPA também ajusta CPU, haverá conflitos e comportamento imprevisível.

4.2. Padrão de arquitetura recomendado

A arquitetura ideal combina:

  • HPA baseado em métricas de aplicação (QPS, latência, tamanho de fila)
  • VPA em modo "Off" para fornecer recomendações de recursos
  • Ajustes manuais periódicos baseados nas recomendações do VPA
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: app-hpa-qps
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: app
  minReplicas: 3
  maxReplicas: 15
  metrics:
  - type: Pods
    pods:
      metric:
        name: qps
      target:
        type: AverageValue
        averageValue: 500

4.3. Exemplo de deployment com HPA customizado e VPA em modo "Off"

apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: app-vpa-recommender
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: app
  updatePolicy:
    updateMode: "Off"

Com essa configuração, o VPA gera recomendações que podem ser consultadas via kubectl describe vpa app-vpa-recommender, sem interferir no escalonamento horizontal.

5. Métricas customizadas e escalonamento baseado em eventos

5.1. Integrando Prometheus Adapter

O Prometheus Adapter permite expor métricas customizadas do Prometheus para o HPA:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: app-hpa-custom
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: app
  metrics:
  - type: Object
    object:
      metric:
        name: requests_per_second
      describedObject:
        apiVersion: v1
        kind: Service
        name: app-service
      target:
        type: Value
        value: 1000

5.2. Uso do KEDA para escalonamento por eventos

O KEDA (Kubernetes Event-driven Autoscaling) estende o HPA para escalonar baseado em eventos de fontes externas:

apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: kafka-scaler
spec:
  scaleTargetRef:
    name: consumer-app
  triggers:
  - type: kafka
    metadata:
      topic: orders
      bootstrapServers: kafka-cluster:9092
      consumerGroup: order-consumers
      lagThreshold: "100"

5.3. Comparação entre HPA nativo e KEDA

Característica HPA Nativo KEDA
Métricas suportadas CPU, memória, custom 50+ fontes (Kafka, RabbitMQ, AWS SQS)
Complexidade Baixa Média
Flexibilidade Limitada Alta
Manutenção Nativo do Kubernetes Componente externo

6. Troubleshooting e boas práticas de escalonamento

6.1. Depuração de HPA

Comandos essenciais para diagnóstico:

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

# Detalhes completos
kubectl describe hpa web-app-hpa

# Logs do controlador HPA
kubectl logs -n kube-system deployment/controller-manager

# Verificar métricas disponíveis
kubectl get --raw /apis/metrics.k8s.io/v1beta1/namespaces/default/pods

6.2. Evitando thrashing

Para evitar oscilações indesejadas:

  • Configure stabilizationWindowSeconds adequado (180-300s para scale-down)
  • Defina limites mínimos e máximos realistas (minReplicas, maxReplicas)
  • Use políticas de scale-up e scale-down diferentes
  • Monitore o comportamento com dashboards

6.3. Monitoramento contínuo

Recomenda-se configurar:

  • Dashboards com métricas de escala (réplicas atuais, desejadas, métricas alvo)
  • Alertas para anomalias (escalonamento excessivo, falha no HPA)
  • Logs centralizados para análise de padrões de escala

7. Cenários avançados e considerações finais

7.1. Escalonamento em clusters multi-nó e com nós spot

Em clusters com nós spot/preemptíveis, configure:

  • podDisruptionBudget para garantir disponibilidade mínima
  • HPA com maxReplicas maior para compensar perda de nós
  • VPA com limites mínimos para evitar pods muito pequenos em nós instáveis

7.2. Integração com Cluster Autoscaler

O Cluster Autoscaler adiciona ou remove nós quando há pods pendentes. A integração com HPA/VPA funciona assim:

  • HPA solicita mais pods → pods ficam pendentes por falta de recursos → Cluster Autoscaler adiciona nós
  • VPA aumenta requests de pods → nós podem ficar sobrecarregados → Cluster Autoscaler adiciona nós

7.3. Tendências futuras

As tendências incluem:

  • Escalonamento preditivo com machine learning: Prever picos de demanda e escalar antecipadamente
  • Karpenter: Substitui o Cluster Autoscaler com provisionamento mais rápido e flexível
  • Escalonamento baseado em custo: Otimizar recursos considerando custos de diferentes tipos de nós

Referências