Guia Prático para Ajuste do Horizontal Pod Autoscaler (HPA) do Kubernetes

Ajuste o HPA do Kubernetes com solicitações de recursos, métricas, comportamento de escala, janelas de estabilização e comandos de validação.

Guia Prático para Ajuste do Horizontal Pod Autoscaler (HPA) do Kubernetes

O Horizontal Pod Autoscaler (HPA) do Kubernetes pode manter seu aplicativo responsivo durante picos de tráfego, mas apenas se as métricas e limites refletirem como o aplicativo se comporta. Um HPA mal ajustado pode escalar tarde demais, reduzir muito rapidamente ou nunca escalar porque as solicitações de recursos estão ausentes.

Este guia mostra como ajustar o HPA do Kubernetes com CPU, memória, métricas personalizadas, métricas externas e controles de comportamento de escala.

Entendendo o Horizontal Pod Autoscaler (HPA)

O HPA escala automaticamente o número de pods no seu aplicativo para cima ou para baixo para corresponder à demanda atual. Ele monitora continuamente métricas especificadas e as compara com valores alvo. Se a métrica observada exceder o alvo, o HPA inicia um evento de escala para cima; se cair abaixo, ele aciona uma escala para baixo. Esse ajuste dinâmico garante que seu aplicativo tenha recursos suficientes para ter um desempenho ideal sem superprovisionamento.

O HPA pode escalar com base em:

  • Métricas de Recursos: Principalmente utilização de CPU e utilização de memória (disponíveis através da API metrics.k8s.io, geralmente servida pelo Kubernetes Metrics Server).
  • Métricas Personalizadas: Métricas específicas do aplicativo expostas através da API custom.metrics.k8s.io (por exemplo, requisições por segundo, profundidade da fila, conexões ativas). Elas geralmente exigem um adaptador como prometheus-adapter.
  • Métricas Externas: Métricas provenientes de fontes fora do cluster expostas através da API external.metrics.k8s.io (por exemplo, tamanho da fila do Google Cloud Pub/Sub, comprimento da fila do AWS SQS). Elas também exigem um servidor de API de métricas personalizadas capaz de buscar métricas externas.

Pré-requisitos para um Ajuste Eficaz do HPA

Antes de mergulhar nas configurações do HPA, garanta que esses elementos fundamentais estejam em vigor:

1. Defina Solicitações e Limites de Recursos Precisos

Este é talvez o pré-requisito mais crucial. O HPA depende fortemente de solicitações de CPU e memória corretamente definidas para calcular porcentagens de utilização. Se um pod não tiver solicitações de CPU definidas, o HPA não pode calcular sua utilização de CPU, tornando a escala baseada em CPU impossível.

  • Solicitações: Defina os recursos mínimos garantidos para seus contêineres. O HPA usa esses valores para determinar a utilização alvo por pod.
  • Limites: Defina os recursos máximos que um contêiner pode consumir. Os limites impedem que um único pod consuma recursos excessivos e impacte outros pods no mesmo nó.
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: my-container
        image: my-image:latest
        resources:
          requests:
            cpu: "200m"  # 20% de um núcleo de CPU
            memory: "256Mi"
          limits:
            cpu: "500m"
            memory: "512Mi"

2. Instale o Kubernetes Metrics Server

Para que o HPA use métricas de utilização de CPU e memória, o Kubernetes Metrics Server deve estar instalado no seu cluster. Ele coleta métricas de recursos dos Kubelets e as expõe através da API metrics.k8s.io.

3. Observabilidade do Aplicativo

Para métricas personalizadas ou externas, seu aplicativo deve expor métricas relevantes (por exemplo, através de um endpoint Prometheus) e você precisará de uma maneira de coletar e expor essas métricas para a API do Kubernetes, geralmente usando um adaptador Prometheus ou um servidor de API de métricas personalizadas.

Configurando o HPA: Parâmetros Principais

Vamos analisar a estrutura básica de um manifesto HPA:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: my-app-hpa
  namespace: default
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

Parâmetros chave:

  • scaleTargetRef: Define o recurso alvo (por exemplo, Deployment) que o HPA irá escalar. Especifique seu apiVersion, kind e name.
  • minReplicas: O número mínimo de pods para o qual o HPA irá reduzir. É uma boa prática definir isso para pelo menos 1 ou 2 para alta disponibilidade, mesmo sob carga zero.
  • maxReplicas: O número máximo de pods para o qual o HPA irá escalar. Isso atua como uma salvaguarda contra escala descontrolada e limita o custo.
  • metrics: Um array definindo as métricas que o HPA deve monitorar.
    • type: Pode ser Resource, Pods, Object ou External.
    • resource.name: Para o tipo Resource, especifica cpu ou memory.
    • target.type: Para o tipo Resource, Utilization (porcentagem do recurso solicitado) ou AverageValue (valor absoluto).
    • averageUtilization: Para o tipo Utilization, a porcentagem alvo. O HPA calcula o número desejado de pods com base em utilizacao_atual / utilizacao_alvo * contagem_atual_de_pods.

