混沌工程实践:使用 Chaos Mesh 注入故障

FreeGuideOnline 最新 2026-06-12

混沌工程与系统韧性设计

1. 什么是混沌工程

混沌工程是在分布式系统上进行实验的科学,目的是增强人们对系统抵御生产环境中湍流的能力的信心。它并非“制造混乱”,而是通过精心设计的受控实验,暴露系统中的弱点,从而主动改进系统韧性。

核心原则:

  • 定义稳态:确定正常运行时系统的可量化指标(如响应时间、错误率、吞吐量)。
  • 假设变化:提出“如果注入了某种故障,稳态是否依然保持”的假设。
  • 注入故障:在可控范围内引入真实世界可能发生的异常(网络中断、节点宕机、资源耗尽)。
  • 观察偏离:对比实验组与控制组的指标,发现稳态的偏离。
  • 复盘修复:分析根因,修复发现的问题,避免故障逃逸到生产环境。

2. 系统韧性设计基础

韧性是指系统在面对故障时维持可接受服务等级的能力。常见设计模式:

  • 超时与重试:避免级联等待,但需配合幂等与退避策略。
  • 熔断器:快速失败,防止故障扩散。
  • 仓壁隔离:将资源划分到不同池中,避免某个模块耗尽全部线程或连接。
  • 优雅降级:核心路径优先,关闭非关键功能以保留有限资源。
  • 冗余与故障转移:多副本部署,自动剔除不健康实例(借助 Kubernetes 的 Readiness 探针和 Service 抽象)。

混沌工程正是验证这些模式是否真正生效的“试金石”。

3. Chaos Mesh 简介

Chaos Mesh 是一个开源的云原生混沌工程平台,原生运行在 Kubernetes 环境。它以自定义资源定义(CRD)的方式声明故障,支持丰富的故障类型,并提供了可视化的管理面板。

核心优势:

  • 全部操作基于 Kubernetes CRD,易于版本控制和 GitOps 集成。
  • 无需修改应用程序代码,通过 Sidecar 或无侵入方式注入。
  • 支持 pod-kill、network-latency、cpu-stress、io-fault 等数十种故障。
  • 提供精细的时间调度和持续时间控制。

4. 安装 Chaos Mesh

Chaos Mesh 依赖 Kubernetes 集群(本地 minikube/kind 或远程集群均可)。使用 Helm 安装是最简单的方式。

前置条件:

  • 一个可访问的 Kubernetes 集群(kubectl 已配置)。
  • Helm 3 已安装。

安装步骤:

# 添加 Chaos Mesh 的 Helm 仓库
helm repo add chaos-mesh https://charts.chaos-mesh.org

# 创建命名空间(建议独立命名空间便于管理)
kubectl create ns chaos-testing

# 安装 Chaos Mesh(默认启用 Dashboard)
helm install chaos-mesh chaos-mesh/chaos-mesh \
  --namespace=chaos-testing \
  --set chaosDaemon.runtime=containerd \
  --set chaosDaemon.socketPath=/run/containerd/containerd.sock

注意runtimesocketPath 需要根据集群实际容器运行时调整(如 docker、containerd、cri-o)。对于 kind 集群,运行时通常为 containerd,以上参数适用。

验证安装:

kubectl get pods -n chaos-testing
# 应该看到 controller-manager、chaos-daemon、chaos-dashboard 等 Pod 运行

访问 Dashboard(可选):

kubectl port-forward -n chaos-testing svc/chaos-dashboard 2333:2333

浏览器打开 http://localhost:2333 即可看到 UI。

5. 第一个实验:Pod Kill

目标:验证当一个 Pod 被随机杀死时,系统是否能通过副本数自动恢复,且服务不中断。

实验对象:一个简单的 nginx Deployment 示例。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-test
  namespace: default
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:alpine
        ports:
        - containerPort: 80

部署并暴露一个 Service 以便外部观察:

kubectl expose deployment nginx-test --port=80 --type=ClusterIP

创建 PodChaos 故障定义,随机杀死该 Deployment 下的一个 Pod:

apiVersion: chaos-mesh.org/v1alpha1
kind: PodChaos
metadata:
  name: kill-random-pod
  namespace: chaos-testing
spec:
  action: pod-kill
  mode: one          # 一次只影响一个 Pod
  selector:
    namespaces:
      - default
    labelSelectors:
      app: nginx     # 匹配标签为 app=nginx 的 Pod
  duration: "30s"    # 实验持续 30 秒(会持续尝试杀死 Pod)
  scheduler:
    cron: "@every 2m" # 每 2 分钟执行一次

应用该故障:

kubectl apply -f kill-random-pod.yaml

观察结果:

  • kubectl get pods -w 观察,会看到某个 nginx Pod 被 Terminating,随后 Deployment 控制器自动创建新 Pod。
  • 使用 kubectl get events 查看事件:被杀死的原因会是 Chaos killed
  • 如果我们在实验期间持续对 Service 发送请求(例如 while true; do curl -s -o /dev/null -w "%{http_code}" <SERVICE_IP>; sleep 0.5; done),应该几乎看不到失败或仅有极少量 5xx(取决于 Service 端点摘除速度)。如果出现大量失败,说明你的服务质量保障机制(如 PreStop Hook、优雅关闭时间)有待改进。

6. 常见故障注入类型

Chaos Mesh 支持多种故障类型,下表列举了最常用的几种及对应 CRD:

