Files
ArgoCD Setup d3656fdce9 docs(aula-05): atualizar README com nova lógica de scaling
- Documentar trigger único (unavailable) em vez de restarts
- Explicar fórmula intuitiva: 5 + (unavailable * 2)
- Adicionar seção sobre scrape interval de 5s
- Documentar fluxo de detecção (~6-7s)
- Explicar por que não usar restarts (CrashLoopBackOff)
- Atualizar lições e trade-offs
2026-01-23 11:15:20 -03:00
..

Aula 05 - KEDA + Victoria Metrics (Auto-scaling por Métricas)

Auto-scaling inteligente baseado em métricas customizadas usando KEDA e Victoria Metrics.

O Problema

HPA padrão do Kubernetes escala apenas por CPU/memória:

# HPA tradicional - limitado
metrics:
  - type: Resource
    resource:
      name: cpu
      targetAverageUtilization: 70

Limitações:

  • App pode estar "saudável" em CPU mas travada
  • Não detecta pods indisponíveis
  • Reação lenta (~15-30s)

A Solução: KEDA

KEDA (Kubernetes Event-driven Autoscaling) permite escalar baseado em qualquer métrica:

Victoria Metrics ──► KEDA ──► HPA ──► Deployment
     │                │
     │                └─ Consulta métricas a cada 1s
     │
     └─ Coleta métricas do cluster a cada 5s (kube-state-metrics)

Arquitetura

┌─────────────────────────────────────────────────────────────┐
│                    Victoria Metrics                         │
│  ┌──────────────────────────────────────────────────────┐  │
│  │  kube_deployment_status_replicas_unavailable = 3     │  │
│  │  Scrape interval: 5s (detecção rápida)               │  │
│  └──────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────┘
                              │
                    Query PromQL a cada 1s
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                         KEDA                                │
│  ┌────────────────────────────────────────────────────────┐│
│  │ Query: 5 + (unavailable * 2)                           ││
│  │                                                        ││
│  │ 0 unavailable → 5 réplicas  (mínimo)                   ││
│  │ 3 unavailable → 11 réplicas (5 + 6)                    ││
│  │ 5 unavailable → 15 réplicas (5 + 10)                   ││
│  └────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────┘
                              │
                         Cria/Atualiza
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                          HPA                                │
│           minReplicas: 5  ──────►  maxReplicas: 30          │
└─────────────────────────────────────────────────────────────┘
                              │
                           Escala
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                      Deployment                             │
│    [Pod1] [Pod2] [Pod3] [Pod4] [Pod5] ... [Pod30]          │
└─────────────────────────────────────────────────────────────┘

Instalação

cd aula-05

# Instala Victoria Metrics, KEDA e NGINX Ingress
./setup.sh

O setup.sh instala:

  1. Victoria Metrics - Coleta e armazena métricas
  2. kube-state-metrics - Expõe métricas do Kubernetes (scrape 5s)
  3. KEDA - Event-driven autoscaler
  4. NGINX Ingress - Load balancer

Trigger: Pods Indisponíveis (Instantâneo)

- type: prometheus
  metricType: AverageValue
  metadata:
    serverAddress: http://vmsingle-vm-victoria-metrics-k8s-stack.monitoring:8428

    # Query que calcula réplicas desejadas diretamente
    query: |
      5 + (kube_deployment_status_replicas_unavailable{
        deployment="node-bugado",
        namespace="default"
      } * 2)

    threshold: '1'

Como funciona a fórmula

Pods Unavailable Query Retorna Réplicas Desejadas
0 5 + (0 × 2) = 5 5 (mínimo)
1 5 + (1 × 2) = 7 7
3 5 + (3 × 2) = 11 11
5 5 + (5 × 2) = 15 15

Vantagem: Detecção instantânea - não precisa de janela de tempo como métricas de restarts.

Configuração de Velocidade

Scrape Rápido (5s)

# vmservicescrape-kube-state-metrics.yaml
apiVersion: operator.victoriametrics.com/v1beta1
kind: VMServiceScrape
spec:
  endpoints:
    - port: http
      interval: 5s  # Default é 30s - muito lento para workshop!

Scale UP - Agressivo

