Docker & Kubernetes

Horizontal Pod Autoscaler: Métricas, Thresholds e Comportamento: Do Básico ao Avançado

14 min de leitura

Horizontal Pod Autoscaler: Métricas, Thresholds e Comportamento: Do Básico ao Avançado

Horizontal Pod Autoscaler: Visão Geral e Arquitetura O Horizontal Pod Autoscaler (HPA) é um recurso nativo do Kubernetes que automatiza a escalabilidade horizontal de suas aplicações. Em vez de você gerenciar manualmente o número de réplicas de um Deployment, StatefulSet ou ReplicaSet, o HPA monitora métricas em tempo real e ajusta o número de pods baseado em regras que você define. Esse comportamento é fundamental para aplicações que enfrentam variação de carga. A arquitetura do HPA funciona em um ciclo contínuo: o controller do HPA consulta as métricas da sua aplicação (CPU, memória ou métricas customizadas) a cada 15 segundos por padrão, compara com os thresholds configurados e toma decisões de scale-up ou scale-down. Esse processo é totalmente automatizado e reduz significativamente a necessidade de intervenção manual, economizando recursos e melhorando a disponibilidade da aplicação durante picos de demanda. Pré-requisitos Técnicos Para que o HPA funcione corretamente, você precisa de dois componentes críticos: o Metrics Server e os resource requests

<h2>Horizontal Pod Autoscaler: Visão Geral e Arquitetura</h2>

<p>O Horizontal Pod Autoscaler (HPA) é um recurso nativo do Kubernetes que automatiza a escalabilidade horizontal de suas aplicações. Em vez de você gerenciar manualmente o número de réplicas de um Deployment, StatefulSet ou ReplicaSet, o HPA monitora métricas em tempo real e ajusta o número de pods baseado em regras que você define. Esse comportamento é fundamental para aplicações que enfrentam variação de carga.</p>

<p>A arquitetura do HPA funciona em um ciclo contínuo: o controller do HPA consulta as métricas da sua aplicação (CPU, memória ou métricas customizadas) a cada 15 segundos por padrão, compara com os thresholds configurados e toma decisões de scale-up ou scale-down. Esse processo é totalmente automatizado e reduz significativamente a necessidade de intervenção manual, economizando recursos e melhorando a disponibilidade da aplicação durante picos de demanda.</p>

<h3>Pré-requisitos Técnicos</h3>

<p>Para que o HPA funcione corretamente, você precisa de dois componentes críticos: o Metrics Server e os resource requests definidos nos seus pods. O Metrics Server coleta métricas de CPU e memória dos nodes e as expõe via API, permitindo que o HPA tome decisões baseadas em dados reais. Sem ele, o HPA não consegue funcionar. Além disso, <strong>todo pod monitorado pelo HPA precisa ter requests de CPU e memória declarados</strong>, pois o HPA calcula percentuais de utilização com base nesses valores.</p>

<pre><code class="language-yaml"># Exemplo de Deployment com requests e limits

apiVersion: apps/v1

kind: Deployment

metadata:

name: app-exemplo

spec:

replicas: 2

selector:

matchLabels:

app: app-exemplo

template:

metadata:

labels:

app: app-exemplo

spec:

containers:

  • name: app

image: nginx:latest

resources:

requests:

cpu: 100m # 0.1 CPU - OBRIGATÓRIO para HPA

memory: 128Mi # 128 MB - OBRIGATÓRIO para HPA

limits:

cpu: 500m

memory: 512Mi

ports:

  • containerPort: 80</code></pre>

<h2>Métricas do HPA: Tipos e Cálculos</h2>

<p>O HPA suporta três categorias principais de métricas: métricas de recursos (CPU e memória), métricas customizadas e métricas externas. Cada uma tem um propósito específico e é calculada de forma diferente pelo controller.</p>

<h3>Métricas de Recursos (CPU e Memória)</h3>

