关于 chaos-engineering
面向负责系统可靠性的工程团队,提供以假设为驱动的混沌工程实验流程,帮助在受控范围内发现韧性缺口。内容涵盖故障注入、实时观测、恢复分析和团队演练,并介绍多种工具。
主要功能
- 01制定稳态假设与指标
- 02受控注入网络及服务故障
- 03实时观察系统表现
- 04检查恢复过程与数据完整性
- 05规划团队故障演练
适用场景
- 01验证数据库故障切换行为
- 02测试第三方依赖不可用时的降级
- 03评估网络延迟或丢包影响
- 04通过演练练习事故响应
MCP 相关
README 提及 LitmusChaos 提供 MCP 服务,可连接 AI 助手与 ChaosCenter。MCP 客户端可用自然语言列出、运行和停止实验。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ petrkindlmann/ qa-skills --skill chaos-engineering安装后在 Claude Code 中输入/chaos-engineering确认已加载。
附带文件references/fault-injection.md
详细介绍
快速导航
| 情况 | 前往 |
|---|---|
| 首次进行实验,团队经验不足 | 从小处着手 → 前三个实验 |
| 设计一项实验 | 混沌实验工作流(5 个步骤) |
| 为你的环境选择工具 | 工具 → 工具选择决策树 |
| 组织团队演练 | 混沌演练规划 |
| 需要可运行的故障注入命令/配置 | references/fault-injection.md |
| 希望无需人工介入即可触发中止 | references/fault-injection.md → 自动中止 |
调研问题
先检查 .agents/qa-project-context.md。如果文件存在,请将其作为上下文,并跳过其中已有答案的问题。
环境与准备情况:
- 混沌实验将在何处运行?(仅限预生产环境、经批准后在生产环境运行、绝不在生产环境运行)
- 团队的监控成熟度如何?能否实时检测问题?
- 团队是否演练过事故响应?是否有运行手册?
- 管理层是否支持混沌工程?(对于生产环境实验尤为重要)
架构:
- 架构是什么?(单体、微服务、无服务器、混合)
- 关键依赖有哪些?(数据库、缓存、消息队列、第三方 API)
- 是否存在单点故障?(单一数据库、单一区域、没有冗余)
- 有哪些冗余和故障转移机制?
当前的韧性实践:
- 服务是否配置了健康检查?检查哪些内容?
- 是否配置了熔断器、重试逻辑或超时?
- 依赖不可用时会发生什么?(优雅降级、硬故障、未知)
- 是否遇到过意外中断?哪些环节发生了故障?
团队与文化:
- 团队是否能坦然面对受控故障?(感到焦虑很正常,应该予以应对)
- 谁可以担任混沌工程的负责人?(需要有人负责推动这项实践)
- 团队倾向于如何起步?(从小处着手还是直接深入)
核心原则
1. 由假设驱动:注入故障前先定义预期行为
每项混沌实验都从一个假设开始:“我们认为,如果发生[故障 X],系统将表现为[预期行为 Y]。”没有假设,你只是在破坏东西。假设要明确具体的稳态指标(基准指标)——错误率、延迟、吞吐量——以及每项指标可变化到的界限。
假设示例:“我们认为,如果主数据库不可用,应用将为读取请求提供缓存数据,并将写入请求排队最多 5 分钟,且用户不会看到错误。影响范围:预发布环境、一个服务。稳态基准:错误率 <0.1%,P95 延迟 <300ms。”
2. 从小处着手:单个服务,控制影响范围
第一次混沌实验不应该是“关闭生产环境”。更合适的做法是“在预发布环境中,为一个非关键服务增加 200ms 延迟”。随着信心和工具逐步成熟,再逐渐扩大范围。
3. 监控是前提条件
如果无法实时检测问题,就无法安全地注入故障。没有监控的混沌实验只是多了几道步骤的服务中断。运行任何实验前,请先确认仪表板、告警和 on-call 流程均已就绪。
4. 混沌演练能够培养肌肉记忆
在自动化流水线中运行混沌实验很有价值,但混沌演练——团队定期一起运行实验并练习响应的活动——能够培养在真实事故中至关重要的应对能力。
混沌实验工作流
每项混沌实验都遵循以下五步流程。
步骤 1:定义稳态假设
确定定义“正常”的指标,并预测实验期间应该发生什么。
Experiment: Database failover
Steady state:
- Error rate: < 0.1%
- P95 latency: < 300ms
- Successful orders per minute: > 50
Hypothesis: When the primary database fails over to the replica,
- Error rate will spike to < 2% for < 30 seconds
- P95 latency will increase to < 1s for < 60 seconds
- No orders will be permanently lost
- The application will recover without manual intervention
步骤 2:引入变量
以可控方式注入故障,并明确范围和持续时间。
Injection:
Target: primary database (PostgreSQL)
Method: block TCP port 5432 on the primary instance
Scope: single database instance
Duration: 60 seconds
Blast radius: staging environment only (first run)
Abort conditions:
- Error rate > 10% for > 2 minutes
- Any data corruption detected
- Manual abort by experiment owner
步骤 3:观察
实验期间,实时监控所有相关指标。安排观察人员负责特定仪表盘。
Observation assignments:
- Engineer A: application error rate and latency dashboard
- Engineer B: database metrics (connections, replication lag, failover status)
- Engineer C: application logs (search for database connection errors)
- Engineer D: business metrics (order count, payment processing)
步骤 4:分析恢复情况和数据完整性
实验结束后,分析实际情况与预期情况之间的差异。
Analysis checklist:
- Did the system behave as hypothesized? (Y/N, with details)
- How long was the impact? (Expected vs. actual duration)
- Were any errors visible to users?
- Was any data lost or corrupted?
- Did monitoring and alerting detect the problem correctly?
- How long before alerts fired?
- What was the recovery time?
步骤 5:修复并迭代
记录发现的问题,修复弹性方面的不足,并安排重新运行以验证修复效果。
Findings document:
Experiment: Database failover (2026-03-20)
Hypothesis: Confirmed / Partially confirmed / Disproved
Recovery time: 45s (expected vs actual: expected <10s, actual 45s)
Data integrity: no rows lost; 3 writes returned 500 instead of queueing
Findings:
- Connection pool did not detect stale connections for 45 seconds (expected: <10s)
- Retry logic worked correctly for read operations
- Write operations returned 500 errors for 38 seconds (expected: queued)
Action items (every one has an owner and a due date — no item is deferred):
- [ ] Configure connection pool health checks — assigned to @maria, due 2026-03-31
- [ ] Implement write queue with 5-minute buffer — assigned to @dan, due 2026-04-02
- [ ] Re-run experiment after fixes deployed (re-run scheduled 2026-04-03);
specific metrics to check on re-run: stale-connection detection <10s,
zero write 500s, error rate <2%
故障注入类型
网络故障
| 故障 | 工具 | 用例 |
|---|---|---|
| 注入延迟 | tc, toxiproxy, Gremlin | 模拟网络缓慢、远距离区域 |
| 丢包 | tc netem, Chaos Mesh | 模拟不可靠网络 |
| DNS 故障 | iptables, CoreDNS manipulation | 模拟 DNS 中断 |
| 网络分区 | iptables, Chaos Mesh | 模拟脑裂场景 |
| 带宽限制 | tc, toxiproxy | 模拟网络拥塞 |
有关 tc netem 延迟/丢包命令和 toxiproxy 延迟配置,请参阅 references/fault-injection.md。
服务故障
| 故障 | 方法 | 用例 |
|---|---|---|
| 服务崩溃 | 终止进程、删除 pod | 模拟意外崩溃 |
| 服务变慢 | CPU 压力测试、线程池耗尽 | 模拟服务过载 |
| 注入错误 | 返回 500/503、抛出异常 | 模拟应用程序错误 |
| 内存压力 | stress-ng, Chaos Mesh | 模拟内存泄漏 |
有关 kubectl delete pod 命令和 LitmusChaos pod-delete ChaosEngine 清单,请参阅 references/fault-injection.md。
基础设施故障
| 故障 | 方法 | 用例 |
|---|---|---|
| 磁盘已满 | fallocate, dd | 模拟磁盘耗尽 |
| CPU 耗尽 | stress-ng | 模拟 CPU 饱和 |
| 内存耗尽 | stress-ng | 模拟 OOM 情况 |
| 时钟偏移 | chrony manipulation, timedatectl | 模拟时间漂移 |
有关 fallocate 磁盘填充命令和 stress-ng CPU/内存命令,请参阅 references/fault-injection.md。
依赖项故障
| 故障 | 方法 | 用例 |
|---|---|---|
| API 宕机 | toxiproxy, mock server | 模拟第三方服务中断 |
| 数据库不可用 | 封锁端口、终止进程 | 模拟数据库中断 |
| 缓存不可用 | 封锁 Redis 端口 | 模拟缓存未命中风暴 |
| 消息队列已满 | 填满队列、阻止消费者 | 模拟背压 |
有关以编程方式集成 toxiproxy、禁用 Redis 并断言系统可优雅降级的测试,请参阅 references/fault-injection.md。
工具
| 工具 | 类型 | 最适合 |
|---|---|---|
| LitmusChaos (3.29.x) | Kubernetes 原生,CNCF | K8s 环境、CI/CD 集成;ChaosCenter UI;用于 GameDay 即代码的工作流;MCP 服务(2025 年 10 月)可通过 AI 助手驱动实验 |
| Chaos Mesh (2.8.x) | Kubernetes 原生,CNCF | 需要精细控制的 K8s 环境;通过 bpfki 运行时实现 eBPF 混沌注入,精确模拟内核级故障 |
| AWS FIS | AWS 托管服务 | 针对 AWS 工作负载(EC2、ECS、RDS、EKS)的云混沌工程;通过 CloudWatch 警报停止条件自动中止——首选云原生方案 |
| Gremlin | 托管平台 | 希望获得引导式实验和合规报告的团队;SLO 违反时,Health Checks 会停止并回滚 |
| Steadybit | 托管平台 | 覆盖 Kubernetes、云和本地环境的可靠性中心;Gremlin 的直接替代方案 |
| kube-monkey | 开源 | 当 Litmus/Chaos Mesh 显得过于繁重时,可选用轻量级 K8s 替代方案 |
| Pumba | 开源 | 仅针对 Docker 的混沌工程(容器、网络);适用于 K8s 之前的环境和边缘环境 |
| toxiproxy | 网络代理,开源 | 在集成测试中注入网络故障 |
| tc (traffic control) | Linux 内核 | 网络延迟和丢包 |
| stress-ng | Linux 工具 | CPU、内存和磁盘压力测试 |
| k6 (+ xk6-disruptor) | 负载测试工具 | 结合负载与混沌的场景 |
避免在新项目中使用 Chaos Monkey (Netflix)——活跃度低,且只能走 Spinnaker 方案(截至 2026 年年中)。 它仍然可用,仓库也未归档,但只能注入实例终止故障,并且需要 Spinnaker 部署流水线。全新项目应选择 Chaos Mesh、LitmusChaos 或 AWS FIS。(较早的 SimianArmy 仓库已于 2021 年归档;请勿将两者混淆。)
选择工具
Decision tree:
Running on Kubernetes?
→ Cloud-managed AWS workloads: AWS FIS (cloud-native, IAM-integrated)
→ On K8s with sidecar tolerance: Chaos Mesh (eBPF, fine-grained)
→ On K8s wanting workflows + UI: LitmusChaos (ChaosCenter, Workflows)
→ On K8s lightweight: kube-monkey
Running on plain VMs / Docker?
→ Docker only: Pumba
→ Linux: tc + stress-ng (manual)
Need network fault injection in integration tests?
→ toxiproxy (lightweight, programmatic API)
Need to combine load testing with chaos?
→ k6 with xk6-disruptor extension
Need managed platform with UI and compliance?
→ Gremlin or Steadybit (both commercial)
GameDay 即代码
2026 年的趋势是将混沌工程作为定期调度的 CI 作业,而非临时活动:Litmus Workflows、Steadybit 可靠性中心和 Gremlin Scenarios 都支持将混沌测试定义为 YAML,并通过 CI 中的 cron 定时触发。请结合下方的 Game Day 规划部分——人为实践仍然重要;自动化只是消除了“我们一直没时间安排”的瓶颈。有关具体的 cron 门控流水线(在非高峰时段每晚删除 Pod),以及自动中止/停止条件示例,请参阅 references/fault-injection.md。
LitmusChaos 于 2025 年 10 月推出了 MCP 服务,可将 Claude 等 AI 助手直接连接到 ChaosCenter:你可以用自然语言列出、运行和停止实验(“在前端 Pod 上运行 pod-delete”、“停止网络延迟实验”),无需手写 YAML。如果你的团队已经通过 AI Agent 驱动运维,这项功能就很适用。
Game Day 规划
Game Day 是一场定期安排的会议,团队会共同运行混沌实验、练习事件响应,并增强对系统韧性的信心。
准备清单
2 weeks before:
- [ ] Define 2-3 experiments to run (don't overload the schedule)
- [ ] Write hypotheses for each experiment
- [ ] Get approval from engineering leadership and affected teams
- [ ] Notify support team and stakeholders
- [ ] Verify monitoring and alerting are working
- [ ] Identify rollback procedures for each experiment
- [ ] Schedule 3-4 hour block (experiments + analysis + retro)
1 day before:
- [ ] Confirm all participants and their roles
- [ ] Test that fault injection tools work in the target environment
- [ ] Verify rollback procedures work (dry run)
- [ ] Prepare dashboards and observation assignments
- [ ] Brief the on-call team
- [ ] Confirm abort criteria for each experiment
沟通与角色
在活动前(安排时间、范围、中止权限)、活动期间(在专用频道中每 15 分钟发布实时更新)和活动后(在 24 小时内总结发现和待办事项)进行沟通。
为每项实验分配角色:实验负责人(运行实验并决定是否中止)、观察员(关注应用指标、基础设施指标、日志和用户体验)以及记录员(记录时间线和决策)。
活动后回顾
针对每项实验:假设是否得到验证?有哪些意外发现?有哪些待办事项?针对流程:监控是否检测到问题?警报是否触发?我们是否能接受影响范围?最后列出待办事项(注明负责人和截止日期),并安排下一次 Game Day。
从小处着手:前三项实验
对于刚接触混沌工程的团队,请先在预生产环境中开展以下三项实验。
实验 1:数据库变慢
为何首先开展: 数据库延迟是导致用户感知变慢的最常见原因,而且这项实验易于设置和还原。
Hypothesis: When database latency increases by 500ms, the application
will remain functional with response times under 3 seconds.
Injection: Add 500ms latency to the database connection using toxiproxy.
Duration: 5 minutes.
Environment: staging.
What to observe:
- Application response times (should increase by ~500ms, not 10x)
- Connection pool behavior (should not exhaust connections)
- Timeout handling (requests should not hang indefinitely)
- Circuit breaker activation (if implemented)
- Cache effectiveness (cached reads should be unaffected)
实验 2:第三方 API 返回 500 错误
**为何排第二:**第三方依赖经常发生故障,而应用对这些故障的处理通常未经测试。
Hypothesis: When the payment provider returns 500 errors, the
application will show a user-friendly error message and allow
retry without duplicate charges.
Injection: Configure mock/proxy to return 500 for payment API calls.
Duration: 10 minutes.
Environment: staging.
What to observe:
- Error message quality (user-friendly, not stack traces)
- Retry behavior (does the application retry? How many times?)
- Idempotency (retries don't create duplicate transactions)
- Fallback (is there an alternative payment path?)
- Monitoring (does the payment failure show up in alerts?)
实验 3:缓存不可用
**为何排第三:**缓存故障会引发“惊群”问题,导致所有流量突然涌向数据库,往往进而造成级联故障。
Hypothesis: When Redis becomes unavailable, the application will fall
back to direct database queries with degraded but functional performance.
Injection: Block Redis port using toxiproxy or iptables.
Duration: 5 minutes.
Environment: staging.
What to observe:
- Database query volume (should increase but not overwhelm)
- Response times (should increase but remain under 5 seconds)
- Error rate (cache miss should not cause errors)
- Connection pool (database connections should not exhaust)
- Recovery (when cache returns, does the application resume normal behavior?)
反模式
混沌实验缺少监控
在无法观察故障影响的情况下注入故障,不是混沌工程——而是蓄意破坏。直到用户投诉,你才会知道实验是否暴露了问题。
**解决方法:**进行任何混沌实验之前,请确认你可以实时查看错误率、延迟、吞吐量和依赖项健康状况。如果做不到,请先投入资源完善监控。还可以更进一步,将监控接入实验,使其在超出阈值时自动中止——例如 AWS FIS CloudWatch 停止条件、Gremlin Health Checks,或在 mode: Continuous 下使用 Litmus 的 promProbe(参见 references/fault-injection.md)。
一开始就做得太大
第一次混沌实验不应该是“干掉生产数据库”。团队还没有通过低影响实验积累经验,就开始高影响实验,会让大家焦虑,也可能导致真实故障。
**解决方法:**从预发环境开始。从非关键服务开始。从可逆的故障注入开始(例如延迟,而不是数据损坏)。逐步建立信心。只有多次成功完成预发环境实验后,才进入生产环境。
没有回滚计划
“实验只有 60 秒,不需要回滚计划。”然后故障注入工具崩溃,故障就会无限期持续(这正是 5 分钟的 tc 延迟注入在命令中途失败后变成 2 小时中断的原因)。
**解决方法:**每项实验都必须有书面回滚流程,并且能在 30 秒内执行。运行实验前先测试回滚,并安排第二个人待命;如果实验负责人无法操作,由其立即中止实验。优先选择由工具强制执行停止条件的方案,而不是依赖人工按下停止开关(参见 references/fault-injection.md 中的“自动中止”)——并选择内置超时的注入方式(如 stress-ng --timeout、Litmus TOTAL_CHAOS_DURATION),确保即使无人监看,故障也会自行清除。
未经批准就在生产环境进行混沌实验
未经工程领导层和受影响团队明确批准,就在生产环境运行混沌实验,会损害信任,也会断送职业生涯。
**解决方法:**每次在生产环境运行之前:取得工程领导层明确且有记录的批准;通知受影响的团队,并向值班团队和支持团队做简要说明;沟通范围和持续时间,并将中止标准告知明确指定的中止负责人;确认爆炸半径已限制在可行的最小目标范围内。先从预发环境开始。任何一项准备工作被跳过,都可能让受控实验演变成事故。
在事故期间运行混沌实验
系统已经出现问题时再人为注入故障,会增加诊断难度并延长中断时间。
**解决方法:**如果系统未处于稳定状态,请取消或推迟混沌实验。开始之前检查是否有正在处理的事故。如果实验期间发生无关事故,请立即中止实验。
未跟进实验发现
实验发现断路器工作不正常。团队说了句“有意思”,就继续做别的事。这个问题始终没有修复。下次真实故障发生时,同样的问题再次出现。
**解决方法:**为每项混沌实验发现的问题创建工单,并指定负责人和截止日期。修复后重新运行实验以验证结果。将混沌实验发现的问题积压与生产事故行动项一并跟踪。
验证
在信任任何一次真实实验之前,先证明安全机制确实有效——从未触发过的中止路径只是一个假设,不是控制措施。先做最小规模的检查:
- 在预发布环境中注入并恢复。 执行影响范围最小的注入(例如
tc qdisc add dev eth0 root netem delay 200ms),作用于一个预发布服务;确认稳态仪表板上的数据发生变化,然后运行文档中说明的回滚命令(tc qdisc del dev eth0 root),并确认指标恢复到基线。记录回滚耗时——必须在规定的时间窗口内完成(少于 30s)。 - 触发自动中止。 在配置了 AWS FIS CloudWatch 停止条件、Gremlin Health Check 或处于
mode: Continuous模式的 LitmuspromProbe的实验中,强制让受监控指标超过阈值(将错误率推高到停止条件之上)。确认实验在无需人工干预的情况下自动停止。如果未触发,则中止机制尚未经过验证(参见references/fault-injection.md)。 - 确认超时后自动清除。 启动有时限的注入(
stress-ng --cpu 4 --timeout 60s,或 LitmusTOTAL_CHAOS_DURATION: '60'),然后离开现场。确认即使无人中止,故障也会在截止时间自行清除。 - 确认问题发现闭环。 在预发布环境中运行后,确认已生成问题发现文档,其中包含基线与实际数据的对比,并且每个差距都已转化为分配了负责人的跟踪工单——实验记录才是交付物,而不是注入操作。
如果无法在预发布环境中演示步骤 1–3,则不得将该实验提升至生产环境。
完成标准
- 每项实验在注入任何故障前,都有记录在案的书面假设(“我们认为,如果发生 [故障 X],系统将 [预期行为 Y]”)
- 明确限定影响范围——目标范围、持续时间和中止条件都记录在实验记录中;任何实验在生产环境运行前,同一实验必须至少在预发布环境成功运行一次
- 每项实验记录都附有稳态快照(仪表板链接或实际基线指标值),并且是在注入前立即采集的
- 每项实验都有一份问题发现文档,包含基线与实际数据的对比、恢复时间,以及明确的数据完整性检查(是否丢失/损坏:是/否)
- 发现的每个弱点都有一个跟踪工单,其中指定了负责人和截止日期,并安排重新运行同一实验以验证修复效果
参考文件(位于 references/ 中)
- fault-injection.md — 用于注入各类故障的可运行命令、配置和测试代码:
tc netem和 toxiproxy 网络故障、kubectl/LitmusChaos 服务故障(带有engineState: active的 ChaosEngine)、fallocate/stress-ng基础设施故障、程序化的 toxiproxy 依赖故障测试,以及自动中止/停止条件示例(AWS FIS、Gremlin、Litmus 探针、Litmus MCP)和由 cron 控制的持续混沌 CI 任务。
相关技能
- testing-in-production — 适用于发布期间的安全渐进发布机制(功能标志、金丝雀发布、暗发布)。混沌工程会有意制造故障以发现弱点;生产环境测试则控制暴露范围,确保故障不会扩散。渐进发布请参阅该技能,故障注入请参阅本技能。
- observability-driven-testing — 当生产遥测数据(跟踪、日志、错误模式)是设计测试或实验的输入时使用。它为假设提供依据;混沌工程则负责验证或证伪该假设。可观测性也是安全开展混沌实验的硬性前提。
- performance-testing — 负载测试可与混沌测试互补;结合负载与故障,模拟真实的故障场景(参见 k6 + xk6-disruptor)。
- release-readiness — 混沌实验结果可用于评估发布是否就绪并决定是否放行。
- test-environments — 预生产环境是开展混沌实验的安全起点。
- qa-metrics — 混沌实验结果(恢复时间、错误影响)是值得跟踪的质量指标。