Docker & Kubernetes

Boas Práticas de Vertical Pod Autoscaler e KEDA: Escalonamento Avançado em Kubernetes para Times Ágeis

15 min de leitura

Boas Práticas de Vertical Pod Autoscaler e KEDA: Escalonamento Avançado em Kubernetes para Times Ágeis

Entendendo o Escalonamento em Kubernetes O Kubernetes é um orquestrador de contêineres poderoso, mas por padrão ele oferece apenas o Horizontal Pod Autoscaler (HPA), que escala o número de réplicas baseado em métricas simples como CPU e memória. Isso funciona bem para muitos cenários, mas deixa duas lacunas importantes: o HPA não otimiza o tamanho dos contêineres (requests e limits) e não entende eventos ou métricas customizadas. É aqui que entram o Vertical Pod Autoscaler (VPA) e o KEDA. O VPA resolve um problema crítico: muitas equipes definem requests e limits de forma arbitrária ou conservadora demais, desperdiçando recursos. O KEDA, por sua vez, permite escalar baseado em qualquer coisa — desde filas de mensagens até métricas de aplicação customizadas — tornando o escalonamento muito mais inteligente e alinhado com a realidade do seu negócio. Neste artigo, você vai aprender não apenas como instalá-los e configurá-los, mas também entender os trade-offs e quando usar cada um. Vertical Pod Autoscaler (VPA):

<h2>Entendendo o Escalonamento em Kubernetes</h2>

<p>O Kubernetes é um orquestrador de contêineres poderoso, mas por padrão ele oferece apenas o Horizontal Pod Autoscaler (HPA), que escala o número de réplicas baseado em métricas simples como CPU e memória. Isso funciona bem para muitos cenários, mas deixa duas lacunas importantes: o HPA não otimiza o tamanho dos contêineres (requests e limits) e não entende eventos ou métricas customizadas. É aqui que entram o Vertical Pod Autoscaler (VPA) e o KEDA.</p>

<p>O VPA resolve um problema crítico: muitas equipes definem requests e limits de forma arbitrária ou conservadora demais, desperdiçando recursos. O KEDA, por sua vez, permite escalar baseado em qualquer coisa — desde filas de mensagens até métricas de aplicação customizadas — tornando o escalonamento muito mais inteligente e alinhado com a realidade do seu negócio. Neste artigo, você vai aprender não apenas como instalá-los e configurá-los, mas também entender os trade-offs e quando usar cada um.</p>

<h2>Vertical Pod Autoscaler (VPA): Otimizando Recursos</h2>

<h3>O que é VPA e por que você precisa dele</h3>

<p>O Vertical Pod Autoscaler funciona de forma completamente diferente do HPA. Enquanto o HPA adiciona mais pods, o VPA recomenda (e opcionalmente aplica) mudanças nos recursos (CPU e memória) de cada pod individual. Ele funciona analisando o histórico de consumo real dos seus contêineres e calculando valores ótimos de requests e limits.</p>

<p>Imagine que você definiu um pod com <code>requests: 500m CPU</code> e <code>2Gi memória</code>, mas em produção ele nunca usa mais de <code>200m CPU</code> e <code>800Mi memória</code>. O VPA detecta esse desperdício e recomenda reduzir os recursos. Inversamente, se um pod frequentemente fica perto de seus limits, o VPA sugere aumentar. Isso resulta em economia direta de infraestrutura e melhor distribuição de carga no cluster.</p>

<h3>Instalando e Configurando VPA</h3>

<p>A instalação do VPA é relativamente simples. Você precisa clonar o repositório oficial e executar o script de instalação:</p>

<pre><code class="language-bash">git clone https://github.com/kubernetes/autoscaler.git

cd autoscaler/vertical-pod-autoscaler

./hack/vpa-up.sh</code></pre>

<p>Este script instala três componentes principais no namespace <code>kube-system</code>:</p>

<ul>