<p>As métricas de recursos são as mais simples e diretas. O HPA calcula a porcentagem de utilização de CPU e memória comparando o uso atual com o request definido no container. Por exemplo, se você configurar um request de 100m (miliCPU) e o pod está usando 50m, a utilização está em 50%. O cálculo é feito para todos os pods de um Deployment e depois é feita uma média: se você tem 3 pods, o HPA calcula a média de todos os três antes de tomar a decisão de escalar.</p>

<pre><code class="language-yaml"># Exemplo: HPA baseado em CPU

apiVersion: autoscaling/v2

kind: HorizontalPodAutoscaler

metadata:

name: app-hpa-cpu

spec:

scaleTargetRef:

apiVersion: apps/v1

kind: Deployment

name: app-exemplo

minReplicas: 2

maxReplicas: 10

metrics:

  • type: Resource

resource:

name: cpu

target:

type: Utilization

averageUtilization: 70 # Escala quando CPU média &gt; 70%

behavior:

scaleDown:

stabilizationWindowSeconds: 300

policies:

  • type: Percent

value: 50

periodSeconds: 15

scaleUp:

stabilizationWindowSeconds: 0

policies:

  • type: Percent

value: 100

periodSeconds: 15</code></pre>

<p>No exemplo acima, o HPA monitorará a CPU média de todos os pods do Deployment <code>app-exemplo</code>. Quando a média ultrapassar 70% do request configurado (100m × 0.70 = 70m), o HPA começará a adicionar pods. O comportamento de scale é controlado pela seção <code>behavior</code> que detalharemos mais adiante.</p>

<h3>Métricas Customizadas</h3>

<p>Métricas customizadas são ideais quando você quer escalar baseado em lógica de negócio específica: número de requisições por segundo, tamanho de fila, latência, ou qualquer outro indicador relevante para sua aplicação. Para usar métricas customizadas, você precisa de um provedor de métricas, como o Prometheus com um adapter customizado.</p>

<pre><code class="language-yaml"># Exemplo: HPA baseado em métrica customizada (requisições por segundo)

apiVersion: autoscaling/v2

kind: HorizontalPodAutoscaler

metadata:

name: app-hpa-custom

spec:

scaleTargetRef:

apiVersion: apps/v1

kind: Deployment

name: app-exemplo

minReplicas: 2

maxReplicas: 20

metrics:

  • type: Pods

pods:

metric:

name: http_requests_per_second

target:

type: AverageValue

averageValue: 1000 # Escala quando RPS médio &gt; 1000

  • type: Resource

resource:

name: cpu

target:

type: Utilization

averageUtilization: 80 # Escala quando CPU &gt; 80%</code></pre>

<p>Neste exemplo, o HPA usa <strong>dois critérios simultaneamente</strong>: ele escalará quando qualquer um dos limites for atingido. Isso oferece mais controle e permite que sua aplicação responda a diferentes tipos de pressão. Se você exponha a métrica <code>http_requests_per_second</code> via Prometheus, o HPA a considerará nas decisões.</p>

<h3>Métricas Externas</h3>

<p>Métricas externas permitem integração com sistemas de monitoramento externos como Google Cloud Monitoring, AWS CloudWatch ou Datadog. Você referencia a métrica pelo nome e o HPA consulta o sistema externo para tomar decisões.</p>

<pre><code class="language-yaml"># Exemplo: HPA baseado em métrica externa (AWS SQS)

apiVersion: autoscaling/v2

kind: HorizontalPodAutoscaler

metadata:

name: worker-hpa-sqs

spec:

scaleTargetRef:

apiVersion: apps/v1

kind: Deployment

name: sqs-worker

minReplicas: 1

maxReplicas: 50

metrics:

  • type: External

external:

metric:

name: sqs_queue_depth

selector:

matchLabels:

queue-name: minha-fila

target:

type: AverageValue

averageValue: &quot;30&quot; # 30 mensagens por pod</code></pre>

<h2>Thresholds, Comportamento e Estratégias de Escala</h2>