Ajustando o HPA para Responsividade e Estabilidade

Além da configuração básica, o HPA oferece opções avançadas de ajuste, especialmente com autoscaling/v2 (ou v2beta2 em versões mais antigas), para gerenciar o comportamento de escala de forma mais granular.

1. Alvos de CPU e Memória (averageUtilization / averageValue)

Definir a utilização alvo correta é crucial. Um alvo mais baixo significa escala mais cedo (mais responsivo, potencialmente mais caro), enquanto um alvo mais alto significa escala mais tarde (menos responsivo, potencialmente mais barato, mas arriscando degradação de desempenho).

  • Como Determinar Alvos Ideais: Testes de carga e perfilagem são seus melhores amigos. Aumente gradualmente a carga no seu aplicativo enquanto monitora o uso de recursos e métricas de desempenho (latência, taxas de erro). Identifique a utilização de CPU/memória na qual seu aplicativo começa a degradar o desempenho. Defina seu alvo HPA abaixo deste limite, tipicamente na faixa de 60-80% para CPU.
  • Ato de Equilíbrio: Mire em um alvo que deixe margem suficiente para picos inesperados, mas não tão baixo que você esteja constantemente superprovisionado.

2. Comportamento de Escala (campo behavior)

Introduzido no HPA autoscaling/v2, o campo behavior fornece controle refinado sobre eventos de escala para cima e para baixo, prevenindo "oscilação" (ciclos rápidos de escala para cima e para baixo).

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: my-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
  behavior:
    scaleUp:
      stabilizationWindowSeconds: 60 # Aguarda 60s antes de escalar novamente
      policies:
      - type: Pods
        value: 4
        periodSeconds: 15 # Adiciona no máximo 4 pods a cada 15 segundos
      - type: Percent
        value: 100
        periodSeconds: 15 # Ou dobra os pods atuais a cada 15 segundos (o que for menos restritivo)
    scaleDown:
      stabilizationWindowSeconds: 300 # Aguarda 5 minutos antes de reduzir
      policies:
      - type: Percent
        value: 50
        periodSeconds: 60 # Remove no máximo 50% dos pods a cada 60 segundos
      selectPolicy: Max # Escolhe a política que permite a maior mudança de redução permitida

Configuração scaleUp:

  • stabilizationWindowSeconds: Isso suaviza as recomendações de escala ao longo de uma janela de tempo recente. A escala para cima geralmente usa uma janela curta para que o aplicativo possa reagir rapidamente.
  • policies: Define como os pods são adicionados durante um evento de escala para cima. Você pode definir várias políticas, e o HPA usará aquela que permite o maior número de pods (escala para cima mais agressiva).
    • type: Pods: Escala para cima por um número fixo de pods. value especifica o número de pods a adicionar. periodSeconds define a janela de tempo durante a qual esta política se aplica.
    • type: Percent: Escala para cima por uma porcentagem da contagem atual de pods. value é a porcentagem.

Configuração scaleDown:

  • stabilizationWindowSeconds: Mais crítico para scaleDown, isso especifica quanto tempo o HPA deve observar métricas abaixo do alvo antes de considerar a redução. Uma janela mais longa (por exemplo, 300-600 segundos) previne redução prematura durante pausas temporárias, evitando "cold starts" e quedas de desempenho. Esta é uma configuração crucial para ambientes estáveis.

  • policies: Semelhante a scaleUp, define como os pods são removidos. O HPA usa a política que resulta no menor número de pods (redução mais agressiva) se selectPolicy for Min, ou a política que resulta no maior número de pods se selectPolicy for Max.

    • type: Pods: Remove um número fixo de pods.
    • type: Percent: Remove uma porcentagem dos pods atuais.
  • selectPolicy: Determina qual política aplicar quando várias políticas de scaleDown são definidas. Max é o padrão e seleciona a política que permite a maior mudança de escala. Use Min quando quiser uma redução mais conservadora.

  • Aviso: Seja cauteloso com políticas agressivas de scaleDown ou stabilizationWindowSeconds curto para scaleDown. Se seu aplicativo tem tempos de inicialização longos ou lida com conexões stateful, a redução rápida pode levar a interrupções de serviço ou aumento de latência para os usuários.

Métricas e Estratégias Avançadas de HPA

Embora CPU e memória sejam comuns, muitos aplicativos escalam melhor com métricas personalizadas ou externas que refletem sua carga de trabalho real.

1. Métricas Personalizadas

Use métricas personalizadas quando CPU/memória não for um indicador direto da carga do seu aplicativo ou gargalo de desempenho. Exemplos: Requisições HTTP por segundo (QPS), conexões ativas, tamanho da fila de mensagens, backlog de jobs em lote.

