As ferramentas de chaos engineering evoluíram de scripts ad-hoc do Netflix para um ecossistema maduro com projetos open-source, produtos comerciais, e serviços gerenciados de cloud. Escolher a ferramenta certa não é trivial: cada uma opera em um nível diferente da pilha (código, processo, rede, Kubernetes, cloud), tem modelo de execução diferente, e serve bem contextos diferentes. Este conceito percorre as principais ferramentas com o critério de quem escolhe para produção — não para quem está avaliando demos.
Chaos Monkey — a origem e o legado
O Chaos Monkey original (2011) era um script simples que terminava aleatoriamente instâncias EC2 da Netflix durante horário comercial. A segunda versão (2016, open-source em Go) formalizou o comportamento: cada serviço pode ter configuração de chaos probability (0 a 1), e o Chaos Monkey respeita exceções configuradas. Por padrão, ele opera apenas em horário comercial — a ideia é que falhas devem acontecer quando engenheiros estão de plantão para responder, não às 3h da manhã.
O Chaos Monkey cresceu para a Simian Army — um conjunto de serviços de chaos com responsabilidades distintas: Chaos Gorilla simulava falha de uma AZ inteira; Chaos Kong simulava falha de uma região; Latency Monkey injetava latência artificial; Conformity Monkey verificava se instâncias seguiam melhores práticas. Hoje, a maioria foi substituída por ferramentas mais modernas e genéricas, mas o Chaos Monkey em si permanece relevante para infraestrutura AWS.
Chaos Toolkit — experiments como código
O Chaos Toolkit (chaostoolkit.org, mantido por ChaosIQ) é a ferramenta mais próxima do método científico descrito no conceito anterior. Experimentos são definidos em JSON ou YAML com estrutura explícita: steady state hypothesis, method (a sequência de ações), e rollbacks. É open-source, extensível, e agnóstico de cloud.
# Experimento Chaos Toolkit — latência no serviço de inventário
version: 1.0.0
title: "Checkout sobrevive a latência no serviço de inventário"
description: >
Verificar que o checkout completa pedidos dentro do SLO mesmo
quando o serviço de inventário tem latência de 500ms adicional.
steady-state-hypothesis:
title: "Checkout operando normalmente"
probes:
- type: probe
name: checkout-disponível
provider:
type: http
url: http://checkout-api/health
timeout: 2
tolerance: 200
- type: probe
name: taxa-de-erro-baixa
provider:
type: python
module: chaoslib.prometheus
func: query
arguments:
query: "rate(http_requests_total{status=~'5..'}[5m]) /
rate(http_requests_total[5m]) * 100"
tolerance:
type: range
range: [0, 1] # máx 1% de erro
method:
- type: action
name: injetar-latencia-inventario
provider:
type: process
path: tc
arguments: "qdisc add dev eth0 root netem delay 500ms"
pauses:
after: 300 # 5 minutos de experimento
rollbacks:
- type: action
name: remover-latencia-inventario
provider:
type: process
path: tc
arguments: "qdisc del dev eth0 root netem"
A estrutura YAML do Chaos Toolkit força o experimentador a pensar em cada componente: o que é normal (steady-state), o que será perturbado (method), e como reverter (rollbacks). Isso torna os experimentos auditáveis, versionáveis em git, e executáveis em CI/CD.
Experiment-as-code (Chaos Toolkit, Litmus) tem uma vantagem operacional enorme: o experimento é documentação. Quando um novo engenheiro pergunta "como testamos que o checkout sobrevive a latência no inventário?", você mostra o arquivo YAML. Experimentos executados manualmente e não documentados evaporam junto com a memória do engenheiro que os executou.
Litmus — chaos nativo para Kubernetes
Litmus (litmuschaos.io, graduado no CNCF como projeto incubating em 2022) é a ferramenta de chaos engineering mais adotada no ecossistema Kubernetes. Experimentos são definidos como ChaosExperiments (CRD do Kubernetes) e executados como pods — integrados naturalmente com o scheduler e RBAC do cluster.
A biblioteca de experimentos do Litmus cobre os cenários mais comuns em Kubernetes:
- pod-delete: termina pods aleatoriamente em um deployment
- container-kill: mata o processo principal dentro de um container
- node-drain: drena um nó do cluster (simula manutenção ou falha de nó)
- network-loss: introduz perda de pacotes nas chamadas entre serviços
- network-latency: adiciona latência nas chamadas de rede
- disk-fill: preenche o disco de um nó até um percentual
- cpu-hog / memory-hog: consome recursos para simular noisy neighbor
Cada experimento tem parâmetros configuráveis (percentagem de pods afetados, duração, seletor de namespace) e integração com monitoramento: o Litmus pode verificar o steady state via Prometheus antes e depois de cada experimento.
Gremlin — plataforma comercial de chaos
Gremlin (gremlin.com) é a plataforma comercial mais madura de chaos engineering, fundada por ex-engenheiros do Netflix (Kolton Andress, Matt Jacobs). Oferece uma interface visual para criar e executar experimentos, biblioteca de ataques pré-configurados, relatórios de resultados, e integração com PagerDuty, Slack, e sistemas de monitoramento.
O diferencial do Gremlin em relação às ferramentas open-source é a camada de segurança e auditoria: quem executou qual experimento, quando, com qual blast radius, e quais foram os resultados. Em ambientes com compliance (SOC2, HIPAA), isso importa. O custo é relevante para times pequenos — Gremlin faz mais sentido para organizações grandes com orçamento de segurança dedicado.
AWS Fault Injection Simulator (FIS)
Para infraestrutura AWS, o FIS (disponível desde 2021) é a opção nativa — zero instalação adicional, integrado com IAM, CloudWatch, e SSM. Experimentos são definidos como FIS Experiment Templates e podem ser executados via console, CLI, ou SDK.
O FIS tem ações para os serviços AWS mais comuns: terminar instâncias EC2, falhar AZs inteiras (simulado), injetar latência em chamadas RDS, deletar registros de Route 53, pausar tarefas ECS. A limitação é o escopo — só funciona para recursos AWS. Para sistemas multi-cloud ou com muita lógica de aplicação, Chaos Toolkit ou Litmus podem cobrir mais terreno.
Estrutura de um experimento reproduzível
Independente da ferramenta, um experimento de chaos bem estruturado sempre tem os mesmos componentes. A disciplina de documentá-los transforma chaos de arte em ciência:
| Componente | Pergunta que responde | Exemplo |
|---|---|---|
| Hipótese | O que acreditamos sobre o sistema? | "Checkout continua com <1% de erro se inventário tiver 500ms de latência" |
| Steady state | Como é o normal, mensurado? | "taxa_erro < 0.1%, P99 < 400ms, throughput > 100 req/s" |
| Método | Qual perturbação aplicar? | "Injetar 500ms de latência nas chamadas ao pod inventory-service" |
| Duração | Por quanto tempo? | "5 minutos" |
| Blast radius | Qual o impacto máximo? | "1 de 3 réplicas do inventory-service" |
| Abort condition | Quando parar automaticamente? | "Se taxa_erro > 2% por mais de 30s" |
| Rollback | Como reverter? | "Remover regra de tc netem; verificar steady state após 2min" |
| Resultado esperado | O que deveria acontecer? | "Checkout usa cache de inventário, continua processando" |
Integrando chaos no CI/CD
O nível 3 de maturidade de chaos (experimentos automatizados em staging) exige integração com o pipeline de CI/CD. O padrão é adicionar um estágio de "chaos gate" após os testes funcionais e antes do deploy para produção:
# GitHub Actions — chaos gate
- name: Run chaos experiments
run: |
pip install chaostoolkit chaostoolkit-kubernetes
chaos run experiments/checkout-inventory-latency.yaml \
--hypothesis-strategy=continuously \
--rollback-strategy=always
env:
KUBERNETES_CONTEXT: staging
- name: Assert chaos results
run: |
chaos report --export-format=json chaos-journal.json
python scripts/assert_chaos_results.py chaos-journal.json
Se os experimentos falham (steady state violado), o deploy é bloqueado. Isso garante que mudanças que regridem resiliência não chegam a produção. O pipeline fica mais lento, mas o trade-off é explícito: velocidade de deploy vs garantia de resiliência.
// Chaos experiment como xUnit test com WireMock
public class CheckoutResilienceTests : IDisposable
{
private readonly WireMockServer _inventoryMock;
private readonly HttpClient _checkoutClient;
public CheckoutResilienceTests()
{
// WireMock simula o serviço de inventário
_inventoryMock = WireMockServer.Start();
_checkoutClient = CreateClientPointingToMock();
}
[Fact]
public async Task Checkout_InventoryLatency500ms_CompletesWithinSLO()
{
// Arrange — steady state
_inventoryMock
.Given(Request.Create().WithPath("/api/stock/*"))
.RespondWith(Response.Create()
.WithDelay(TimeSpan.FromMilliseconds(500)) // fault inject
.WithStatusCode(200)
.WithBody(@"{""available"": true}"));
var stopwatch = Stopwatch.StartNew();
// Act
var response = await _checkoutClient.PostAsJsonAsync(
"/api/orders", new { ProductId = "P123", Quantity = 1 });
stopwatch.Stop();
// Assert — steady state hypothesis
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.True(stopwatch.ElapsedMilliseconds < 1000,
$"Latência {stopwatch.ElapsedMilliseconds}ms viola SLO de 1000ms");
var body = await response.Content.ReadFromJsonAsync<OrderResult>();
Assert.NotNull(body?.OrderId);
}
public void Dispose() => _inventoryMock.Stop();
}
WireMock.Net permite simular fault injection a nível de HTTP — latência, erros, timeouts. Mais controlado que injeção de rede, suficiente para validar a camada de código.
import pytest
import httpx
import respx
import time
import asyncio
@pytest.mark.asyncio
async def test_checkout_survives_inventory_latency():
"""Checkout deve completar dentro do SLO com 500ms de latência no inventário."""
async def slow_inventory_response(request):
await asyncio.sleep(0.5) # 500ms fault inject
return httpx.Response(200, json={"available": True})
with respx.mock(base_url="http://inventory-service") as mock:
mock.get("/api/stock/P123").mock(side_effect=slow_inventory_response)
async with httpx.AsyncClient(base_url="http://checkout-api") as client:
start = time.monotonic()
response = await client.post("/api/orders", json={
"product_id": "P123", "quantity": 1
})
elapsed = time.monotonic() - start
# steady state hypothesis
assert response.status_code == 200, f"Checkout falhou: {response.status_code}"
assert elapsed < 1.0, f"Latência {elapsed:.2f}s viola SLO de 1s"
data = response.json()
assert "order_id" in data, "Order ID ausente na resposta"
respx é o mock de httpx para Python async — permite simular respostas com delay, erros, e comportamento customizado. Ideal para chaos de código sem infraestrutura adicional.
func TestCheckout_InventoryLatency_MeetsSLO(t *testing.T) {
// Simular inventário com latência de 500ms
inventoryServer := httptest.NewServer(
http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
time.Sleep(500 * time.Millisecond) // fault inject
w.Header().Set("Content-Type", "application/json")
fmt.Fprintln(w, `{"available": true}`)
}),
)
defer inventoryServer.Close()
// Inicializar checkout apontando para mock de inventário
checkoutSvc := NewCheckoutService(inventoryServer.URL)
start := time.Now()
result, err := checkoutSvc.PlaceOrder(
context.Background(),
Order{ProductID: "P123", Quantity: 1},
)
elapsed := time.Since(start)
// Steady state hypothesis
require.NoError(t, err, "Checkout não deve falhar com latência no inventário")
assert.Less(t, elapsed, time.Second,
"Latência %v viola SLO de 1s", elapsed)
assert.NotEmpty(t, result.OrderID)
assert.Equal(t, "inventory_cache", result.InventorySource,
"Deve ter usado o cache de inventário como fallback")
}
O assert final verifica não só que o checkout funcionou, mas que usou o fallback esperado (inventory_cache). Isso transforma o teste em validação do comportamento de degradação, não só do happy path.
Escolhendo a ferramenta certa
A escolha depende do contexto mais do que da ferramenta em si:
Time começando com chaos (sem Kubernetes): Chaos Toolkit. Curva de aprendizado baixa, experimentos em YAML/JSON, integração simples com CI.
Time em Kubernetes: Litmus. Nativo para o cluster, sem agente externo, biblioteca de experimentos pronta para os cenários Kubernetes mais comuns.
Organização enterprise com compliance: Gremlin ou AWS FIS. Auditoria, RBAC, integração com sistemas existentes de ticketing e monitoramento.
Infraestrutura majoritariamente AWS: AWS FIS. Zero instalação, integrado com IAM e CloudWatch, sem custo adicional de plataforma.
Chaos em testes de integração (sem infra de chaos): WireMock (Java/.NET), respx (Python), httptest (Go). Fault injection a nível de HTTP, sem infraestrutura adicional, rodando em CI.
Como praticar
- Executar um experimento com Chaos Toolkit. Instale o Chaos Toolkit (
pip install chaostoolkit). Escreva um experimento YAML que verifica se um serviço responde após um kill de processo (usandoos.killou similar). Execute localmente. Observe como a estrutura de steady-state/method/rollback força clareza sobre o que está sendo testado. - Converter um teste de integração em chaos test. Pegue um teste de integração existente que chama um serviço externo. Adicione fault injection (via mock com delay ou erro) para um dos dependentes. Verifique que o teste agora valida o comportamento sob falha, não apenas o happy path.
- Comparar Litmus e AWS FIS. Se sua infraestrutura é Kubernetes em AWS, instale o Litmus em um cluster de staging. Execute o experimento
pod-deleteem um deployment de baixo risco. Depois execute o mesmo cenário via AWS FIS. Compare: qual foi mais simples? Qual deu mais visibilidade? Qual integraria melhor com seu pipeline existente?
Referências para aprofundar
- docs Chaos Toolkit Documentation — chaostoolkit.org.
- livro Learning Chaos Engineering — Russ Miles (O'Reilly, 2019).
- docs Litmus Chaos — Documentation — litmuschaos.io/docs.
- artigo Chaos Engineering with AWS FIS — AWS Docs, 2023.
- artigo Automating Chaos with CI/CD — Gremlin Blog, 2021.
- docs Netflix Chaos Monkey — GitHub — github.com/Netflix/chaosmonkey.
- artigo WireMock — Testing with Fault Injection — wiremock.org.
- artigo Comparing Chaos Engineering Tools — CNCF Blog, 2022.
- vídeo Chaos Engineering with Litmus at KubeCon — CNCF, 2022.
- artigo Chaos Engineering at Shopify — Shopify Engineering Blog, 2021.
- docs respx — Mock HTTPX in Python — github.com/lundberg/respx.
- livro Chaos Engineering — Casey Rosenthal et al. (O'Reilly, 2020).