<p>Os thresholds definem os limites que disparam a escalabilidade, mas o comportamento da escala (como rápido ela ocorre, com que agressividade) é controlado pela seção <code>behavior</code> do HPA. Essa é uma das partes mais críticas e frequentemente negligenciada na configuração.</p>

<h3>Configuração de Thresholds</h3>

<p>Um threshold é simplesmente o valor limite que, quando atingido, causa uma ação de escala. No exemplo anterior de CPU, 70% era o threshold. O HPA calcula se a métrica atual está acima ou abaixo do threshold e faz as contas sobre quantos pods são necessários para trazer a métrica de volta ao nível desejado.</p>

<p>A fórmula básica que o HPA usa internamente é:</p>

<pre><code>desiredReplicas = ceil[currentReplicas × (currentMetricValue / targetMetricValue)]</code></pre>

<p>Se você tem 5 pods usando 85% de CPU e seu target é 70%, o cálculo seria: <code>ceil[5 × (85 / 70)] = ceil[6.07] = 7 pods</code>. Isso é uma decisão de scale-up. Inversamente, se estiver usando 35% de CPU, o cálculo daria menos replicas e ocorreria um scale-down.</p>

<h3>Behavior: Controlando Agressividade</h3>

<p>A seção <code>behavior</code> controla <strong>como</strong> e <strong>com que rapidez</strong> o HPA escala. Sem ela configurada corretamente, você pode enfrentar &quot;flapping&quot; — escalas constantes para cima e para baixo — ou respostas muito lentas a picos de carga.</p>

<pre><code class="language-yaml"># Exemplo completo com behavior refinado

apiVersion: autoscaling/v2

kind: HorizontalPodAutoscaler

metadata:

name: app-hpa-produção

spec:

scaleTargetRef:

apiVersion: apps/v1

kind: Deployment

name: aplicacao-critica

minReplicas: 3

maxReplicas: 50

metrics:

  • type: Resource

resource:

name: cpu

target:

type: Utilization

averageUtilization: 70

  • type: Resource

resource:

name: memory

target:

type: Utilization

averageUtilization: 80

behavior:

Configuração para SCALE UP (aumentar pods)

scaleUp:

stabilizationWindowSeconds: 0 # Sem espera, reage rápido

policies:

  • type: Percent

value: 100 # Dobra a cada período

periodSeconds: 15

  • type: Pods

value: 4 # Ou adiciona 4 pods (o que for maior)

periodSeconds: 15

selectPolicy: Max # Escolhe a política que resulta em mais pods

Configuração para SCALE DOWN (reduzir pods)

scaleDown:

stabilizationWindowSeconds: 300 # Espera 5 min antes de desescalar

policies:

  • type: Percent

value: 50 # Remove até 50% dos pods

periodSeconds: 15

  • type: Pods

value: 2 # Ou remove 2 pods no máximo

periodSeconds: 15

selectPolicy: Min # Escolhe a política que resulta em menos pods</code></pre>

<h3>Entendendo Stabilization Window</h3>

<p>A <code>stabilizationWindowSeconds</code> é um conceito crucial. No scale-up, geralmente colocamos <code>0</code> para responder imediatamente a picos. No scale-down, colocamos um valor maior (300 segundos = 5 minutos é comum) para evitar remover pods prematuramente quando a carga cai temporariamente. Isso previne flapping e garante estabilidade.</p>

<p>Durante a janela de estabilização, o HPA procura pelo <strong>maior valor de métrica observado</strong> naquele período. Isso significa que se em 5 minutos de scale-down a métrica subir novamente, o HPA pode cancelar o scale-down planejado. É um mecanismo de amortecimento muito inteligente.</p>

<h2>Comportamento Prático e Monitoramento</h2>

<p>Entender como o HPA se comporta em tempo real é essencial para debugging e otimização. Você pode inspecionar o estado do HPA, seus eventos e decisões através de comandos kubectl e pela análise de logs.</p>

<h3>Inspecionando Status do HPA</h3>