Para usar métricas personalizadas:

  1. Seu aplicativo deve expor essas métricas (por exemplo, através de um exportador Prometheus).
  2. Implante um adaptador de métricas personalizadas (por exemplo, prometheus-adapter) que possa coletar essas métricas e expô-las através da API custom.metrics.k8s.io.
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: my-app-hpa-qps
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: my-app
  minReplicas: 2
  maxReplicas: 15
  metrics:
  - type: Pods # Ou Object se a métrica for para o deployment como um todo
    pods:
      metric:
        name: http_requests_per_second # O nome da métrica exposta pelo seu aplicativo/adaptador
      target:
        type: AverageValue
        averageValue: "10k" # Alvo de 10.000 requisições por segundo por pod

2. Métricas Externas

Métricas externas são úteis quando a carga de trabalho do seu aplicativo é impulsionada por um sistema externo que não está rodando diretamente no Kubernetes. Exemplos: Profundidade da fila do AWS SQS, lag do tópico Kafka, backlog da assinatura Pub/Sub.

Para usar métricas externas:

  1. Você precisa de um servidor de API de métricas personalizadas que possa buscar métricas do seu sistema externo (por exemplo, um adaptador específico para AWS CloudWatch ou GCP Monitoring).
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: my-worker-hpa-sqs
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: my-worker
  minReplicas: 1
  maxReplicas: 20
  metrics:
  - type: External
    external:
      metric:
        name: aws_sqs_queue_messages_visible # Nome da métrica da sua fonte externa
        selector:
          matchLabels:
            queue: my-queue-name
      target:
        type: AverageValue
        averageValue: "100" # Alvo de 100 mensagens visíveis na fila por pod

3. Múltiplas Métricas

O HPA pode ser configurado para monitorar múltiplas métricas simultaneamente. Quando múltiplas métricas são especificadas, o HPA calcula a contagem de réplicas desejada para cada métrica independentemente e então seleciona a maior dessas contagens de réplicas desejadas. Isso garante que o aplicativo escale suficientemente para todas as dimensões de carga observadas.

# ... (cabeçalho HPA)
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
  - type: Pods
    pods:
      metric:
        name: http_requests_per_second
      target:
        type: AverageValue
        averageValue: "10k"

Monitoramento e Validação

O ajuste eficaz do HPA é um processo iterativo que requer monitoramento e validação contínuos:

  • Observe os Eventos do HPA: Use kubectl describe hpa <nome-do-hpa> para ver o status, eventos e decisões de escala do HPA. Isso fornece insights valiosos sobre por que o HPA escalou para cima ou para baixo.
  • Monitore Métricas e Réplicas: Use sua pilha de observabilidade (por exemplo, Prometheus, Grafana) para visualizar o uso de recursos do seu aplicativo (CPU, memória), métricas personalizadas/externas e o número real de réplicas de pods ao longo do tempo. Correlacione isso com mudanças na carga recebida.
  • Teste de Carga: Simule cargas esperadas e de pico para validar a responsividade do HPA e garantir que seu aplicativo tenha o desempenho esperado sob estresse. Ajuste os parâmetros do HPA com base nesses testes.

Melhores Práticas para Ajuste do HPA

  • Comece com Solicitações/Limites de Recursos Bem Definidos: Eles são a base de um HPA preciso baseado em recursos. Sem eles, o HPA não pode funcionar efetivamente para CPU/memória.
  • Defina minReplicas e maxReplicas Realistas: minReplicas fornece uma linha de base para disponibilidade, enquanto maxReplicas atua como uma rede de segurança contra custos descontrolados e exaustão de recursos.
  • Ajuste Gradualmente a Utilização Alvo: Comece com um alvo de CPU ligeiramente conservador (por exemplo, 60-70%) e itere. Não vise 100% de utilização, pois não deixa buffer para latência ou picos de processamento.
  • Aproveite stabilizationWindowSeconds: Essencial para prevenir oscilações rápidas de escala. Use uma janela mais longa para scaleDown (por exemplo, 5-10 minutos) do que para scaleUp (por exemplo, 1-2 minutos) para garantir estabilidade.
  • Priorize Métricas Específicas do Aplicativo: Se CPU ou memória não se correlacionar diretamente com os gargalos de desempenho do seu aplicativo, use métricas personalizadas ou externas para uma escala mais precisa e eficiente.
  • Monitore, Teste, Itere: O ajuste do HPA não é uma configuração única. O comportamento do aplicativo, os padrões de tráfego e a infraestrutura subjacente podem mudar. Revise regularmente o desempenho do HPA e ajuste as configurações conforme necessário.
  • Entenda as Características de Escala do Seu Aplicativo: Ele escala linearmente com as requisições? Ele tem tempos de inicialização longos? Ele é stateful? Essas características influenciam sua estratégia de HPA.

Conclusão Final

Trate o ajuste do HPA como um ciclo de feedback. Comece com solicitações de recursos precisas, defina minReplicas e maxReplicas realistas, escolha uma métrica que rastreie a demanda real e valide o comportamento de escala para cima e para baixo com testes de carga antes que o tráfego de produção dependa dele.