<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: "apps/v1"
kind: Deployment
name: meu-app
updatePolicy:
updateMode: "Auto"
resourcePolicy:
containerPolicies:
- containerName: "app"
minAllowed:
cpu: 100m
memory: 128Mi
maxAllowed:
cpu: 2
memory: 4Gi</code></pre>
<p>O campo <code>updateMode</code> é crítico: use <code>"Off"</code> apenas para recomendações sem aplicação automática, <code>"Initial"</code> para aplicar apenas em novos pods, e <code>"Auto"</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: "Off"</code>, validar as recomendações por alguns dias, e depois mudar para <code>"Auto"</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 > 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: "5"
awsRegion: "us-east-1"
authenticationRef:
name: aws-credentials</code></pre>
<p>O trigger <code>aws-sqs-queue</code> consulta o número de mensagens na fila. <code>queueLength: "5"</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: "10"
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: "20"</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: "10"
awsRegion: "us-east-1"
---
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: queue-worker-vpa
namespace: production
spec:
targetRef:
apiVersion: "apps/v1"
kind: Deployment
name: queue-worker
updatePolicy:
updateMode: "Auto"
resourcePolicy:
containerPolicies:
- containerName: "worker"
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>"Auto"</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>"Off"</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> > 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 "unable to compute desired replicas", 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 "Off" ou "Initial" (sem aplicação automática), coletar dados por uma semana, validar as recomendações, e só depois ir para modo "Auto" 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><!-- FIM --></p>