MÓDULO 08 · CONCEITO 07 DE 14

Chaos Tooling

Do Chaos Monkey ao Chaos Toolkit — como estruturar experimentos reproduzíveis com hipótese, método e rollback

Tempo de leitura ~21 min Pré-requisito 06 · Chaos engineering — fundamentos Próximo 08 · Fault injection

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.

heurística do sênior

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:

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.

C# — Experiment runner integrado com testes
// 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.

Python — Chaos experiment com pytest e respx
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.

Go — Chaos test com httptest e fault injection
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

  1. 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 (usando os.kill ou similar). Execute localmente. Observe como a estrutura de steady-state/method/rollback força clareza sobre o que está sendo testado.
  2. 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.
  3. Comparar Litmus e AWS FIS. Se sua infraestrutura é Kubernetes em AWS, instale o Litmus em um cluster de staging. Execute o experimento pod-delete em 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

  1. docs Chaos Toolkit Documentation — chaostoolkit.org. Documentação completa do Chaos Toolkit — guia de início, referência de YAML, extensões disponíveis (Kubernetes, AWS, GCP, Azure).
  2. livro Learning Chaos Engineering — Russ Miles (O'Reilly, 2019). Guia prático focado no Chaos Toolkit — o autor é o criador da ferramenta. Cobre desde instalação até integração com CI/CD.
  3. docs Litmus Chaos — Documentation — litmuschaos.io/docs. Documentação do Litmus com catálogo completo de experimentos para Kubernetes. Inclui instalação via Helm e exemplos de ChaosEngine.
  4. artigo Chaos Engineering with AWS FIS — AWS Docs, 2023. docs.aws.amazon.com/fis. Tutorial oficial de AWS Fault Injection Simulator — exemplos de templates para EC2, ECS, RDS, e Networking.
  5. artigo Automating Chaos with CI/CD — Gremlin Blog, 2021. Como integrar experimentos de chaos no pipeline Jenkins, GitHub Actions, e GitLab CI — com exemplos de configuração.
  6. docs Netflix Chaos Monkey — GitHub — github.com/Netflix/chaosmonkey. Repositório oficial do Chaos Monkey v2 em Go — documentação de configuração, spinnaker integration, e estratégias de chaos.
  7. artigo WireMock — Testing with Fault Injection — wiremock.org. Documentação de fault injection HTTP com WireMock — delays, erros, chunked responses. Útil para chaos em testes sem infraestrutura dedicada.
  8. artigo Comparing Chaos Engineering Tools — CNCF Blog, 2022. Análise comparativa de Litmus, Chaos Toolkit, Gremlin, e AWS FIS — critérios de avaliação, trade-offs, casos de uso ideais.
  9. vídeo Chaos Engineering with Litmus at KubeCon — CNCF, 2022. YouTube. Demonstração ao vivo de experimentos Litmus em Kubernetes — útil para ver o workflow completo antes de instalar.
  10. artigo Chaos Engineering at Shopify — Shopify Engineering Blog, 2021. Como a Shopify usa chaos engineering no Black Friday — ferramentas, processo, e lições aprendidas em escala.
  11. docs respx — Mock HTTPX in Python — github.com/lundberg/respx. Documentação do respx — fault injection HTTP para código Python assíncrono com httpx. Inclui side_effect para respostas customizadas com delay.
  12. livro Chaos Engineering — Casey Rosenthal et al. (O'Reilly, 2020). Capítulo 8 cobre tooling em detalhe — com análise de como cada ferramenta implementa os princípios e quando cada uma é mais adequada.