<pre><code class="language-bash"># Ver status atual do HPA

kubectl get hpa -n seu-namespace

Ver detalhes completos (muito útil!)

kubectl describe hpa app-hpa-cpu -n seu-namespace

Exemplo de saída do describe:

Name: app-hpa-cpu

Namespace: default

Labels: &lt;none&gt;

Annotations: &lt;none&gt;

CreationTimestamp: Mon, 15 Jan 2024 10:30:00 +0000

Reference: Deployment/app-exemplo

Metrics: ( current / target )

resource cpu on pods ( 65% / 70% )

Min replicas: 2

Max replicas: 10

Deployment pods: 5 current / 5 desired

Conditions:

Type Status Reason Message

---- ------ ------ -------

AbleToScale True ReadyForNewScale recommended size matches current size

ScalingActive True ValidMetricsFound the HPA was able to compute the replica count

ScalingLimited False DesiredWithinRange the desired count is within the acceptable range</code></pre>

<p>Essa saída te diz exatamente o que está acontecendo: qual é o uso atual, qual é o target, quantos pods existem, e por que o HPA está ou não escalando.</p>

<h3>Monitorando Decisões do HPA</h3>

<p>O HPA registra eventos importantes no Kubernetes. Você pode consultá-los para entender todas as decisões:</p>

<pre><code class="language-bash"># Ver eventos do HPA em tempo real

kubectl get events -n seu-namespace --field-selector involvedObject.name=app-hpa-cpu --sort-by=&#039;.lastTimestamp&#039;

Exemplo de eventos:

LAST SEEN TYPE REASON OBJECT MESSAGE

2m Normal SuccessfulRescale hpa/app-hpa-cpu New size: 7; reason: cpu resource utilization (actual: 75%, target: 70%)

5m Normal SuccessfulRescale hpa/app-hpa-cpu New size: 5; reason: cpu resource utilization (actual: 68%, target: 70%)</code></pre>

<h3>Caso Prático: Diagnóstico de Problemas</h3>

<p>Um problema comum é o HPA não funcionar. Aqui está como diagnosticar:</p>

<pre><code class="language-bash"># 1. Verificar se Metrics Server está instalado

kubectl get deployment metrics-server -n kube-system

2. Verificar se métricas estão disponíveis

kubectl top pods -n seu-namespace

kubectl top nodes

3. Verificar requests nos containers

kubectl get pods seu-pod -o yaml | grep -A 10 &quot;resources:&quot;

4. Se nada disso mostrar métricas, o HPA ficará em estado:

ScalingActive: False, Reason: UnableComputeReplicaCountReason</code></pre>

<p>Se você vir <code>ScalingActive: False</code>, o problema é falta de métricas. Sempre comece verificando o Metrics Server e os requests nos containers.</p>

<h2>Exemplos Avançados: Combinando Tudo</h2>

<p>Vamos construir um exemplo realista que combina tudo que aprendemos:</p>

<pre><code class="language-yaml"># Aplicação web com auto-scaling inteligente

apiVersion: apps/v1

kind: Deployment

metadata:

name: api-produção

spec:

replicas: 3

selector:

matchLabels:

app: api

template:

metadata:

labels:

app: api

spec:

containers:

  • name: api

image: minha-api:v1.2.0

resources:

requests:

cpu: 250m

memory: 256Mi

limits:

cpu: 1000m

memory: 1Gi

ports:

  • containerPort: 8080

livenessProbe:

httpGet:

path: /health

port: 8080

initialDelaySeconds: 10

periodSeconds: 10

readinessProbe:

httpGet:

path: /ready

port: 8080

initialDelaySeconds: 5

periodSeconds: 5

---

apiVersion: autoscaling/v2

kind: HorizontalPodAutoscaler

metadata:

name: api-produção-hpa

spec:

scaleTargetRef:

apiVersion: apps/v1

kind: Deployment

name: api-produção

minReplicas: 3 # Sempre manter ao menos 3 (alta disponibilidade)

