# 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: ```yaml # 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 ```bash 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) ```yaml - 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) ```yaml # 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 ```yaml scaleUp: stabilizationWindowSeconds: 0 # Sem espera policies: - type: Pods value: 5 # +5 pods por vez periodSeconds: 1 # A cada 1s ``` ### Scale DOWN - Agressivo ```yaml 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 ```bash # 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 ```bash # 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 ```promql # 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: ```yaml # ❌ 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 ```bash ./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.