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
- Hipótese primeiro: Defina o que você quer testar
- Comece pequeno: Aumente gradualmente
- Máximo impacto, mínimo dano: Controle o blast radius
- Monitore sempre: Observe métricas durante experimentos
- 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
# 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{6727d158e4474b0847515bd23a8ee4bebd5f1aac7a18bc968e51d8985dccb442}, 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
# 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
# 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)
# 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
# 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}{6727d158e4474b0847515bd23a8ee4bebd5f1aac7a18bc968e51d8985dccb442} success rate"
assert timeouts <= 5, f"Too many timeouts: {timeouts}"
2. Database Failover
# 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
# 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
#!/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 "{6727d158e4474b0847515bd23a8ee4bebd5f1aac7a18bc968e51d8985dccb442}{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)
# 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):
"""{6727d158e4474b0847515bd23a8ee4bebd5f1aac7a18bc968e51d8985dccb442} 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{6727d158e4474b0847515bd23a8ee4bebd5f1aac7a18bc968e51d8985dccb442}
remaining = budget.budget_remaining_percentage(actual_uptime)
print(f"Budget remaining: {remaining:.1f}{6727d158e4474b0847515bd23a8ee4bebd5f1aac7a18bc968e51d8985dccb442}")
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:
- Comece com hipóteses – O que você quer provar?
- Amplitude controlada – Limite o blast radius
- Monitore – Observabilidade durante experimentos
- Automação – Execute continuamente
- 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.
