Um Guia Prático para Otimização do Kubernetes Horizontal Pod Autoscaler (HPA)

Desvende o desempenho ideal da aplicação e a eficiência de custos com este guia prático para a otimização do Kubernetes Horizontal Pod Autoscaler (HPA). Aprenda a configurar o HPA usando métricas de CPU, personalizadas e externas, e domine comportamentos avançados de escalonamento com `stabilizationWindowSeconds` e `policies`. Este artigo fornece etapas acionáveis, exemplos de código e melhores práticas para garantir que suas implantações Kubernetes se adaptem dinamicamente a cargas flutuantes, previnam o superprovisionamento de recursos e mantenham alta disponibilidade.

31 visualizações

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

O Kubernetes revolucionou a forma como as aplicações são implantadas, gerenciadas e escaladas. No cerne de suas capacidades de escalonamento está o Horizontal Pod Autoscaler (HPA), um mecanismo poderoso que ajusta automaticamente o número de réplicas de pods em um deployment, replication controller, replicaset ou statefulset com base na utilização de CPU observada ou outras métricas selecionadas. Embora o HPA ofereça imensos benefícios para lidar com cargas flutuantes, seu verdadeiro potencial é desbloqueado através de configuração e ajuste cuidadosos.

Este guia aprofunda-se nos aspectos práticos da configuração e otimização do Horizontal Pod Autoscaler do Kubernetes. Abordaremos conceitos fundamentais, parâmetros essenciais, estratégias de ajuste avançado e melhores práticas para garantir que suas aplicações possam se adaptar eficientemente à demanda, manter o desempenho sob cargas variáveis e otimizar os custos de infraestrutura. Ao final deste artigo, você terá uma compreensão sólida de como aproveitar o HPA ao máximo.

Entendendo o Horizontal Pod Autoscaler (HPA)

O HPA escala automaticamente o número de pods em sua aplicação para cima ou para baixo para corresponder à demanda atual. Ele monitora continuamente as métricas especificadas e as compara com os valores alvo. Se a métrica observada exceder o alvo, o HPA inicia um evento de scale-up; se cair abaixo, ele aciona um scale-down. Esse ajuste dinâmico garante que sua aplicação tenha recursos suficientes para ter um desempenho ideal sem provisionamento excessivo.

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 da aplicação expostas através da API custom.metrics.k8s.io (por exemplo, requisições por segundo, profundidade da fila, conexões ativas). Estas geralmente requerem um adaptador como o 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 AWS SQS). Estas também requerem um servidor de API de métricas personalizadas capaz de buscar métricas externas.

Pré-requisitos para Ajuste Eficaz do HPA

Antes de mergulhar nas configurações do HPA, certifique-se de que estes elementos fundamentais estejam implementados:

1. Definir Requisições e Limites de Recurso Precisos

Este é talvez o pré-requisito mais crucial. O HPA depende fortemente de requisições de CPU e memória corretamente definidas para calcular as porcentagens de utilização. Se um pod não tiver requisições de CPU definidas, o HPA não poderá calcular sua utilização de CPU, tornando o escalonamento baseado em CPU impossível.

  • Requests: Defina os recursos mínimos garantidos para seus contêineres. O HPA usa esses valores para determinar a utilização alvo por pod.
  • Limits: 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. Instalar o Kubernetes Metrics Server

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

3. Observabilidade da Aplicação

Para métricas personalizadas ou externas, sua aplicação 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 à API Kubernetes, tipicamente usando um adaptador Prometheus ou um servidor de API de métricas personalizadas.

Configurando o HPA: Parâmetros Essenciais

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 escalará. Especifique sua apiVersion, kind e name.
  • minReplicas: O número mínimo de pods para os quais o HPA escalará para baixo. É uma boa prática definir este valor para pelo menos 1 ou 2 para alta disponibilidade, mesmo sob carga zero.
  • maxReplicas: O número máximo de pods para os quais o HPA escalará para cima. Isso funciona como uma salvaguarda contra escalonamento descontrolado e limita custos.
  • metrics: Uma matriz 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 utilização_atual / utilização_alvo * contagem_atual_de_pods.

Ajustando o HPA para Responsividade e Estabilidade

Além da configuração básica, o HPA oferece opções de ajuste avançado, especialmente com autoscaling/v2 (ou v2beta2 em versões mais antigas), para gerenciar o comportamento de escalonamento 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 escalonamento mais cedo (mais responsivo, potencialmente mais caro), enquanto um alvo mais alto significa escalonamento mais tarde (menos responsivo, potencialmente mais barato, mas arriscando degradação de desempenho).

  • Como Determinar Alvos Ótimos: Testes de carga e profiling são seus melhores amigos. Aumente gradualmente a carga em sua aplicação enquanto monitora o uso de recursos e as métricas de desempenho (latência, taxas de erro). Identifique a utilização de CPU/memória na qual sua aplicação começa a degradar o desempenho. Defina seu alvo HPA abaixo desse limite, tipicamente na faixa de 60-80% para CPU.
  • Equilíbrio: Busque um alvo que deixe folga suficiente para picos inesperados, mas que não seja tão baixo que você esteja constantemente com provisionamento excessivo.