<li><strong>Recommender</strong>: monitora o histórico de métricas e calcula recomendações</li>

<li><strong>Updater</strong>: aplica as recomendações (removendo e recriando pods)</li>

<li><strong>Admission Controller</strong>: valida as novas solicitações de recursos</li>

</ul>

<p>Depois de instalado, você cria um recurso VPA para seus Deployments:</p>

<pre><code class="language-yaml">apiVersion: autoscaling.k8s.io/v1

kind: VerticalPodAutoscaler

metadata:

name: meu-app-vpa

namespace: production

spec:

targetRef:

apiVersion: &quot;apps/v1&quot;

kind: Deployment

name: meu-app

updatePolicy:

updateMode: &quot;Auto&quot;

resourcePolicy:

containerPolicies:

  • containerName: &quot;app&quot;

minAllowed:

cpu: 100m

memory: 128Mi

maxAllowed:

cpu: 2

memory: 4Gi</code></pre>

<p>O campo <code>updateMode</code> é crítico: use <code>&quot;Off&quot;</code> apenas para recomendações sem aplicação automática, <code>&quot;Initial&quot;</code> para aplicar apenas em novos pods, e <code>&quot;Auto&quot;</code> para aplicar continuamente (com recreação de pods). Sempre defina <code>minAllowed</code> e <code>maxAllowed</code> para evitar surpresas.</p>

<h3>Monitorando e Validando Recomendações</h3>

<p>O VPA leva tempo para coletar dados. Espere pelo menos 8-24 horas antes de esperar recomendações sensatas. Você pode verificar as recomendações com:</p>

<pre><code class="language-bash">kubectl describe vpa meu-app-vpa -n production</code></pre>

<p>A saída mostrará seções como <code>Recommendation</code>, indicando o target, lower bound e upper bound sugeridos. Uma estratégia segura é começar com <code>updateMode: &quot;Off&quot;</code>, validar as recomendações por alguns dias, e depois mudar para <code>&quot;Auto&quot;</code>.</p>

<h2>KEDA: Escalonamento Baseado em Eventos</h2>

<h3>Conceito Fundamental: Por que HPA é insuficiente</h3>

<p>O HPA escala baseado em métricas simples: se CPU &gt; 70%, cria mais pods. Mas e se seu aplicativo processa mensagens de uma fila? Se há 10.000 mensagens esperando, você precisa de 100 pods, não 2. Se há zero mensagens, nenhum pod deveria estar rodando. O KEDA (Kubernetes Event Driven Autoscaling) resolve exatamente isso: ele entende eventos e métricas customizadas do mundo real.</p>

<p>KEDA introduz dois novos conceitos: <strong>Scalers</strong> (conectores para diferentes fontes de dados) e <strong>Triggers</strong> (regras que definem quando e como escalar). Ele funciona instalando um componente no cluster que periodicamente consulta essas fontes externas e alimenta um HPA customizado.</p>

<h3>Instalando KEDA</h3>

<p>A instalação é feita via Helm:</p>

<pre><code class="language-bash">helm repo add kedacore https://kedacore.github.io/charts

helm repo update

helm install keda kedacore/keda --namespace keda --create-namespace</code></pre>

<p>Isso instala o operador KEDA e seus componentes necessários. Diferente do VPA, KEDA é um projeto CNCF sandbox muito ativo com excelente documentação.</p>

<h3>Exemplo Prático 1: Escalonamento baseado em Fila SQS</h3>

<p>Vamos começar com um caso comum: seu aplicativo processa mensagens de uma fila AWS SQS. Você quer que ele escale automaticamente baseado no tamanho da fila:</p>

<pre><code class="language-yaml">apiVersion: keda.sh/v1alpha1

kind: ScaledObject

metadata:

name: sqs-consumer-scaled

namespace: production

spec:

scaleTargetRef:

name: sqs-consumer

kind: Deployment

minReplicaCount: 1

maxReplicaCount: 50

triggers:

  • type: aws-sqs-queue

