diff --git a/aula-05/README.md b/aula-05/README.md index 47ad7f1..cdb9745 100644 --- a/aula-05/README.md +++ b/aula-05/README.md @@ -18,7 +18,7 @@ metrics: **Limitações:** - App pode estar "saudável" em CPU mas travada - Não detecta pods indisponíveis -- Não reage a restarts frequentes +- Reação lenta (~15-30s) ## A Solução: KEDA @@ -29,7 +29,7 @@ Victoria Metrics ──► KEDA ──► HPA ──► Deployment │ │ │ └─ Consulta métricas a cada 1s │ - └─ Coleta métricas do cluster (kube-state-metrics) + └─ Coleta métricas do cluster a cada 5s (kube-state-metrics) ``` ## Arquitetura @@ -38,8 +38,8 @@ Victoria Metrics ──► KEDA ──► HPA ──► Deployment ┌─────────────────────────────────────────────────────────────┐ │ Victoria Metrics │ │ ┌──────────────────────────────────────────────────────┐ │ -│ │ kube_deployment_status_replicas_unavailable = 2 │ │ -│ │ kube_pod_container_status_restarts_total = 5 │ │ +│ │ kube_deployment_status_replicas_unavailable = 3 │ │ +│ │ Scrape interval: 5s (detecção rápida) │ │ │ └──────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────┘ │ @@ -48,10 +48,13 @@ Victoria Metrics ──► KEDA ──► HPA ──► Deployment ▼ ┌─────────────────────────────────────────────────────────────┐ │ KEDA │ -│ ┌────────────────┐ ┌─────────────────────────────────┐ │ -│ │ ScaledObject │───►│ unavailable >= 1 ? SCALE UP │ │ -│ │ │ │ restarts >= 1 ? SCALE UP │ │ -│ └────────────────┘ └─────────────────────────────────┘ │ +│ ┌────────────────────────────────────────────────────────┐│ +│ │ 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 @@ -82,97 +85,110 @@ cd aula-05 O setup.sh instala: 1. **Victoria Metrics** - Coleta e armazena métricas -2. **kube-state-metrics** - Expõe métricas do Kubernetes +2. **kube-state-metrics** - Expõe métricas do Kubernetes (scrape 5s) 3. **KEDA** - Event-driven autoscaler -4. **NGINX Ingress** - Com suporte a Lua (Keep Request) +4. **NGINX Ingress** - Load balancer -## Triggers Configurados - -### Trigger 1: Pods Indisponíveis +## Trigger: Pods Indisponíveis (Instantâneo) ```yaml -query: | - kube_deployment_status_replicas_unavailable{ - deployment="node-bugado", - namespace="default" - } -threshold: '1' +- 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' ``` -**Comportamento:** Se 1 ou mais pods estão indisponíveis → SCALE UP +### Como funciona a fórmula -### Trigger 2: Restarts Frequentes +| 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 -query: | - sum(increase( - kube_pod_container_status_restarts_total{ - namespace="default", - pod=~"node-bugado.*" - }[2m] - )) -threshold: '1' +# vmservicescrape-kube-state-metrics.yaml +apiVersion: operator.victoriametrics.com/v1beta1 +kind: VMServiceScrape +spec: + endpoints: + - port: http + interval: 5s # Default é 30s - muito lento para workshop! ``` -**Comportamento:** Se houve 1+ restart nos últimos 2 min → SCALE UP - -## Configuração de Scaling +### Scale UP - Agressivo ```yaml -# Limites -minReplicaCount: 5 # Alta disponibilidade -maxReplicaCount: 30 # Limite de recursos - -# Velocidade -pollingInterval: 1 # Verifica a cada 1s - -# Scale UP - Agressivo scaleUp: - stabilizationWindowSeconds: 0 # Imediato + stabilizationWindowSeconds: 0 # Sem espera policies: - type: Pods value: 5 # +5 pods por vez periodSeconds: 1 # A cada 1s - -# Scale DOWN - Conservador -scaleDown: - stabilizationWindowSeconds: 10 # Aguarda 10s - policies: - - type: Percent - value: 50 # -50% por vez - periodSeconds: 5 # A cada 5s ``` -### Exemplo de Scaling +### 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 1s: Pod1 trava, 1 unavailable → KEDA detecta -Tempo 2s: Escala para 10 pods (+5) -Tempo 3s: Pod2 trava, 2 unavailable -Tempo 4s: Escala para 15 pods (+5) +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 10s: 30 pods (máximo) -Tempo 20s: Pods reiniciaram, 0 unavailable -Tempo 30s: Scale down: 30 → 15 → 8 → 5 +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 +watch kubectl get pods -l app=node-bugado # Terminal 2: Monitorar HPA watch kubectl get hpa # Terminal 3: Teste de stress ./teste-stress.sh - -# Ou manualmente - 1000 requests -for i in {1..1000}; do - curl -s http://localhost/ & -done ``` ## Comandos Úteis @@ -188,35 +204,46 @@ 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?query=kube_deployment_status_replicas_unavailable" + -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 - -# Métricas em tempo real -watch -n1 'kubectl get pods | grep node-bugado | wc -l' ``` -## Queries PromQL +## Queries PromQL Úteis ```promql -# Pods indisponíveis +# Pods indisponíveis (usado pelo KEDA) kube_deployment_status_replicas_unavailable{deployment="node-bugado"} -# Total de restarts -sum(kube_pod_container_status_restarts_total{pod=~"node-bugado.*"}) - -# Restarts nos últimos 2 minutos -sum(increase(kube_pod_container_status_restarts_total{pod=~"node-bugado.*"}[2m])) +# Query completa do KEDA +5 + (kube_deployment_status_replicas_unavailable{deployment="node-bugado"} * 2) # Pods prontos kube_deployment_status_replicas_ready{deployment="node-bugado"} -# Réplicas desejadas vs disponíveis -kube_deployment_status_replicas{deployment="node-bugado"} -kube_deployment_status_replicas_available{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 | @@ -235,22 +262,22 @@ kube_deployment_status_replicas_available{deployment="node-bugado"} ## Lições -1. **Métricas customizadas**: Escale por qualquer métrica, não só CPU/memória -2. **Reação rápida**: KEDA pode verificar a cada 1 segundo -3. **Scale UP agressivo**: Adicione capacidade rapidamente quando necessário -4. **Scale DOWN conservador**: Evite oscilação (flapping) -5. **Observabilidade**: Métricas são a base para automação inteligente +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 | -|---------|------------|------| +| Aspecto | HPA Padrão | KEDA (esta aula) | +|---------|------------|------------------| | Configuração | Simples | Mais complexa | | Métricas | CPU/Mem | Qualquer | -| Dependências | Nenhuma | Victoria Metrics/Prometheus | +| Latência | ~15-30s | ~6-7s | +| Dependências | Nenhuma | Victoria Metrics | | Flexibilidade | Baixa | Alta | -| Latência | ~15s | ~1s (configurável) | ## Próxima Aula -**Aula 06**: Deploy do n8n via Helm em ambiente local (OrrStack/k3s/Docker Desktop/minikube/kind/etc). +**Aula 06**: Deploy do n8n via Helm em ambiente local.