Files
workshop/aula-04

Aula 04 - NGINX Ingress com Keep Request (Lua)

Zero-downtime absoluto usando Lua para segurar requisições enquanto pods reiniciam.

O Problema

Mesmo com 5 réplicas e readiness probe (aula-03), existe uma janela de tempo onde:

Tempo 0.0s: Pod1 trava, readinessProbe ainda não detectou
Tempo 0.5s: Request chega, NGINX roteia para Pod1 → 502 Bad Gateway
Tempo 1.0s: readinessProbe falha, Pod1 removido do Service

Resultado: Usuário vê erro 502 durante ~1 segundo.

A Solução: Keep Request

Tempo 0.0s: Pod1 trava
Tempo 0.5s: Request chega → NGINX tenta Pod1 → erro 502
            ↓
            Lua intercepta o 502
            ↓
            Loop: tenta conectar no backend a cada 1s
            ↓
Tempo 2.0s: Pod1 reinicia, responde OK
            ↓
            Lua faz redirect interno → usuário recebe resposta

Resultado: Usuário espera 1.5s mas recebe resposta válida (não erro).

Arquitetura

              Cliente
                 │
                 ▼
        ┌────────────────┐
        │ NGINX Ingress  │
        │   + Lua        │
        └───────┬────────┘
                │
      ┌─────────┼─────────┐
      │    502/503/504?   │
      │         │         │
      │    ┌────▼────┐    │
      │    │  Lua    │    │
      │    │  Loop   │◄───┼── Aguarda até 99s
      │    └────┬────┘    │
      │         │         │
      └─────────┼─────────┘
                │
                ▼
        ┌───────────────┐
        │   Service     │
        │  node-bugado  │
        └───────┬───────┘
                │
    ┌───────────┼───────────┐
    ▼           ▼           ▼
┌───────┐  ┌───────┐  ┌───────┐
│ Pod 1 │  │ Pod 2 │  │ Pod 3 │
└───────┘  └───────┘  └───────┘

Como Funciona o Lua

-- 1. Intercepta erros 502, 503, 504
error_page 502 503 504 = @wait_for_backend;

-- 2. Location interno que aguarda
location @wait_for_backend {
  content_by_lua_block {
    local max_wait = 99  -- segundos máximos de espera

    while (ngx.now() - start) < max_wait do
      -- Tenta conexão TCP com o backend
      local ok = sock:connect(backend_host, backend_port)

      if ok then
        -- Backend disponível! Redirect interno
        return ngx.exec(ngx.var.request_uri)
      end

      -- Aguarda 1 segundo e tenta novamente
      ngx.sleep(1)
    end

    -- Timeout: retorna 503 após 99s
    ngx.exit(503)
  }
}

Instalação

cd aula-04

# Instalar NGINX Ingress com suporte a Lua
./setup.sh

# Aplicar recursos
kubectl apply -f configmap.yaml
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
kubectl apply -f ingress-nginx.yaml

Pré-requisitos

O NGINX Ingress Controller precisa de suporte a Lua (snippets habilitados):

# No Helm values do ingress-nginx
controller:
  config:
    allow-snippet-annotations: "true"
  extraArgs:
    enable-ssl-passthrough: "true"

Teste de Stress

# Terminal 1: Monitorar pods
kubectl get pods -w

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

# Ou manualmente:
for i in {1..100}; do
  curl -s -o /dev/null -w "%{http_code}\n" http://localhost:3000/
  sleep 0.1
done

Resultado Esperado

# Sem Keep Request (aula-03):
200 200 200 502 502 200 200 200 502 200
           ^^^     ^^^ erros visíveis

# Com Keep Request (aula-04):
200 200 200 200 200 200 200 200 200 200
           ^^^ request demorou 2s mas retornou 200

Configuração

Parâmetro Valor Descrição
max_wait 99s Tempo máximo de espera
interval 1s Intervalo entre tentativas
proxy-connect-timeout 2s Timeout de conexão (falha rápido)
proxy-read-timeout 3s Timeout de leitura

Logs do NGINX

# Ver logs do Lua
kubectl logs -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx -f | grep KeepRequest

# Exemplo de output:
[KeepRequest] Aguardando backend por ate 99s...
[KeepRequest] Backend indisponivel: connection refused
[KeepRequest] Backend indisponivel: connection refused
[KeepRequest] Backend ready apos 2s

Trade-offs

Aspecto Sem Keep Request Com Keep Request
Latência normal ~10ms ~10ms
Latência durante restart Erro 502 +1-5s espera
Experiência usuário Vê erro Espera mais, sem erro
Recursos NGINX Baixo Conexões mantidas
Complexidade Simples Lua/snippets

Quando Usar

Use Keep Request quando:

  • Zero tolerância a erros visíveis
  • Operações críticas (pagamentos, submissões)
  • SLA exige 99.99% de disponibilidade

Evite quando:

  • Aplicações real-time (latência crítica)
  • Alto volume de requests (conexões acumulam)
  • Backend demora muito para reiniciar (>30s)

Cleanup

./cleanup.sh

Lições

  1. Probes não são instantâneos: Há sempre uma janela de falha
  2. Lua no NGINX: Poderoso para lógica customizada
  3. Trade-off latência vs erro: Usuário prefere esperar a ver erro
  4. Defense in depth: Múltiplas camadas de resiliência

Próxima Aula

Aula 05: KEDA + Victoria Metrics para auto-scaling baseado em métricas customizadas.