metadata:

queueURL: https://sqs.us-east-1.amazonaws.com/123456789/minha-fila

queueLength: &quot;5&quot;

awsRegion: &quot;us-east-1&quot;

authenticationRef:

name: aws-credentials</code></pre>

<p>O trigger <code>aws-sqs-queue</code> consulta o número de mensagens na fila. <code>queueLength: &quot;5&quot;</code> significa que cada pod pode processar 5 mensagens (se há 100 mensagens, serão criados 20 pods). As credenciais AWS são gerenciadas via:</p>

<pre><code class="language-yaml">apiVersion: keda.sh/v1alpha1

kind: TriggerAuthentication

metadata:

name: aws-credentials

namespace: production

spec:

secretTargetRef:

  • parameter: awsAccessKeyID

name: aws-secret

key: access-key

  • parameter: awsSecretAccessKey

name: aws-secret

key: secret-key</code></pre>

<h3>Exemplo Prático 2: Escalonamento baseado em Métrica Customizada do Prometheus</h3>

<p>Se você usa Prometheus para monitorar métricas customizadas da sua aplicação, pode usá-las para escalar:</p>

<pre><code class="language-yaml">apiVersion: keda.sh/v1alpha1

kind: ScaledObject

metadata:

name: api-response-time-scaled

namespace: production

spec:

scaleTargetRef:

name: api-gateway

kind: Deployment

minReplicaCount: 2

maxReplicaCount: 20

triggers:

  • type: prometheus

metadata:

serverAddress: http://prometheus:9090

metricName: requests_queued

query: |

sum(rate(http_requests_pending[1m]))

threshold: &quot;10&quot;

authenticationRef:

name: prometheus-auth</code></pre>

<p>Este exemplo usa a métrica <code>requests_queued</code> do Prometheus. Se a soma de requisições pendentes exceder 10, novos pods são criados. Threshold é sempre o valor por pod, então com 100 requisições pendentes e threshold 10, você terá 10 pods.</p>

<h3>Exemplo Prático 3: Escalonamento baseado em Cron</h3>

<p>Para workloads previsíveis (processamentos noturnos, relatórios diários), você pode usar triggers cron:</p>

<pre><code class="language-yaml">apiVersion: keda.sh/v1alpha1

kind: ScaledObject

metadata:

name: batch-job-scaled

namespace: production

spec:

scaleTargetRef:

name: batch-processor

kind: Deployment

minReplicaCount: 0

maxReplicaCount: 30

triggers:

  • type: cron

metadata:

timezone: America/Sao_Paulo

start: 0 22 *

end: 0 6 *

desiredReplicas: &quot;20&quot;</code></pre>

<p>Aqui, entre 22h e 6h (horário de São Paulo), sempre haverá 20 replicas. Fora desse horário, zero. Perfeito para jobs que você sabe quando vão rodar.</p>

<h2>Combinando VPA e KEDA: Uma Estratégia Completa</h2>

<h3>Quando Usar Cada Um</h3>

<p>A chave está em entender que VPA e KEDA resolvem problemas diferentes. VPA otimiza o tamanho (requests/limits) de cada pod. KEDA decide o número de pods. Frequentemente você quer usar <strong>ambos simultaneamente</strong>.</p>

<p>Um exemplo realista: você tem um consumer de fila que deve escalar horizontalmente (KEDA) baseado no tamanho da fila. Mas também quer garantir que cada pod tenha a quantidade certa de recursos (VPA). A solução é aplicar ambos no mesmo Deployment:</p>

<pre><code class="language-yaml">apiVersion: apps/v1

kind: Deployment

metadata:

name: queue-worker

namespace: production

spec:

selector:

matchLabels:

app: queue-worker

template:

metadata:

labels:

app: queue-worker

spec:

containers:

  • name: worker

image: meu-registry/queue-worker:1.0.0

resources:

requests:

cpu: 500m

memory: 1Gi

