混沌工程与故障注入
一句话:混沌工程是主动注入故障,验证系统能不能扛住——不是等线上出事才发现没冗余,而是在安全环境下提前暴露隐藏风险。
核心理念
传统方式: 故障发生了 → 排查 → 修复 → 下次出新的故障 → 循环
混沌方式: 主动注入故障 → 验证恢复能力 → 提前修复 → 故障减少
混沌工程原则
| 原则 | 含义 |
|---|
| 假设系统会故障 | 不是”会不会”,是”什么时候” |
| 从小范围开始 | 先单实例、再单 AZ、再跨 AZ |
| 自动化运行 | 定期自动执行,不依赖人 |
| 最小化爆炸半径 | 在可控范围内注入,不搞垮生产 |
| 可观测 | 实验过程全程监控,有回滚机制 |
故障注入类型
| 类型 | ChaosMesh 实验 | 验证什么 |
|---|
| Pod 故障 | PodKill / PodChaos | 多副本高可用 |
| 网络延迟 | NetworkChaos (delay) | 超时重试、降级 |
| 网络丢包 | NetworkChaos (loss) | 重试机制、幂等 |
| 网络分区 | NetworkChaos (partition) | 脑裂处理 |
| CPU 压力 | StressChaos (cpu) | 容量、扩缩容 |
| 内存压力 | StressChaos (memory) | OOM 处理 |
| IO 压力 | IOChaos | 磁盘瓶颈 |
| 时钟偏移 | TimeChaos | 分布式时间依赖 |
| DNS 故障 | DNSChaos | DNS 缓存与容错 |
ChaosMesh 实战
安装
# 安装 ChaosMesh
kubectl create namespace chaos-mesh
helm install chaos-mesh chaos-mesh/chaos-mesh \
-n chaos-mesh \
--set chaosDaemon.runtime=containerd \
--set dashboard.create=true
# 访问 Dashboard
kubectl port-forward -n chaos-mesh svc/chaos-dashboard 2333:2333
实验 1:Pod 随机杀死
apiVersion: chaos-mesh.org/v1alpha1
kind: PodChaos
metadata:
name: kill-random-pod
namespace: production
spec:
action: pod-kill
mode: one # 每次杀一个
selector:
namespaces: [production]
labelSelectors:
app: api-gateway
scheduler:
cron: "@every 10m" # 每 10 分钟杀一个
duration: "0s" # 立即杀
实验 2:网络延迟注入
apiVersion: chaos-mesh.org/v1alpha1
kind: NetworkChaos
metadata:
name: inject-network-delay
namespace: production
spec:
action: delay
mode: all
selector:
namespaces: [production]
labelSelectors:
app: order-service
delay:
latency: "200ms" # 注入 200ms 延迟
correlation: "0"
jitter: "50ms" # ±50ms 抖动
direction: to # 出向流量
target:
selector:
namespaces: [production]
labelSelectors:
app: mysql
mode: all
duration: "5m"
scheduler:
cron: "@every 1h"
实验 3:CPU 压力
apiVersion: chaos-mesh.org/v1alpha1
kind: StressChaos
metadata:
name: cpu-stress
namespace: production
spec:
mode: one
selector:
namespaces: [production]
labelSelectors:
app: api-gateway
stressors:
cpu:
workers: 4 # 4 个 CPU 压力线程
load: 80 # 80% CPU
duration: "3m"
scheduler:
cron: "@every 2h"
实验流程
graph TD
HYP[定义假设<br/>杀 Pod 后 30s 内恢复] --> SETUP[准备实验<br/>选择目标/范围/时长]
SETUP --> BASELINE[记录基线<br/>SLI 当前值]
BASELINE --> EXEC[执行实验<br/>注入故障]
EXEC --> MONITOR[监控观察<br/>SLI 变化/告警/恢复]
MONITOR -->|SLI 正常| PASS[实验通过]
MONITOR -->|SLI 违反| FAIL[实验失败<br/>发现问题]
FAIL --> FIX[修复改进<br/>新增冗余/告警/Runbook]
FIX --> RETRY[重新实验验证]
PASS --> AUTO[纳入定期自动执行]
实验分级
| 级别 | 范围 | 风险 | 执行频率 | 批准 |
|---|
| L1 | 单 Pod | 极低 | 每小时 | 自动 |
| L2 | 单节点 | 低 | 每天 | 自动 |
| L3 | 单 AZ | 中 | 每周 | SRE 负责人 |
| L4 | 跨 AZ | 高 | 每月 | 技术负责人 |
| L5 | 跨 Region | 极高 | 每季度 | CTO |
游戏日(Game Day)
游戏日 = 有组织的混沌演练
流程:
1. 定义场景(模拟真实故障组合)
2. 召集参与者(SRE + 开发 + 业务)
3. 注入故障
4. 观察团队响应(MTTD/MTTA/MTTR)
5. 验证恢复
6. 复盘改进
游戏日 vs 自动混沌:
自动混沌 = 验证系统能力(系统能不能扛)
游戏日 = 验证团队能力(人能不能扛)
安全护栏
# 自动回滚机制
safety:
# 实验超时自动停止
max_duration: "10m"
# SLI 违反时自动停止
abort_conditions:
- metric: success_rate
threshold: 0.95 # 成功率 < 95% 立即停止
window: 1m
- metric: p99_latency
threshold: 2000 # P99 > 2s 立即停止
window: 1m
- alert: "SEV1" # 任何 SEV1 告警立即停止
# 时间窗口限制
schedule:
allowed_hours: "10:00-16:00" # 只在工作时间
blackout_periods: # 禁止期
- "大促期间"
- "发版窗口"
常见问题 / 坑点
| 问题 | 原因 | 解决方案 |
|---|
| 实验搞垮生产 | 范围太大 | 从 L1 开始逐步升级 + 自动回滚 |
| 实验发现太多问题 | 系统韧性差 | 按优先级修复,不是全修 |
| 没人愿意批准 | 怕担责 | 自动化 L1-L2 + 定期游戏日形成习惯 |
| 实验结果不可复现 | 缺少基线记录 | 每次记录基线 + 实验条件 |
| 只做系统不做人 | 忽略团队响应能力 | 定期游戏日验证 MTTR |
关联知识
参考资源
状态