scaleUp:
  stabilizationWindowSeconds: 0   # Sem espera
  policies:
    - type: Pods
      value: 5                    # +5 pods por vez
      periodSeconds: 1            # A cada 1s

Scale DOWN - Agressivo

scaleDown:
  stabilizationWindowSeconds: 0   # Sem espera
  policies:
    - type: Pods
      value: 10                   # -10 pods por vez
      periodSeconds: 1            # A cada 1s

Fluxo de Detecção

Tempo 0.0s: Pod crasha
Tempo 0.0s: kube-state-metrics atualiza (imediato)
Tempo 5.0s: Victoria Metrics coleta (scrape interval)
Tempo 6.0s: KEDA consulta (polling interval)
Tempo 6.0s: HPA escala (imediato)
─────────────────────────────────────────────────
Total: ~6-7 segundos de reação

Exemplo de Scaling

Tempo 0s:   5 pods, 0 unavailable
Tempo 6s:   Pod1 trava → detectado → escala para 7 pods
Tempo 7s:   Pod2 trava → detectado → escala para 9 pods
Tempo 8s:   Pod3 trava → detectado → escala para 11 pods
...
Tempo 15s:  Pods reiniciaram, 0 unavailable
Tempo 16s:  Scale down: 15 → 5 (instantâneo)

Teste de Stress

# Terminal 1: Monitorar pods
watch kubectl get pods -l app=node-bugado

# Terminal 2: Monitorar HPA
watch kubectl get hpa

# Terminal 3: Teste de stress
./teste-stress.sh

Comandos Úteis

# Ver ScaledObject
kubectl get scaledobject
kubectl describe scaledobject node-bugado-scaledobject

# Ver HPA criado pelo KEDA
kubectl get hpa
kubectl describe hpa keda-hpa-node-bugado-scaledobject

# Testar query no Victoria Metrics
kubectl run curl --rm -it --restart=Never --image=curlimages/curl -- \
  -s 'http://vmsingle-vm-victoria-metrics-k8s-stack.monitoring:8428/api/v1/query' \
  --data-urlencode 'query=5 + (kube_deployment_status_replicas_unavailable{deployment="node-bugado"} * 2)'

# Logs do KEDA
kubectl logs -n keda -l app=keda-operator -f

Queries PromQL Úteis

# Pods indisponíveis (usado pelo KEDA)
kube_deployment_status_replicas_unavailable{deployment="node-bugado"}

# Query completa do KEDA
5 + (kube_deployment_status_replicas_unavailable{deployment="node-bugado"} * 2)

# Pods prontos
kube_deployment_status_replicas_ready{deployment="node-bugado"}

# Total de restarts (para debug)
sum(kube_pod_container_status_restarts_total{pod=~"node-bugado.*"})

Por que não usar Restarts como trigger?

O trigger de restarts usa increase([window]) que requer uma janela de tempo:

# ❌ Problema: CrashLoopBackOff usa backoff exponencial
# Restart 1: imediato
# Restart 2: espera 10s
# Restart 3: espera 20s
# Restart 4: espera 40s
#
# Com janela de 15s, após restart 3+, o backoff > janela
# → increase([15s]) = 0 → KEDA não detecta!

Solução: Usar kube_deployment_status_replicas_unavailable que é instantâneo.

Victoria Metrics vs Prometheus

Aspecto Prometheus Victoria Metrics
Recursos Alto consumo Baixo consumo
Armazenamento Local apenas Distribuído opcional
API Nativa Compatível 100%
Performance Boa Excelente
Para este workshop Funciona Recomendado

Cleanup

./cleanup.sh

Lições

  1. Métrica instantânea: Use unavailable em vez de restarts para detecção imediata
  2. Scrape rápido: Configure 5s em vez do default 30s
  3. Query intuitiva: 5 + (unavailable * 2) calcula réplicas diretamente
  4. Scale agressivo: stabilizationWindow: 0 para reação imediata
  5. metricType correto: AverageValue para cálculo proporcional

Trade-offs

Aspecto HPA Padrão KEDA (esta aula)
Configuração Simples Mais complexa
Métricas CPU/Mem Qualquer
Latência ~15-30s ~6-7s
Dependências Nenhuma Victoria Metrics
Flexibilidade Baixa Alta

Próxima Aula

Aula 06: Deploy do n8n via Helm em ambiente local.