ElIauk

故障演练与混沌工程入门

混沌工程不是随机搞破坏 很多人把混沌工程理解成“在线上随便杀几个 Pod,看系统会不会挂”,这既危险又没意义。它的真实目的是用受控的实验,把系统在故障下的行为从“未知”变成“已知”:哪个依赖断了会降级、哪个超时配置会导致级联失败、告警能不能在 1 分钟内触发。 关键在“受控”。没有稳态假设、没有爆炸

评论
故障演练与混沌工程入门

混沌工程不是随机搞破坏

很多人把混沌工程理解成“在线上随便杀几个 Pod,看系统会不会挂”,这既危险又没意义。它的真实目的是用受控的实验,把系统在故障下的行为从“未知”变成“已知”:哪个依赖断了会降级、哪个超时配置会导致级联失败、告警能不能在 1 分钟内触发。

关键在“受控”。没有稳态假设、没有爆炸半径、没有自动中止的故障注入,只是一次事故演练,而且很可能演成真事故。

实验的四个要素

稳态假设:先定义“正常”的可测指标,比如“下单接口成功率高于 99.5%、P99 低于 300ms、订单创建延迟小于 1 秒”。实验期间这些指标必须持续被采集,否则你无法判断影响。

爆炸半径:从最小开始。单个 Pod、单个可用区、单个非核心依赖,再逐步扩大。第一轮实验永远不要碰核心链路和全量流量。

实验方法:延迟、丢包、错误码、CPU/内存压力、Pod 杀死、依赖不可用、时钟偏移。一次只注入一种故障,否则出问题无法归因。

中止条件:稳态指标跌破阈值时自动停止实验并回滚,同时保留人工急停按钮。这一步要在实验开始前就配置好,而不是等出事了再手动操作。

一次网络延迟实验

假设要验证“库存服务变慢时,订单服务能否在 800ms 内降级而不是雪崩”。用 Chaos Mesh 给订单到库存的调用加 300ms 延迟:

apiVersion: chaos-mesh.org/v1alpha1
kind: NetworkChaos
metadata:
  name: order-to-inventory-delay
  namespace: shop-prod
spec:
  action: delay
  mode: one
  selector:
    namespaces:
      - shop-prod
    labelSelectors:
      app: order-api
  delay:
    latency: "300ms"
    jitter: "50ms"
    correlation: "25"
  direction: to
  target:
    mode: all
    selector:
      namespaces:
        - shop-prod
      labelSelectors:
        app: inventory-api
  duration: "5m"
  scheduler:
    cron: "@every 168h"

mode: one 表示只影响一个订单服务 Pod,direction: to 表示只影响出方向,target 锁定被调用的库存服务。这三处共同决定了爆炸半径。

实验期间要持续采样稳态指标:

for i in $(seq 1 300); do
  code=$(curl -s -o /dev/null -w '%{http_code}' -m 2 \
    http://order-api.shop-prod/actuator/health/readiness)
  echo "$(date +%H:%M:%S) readiness=$code"
  sleep 1
done

更完整的做法是把成功率、P99、熔断器状态、降级次数一起打到实验面板上,与实验开始时间对齐。只看日志里有没有报错,会漏掉“没有报错但请求全部变慢”的情况。

从演练到常态化

第一次实验通常是手工的:挑一个低峰窗口,业务方知情,值班同学盯着,出问题立刻回滚。这套流程跑顺之后,可以逐步自动化:

  • 把实验写成 YAML 存进仓库,和告警规则、runbook 放在一起;
  • 在预发环境按周定时跑,结果自动出报告;
  • 生产环境只在低峰窗口、且稳态指标正常时允许触发,并强制设置 duration;
  • 每次实验的结论要落成具体改动:调超时、加降级、改告警阈值、补 runbook。

没有产出改动的演练,本质上是一次团建。衡量混沌工程是否有效,看的不是做了多少次实验,而是“实验暴露的问题被修复了多少”。

常见坑

在没有可观测性的系统上做实验。 故障注入了,但没人能说清影响范围,最后只能等用户投诉。

一次注入多种故障。 网络延迟加 Pod 杀死同时上,故障恢复了也不知道是谁的功劳,实验结论不可信。

爆炸半径直接开到 100%。 生产全量丢包,本意是验证容灾,实际结果是全站不可用。要从一个 Pod、百分之一流量起步。

忽略依赖的重试放大。 注入 300ms 延迟后,上游重试三次,下游实际收到三倍流量,实验结论变成“系统扛不住三倍流量”,而不是原本想验证的超时治理。

实验后不复盘。 记录里只有“实验成功”四个字,没有指标曲线、没有发现的问题、没有后续动作,下次还得从头再来。

把混沌工程当成常驻故障源。 实验必须有明确的开始、结束和清理步骤。忘了清理的 NetworkChaos 会一直生效,直到有人发现某个接口莫名慢了两周。

参考

评论

推荐阅读

订阅邮件

订阅更新,及时收到最新文章。

作者