limits:

cpu: 2

memory: 4Gi

---

apiVersion: keda.sh/v1alpha1

kind: ScaledObject

metadata:

name: queue-worker-keda

namespace: production

spec:

scaleTargetRef:

name: queue-worker

kind: Deployment

minReplicaCount: 2

maxReplicaCount: 100

triggers:

  • type: aws-sqs-queue

metadata:

queueURL: https://sqs.us-east-1.amazonaws.com/123456789/worker-queue

queueLength: &quot;10&quot;

awsRegion: &quot;us-east-1&quot;

---

apiVersion: autoscaling.k8s.io/v1

kind: VerticalPodAutoscaler

metadata:

name: queue-worker-vpa

namespace: production

spec:

targetRef:

apiVersion: &quot;apps/v1&quot;

kind: Deployment

name: queue-worker

updatePolicy:

updateMode: &quot;Auto&quot;

resourcePolicy:

containerPolicies:

  • containerName: &quot;worker&quot;

minAllowed:

cpu: 250m

memory: 512Mi

maxAllowed:

cpu: 4

memory: 8Gi</code></pre>

<p>Neste setup: KEDA escala o número de replicas baseado na fila SQS. VPA otimiza os requests/limits de cada replica conforme o consumo real. O HPA tradicional não é necessário.</p>

<h3>Trade-offs e Considerações de Produção</h3>

<p>Usar VPA em modo <code>&quot;Auto&quot;</code> significa que seus pods serão recriados quando as recomendações mudarem. Isso requer que sua aplicação seja stateless ou tenha um estado gerenciado externamente. Se você usa StatefulSets, considere usar VPA apenas em modo <code>&quot;Off&quot;</code> para recomendações sem aplicação automática.</p>

<p>KEDA com muitos triggers personalizados pode adicionar latência. Um trigger do Prometheus que consulta dados cada 15-30 segundos é aceitável, mas se você tiver 10 triggers em cada ScaledObject, isso começa a impactar. Monitore o componente <code>keda-operator</code> com Prometheus.</p>

<p>Sempre defina <code>minReplicaCount</code> &gt; 0 para aplicações críticas. Zero replicas significa que sua aplicação fica indisponível por alguns segundos enquanto o primeiro pod é criado. Para filas, isso é ok. Para APIs, mantenha pelo menos 2-3 pods em produção.</p>

<h2>Monitoramento e Troubleshooting</h2>

<h3>Verificando o Status do VPA</h3>

<p>Para entender se o VPA está funcionando corretamente:</p>

<pre><code class="language-bash"># Ver todas as recomendações

kubectl get vpa -A -o wide

Detalhar uma recomendação específica

kubectl describe vpa meu-app-vpa -n production

Ver logs do recommender (debug)

kubectl logs -n kube-system deployment/vpa-recommender -f</code></pre>

<p>Procure pela seção <code>Recommendation</code> no describe. Ela mostrará campos como <code>Target</code>, <code>Uncapped Target</code>, <code>Lower Bound</code> e <code>Upper Bound</code>. Se <code>Target</code> for nil, o VPA ainda está coletando dados. Espere pelo menos 8 horas com a aplicação rodando antes de se preocupar.</p>

<h3>Verificando o Status do KEDA</h3>

<p>Para validar o KEDA:</p>

<pre><code class="language-bash"># Ver todos os ScaledObjects

kubectl get scaledobjects -A

Detalhar um ScaledObject

kubectl describe scaledobject sqs-consumer-scaled -n production

Ver logs do operador

kubectl logs -n keda deployment/keda-operator -f

Verificar as métricas que KEDA está passando para o HPA

kubectl get hpa -A -o wide</code></pre>

<p>O KEDA cria automaticamente um HPA para cada ScaledObject. Se o ScaledObject não está escalonando, verifique:</p>

<ol>

<li>Se as credenciais de autenticação estão corretas (<code>kubectl get triggerauthentication -A</code>)</li>

