混沌工程 / 演练的价值与成本

一句话速记

混沌工程(Chaos Engineering)是主动在生产(或预生产)环境注入故障,验证系统是否如预期降级/恢复,而不是等真实故障发生时才发现缺陷。核心思想:「黑天鹅事件不可避免,与其被动等待,不如主动演练,找出弱点并修复」。Netflix 的 Chaos Monkey 是最著名的实践——随机终止生产实例,倒逼工程师确保系统在实例失败时仍可用。

关键细节

1)为什么需要混沌工程

传统做法的问题:
  单元测试 → 只测代码逻辑,不测系统行为
  集成测试 → 模拟故障,但环境与生产不同
  压测 → 测性能,不测故障恢复
  
  结果:生产环境出现一个真实故障(机器宕机、网络抖动、依赖超时)
        → 系统崩溃 → 紧急抢修 → 深夜 Oncall
        
混沌工程的目的:
  主动制造故障(受控) → 观察系统行为 → 发现弱点 → 修复
  使系统对真实故障有"免疫力"(Resilience)
  
价值:"如果我们不主动找到这些弱点,真实的故障会替我们找到"

2)混沌实验的四步法

Step 1:定义"稳定状态"(Steady State)
  什么是正常?如:
  - 下单成功率 > 99.9%
  - p99 响应时间 < 500ms
  - 错误率 < 0.1%

Step 2:假设注入故障后稳定状态不变
  假设:"即使随机终止一个支付服务实例,下单成功率仍 > 99.9%"

Step 3:注入故障(受控)
  - 终止一个支付服务实例(Chaos Monkey)
  - 引入网络延迟(100ms 随机延迟)
  - 模拟 Redis 连接超时
  - 注入 CPU 满载(stress-ng)

Step 4:验证假设
  观察监控:稳定状态指标是否维持
  假设成立 → 系统有韧性,记录验证报告
  假设不成立 → 找到弱点,修复,再次演练

3)常见的故障注入类型

基础设施层:
  实例故障:随机终止容器/Pod(Chaos Monkey, Chaos Mesh kill pod)
  机器故障:模拟宿主机宕机(物理层演练)
  AZ 故障:模拟整个可用区断网

网络层:
  延迟:为特定服务注入 100-500ms 延迟
  丢包:模拟 10% 丢包率
  带宽限制:限制出站带宽
  DNS 故障:DNS 解析失败

应用层:
  依赖超时:让某个下游服务响应变慢(> 超时时间)
  依赖错误:让某个下游返回 500
  内存泄漏:注入持续内存增长,触发 OOM

数据层:
  主从切换:手动触发 Redis/MySQL 主从切换
  慢查询:注入 sleep 模拟慢 SQL
  磁盘满:填满磁盘(在预生产)

4)工具生态

Chaos Monkey(Netflix 开源):
  在 AWS 上随机终止实例
  后来演进为 Chaos Engineering Platform(ChAP)

Chaos Mesh(PingCAP 开源,K8s 原生):
  CRD 定义混沌实验(YAML 配置)
  支持:Pod kill, Network chaos, IO chaos, Time chaos
  有 Dashboard,实验结果可视化

Litmus(CNCF 项目):
  类似 Chaos Mesh,K8s 原生

Gremlin(商业版):
  企业级混沌工程平台,覆盖更多场景

自研脚本(小团队常见):
  写 Python/Shell 脚本模拟故障(iptables 封端口,kill 进程等)
  简单,但缺乏可观测性和统一管理

5)成本与风险控制

成本:
  人力:设计实验、修复发现的问题(高)
  工具:Chaos Mesh(开源),Gremlin(付费)
  影响面:生产实验可能造成真实故障(影响用户)
  
风险控制:
  从预生产环境开始(不影响用户)
  生产环境演练:
    1. 从低峰期开始(凌晨 3 点)
    2. 先小范围(单个实例,而不是整个集群)
    3. 自动终止条件(稳定状态指标下降 → 自动停止实验)
    4. 有 Rollback 按钮(一键终止实验)
  
  Chaos Mesh 的 Abort 机制:
  apiVersion: chaos-mesh.org/v1alpha1
  kind: NetworkChaos
  spec:
    action: delay
    delay:
      latency: "200ms"
    duration: "5m"   # 自动在 5 分钟后结束(有明确终止时间)
    abort: true      # 稳定状态恢复后自动终止

6)与故障演练的区别

故障演练(Fire Drill):
  有脚本(事先规划好步骤)
  目标:验证流程(响应流程、升级路径、Runbook)
  频率:季度/半年
  
混沌工程(Chaos Engineering):
  有科学假设,结果不确定
  目标:发现未知弱点(你不知道会发现什么)
  频率:持续/频繁
  
两者互补:故障演练保证"知道怎么做",混沌工程保证"知道会出什么问题"

延伸追问

  • Q:中小团队有必要做混沌工程吗? → 未必需要完整的混沌工程平台。但故障演练(手动停一个服务、手动重启数据库)是低成本高价值的实践,任何团队都应该做。完整混沌工程适合:系统规模大(微服务几十个)、SLA 要求高(99.99%)、有专职 SRE 团队的场景。
  • Q:如何说服管理层做混沌工程(影响生产)? → 对比成本:“主动演练出问题,影响用户 N 分钟(受控);等真实故障发生,影响用户 N 小时(不可控)。“从非核心服务开始,积累成功案例,再扩展到核心服务。数据说话:展示演练发现并修复的漏洞(如:发现 Redis 主从切换时有 30s 服务不可用,修复后降为 0)。

我的记法

  • 混沌工程 = 主动注入故障 + 验证假设 + 发现弱点 + 修复
  • 四步法:定义稳定状态 → 假设 → 注入故障 → 验证
  • 工具:Chaos Mesh(K8s 原生,开源推荐)
  • 风险控制:低峰期 + 小范围 + 自动终止 + Rollback 按钮
  • 与故障演练区别:演练 = 有脚本验流程;混沌 = 有假设找弱点
  • 一句话:「主动找弱点,而不是被动等故障」

状态

  • 已背速记
  • 能说混沌工程四步法
  • 能说与故障演练的区别