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 oprometheus-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 suaapiVersion,kindename.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 serResource,Pods,ObjectouExternal.resource.name: Para o tipoResource, especificacpuoumemory.target.type: Para o tipoResource,Utilization(porcentagem do recurso solicitado) ouAverageValue(valor absoluto).averageUtilization: Para o tipoUtilization, a porcentagem alvo. O HPA calcula o número desejado de pods com base emutilizaçã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.valueespecifica o número de pods a serem adicionados.periodSecondsdefine 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 parascaleDown, 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 ascaleUp, 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) seselectPolicyforMin, ou a política que resulta no maior número de pods seselectPolicyforMax.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 descaleDownsão definidas.Miné o padrão e geralmente recomendado para downscaling mais conservador;Maxselecionaria a política que resulta no maior número de pods (downscaling menos agressivo). -
Aviso: Tenha cuidado com políticas agressivas de
scaleDownoustabilizationWindowSecondscurtos parascaleDown. 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
minReplicasemaxReplicasRealistas:minReplicasfornece uma linha de base para disponibilidade, enquantomaxReplicasatua 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 parascaleDown(por exemplo, 5-10 minutos) do que parascaleUp(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.