2. Comportamento de Escalonamento (campo behavior)

Introduzido no HPA autoscaling/v2, o campo behavior fornece controle granular sobre os eventos de scale-up e scale-down, prevenindo "thrashing" (ciclos rápidos de scale-up e scale-down).

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 # Espera 60s antes de escalar para cima 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 # Espera 5 minutos antes de escalar para baixo
      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 o 'mais agressivo' (menor número de) pods

Configuração scaleUp:

  • stabilizationWindowSeconds: Isso impede ciclos rápidos de escalonamento para cima e para baixo (flapping). O HPA considera métricas desta janela ao escalar para cima, garantindo que ele só escale para cima se a métrica mais alta persistir. Um valor típico é de 30 a 60 segundos.
  • policies: Define como os pods são adicionados durante um evento de scale-up. Você pode definir várias políticas, e o HPA usará aquela que permite o maior número de pods (scale-up mais agressivo).
    • type: Pods: Escala para cima por um número fixo de pods. value especifica o número de pods a serem adicionados. periodSeconds define a janela de tempo sobre 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 por quanto tempo o HPA deve observar métricas abaixo do alvo antes de considerar o escalonamento para baixo. Uma janela mais longa (por exemplo, 300-600 segundos) impede o escalonamento prematuro durante períodos de calmaria temporários, 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 (scale-down mais agressivo) 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. Min é o padrão e geralmente recomendado para downscaling mais conservador; Max selecionaria a política que resulta no maior número de pods (downscaling menos agressivo).

  • Aviso: Tenha cuidado com políticas agressivas de scaleDown ou stabilizationWindowSeconds curtos para scaleDown. Se sua aplicação tiver tempos de inicialização longos ou lidar com conexões stateful, o escalonamento rápido para baixo pode levar a interrupções de serviço ou aumento da latência para os usuários.

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

Embora CPU e memória sejam comuns, muitas aplicações 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 ou gargalo de desempenho de sua aplicação. Exemplos: requisições HTTP por segundo (QPS), conexões ativas, comprimento da fila de mensagens, backlog de jobs em lote.

Para usar métricas personalizadas:
1. Sua aplicação deve expor essas métricas (por exemplo, através de um exporter 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 por sua aplicação/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 de sua aplicação é impulsionada por um sistema externo não diretamente executado no Kubernetes. Exemplos: profundidade da fila AWS SQS, atraso 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 de 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 de 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 várias métricas simultaneamente. Quando várias métricas são especificadas, o HPA calcula o número de réplicas desejado para cada métrica independentemente e, em seguida, seleciona o maior desses números de réplicas desejados. Isso garante que a aplicação escale suficientemente para todas as dimensões de carga observadas.

# ... (boilerplate 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

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

  • Observar Eventos do HPA: Use kubectl describe hpa <nome-do-hpa> para ver o status, eventos e decisões de escalonamento do HPA. Isso fornece insights valiosos sobre por que o HPA escalou para cima ou para baixo.
  • Monitorar Métricas e Réplicas: Use sua pilha de observabilidade (por exemplo, Prometheus, Grafana) para visualizar o uso de recursos de sua aplicação (CPU, memória), métricas personalizadas/externas e o número real de réplicas de pods ao longo do tempo. Correlacione isso com as mudanças na carga de entrada.
  • Testes de Carga: Simule cargas esperadas e de pico para validar a responsividade do HPA e garantir que sua aplicação 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 Requisições/Limites de Recurso Bem Definidos: Eles são a base do 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 mire em 100% de utilização, pois isso não deixa margem para latência ou picos de processamento.
  • Aproveite stabilizationWindowSeconds: Essencial para prevenir oscilações rápidas de escalonamento. Use uma janela mais longa para scaleDown (por exemplo, 5-10 minutos) do que para scaleUp (por exemplo, 1-2 minutos) para garantir a estabilidade.
  • Priorize Métricas Específicas da Aplicação: Se CPU ou memória não se correlacionam diretamente com os gargalos de desempenho de sua aplicação, use métricas personalizadas ou externas para um escalonamento mais preciso e eficiente.
  • Monitore, Teste, Itere: O ajuste do HPA não é uma configuração única. O comportamento da aplicação, 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 Escalonamento da Sua Aplicação: Ela escala linearmente com as requisições? Ela tem longos tempos de inicialização? Ela é stateful? Essas características influenciam sua estratégia de HPA.

Conclusão

O Horizontal Pod Autoscaler do Kubernetes é um componente crítico para construir aplicações resilientes, eficientes em termos de custo e de alto desempenho em um ambiente Kubernetes. Ao entender sua mecânica central, definir requisições de recursos precisas e ajustar cuidadosamente seus parâmetros de comportamento de escalonamento, você pode garantir que suas aplicações se adaptem automaticamente a cargas variáveis com precisão.

Um ajuste eficaz do HPA é uma jornada contínua de medição, observação e ajuste. Abrace o processo iterativo, aproveite métricas avançadas onde apropriado e monitore continuamente o desempenho de sua aplicação para desbloquear todo o potencial do escalonamento dinâmico dentro do Kubernetes.