核心思想
主动在生产环境中注入故障,验证系统的韧性(resilience)。
为什么主动搞破坏:因为分布式系统的故障模式难以预测——你无法仅通过代码审查和测试,确信系统在某个组件失效时仍能正常工作。
混沌工程的信条:与其等待故障发生,不如主动制造它们(在可控范围内),从而:
- 发现系统的弱点;
- 验证监控和告警是否有效;
- 验证自动恢复机制是否工作;
- 让团队熟悉应急流程。
起源
Netflix 是这一领域的先驱。
2011 年前后,Netflix 在向 AWS 云迁移的过程中,面临"云实例可能随时失效"的现实——因此设计了 Chaos Monkey:在生产环境中随机关闭服务实例,强迫工程师构建能容忍实例失效的系统。
后来发展成 Simian Army(猿猴军团),包括更丰富的故障注入工具。
与其它实践的区别
| 目标 | 方式 | |
|---|---|---|
| 测试 | 验证"功能是否符合预期" | 已知输入 → 验证输出 |
| 混沌工程 | 验证"系统在异常条件下的行为" | 注入故障 → 观察系统表现 |
混沌工程是"实验",不是"测试"——你有一个假设("如果缓存挂了,系统会降级到数据库,响应时间增加但不会宕机"),然后通过实验验证或推翻这个假设。
实验流程
一、定义稳态(Steady State)
确定系统的正常行为指标(如 QPS、P99 延迟、错误率)。
二、提出假设
"如果 X 发生故障,系统指标 Y 会 Z。"
三、设计实验
- 选择注入的故障类型;
- 确定爆炸半径(影响范围)——从最小开始;
- 确定中止条件(什么情况下立即停止实验)。
四、在小范围执行
先在一个服务、一个可用区、少量流量上做。
五、验证假设
对比实验期间与稳态的指标。
六、修复问题并再次验证
七、逐步扩大范围
常见的故障注入类型
基础设施层:
- 随机关闭虚拟机/容器;
- 关闭整个可用区(模拟 AZ 故障);
- 磁盘填满;
- 网络延迟、丢包、分区(Network Partition);
- CPU / 内存压力。
应用层:
- 杀死进程;
- 使某个服务的响应变慢或返回错误;
- 依赖服务不可用(如数据库、缓存、第三方 API);
- 使时钟偏移。
Kubernetes 环境:
kubectl delete pod的自动化版本;- 注入到特定 Pod 的网络故障;
- 节点不可用。
工具
- Chaos Mesh(CNCF 项目,K8s 原生);
- LitmusChaos(CNCF 项目);
- Gremlin(商业);
- Chaos Monkey / Simian Army(Netflix 开源);
- toxiproxy:用于模拟网络故障(Shopify 开源);
- 云厂商提供的故障注入服务(如 AWS FIS)。
关键原则
一、从生产环境开始(但要小心)
混沌工程的倡导者认为:只有在生产环境才有意义——因为预发环境的流量模式、数据、依赖关系与生产不同。
但这需要前提:
- 系统已具备一定的韧性(否则一注就全挂);
- 有完善的监控和中止机制;
- 团队有能力快速响应。
务实的做法:先在非生产环境验证实验脚本,再谨慎地进入生产,从最小爆炸半径开始。
二、最小化爆炸半径
第一次实验应该只影响:一个实例、一小部分用户、一个非关键功能。
三、始终有中止机制
- 明确的指标阈值(如错误率超过 X% 立即停止);
- 一个"大红按钮"(能立即停止实验并恢复)。
四、要有可观测性作为前提
没有监控,就不要做混沌工程——因为你无法判断实验的结果。
监控不到位时,混沌实验的结果是"什么都没观察到",而这毫无价值。
五、自动化与常态化
理想状态是持续运行混沌实验(如每隔一段时间自动注入故障),而不是一次性活动。
原因:系统在不断变化,上一次验证过的韧性,下次部署后可能就失效了。
一个常见误解
"混沌工程就是随机搞破坏。"
不是。 它是有假设、有控制、有度量的科学实验。
随机破坏只会带来混乱,不会带来认知。
一句话
混沌工程的价值,在于把"我们以为系统会怎样"变成"我们验证过系统会怎样"。
说明:本文为可靠性工程的知识整理。