RUNBOOK que Funciona às 3h da Manhã: Arquitetura de Resposta a Incidentes
# RUNBOOK que Funciona às 3h da Manhã: Arquitetura de Resposta a Incidentes
Quando o alerta toca no meio da madrugada e o serviço está fora do ar, ninguém quer tentar lembrar comandos complexos de terminal ou adivinhar por que o banco de dados não responde.
Neste artigo, apresento a arquitetura de **Observabilidade e Resposta a Incidentes** que implementamos na plataforma **makisjeanty.com**, projetada para ser operada com clareza mesmo sob pressão extrema.
---
## 1. Probes de Orquestração: Liveness vs Readiness
Um dos erros mais comuns em deploys com Docker ou Kubernetes é usar um único endpoint de health check ingênuo que apenas retorna `200 OK`.
Na nossa aplicação Django, separamos rigorosamente a sondagem em dois níveis:
### A. Liveness Probe (`/health/live/`)
Apenas confirma que o processo Python/ASGI (Daphne) está vivo e respondendo a requisições de rede.
```python
def health_check_live(request):
return JsonResponse({'status': 'alive'})
```
### B. Readiness Probe (`/health/ready/`)
Valida ativamente se todas as dependências críticas do sistema estão saudáveis antes de rotear tráfego real de usuários:
```python
def health_check_ready(request):
db_ok, db_erro = _checar_banco()
redis_ok, redis_erro = _checar_redis()
status_code = 200 if (db_ok and redis_ok) else 503
return JsonResponse({
'status': 'ready' if status_code == 200 else 'degraded',
'checks': {
'banco_dados': 'ok' if db_ok else f'erro: {db_erro}',
'redis_cache': 'ok' if redis_ok else f'erro: {redis_erro}',
}
}, status=status_code)
```
Se o MySQL ou o Redis caírem, o endpoint retorna `503 Service Unavailable`, instruindo o Nginx ou o orquestrador a não enviar novas conexões para esse nó.
---
## 2. Dashboard de Monitoria Administrativa
Para acelerar o diagnóstico, criamos um painel interno acessível exclusivamente por superusuários em uma URL ofuscada (`MONITORIA_URL`):
- **Status Instantâneo de Recursos:** Estado de conexão do MySQL e Redis em tempo real.
- **Auditoria de Operações:** Ações administrativas (purga de cache, aprovação de comentários) registram logs estruturados com IP, usuário e timestamp UTC.
- **Exportação Segura de Leads:** Sanitização contra injeção de fórmulas no Excel/CSV (prevenção de *CSV Injection* prefixando caracteres `=, +, -, @` com aspas simples).
---
## 3. Filosofia Fail-Closed em Webhooks
Ao lidar com gateways de pagamento (Kiwify), a premissa de ouro é: **se a segurança não puder ser comprovada, a requisição é imediatamente rejeitada**.
```python
if not settings.KIWIFY_TOKEN:
logger.error("KIWIFY_TOKEN não configurado. Rejeitando requisição por segurança.")
return HttpResponse(status=503)
if not hmac.compare_digest(token_recebido, settings.KIWIFY_TOKEN):
return HttpResponse(status=403)
```
A validação em tempo constante via `hmac.compare_digest` impede que atacantes descubram o token por meio de análise de latência (*Timing Attacks*).
---
## 4. Conclusão: Documentação Viva como Parte do Produto
Ter um `RUNBOOK.md` na raiz do repositório contendo comandos exatos de restauração de backup MySQL e reinício de serviços faz a diferença entre 5 minutos de instabilidade e horas de downtime.
> **Princípio:** Automatize o que for possível, padronize os diagnósticos e torne as ações de emergência óbvias.
Comentários
Seja o primeiro a comentar.
Artigos relacionados
A Anatomia de um Timing Attack e Como Mitigar com HMAC em Python
Por que comparar tokens com == vaza segredos por canal lateral de tempo, e como hmac.compare_digest e HMAC-SHA256 resolvem — com o caso real do webhook de pagamento deste site.
Como Estruturei uma Arquitetura Web Resiliente com Django 6, Docker e Cloudflare em VPS
Guia prático e estudo de caso real sobre como provisionar um servidor de produção resiliente com SSL Full, containerização não-root, cache em Redis e monitoramento de saúde.
Do Zero à Produção: Django + Docker em VPS
Guia completo de como subir uma aplicação Django 6 com Channels, Daphne, Docker, Nginx e MySQL em uma VPS Ubuntu 24.04.