maxReplicas: 50 # Não gastar demais em recursos

metrics:

Métrica 1: CPU é o trigger primário

  • type: Resource

resource:

name: cpu

target:

type: Utilization

averageUtilization: 70

Métrica 2: Memória como failsafe

  • type: Resource

resource:

name: memory

target:

type: Utilization

averageUtilization: 85

behavior:

scaleUp:

stabilizationWindowSeconds: 0

policies:

  • type: Percent

value: 50

periodSeconds: 15

  • type: Pods

value: 2

periodSeconds: 15

selectPolicy: Max

scaleDown:

stabilizationWindowSeconds: 300 # 5 minutos

policies:

  • type: Percent

value: 10

periodSeconds: 60

  • type: Pods

value: 1

periodSeconds: 60

selectPolicy: Min</code></pre>

<p>Neste exemplo produção:</p>

<ul>

<li><strong>Scale-up é agressivo</strong>: responde imediatamente e pode dobrar os pods (50% + limites significam crescimento rápido)</li>

<li><strong>Scale-down é conservador</strong>: aguarda 5 minutos e remove pods lentamente (10% + máximo 1 pod)</li>

<li><strong>Dois critérios de métrica</strong>: se CPU OU memória atingirem o limite, escala</li>

<li><strong>Min/Max realista</strong>: começa com 3 pods (redundância) e máximo 50 (custo controlado)</li>

</ul>

<h2>Conclusão</h2>

<p>Três aprendizados fundamentais que você deve levar daqui: primeiro, o HPA é inútil sem Metrics Server e requests bem definidos nos containers — esses são pré-requisitos absolutos, não opcionais. Segundo, o <code>behavior</code> é mais importante que os thresholds — você pode ter um threshold perfeito, mas com um behavior mal configurado, sua aplicação sofrerá com flapping ou respostas lentas a picos. Terceiro, sempre monitore os eventos do HPA com <code>describe</code> e <code>events</code> para entender exatamente o que está acontecendo; o Kubernetes oferece visibilidade completa, basta saber onde olhar.</p>

<h2>Referências</h2>

<ul>

<li><a href="https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/" target="_blank" rel="noopener noreferrer">Documentação Oficial do HPA - Kubernetes</a></li>

<li><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#horizontalpodautoscaler-v2-autoscaling" target="_blank" rel="noopener noreferrer">API Reference: HorizontalPodAutoscaler v2</a></li>

<li><a href="https://github.com/kubernetes-sigs/metrics-server" target="_blank" rel="noopener noreferrer">Metrics Server - GitHub</a></li>

<li><a href="https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/" target="_blank" rel="noopener noreferrer">Best Practices for HPA - Kubernetes Documentation</a></li>

<li><a href="https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/" target="_blank" rel="noopener noreferrer">Understanding Kubernetes Resource Requests and Limits</a></li>

</ul>

<p>&lt;!-- FIM --&gt;</p>

Comentários

Mais em Docker & Kubernetes

Supply Chain Security: SBOM, Cosign e Verificação de Imagens: Do Básico ao Avançado
Supply Chain Security: SBOM, Cosign e Verificação de Imagens: Do Básico ao Avançado

Supply Chain Security: Protegendo sua Pipeline de Software A segurança da cad...

O que Todo Dev Deve Saber sobre Docker Compose para Desenvolvimento: Hot Reload e Ambientes Reproduzíveis
O que Todo Dev Deve Saber sobre Docker Compose para Desenvolvimento: Hot Reload e Ambientes Reproduzíveis

Docker Compose para Desenvolvimento: Hot Reload e Ambientes Reproduzíveis O D...

Como Usar FinOps em Kubernetes: Kubecost, Right-sizing e Spot Instances em Produção
Como Usar FinOps em Kubernetes: Kubecost, Right-sizing e Spot Instances em Produção

FinOps em Kubernetes: Uma Introdução Prática FinOps é a disciplina que une fi...