# Chaos Engineering: Testando Resiliência e Confiabilidade

**Meta Description:** Aprenda Chaos Engineering: princípios, ferramentas (Chaos Monkey, Gremlin), inject faults deliberadamente e garantir resiliência do sistema.

---

## O Que é Chaos Engineering?

Chaos Engineering é a prática de injectar falhas deliberadamente em sistemas para testar resiliência e descobrir vulnerabilidades antes que elas causem problemas em produção.

### Princípios

1. **Hipótese primeiro**: Defina o que você quer testar
2. **Comece pequeno**: Aumente gradualmente
3. **Máximo impacto, mínimo dano**: Controle o blast radius
4. **Monitore sempre**: Observe métricas durante experimentos
5. **Automação**: Execute experimentos continuamente

---

## Prática de Chaos Engineering

### Ciclo de Experimentos

```
┌─────────────────────────────────────┐
│                                     │
│  1. Define Hipótese                 │
│     "O sistema funciona se DB cair"  │
│                                     │
│  2. Planeja Experimento             │
│     "DB node mata por 60s"          │
│                                     │
│  3. Executa em Prod-like            │
│     "Staging environment"           │
│                                     │
│  4. Observa Métricas                │
│     "Taxa de erro aumenta?"          │
│                                     │
│  5. Analisa Resultados              │
│     "Sistema degradou graciosamente"│
│                                     │
│  6. Melhora Sistema                 │
│     "Adicionar circuit breaker"      │
│                                     │
└─────────────────────────────────────┘
```

### Hipóteses de Teste

```markdown
# Hipóteses de Chaos Engineering

## 1. Alta Disponibilidade
Hipótese: "Se um node da API morrer, o sistema continuará funcionando"
Experimento: Matar 1 instance de API
Métricas: Throughput, error rate, latency
Resultado Esperado: Throughput cai 20%, mas sem erros 5xx

## 2. Database Resilience
Hipótese: "Se o banco primário ficar indisponível, failover ocurrerrá automaticamente"
Experimento: Matar database primary
Métricas: Time to failover, error rate
Resultado Esperado: Failover em <60s, erros apenas durante transição

## 3. Network Partition
Hipótese: "Se rede entre serviços degrada, retry logic funcionará"
Experimento: Adicionar latência de 500ms
Métricas: Retry count, timeout rate
Resultado Esperado: Retries com backoff, nenhum erro usuário final

## 4. Memory Leak
Hipótese: "Se memory leak ocurrer, sistema reiniciará corretamente"
Experimento: Simular leak por alocar memória
Métricas: Memory usage, restart count
Resultado Esperado: Service restart gracefully
```

---

## Ferramentas

### Chaos Monkey

```bash
# Instalação
brew install chaos-monkey
# ou
docker pull chaosmonkey/chaos-monkey

# Configuração (chaos-monkey.json)
{
  "enabled": true,
  "runScheme": "fixed",
  "startTime": "08:00",
  "endTime": "20:00",
  "daysOfWeek": ["monday", "tuesday", "wednesday", "thursday", "friday"],
  "kind": "exp-random",
  "services": [
    {
      "name": "api-service",
      "probability": 30,
      "attacks": ["kill-container"]
    },
    {
      "name": "payment-service",
      "probability": 50,
      "attacks": ["network-latency"]
    }
  ]
}

# Executar
chaos-monkey run --config chaos-monkey.json
```

### Gremlin

```bash
# CLI Installation
curl - https://www.gremlin.com/gremlin-cli.tar.gz | tar -xz
sudo mv gremlin /usr/local/bin/

# Initialize
gremlin init --teamid YOUR_TEAM_ID --secret YOUR_SECRET

# Attack Examples

# 1. CPU Attack
gremlin attack cpu --length 60 --percent 100

# 2. Memory Attack
gremlin attack memory --length 60 --percent 50

# 3. IO Attack
gremlin attack io --length 60 --percent 100

# 4. Network Attack
gremlin attack network --delay 500 --loss 10 --percent 50

# 5. Process Kill
gremlin attack process --process-name nginx

# 6. DNS Attack
gremlin attack dns --hostname api.example.com --ip 127.0.0.1
```

### LitmusChaos (Kubernetes)

```yaml
# Pod Delete Experiment
apiVersion: litmuschaos.io/v1alpha1
kind: ChaosEngine
metadata:
  name: pod-delete-chaos
  namespace: litmus
spec:
  appinfo:
    appns: production
    applabel: "app=api"
  chaosServiceAccount: litmus-admin
  experiments:
    - name: pod-delete
      spec:
        components:
          env:
            - name: TOTAL_CHAOS_DURATION
              value: '30'
            - name: CHAOS_INTERVAL
              value: '10'
            - name: FORCE
              value: 'false'
```

---

## Exemplos de Experimentos

### 1. API Latency Injection

