文章

混沌工程与故障注入

混沌工程与故障注入

一句话:混沌工程是主动注入故障,验证系统能不能扛住——不是等线上出事才发现没冗余,而是在安全环境下提前暴露隐藏风险。

核心理念

传统方式: 故障发生了 → 排查 → 修复 → 下次出新的故障 → 循环
混沌方式: 主动注入故障 → 验证恢复能力 → 提前修复 → 故障减少

混沌工程原则

原则含义
假设系统会故障不是”会不会”,是”什么时候”
从小范围开始先单实例、再单 AZ、再跨 AZ
自动化运行定期自动执行,不依赖人
最小化爆炸半径在可控范围内注入,不搞垮生产
可观测实验过程全程监控,有回滚机制

故障注入类型

类型ChaosMesh 实验验证什么
Pod 故障PodKill / PodChaos多副本高可用
网络延迟NetworkChaos (delay)超时重试、降级
网络丢包NetworkChaos (loss)重试机制、幂等
网络分区NetworkChaos (partition)脑裂处理
CPU 压力StressChaos (cpu)容量、扩缩容
内存压力StressChaos (memory)OOM 处理
IO 压力IOChaos磁盘瓶颈
时钟偏移TimeChaos分布式时间依赖
DNS 故障DNSChaosDNS 缓存与容错

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

关联知识

参考资源

状态

  • 混沌工程理念
  • 故障注入类型
  • ChaosMesh 实战
  • 实验流程与分级
  • 游戏日
  • 安全护栏