Como usar o chaos toolkit para automatizar experimentos de chaos engineering

1. Introdução ao Chaos Toolkit e seus fundamentos

O Chaos Toolkit é uma ferramenta open-source de código aberto que permite criar, executar e automatizar experimentos de Chaos Engineering de forma declarativa. Sua arquitetura é baseada em drivers extensíveis, o que significa que você pode conectar-se a diferentes plataformas de nuvem (AWS, Azure, GCP), orquestradores de containers (Kubernetes, Docker Swarm) e serviços de monitoramento (Prometheus, Datadog).

Os conceitos-chave que sustentam o Chaos Toolkit são:

  • Experimentos: arquivos JSON ou YAML que descrevem o que será testado, como será testado e o que deve ser verificado.
  • Hipóteses: suposições sobre o comportamento esperado do sistema durante o caos.
  • Steady-state: o estado normal do sistema antes da injeção de falhas.
  • Probes: verificações que medem o estado do sistema (saúde, latência, métricas).
  • Actions: ações que injetam falhas controladas no ambiente.

Diferentemente de ferramentas como Gremlin (plataforma SaaS) ou Litmus (focada exclusivamente em Kubernetes), o Chaos Toolkit é agnóstico de plataforma e pode ser integrado a múltiplos ambientes simultaneamente.

2. Instalação e configuração do ambiente

Para começar, você precisa de Python 3.8+, Docker e acesso a um cluster Kubernetes (local ou remoto). A instalação é simples:

pip install chaostoolkit
pip install chaostoolkit-kubernetes
pip install chaostoolkit-http

Crie uma estrutura de diretórios organizada:

chaos-experiments/
├── experiments/
│   └── kill-pod.json
├── probes/
│   └── custom_probe.py
├── secrets/
│   └── kube-config.yaml
└── .env

Configure as variáveis de ambiente essenciais:

export KUBECONFIG=./secrets/kube-config.yaml
export CHAOSTOOLKIT_LOG_LEVEL=debug

3. Estrutura de um experimento no Chaos Toolkit

Um experimento no Chaos Toolkit segue uma anatomia bem definida. Veja um exemplo completo em JSON:

{
  "version": "1.0.0",
  "title": "Kill pod and verify recovery",
  "description": "Mata um pod do serviço de pedidos e verifica se o Kubernetes recupera automaticamente",
  "tags": ["kubernetes", "resilience", "pod-failure"],
  "steady-state-hypothesis": {
    "title": "Serviço de pedidos está saudável",
    "probes": [
      {
        "type": "probe",
        "name": "health-check",
        "tolerance": 200,
        "provider": {
          "type": "http",
          "url": "http://service-orders:8080/health"
        }
      }
    ]
  },
  "method": [
    {
      "type": "action",
      "name": "kill-pod",
      "provider": {
        "type": "python",
        "module": "chaosk8s.pod.actions",
        "func": "delete_pod",
        "arguments": {
          "name_pattern": "orders-service-*",
          "namespace": "production"
        }
      },
      "pauses": {
        "after": 5
      }
    }
  ],
  "rollbacks": [
    {
      "type": "action",
      "name": "ensure-minimum-pods",
      "provider": {
        "type": "python",
        "module": "chaosk8s.pod.actions",
        "func": "scale_deployment",
        "arguments": {
          "name": "orders-service",
          "namespace": "production",
          "replicas": 3
        }
      }
    }
  ]
}

4. Automação de experimentos com pipelines CI/CD

Integrar o Chaos Toolkit com pipelines de CI/CD permite executar experimentos automaticamente após deploys ou em horários programados. Exemplo com GitHub Actions:

name: Chaos Engineering Pipeline

on:
  schedule:
    - cron: '0 2 * * 1-5'  # Executa segunda a sexta às 2h
  workflow_dispatch:  # Permite execução manual

jobs:
  chaos-experiment:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Setup Python
        uses: actions/setup-python@v4
        with:
          python-version: '3.10'

      - name: Install Chaos Toolkit
        run: |
          pip install chaostoolkit chaostoolkit-kubernetes chaostoolkit-http

      - name: Configure K8s context
        run: |
          echo "${{ secrets.KUBE_CONFIG }}" > kubeconfig.yaml
          export KUBECONFIG=kubeconfig.yaml

      - name: Run experiment
        id: chaos
        continue-on-error: true
        run: |
          chaos run experiments/kill-pod.json --rollback-strategy=always

      - name: Notify Slack on failure
        if: steps.chaos.outcome == 'failure'
        uses: slackapi/slack-github-action@v1.24.0
        with:
          payload: |
            {
              "text": "Experimento de Chaos falhou! Verifique os logs."
            }
        env:
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}