```python
# Testando timeout e retry
import requests
import time
import random

def test_api_resilience():
    """
    Hipótese: API cliente deve ter timeout e retry configurados
    """
    base_url = "http://api-service:8080"
    timeouts = 0
    successes = 0
    retries = 0
    
    for i in range(100):
        try:
            response = requests.get(
                f"{base_url}/data",
                timeout=5,
                headers={"X-Client-Id": f"test-{i}"}
            )
            if response.status_code == 200:
                successes += 1
        except requests.Timeout:
            timeouts += 1
        except requests.ConnectionError:
            retries += 1
    
    # Assertions
    assert successes >= 90, f"Only {successes}% success rate"
    assert timeouts <= 5, f"Too many timeouts: {timeouts}"
```

### 2. Database Failover

```bash
# Teste manual de failover
# 1. Identificar primary
psql -h db-cluster -c "SELECT pg_is_in_recovery();"

# 2. Simular failure no primary
# (Em produção, usar orquestrador)

# 3. Verificar failover
psql -h db-cluster -c "SELECT pg_is_in_recovery();"
# Deve retornar 't' no novo primary

# 4. Verificar aplicação
curl http://api-service:8080/health
# Deve estar healthy após breve degradation
```

### 3. Network Partition

```yaml
# iptables para simular latência
# Adicionar latência
iptables -A INPUT -p tcp --dport 5432 -m state --state NEW \
  -m recent --set --name DBPOSTGRES

iptables -A INPUT -p tcp --dport 5432 -m state --state NEW \
  -m recent --update --seconds 1 --hitcount 10 --name DBPOSTGRES \
  -j DROP

# Adicionar delay de 500ms
tc qdisc add dev eth0 root netem delay 500ms

# Remover (cleanup)
tc qdisc del dev eth0 root
```

### 4. Container Kill

```bash
#!/bin/bash
# chaos-test.sh

echo "=== Chaos Engineering Test ==="
echo "Target: Random API pod"

# Get random API pod
POD=$(kubectl get pods -n production -l app=api \
  -o jsonpath='{.items[0].metadata.name}')

echo "Killing pod: $POD"

# Get metrics before
kubectl top pods $POD -n production
ERROR_RATE_BEFORE=$(curl -s http://api-service/metrics | grep error_rate)

# Kill pod
kubectl delete pod $POD -n production

# Monitor recovery
echo "Monitoring recovery..."
for i in {1..30}; do
    RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" http://api-service/health)
    if [ "$RESPONSE" == "200" ]; then
        echo "Recovered after ${i} seconds"
        break
    fi
    sleep 1
done

# Get metrics after
kubectl top pods -n production -l app=api
ERROR_RATE_AFTER=$(curl -s http://api-service/metrics | grep error_rate)

echo "Error rate before: $ERROR_RATE_BEFORE"
echo "Error rate after: $ERROR_RATE_AFTER"

# Validate
if [ $i -lt 30 ]; then
    echo "✅ Recovery successful"
else
    echo "❌ Recovery failed"
    exit 1
fi
```

---

## SRE错误预算 (Error Budgets)

```python
# Error Budget Calculator
class ErrorBudget:
    def __init__(self, slo_percentage, window_days=30):
        self.slo = slo_percentage / 100
        self.window_hours = window_days * 24 * 60 * 60
    
    def allowed_downtime(self):
        """Tempo máximo de downtime permitido"""
        return (1 - self.slo) * self.window_hours
    
    def current_budget(self, actual_uptime):
        """Orçamento restante"""
        budget_used = (1 - actual_uptime) * self.window_hours
        return self.allowed_downtime() - budget_used
    
    def budget_remaining_percentage(self, actual_uptime):
        """% de orçamento restante"""
        budget = self.current_budget(actual_uptime)
        return (budget / self.allowed_downtime()) * 100

# Uso
budget = ErrorBudget(slo_percentage=99.9, window_days=30)
allowed = budget.allowed_downtime()
print(f"Allowed downtime: {allowed/60:.1f} minutes per month")

# Verificar se pode fazer chaos
actual_uptime = 0.998  # 99.8%
remaining = budget.budget_remaining_percentage(actual_uptime)
print(f"Budget remaining: {remaining:.1f}%")

if remaining > 50:
    print("✅ Safe to run chaos experiments")
else:
    print("⚠️ Budget low, avoid chaos")
```

---

## Conclusão

Chaos Engineeringprevine falhas em produção. As chaves são:

1. **Comece com hipóteses** - O que você quer provar?
2. **Amplitude controlada** - Limite o blast radius
3. **Monitore** - Observabilidade durante experimentos
4. **Automação** - Execute continuamente
5. **Cultura** - Aprenda com falhas, não puna

---

### FAQ

**P: Chaos Engineering é seguro?**  
R: Sim, quando feito com controle de blast radius e rollback.

**P: Quando começar?**  
R: Quando você tiver observabilidade básica (métricas, logs, alertas).

**P: Qual ambiente usar?**  
R: Comece em staging, depois produção controlada.