<li>Se o trigger consegue acessar a fonte de dados (tente um port-forward para Prometheus, por exemplo)</li>

<li>Se o <code>threshold</code> está definido corretamente (lembre-se: é por pod)</li>

</ol>

<h3>Exemplo de Troubleshooting Real</h3>

<pre><code class="language-bash"># Seu deployment não está escalando. Primeira verificação:

kubectl describe scaledobject queue-worker-keda -n production

Se ver &quot;unable to compute desired replicas&quot;, o trigger está falhando.

Verifique as credenciais:

kubectl get secret aws-credentials -n production -o yaml

Teste manualmente se o KEDA consegue acessar SQS:

kubectl port-forward -n keda svc/keda-operator 8080:8080

curl http://localhost:8080/metrics | grep sqs

Se continuar falhando, veja os logs completos:

kubectl logs -n keda deployment/keda-operator -f | grep queue-worker</code></pre>

<h2>Conclusão</h2>

<p>Você aprendeu que escalonamento em Kubernetes vai muito além do HPA básico. <strong>Primeiro ponto importante</strong>: o Vertical Pod Autoscaler resolve o problema de desperdício de recursos otimizando requests e limits baseado em consumo real, economizando infraestrutura e melhorando a eficiência. <strong>Segundo ponto</strong>: o KEDA permite escalonamento inteligente baseado em eventos e métricas customizadas — filas, eventos de webhook, métricas de Prometheus — alinhando a quantidade de pods com a demanda real do negócio. <strong>Terceiro ponto</strong>: em produção, usar VPA e KEDA juntos fornece uma solução completa: KEDA escala horizontalmente (número de pods) e VPA escala verticalmente (recursos por pod), automatizando o que antes era uma tarefa manual e propensa a erros.</p>

<p>A próxima etapa é escolher qual ferramenta se aplica melhor ao seu workload específico, começar com modo &quot;Off&quot; ou &quot;Initial&quot; (sem aplicação automática), coletar dados por uma semana, validar as recomendações, e só depois ir para modo &quot;Auto&quot; em produção. A automação sem validação é o caminho para o desastre — comece devagar, meça e aprenda.</p>

<h2>Referências</h2>

<ul>

<li><a href="https://github.com/kubernetes/autoscaler/tree/master/vertical-pod-autoscaler" target="_blank" rel="noopener noreferrer">Kubernetes Vertical Pod Autoscaler - Documentação Oficial</a></li>

<li><a href="https://keda.sh/" target="_blank" rel="noopener noreferrer">KEDA - Kubernetes Event Driven Autoscaling</a></li>

<li><a href="https://keda.sh/docs/latest/scalers/" target="_blank" rel="noopener noreferrer">KEDA Scalers - Catálogo Completo</a></li>

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

<li><a href="https://keda.sh/docs/latest/scalers/aws-sqs-queue/" target="_blank" rel="noopener noreferrer">AWS SQS Scaler no KEDA</a></li>

</ul>

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

Comentários

Mais em Docker & Kubernetes

Como Usar Container Registry Privado: Harbor, GHCR e AWS ECR na Prática em Produção
Como Usar Container Registry Privado: Harbor, GHCR e AWS ECR na Prática em Produção

Introdução: Por Que Um Container Registry Privado? Quando você trabalha com c...

Guia Completo de CIS Benchmark para Kubernetes: Hardening e Auditoria de Cluster
Guia Completo de CIS Benchmark para Kubernetes: Hardening e Auditoria de Cluster

O que é CIS Benchmark para Kubernetes O CIS Benchmark (Center for Internet Se...

O que Todo Dev Deve Saber sobre Progressive Delivery com Argo Rollouts: Canary e Blue-Green Automatizados
O que Todo Dev Deve Saber sobre Progressive Delivery com Argo Rollouts: Canary e Blue-Green Automatizados

O que é Progressive Delivery? Progressive Delivery é um modelo de implantação...