5. Estratégias de steady-state e hipóteses avançadas

Modelar hipóteses robustas é essencial para experimentos significativos. Exemplo de hipótese avançada:

"steady-state-hypothesis": {
  "title": "Latência da API não ultrapassa 500ms",
  "probes": [
    {
      "type": "probe",
      "name": "latency-check",
      "tolerance": {
        "type": "lt",
        "value": 500
      },
      "provider": {
        "type": "http",
        "url": "http://api-gateway:8080/orders",
        "timeout": 10,
        "headers": {
          "Accept": "application/json"
        }
      }
    },
    {
      "type": "probe",
      "name": "database-connection",
      "tolerance": true,
      "provider": {
        "type": "python",
        "module": "probes.custom_probe",
        "func": "check_database_pool",
        "arguments": {
          "max_connections": 50
        }
      }
    }
  ]
}

6. Gerenciamento de experimentos em escala e boas práticas

Para gerenciar experimentos em escala, versionamento e reuso são fundamentais:

chaos-experiments/
├── templates/
│   ├── base-experiment.json
│   └── probes-common.json
├── experiments/
│   ├── kill-pod-db.json
│   ├── network-latency.json
│   └── cpu-stress.json
├── .gitignore
└── README.md

Boas práticas incluem:
- Executar experimentos paralelamente em namespaces diferentes
- Definir timeouts máximos (ex: 300 segundos)
- Usar tags para filtrar experimentos por criticidade
- Registrar resultados em formato JSON para análise histórica

7. Estudo de caso prático: experimento de falha em pod Kubernetes

Vamos criar um experimento completo que mata um pod e verifica a recuperação automática:

{
  "version": "1.0.0",
  "title": "Pod failure recovery test",
  "description": "Mata um pod do serviço de pagamentos e valida recuperação em 30 segundos",
  "tags": ["kubernetes", "payment-service", "recovery"],
  "steady-state-hypothesis": {
    "title": "Serviço de pagamentos está operacional",
    "probes": [
      {
        "name": "health-probe",
        "type": "probe",
        "tolerance": 200,
        "provider": {
          "type": "http",
          "url": "http://payment-service:8080/health",
          "timeout": 5
        }
      },
      {
        "name": "latency-probe",
        "type": "probe",
        "tolerance": {
          "type": "lt",
          "value": 300
        },
        "provider": {
          "type": "http",
          "url": "http://payment-service:8080/api/health/latency",
          "timeout": 5
        }
      }
    ]
  },
  "method": [
    {
      "type": "action",
      "name": "delete-payment-pod",
      "provider": {
        "type": "python",
        "module": "chaosk8s.pod.actions",
        "func": "delete_pod",
        "arguments": {
          "name_pattern": "payment-service-*",
          "namespace": "production",
          "labels": {
            "app": "payment-service"
          }
        }
      },
      "pauses": {
        "after": 10
      }
    },
    {
      "type": "probe",
      "name": "recovery-check",
      "tolerance": 200,
      "provider": {
        "type": "http",
        "url": "http://payment-service:8080/health",
        "timeout": 30
      }
    }
  ],
  "rollbacks": {
    "auto": true,
    "retry": 3,
    "pauses": {
      "between_retries": 5
    }
  }
}

Execute o experimento:

chaos run experiments/pod-failure.json --rollback-strategy=always

8. Monitoramento pós-experimento e lições aprendidas

Após cada experimento, colete métricas e logs para análise:

chaos run experiments/pod-failure.json --export-format=json > results/experiment-2024-01-15.json

Utilize ferramentas como Prometheus para monitorar:

{
  "steady-state-hypothesis": {
    "probes": [
      {
        "name": "prometheus-metrics",
        "type": "probe",
        "provider": {
          "type": "http",
          "url": "http://prometheus:9090/api/v1/query?query=rate(http_requests_total[5m])",
          "headers": {
            "Content-Type": "application/json"
          }
        }
      }
    ]
  }
}

Documente as lições aprendidas em um formato padronizado:

EXPERIMENTO: Pod Failure Recovery
DATA: 2024-01-15
RESULTADO: Sucesso (recuperação em 12s)
IMPACTO: Latência máxima de 450ms durante falha
AÇÕES: Aumentar réplicas mínimas de 2 para 3

A análise histórica dos experimentos permite identificar padrões de falha e melhorar continuamente a resiliência do sistema. O Chaos Toolkit fornece uma base sólida para automatizar esse processo, garantindo que sua equipe possa experimentar com segurança e aprender com cada falha controlada.

Referências