Chaos Engineering: como injetar falhas de propósito para provar a resiliência
Aprenda a disciplina de quebrar sistemas de propósito: steady state, hipótese, blast radius e experimentos para provar que sua infraestrutura aguenta.
Neste artigo
Você provavelmente já viveu isto: um sistema que passou em todos os testes, rodou meses sem incidente e, numa terça-feira qualquer às três da tarde, caiu por um motivo que ninguém previu. Um pod que travou e não foi reiniciado, uma dependência que ficou lenta em vez de cair, uma zona de disponibilidade que sumiu por trinta segundos. Sistemas distribuídos não falham de forma limpa e previsível — eles falham de formas emergentes, na interação entre componentes que, isolados, pareciam saudáveis.
A premissa do Chaos Engineering é desconfortável mas honesta: a única maneira de confiar que seu sistema sobrevive a uma falha é provocar essa falha de propósito, sob controle, e observar o que acontece. Em vez de esperar o incidente real acontecer no pior momento possível — no meio da noite, num pico de tráfego, sem ninguém de plantão preparado —, você agenda a falha para um horário conveniente, com toda a equipe olhando e com o botão de desligar na mão. Você troca a surpresa por um experimento.
Este guia é sobre transformar essa ideia numa disciplina. Não é sobre "quebrar coisas pra ver o que acontece" — isso é vandalismo, não engenharia. É sobre formular hipóteses testáveis, medir o comportamento do sistema com rigor, limitar o dano de cada experimento e automatizar tudo para rodar continuamente. Ao longo do texto você vai entender os princípios, os tipos de experimento, as ferramentas do mercado e, principalmente, os pré-requisitos que você precisa ter antes de tocar em qualquer coisa.
De onde veio a ideia#
A prática nasceu de uma necessidade concreta. Por volta de 2010, quando a Netflix migrava sua infraestrutura para a nuvem pública da AWS, a equipe percebeu que não bastava projetar para a falha — era preciso ter certeza de que os mecanismos de tolerância realmente funcionavam. Instâncias na nuvem morrem sem aviso; a promessa da arquitetura era que a queda de uma máquina não afetaria o usuário. Mas promessa não testada é só uma esperança.
A resposta foi o Chaos Monkey, uma ferramenta que, durante o horário comercial, escolhia instâncias de produção ao acaso e as desligava. A lógica era brilhante em sua simplicidade: se a queda de uma instância derruba o serviço, é melhor que isso aconteça às dez da manhã, com os engenheiros na mesa e cafeína no sangue, do que às três da madrugada. Ao forçar falhas constantes e pequenas, a Netflix obrigava suas equipes a construir sistemas genuinamente resilientes — e nunca mais confiar em suposições.
O Chaos Monkey virou parte de um conjunto maior, a Simian Army ("exército de macacos"), com ferramentas para simular diferentes desastres: o Latency Monkey injetava atrasos artificiais em chamadas de rede, o Chaos Gorilla derrubava uma zona de disponibilidade inteira, o Chaos Kong simulava a perda de uma região da AWS. Cada macaco atacava uma classe de falha. Dessa cultura surgiu a formalização da prática, com os Princípios do Chaos Engineering publicados por engenheiros da própria Netflix, e o campo cresceu para além de uma única empresa. Hoje é uma disciplina madura, com ferramentas open source, produtos comerciais e uma comunidade que fala em conferências e escreve livros sobre o assunto.
Os princípios: um experimento, não uma travessura#
A diferença entre Chaos Engineering e simplesmente "puxar cabos" está no método. Um experimento de caos bem-feito é um experimento científico de verdade, com todas as etapas que isso implica. Vamos por partes.
Defina o estado estável (steady state)#
Antes de quebrar qualquer coisa, você precisa saber como é o sistema saudável. O steady state é a descrição do comportamento normal do sistema em termos de métricas de negócio ou de output — não de métricas internas. A pergunta não é "a CPU está em 40%?", e sim "estamos processando o número esperado de pedidos por segundo?".
Boas métricas de steady state são observáveis de fora e ligadas ao valor entregue: taxa de requisições bem-sucedidas, latência no percentil 99, pedidos concluídos por minuto, mensagens processadas na fila. A escolha importa porque é ela que vai dizer se o experimento passou ou falhou. Se você define o steady state como "uso de CPU", pode acabar comemorando um sistema que está com CPU tranquila justamente porque parou de atender ninguém.
Formule uma hipótese#
Todo experimento começa com uma afirmação testável sobre o que você espera que aconteça. A forma canônica é: "quando eu introduzir a falha X, o steady state Y vai se manter dentro dos limites Z". Por exemplo: "quando eu matar uma réplica do serviço de checkout, a taxa de sucesso dos pedidos permanece acima de 99,5% e a latência p99 não passa de 800ms".
Note o que a hipótese faz: ela transforma uma expectativa vaga ("acho que aguenta") numa previsão específica que pode ser confirmada ou refutada. Se o resultado contradiz a hipótese, você encontrou uma fraqueza — e esse é o momento mais valioso de todo o processo. Rodar um experimento sem hipótese é a armadilha número um: você quebra algo, olha os gráficos, dá de ombros e não aprendeu nada, porque não tinha um critério prévio de sucesso.
Minimize o raio de explosão (blast radius)#
O blast radius é o conjunto de usuários, requisições ou componentes potencialmente afetados pelo experimento. O princípio central é: comece o menor possível e aumente gradualmente. Seu primeiro experimento com latência de rede não deve atingir 100% do tráfego de produção — deve atingir 1% dele, ou um único pod, ou o ambiente de staging.
À medida que você ganha confiança e o sistema prova que aguenta, você amplia o escopo: de um pod para um deployment, de 1% do tráfego para 5%, de staging para produção com uma fração dos usuários. Essa escalada controlada é o que separa o experimento responsável do incidente autoprovocado. Junto com ela vem o pré-requisito inegociável do kill switch: um mecanismo para abortar o experimento e restaurar o estado normal imediatamente, sem depender de nada que o próprio caos possa ter quebrado.
Rode em produção — com cuidado#
Este é o princípio mais provocador. A defesa é lógica: staging nunca reproduz produção com fidelidade. O tráfego real, os padrões de uso, o estado acumulado dos dados, as interações entre serviços em escala — nada disso existe no ambiente de teste. Um sistema pode ser perfeitamente resiliente em staging e desmoronar em produção porque as condições são diferentes.
Isso não significa que você deve sair injetando caos na produção no primeiro dia. Significa que produção é o objetivo, alcançado depois de você ter maturidade, observabilidade, blast radius controlado e kill switch confiável. Muitas equipes começam em staging ou em pré-produção justamente para calibrar o processo antes de encarar o ambiente real. A regra prática: você só experimenta em produção quando o custo esperado de aprender ali é menor que o custo de ser surpreendido por um incidente real.
Automatize e rode continuamente#
Um experimento feito uma vez prova como o sistema estava naquele dia. Sistemas mudam — deploys novos, dependências atualizadas, configurações alteradas — e a resiliência de ontem não garante a de amanhã. Por isso, o objetivo de longo prazo é automatizar os experimentos e integrá-los ao ciclo de vida do software, rodando de forma contínua, idealmente no pipeline. O caos deixa de ser um evento e vira uma verificação permanente, como um teste de regressão para a resiliência.
Os tipos de experimento#
Cada experimento ataca uma classe específica de falha. Conhecer o catálogo ajuda você a mapear o que vale a pena testar no seu contexto.
- Matar pods ou instâncias. O experimento fundador. Você termina abruptamente um processo, container ou máquina virtual e verifica se o orquestrador reagenda a carga, se as réplicas restantes absorvem o tráfego e se o usuário percebe algo.
- Latência de rede. Em vez de derrubar uma dependência, você a deixa lenta. Falhas lentas costumam ser mais perigosas que falhas rápidas, porque esgotam pools de conexão e threads em cascata enquanto todos esperam. Testa timeouts, circuit breakers e retries.
- Partição de rede (split-brain). Você corta a comunicação entre grupos de nós, simulando um cenário onde metade do cluster não enxerga a outra. Crítico para bancos distribuídos e sistemas de consenso, que precisam decidir corretamente quem continua servindo.
- Esgotar recursos. Consumir toda a CPU, memória ou disco de um nó revela o que acontece sob pressão: o pod é despejado? O serviço degrada com elegância ou trava? O disco cheio derruba o log e cega sua observabilidade justo quando você mais precisa dela?
- Falha de dependência. Você simula a indisponibilidade de um serviço do qual você depende — um banco, um cache, uma API de terceiro. Testa se há fallback, se o circuit breaker abre e se a falha fica contida em vez de se propagar por todo o sistema.
- Falha de zona ou região. O experimento de maior escala. Derrubar uma zona de disponibilidade inteira testa se sua arquitetura multi-zona realmente funciona; simular a perda de uma região testa seu plano de disaster recovery de verdade, não no papel.
Pré-requisitos: nunca quebre no escuro#
Aqui está a parte que separa quem faz Chaos Engineering de quem provoca incidentes. Antes de injetar qualquer falha, você precisa de duas coisas: observabilidade e capacidade de rollback.
Observabilidade é a condição para o experimento ter sentido. Se você não consegue medir o steady state em tempo real, não sabe dizer se a hipótese se sustentou. Você precisa de métricas (a taxa de sucesso, a latência p99), de logs correlacionados por trace_id e de rastreamento distribuído para enxergar como a falha se propaga entre serviços. Injetar caos sem observabilidade é apagar a luz e chutar as coisas para ver o barulho — você quebra, mas não aprende. Rodar sem baseline — sem ter medido o comportamento normal de antemão — é a segunda grande armadilha, porque sem o "antes" você não tem com o que comparar o "depois".
Rollback é a condição para o experimento ser seguro. Você precisa poder reverter a falha instantaneamente e restaurar o sistema. Isso engloba o kill switch do experimento, mas vai além: se um pod morto não é reagendado sozinho, você precisa reagendá-lo; se uma regra de latência ficou presa, você precisa removê-la. Rodar sem kill switch é a terceira armadilha clássica, e a mais perigosa, porque transforma um experimento em um incidente que você mesmo causou e não consegue parar.
Uma prática que institucionaliza esses cuidados é o game day: um exercício agendado em que a equipe se reúne, escolhe um cenário de falha, formula a hipótese em conjunto, executa o experimento de forma controlada e discute os resultados. O game day é o Chaos Engineering em sua forma mais deliberada e humana — todo mundo presente, ninguém surpreso, aprendizado compartilhado.
As ferramentas#
O ecossistema amadureceu e hoje há opções para diferentes contextos. Todas partem do mesmo princípio, mudam a interface e o alcance.
- Chaos Monkey. A ferramenta original da Netflix, focada em terminar instâncias de forma aleatória. Simples, opinativa e histórica; integra-se ao ecossistema de deploy da própria Netflix (o Spinnaker).
- Chaos Mesh. Plataforma open source nativa de Kubernetes, mantida como projeto da CNCF. Você declara os experimentos como recursos do próprio cluster (CRDs), o que os torna versionáveis e integráveis ao GitOps. Cobre falhas de pod, rede, stress de recursos, I/O e mais.
- LitmusChaos. Outra plataforma open source e projeto da CNCF, também centrada em Kubernetes, com um catálogo de experimentos prontos (o "ChaosHub") e um forte foco em rodar caos como parte do pipeline de CI/CD.
- Gremlin. Uma oferta comercial ("Failure as a Service") com interface gráfica, controles de blast radius e kill switch de primeira classe, além de suporte a ambientes além do Kubernetes. Troca o esforço de montar tudo você mesmo pela conveniência de um produto pronto.
Para dar concretude, veja como um experimento fica declarado no Chaos Mesh. Este mata um dos pods do serviço de checkout, atingindo apenas um pod de cada vez, e o experimento se encerra sozinho em trinta segundos — um blast radius deliberadamente pequeno:
```yaml apiVersion: chaos-mesh.org/v1alpha1 kind: PodChaos metadata: name: mata-um-pod-checkout namespace: chaos-testing spec: action: pod-kill # termina o pod abruptamente mode: one # atinge apenas UM pod (blast radius mínimo) selector: namespaces:
- producao
labelSelectors: app: checkout duration: "30s" # experimento se encerra sozinho ```
O experimento de latência é ainda mais revelador, porque falha lenta costuma machucar mais que falha seca. Este injeta 500ms de atraso em metade das chamadas ao banco de dados, por dois minutos — o suficiente para você observar se os timeouts e circuit breakers reagem:
```yaml apiVersion: chaos-mesh.org/v1alpha1 kind: NetworkChaos metadata: name: latencia-banco namespace: chaos-testing spec: action: delay mode: fixed-percent value: "50" # atinge 50% do tráfego selecionado selector: namespaces:
- producao
labelSelectors: app: checkout delay: latency: "500ms" # atraso injetado por chamada jitter: "100ms" direction: to target: mode: all selector: namespaces:
- producao
labelSelectors: app: postgres duration: "2m" ```
Antes de aplicar qualquer um desses manifestos, você abre seu painel de observabilidade e confirma o baseline. O ciclo de um game day em torno do primeiro experimento se parece com isto:
```bash # 1. Confirme o baseline ANTES de tocar em qualquer coisa. # Anote a taxa de sucesso e a latência p99 atuais. curl -s "http://prometheus:9090/api/v1/query" \ --data-urlencode 'query=sum(rate(http_requests_total{app="checkout",status=~"2.."}[1m]))'
# 2. Aplique o experimento (o menor possível primeiro). kubectl apply -f mata-um-pod-checkout.yaml
# 3. Observe o steady state DURANTE o experimento, ao vivo. watch -n 2 'kubectl get pods -n producao -l app=checkout'
# 4. KILL SWITCH — aborte e restaure a qualquer momento. kubectl delete podchaos mata-um-pod-checkout -n chaos-testing
# 5. Compare o "depois" com o baseline do passo 1 e valide a hipótese. ```
Seu primeiro experimento com segurança#
Se você chegou até aqui convencido, resista à vontade de começar grande. O primeiro experimento deve ser tão pequeno que quase pareça inútil — e essa modéstia é justamente o que torna a prática segura e sustentável. Aqui está um roteiro conservador para começar sem se machucar.
Primeiro, escolha o alvo mais bem-comportado que você tem. Um serviço com réplicas suficientes, health checks configurados e reagendamento automático. Você quer que o primeiro experimento tenda a passar, porque o objetivo inicial é validar o processo — a observabilidade, o kill switch, a comunicação da equipe — e não descobrir o pior bug do sistema logo de cara.
Segundo, rode primeiro em staging. Sim, staging não é produção, e você já sabe das limitações. Mas o primeiro game day serve para calibrar a mecânica: confirmar que seus dashboards mostram o steady state em tempo real, que o kill switch funciona, que todo mundo sabe seu papel. Só depois que essa coreografia estiver azeitada é que faz sentido levar o caos para produção com um blast radius mínimo.
Terceiro, escreva a hipótese antes e defina os limites de abortagem. Anote, em uma frase, o que você espera que aconteça e qual métrica, se ultrapassar qual limite, dispara o kill switch automaticamente ou manualmente. "Se a taxa de sucesso cair abaixo de 99%, aborto na hora." Ter esse gatilho definido de antemão remove a hesitação do calor do momento.
Quarto, rode, observe e documente. Execute o experimento no horário combinado, com a equipe presente, olhando os gráficos. Se a hipótese se confirmar, ótimo — você ganhou confiança justificada, não uma esperança. Se ela for refutada, melhor ainda: você encontrou uma fraqueza real num ambiente controlado, com todo mundo pronto para agir, em vez de descobri-la num incidente de madrugada. Registre o que aprendeu, corrija o que precisa ser corrigido e agende o próximo experimento, um pouco mais ambicioso.
O Chaos Engineering, no fim, é um ato de humildade técnica. É admitir que você não conhece todos os modos de falha do seu sistema e que a única forma honesta de descobri-los é provocá-los sob condições que você controla. A alternativa — esperar que o universo escolha a hora — nunca foi mais barata. Comece pequeno, meça tudo, mantenha o dedo no botão de desligar, e transforme a próxima falha de uma surpresa em três da manhã para um experimento das dez da manhã.