故障种类 CRD 名称 作用 典型场景
杀掉 Pod PodChaos 强制杀死指定 Pod 验证 Pod 级故障自动恢复
网络故障 NetworkChaos 注入延迟、丢包、分区、带宽限制 模拟数据中心间网络抖动、微服务间通信异常
压力故障 StressChaos 在容器内施加 CPU 或内存压力 测试资源抢占下的限流与降级策略
IO 故障 IOChaos 对文件系统注入延迟或错误 验证依赖文件系统的服务(数据库)的容错
DNS 故障 DNSChaos 篡改 DNS 解析 模拟 DNS 劫持或服务发现异常
时间故障 TimeChaos 修改容器内时钟偏移 测试证书过期、时序依赖逻辑
内核故障 KernelChaos 注入内核层面的故障(挂载点错误等) 深层次验证系统行为

6.1 网络延迟注入(NetworkChaos)

模拟微服务 A 到微服务 B 的调用延迟突然升高。

apiVersion: chaos-mesh.org/v1alpha1
kind: NetworkChaos
metadata:
  name: net-delay-example
  namespace: chaos-testing
spec:
  action: delay
  mode: all
  selector:
    namespaces:
      - default
    labelSelectors:
      app: service-a      # 影响 app=service-a 的 Pod
  delay:
    latency: "500ms"
    jitter: "100ms"       # 延迟波动范围
  duration: "5m"

应用后,从 service-a 发出的所有向外请求都会增加 500ms 左右的延迟。结合监控观察调用方service-a的 p99 延迟是否飙升,并检查是否触发超时或熔断。

6.2 CPU 压力注入(StressChaos)

模拟某个 Pod 突然遭受 CPU 飚高,观察其响应能力和调度行为。

apiVersion: chaos-mesh.org/v1alpha1
kind: StressChaos
metadata:
  name: cpu-stress-test
  namespace: chaos-testing
spec:
  mode: one
  selector:
    labelSelectors:
      app: api-server
  stressors:
    cpu:
      workers: 4
      load: 90          # 添加 4 个 worker,每个尝试占满 90% CPU
  duration: "3m"

7. 实验前准备:定义稳态假设与监控

没有基准的混沌实验是盲目的。开始前必须明确:

稳态指标示例:

  • HTTP 错误率 < 0.1%
  • P99 延迟 < 200ms
  • 订单处理队列长度稳定

监控工具集成: Chaos Mesh 本身不提供业务监控,你需要集成 Prometheus、Grafana、Datadog 等。实验时,使用 Chaos Mesh 的 Dashboard 或通过 kubectl get events 可以看到故障注入事件,但业务指标变化需要从监控系统观察。

推荐做法: 创建一个 Grafana 看板,同时展示故障注入时间轴(从 Chaos Mesh 事件中提取)与业务指标曲线,这样一目了然地判断故障是否导致了业务劣化。

8. 实战演练:对微服务应用注入网络延迟

场景:简单电商系统,包含 frontend(查询商品)、catalog(商品服务)、recommendation(推荐服务)。frontend 调用 catalogrecommendation。我们假设 recommendation 是一个非关键路径,希望注入延迟验证降级效果。

步骤:

  1. 部署示例应用(略,假设已部署,并带有标签 app=recommendation)。
  2. 定义稳态:在 Grafana 中记录 frontend 的请求成功率、延迟,以及 recommendation 的延迟基线。
  3. 设计假设:“当 recommendation 响应延迟超过 2s 时,frontend 能够在 500ms 内触发降级,返回缓存数据或默认推荐,且整体错误率不升高。”
  4. 创建 NetworkChaos
    apiVersion: chaos-mesh.org/v1alpha1
    kind: NetworkChaos
    metadata:
      name: delay-recommendation
      namespace: chaos-testing
    spec:
      action: delay
      mode: all
      selector:
        labelSelectors:
          app: recommendation
      delay:
        latency: "2500ms"
        jitter: "500ms"
      duration: "5m"
      scheduler:
        cron: "@every 15m"   # 每隔15分钟自动开始一次实验,每次持续5分钟
    
  5. 执行实验kubectl apply -f delay-recommendation.yaml
  6. 观察:查看 frontend 的调用链,是否在 2s 左右触发了熔断或超时,降级逻辑是否生效。同时关注 catalog 的正常调用是否受影响(应不受影响)。
  7. 结束与清理:实验结束后可删除 Chaos CR 或等待 duration 到期自动停止。若需立即终止,删除该 Chaos 对象:
    kubectl delete networkchaos delay-recommendation -n chaos-testing
    

9. 最佳实践

  • 从小规模到大规模:先 mode: one(单个 Pod)再 mode: all 或百分比模式,避免一上来就把系统搞垮。
  • 设定爆炸半径:利用 namespaceslabelSelectors 精确定位目标,避免误伤。
  • 实验自动化:将 Chaos CR 纳入 CI/CD 管道,每次部署后自动运行预设的混沌实验集合,实现“持续混沌”。
  • 结合金丝雀部署:先对新版本注入故障,比对旧版本的韧性,决定是否推全。
  • 始终保留“中止开关”:确保能快速删除 Chaos 资源终止实验,Dashboard 或 kubectl delete 都能做到。
  • 记录与复盘:每次实验后记录发现的问题、修复措施,形成知识库,不断提升系统韧性。

10. 总结

混沌工程是构建韧性系统的必要一环。Chaos Mesh 通过 Kubernetes 原生方式降低了故障注入的门槛,使你能够以声明式、安全的方式对系统进行“压力测试”。从简单的 Pod Kill 到复杂的网络延迟和资源压力组合,逐步构建你对生产环境稳定性的信心。

开始你的第一个混沌实验吧——从杀死一个 Pod 开始,亲眼看看你的系统是否真的“韧不可摧”。