第19章 混沌工程¶
学习时间: 2.5小时 难度级别: 高级 重要性: ⭐⭐⭐⭐ 构建弹性系统的关键实践
🎯 学习目标¶
完成本章后,你将能够: - 理解混沌工程的核心原则与方法论 - 对比主流混沌工程工具并选择合适方案 - 使用 Litmus 在 Kubernetes 中实施混沌实验 - 将混沌工程集成到 CI/CD 流水线 - 组织和执行 GameDay 演练
1. 混沌工程原则¶
1.1 什么是混沌工程?¶
混沌工程是一种通过主动注入故障来验证系统弹性的工程实践。其核心理念是:在可控环境中提前发现问题,而不是在生产事故中被动发现。
"混沌工程是在分布式系统上进行实验的学科,目的是建立对系统抵御生产环境中湍流条件的能力的信心。" — Principles of Chaos Engineering
1.2 五大核心原则¶
1. 建立稳态假设(Steady State Hypothesis)
├── 定义系统正常行为的可量化指标
├── 例:p99 延迟 < 200ms、错误率 < 0.1%、订单成功率 > 99.9%
└── 实验前后对比这些指标来判断系统是否弹性
2. 用真实世界事件做变量
├── 模拟真实生产故障(而非理论化的场景)
├── 例:节点宕机、网络分区、磁盘满、依赖服务超时
└── 参考历史事故记录选择实验类型
3. 在生产环境运行实验
├── 预生产环境可能无法复现生产问题
├── 生产实验需要更严格的安全措施
└── 从非关键路径开始,逐步扩大范围
4. 持续自动化运行
├── 手动实验无法持续发现回归问题
├── 集成到 CI/CD 流水线自动执行
└── 定期在生产环境执行(如每周一次)
5. 最小化爆炸半径(Minimize Blast Radius)
├── 从最小范围开始(单个 Pod → 单个节点 → 单个 AZ)
├── 设置自动回滚机制和超时时间
├── 确保有人值守和监控告警
└── 有明确的终止条件和回滚流程
1.3 混沌实验流程¶
┌─────────────────────────────────────────────────┐
│ 混沌实验生命周期 │
│ │
│ 1. 稳态假设 → 2. 注入故障 → 3. 观察行为 │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 定义正常 │ │ 执行混沌 │ │ 监控指标 │ │
│ │ 行为指标 │ │ 实验 │ │ 对比基线 │ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ │ │ │
│ └────────── 4. 分析结论 ─────────┘ │
│ ┌──────────┐ │
│ │ 通过/失败 │ │
│ │ 改进建议 │ │
│ └──────────┘ │
└─────────────────────────────────────────────────┘
2. 工具对比¶
2.1 主流工具概览¶
| 工具 | 来源 | 平台支持 | 特点 | 适用场景 |
|---|---|---|---|---|
| Chaos Monkey | Netflix | AWS | 随机终止实例 | EC2 弹性验证 |
| Litmus | CNCF | Kubernetes | 声明式实验、Hub 丰富 | K8s 原生混沌 |
| ChaosBlade | 阿里巴巴 | K8s/主机/JVM | 中文友好、故障类型丰富 | 国内企业 |
| Chaos Mesh | PingCAP | Kubernetes | Dashboard 直观、与 TiDB 深度集成 | K8s 故障注入 |
| Gremlin | SaaS | 多平台 | 企业级 SaaS、安全功能强 | 企业级合规 |
| AWS FIS | AWS | AWS 服务 | 与 AWS 深度集成 | AWS 原生 |
2.2 选择建议¶
决策矩阵:
Kubernetes 环境?
├── YES → 需要 CNCF 生态?
│ ├── YES → Litmus(CNCF 孵化项目)
│ └── NO → 需要中文支持?
│ ├── YES → ChaosBlade
│ └── NO → Chaos Mesh
├── AWS 环境?
│ └── YES → AWS FIS(原生集成)
└── 多平台/企业级?
└── Gremlin(SaaS 方案)
3. Litmus 实战¶
3.1 Litmus 架构¶
┌─────────────────────────────────────┐
│ Litmus Control Plane │
│ ┌───────────┐ ┌────────────────┐ │
│ │ Litmus │ │ ChaosCenter │ │
│ │ API Server│ │ (Web UI) │ │
│ └─────┬─────┘ └───────┬────────┘ │
│ │ │ │
├────────┼─────────────────┼───────────┤
│ │ Execution │ │
│ ┌─────▼─────────────────▼────┐ │
│ │ Chaos Infrastructure │ │
│ │ (Subscriber + Runner) │ │
│ └─────────────┬──────────────┘ │
│ │ │
│ ┌─────────────▼──────────────┐ │
│ │ ChaosExperiment │ │
│ │ ChaosEngine │ │
│ │ ChaosResult │ │
│ └────────────────────────────┘ │
└─────────────────────────────────────┘
3.2 安装 Litmus¶
# 安装 LitmusChaos(Helm)
helm repo add litmuschaos https://litmuschaos.github.io/litmus-helm/
helm install litmus litmuschaos/litmus \
--namespace litmus --create-namespace \
--set portal.frontend.service.type=NodePort
# 安装 Chaos Infrastructure(连接目标集群)
# 通过 ChaosCenter UI 添加,或使用 CLI:
litmusctl connect chaos-infra \
--name="production-cluster" \
--namespace="litmus" \
--non-interactive
3.3 Pod Kill 实验¶
# pod-kill-experiment.yaml
apiVersion: litmuschaos.io/v1alpha1
kind: ChaosEngine
metadata:
name: pod-kill-chaos
namespace: default
spec:
engineState: active
appinfo:
appns: default
applabel: app=nginx
appkind: deployment
chaosServiceAccount: litmus-admin
experiments:
- name: pod-delete
spec:
components:
env:
# 强制删除(不等待优雅关闭)
- name: FORCE
value: "true"
# 混沌持续时间(秒)
- name: TOTAL_CHAOS_DURATION
value: "60"
# 每次杀死的 Pod 数量
- name: PODS_AFFECTED_PERC
value: "50"
# 两次杀 Pod 之间的间隔
- name: CHAOS_INTERVAL
value: "10"
# 序列模式:parallel 或 serial
- name: SEQUENCE
value: "parallel"
probe:
- name: check-app-availability
type: httpProbe
mode: Continuous
httpProbe/inputs:
url: "http://nginx-service:80"
method:
get:
criteria: ==
responseCode: "200"
runProperties:
probeTimeout: 5s
retry: 3
interval: 5s
--- # YAML文档分隔符
# 稳态假设验证
apiVersion: litmuschaos.io/v1alpha1
kind: ChaosResult
metadata:
name: pod-kill-chaos-pod-delete
namespace: default
# 实验完后检查此对象的 status
3.4 Network Chaos 实验¶
# network-chaos-experiment.yaml
apiVersion: litmuschaos.io/v1alpha1
kind: ChaosEngine
metadata:
name: network-chaos
namespace: default
spec:
engineState: active
appinfo:
appns: default
applabel: app=order-service
appkind: deployment
chaosServiceAccount: litmus-admin
experiments:
- name: pod-network-latency
spec:
components:
env:
# 网络延迟(ms)
- name: NETWORK_LATENCY
value: "500"
# 延迟抖动(ms)
- name: JITTER
value: "100"
# 目标容器
- name: TARGET_CONTAINER
value: "order-service"
# 影响的网络接口
- name: NETWORK_INTERFACE
value: "eth0"
# 目标端口(可选)
- name: DESTINATION_PORTS
value: "3306,6379"
# 持续时间
- name: TOTAL_CHAOS_DURATION
value: "120"
probe:
- name: check-order-latency
type: promProbe
mode: Edge
promProbe/inputs:
endpoint: "http://prometheus:9090"
query: >
histogram_quantile(0.99,
rate(http_request_duration_seconds_bucket{
service="order-service"
}[1m])
)
comparator:
type: float
criteria: "<="
value: "2.0" # p99 <= 2s
runProperties:
probeTimeout: 10s
interval: 15s
- name: pod-network-loss
spec:
components:
env:
# 丢包率(百分比)
- name: NETWORK_PACKET_LOSS_PERCENTAGE
value: "30"
- name: TOTAL_CHAOS_DURATION
value: "60"
- name: TARGET_CONTAINER
value: "order-service"
3.5 Stress Chaos 实验¶
# stress-chaos-experiment.yaml
apiVersion: litmuschaos.io/v1alpha1 # apiVersion指定K8s API版本
kind: ChaosEngine # kind指定资源类型
metadata:
name: stress-chaos
namespace: default
spec: # spec定义资源的期望状态
engineState: active
appinfo:
appns: default
applabel: app=payment-service
appkind: deployment
chaosServiceAccount: litmus-admin
experiments:
- name: pod-cpu-hog
spec:
components:
env:
# CPU 核心数
- name: CPU_CORES
value: "2"
# CPU 使用百分比(每个核心)
- name: CPU_LOAD
value: "80"
- name: TOTAL_CHAOS_DURATION
value: "120"
- name: TARGET_CONTAINER
value: "payment-service"
probe:
- name: check-payment-health
type: httpProbe
mode: Continuous
httpProbe/inputs:
url: "http://payment-service:8080/health"
method:
get:
criteria: ==
responseCode: "200"
runProperties:
probeTimeout: 3s
retry: 2
interval: 10s
- name: pod-memory-hog
spec:
components:
env:
# 内存消耗量(MB)
- name: MEMORY_CONSUMPTION
value: "500"
- name: TOTAL_CHAOS_DURATION
value: "90"
- name: TARGET_CONTAINER
value: "payment-service"
4. 混沌工程与 CI/CD 集成¶
4.1 GitHub Actions 集成¶
# .github/workflows/chaos-testing.yml
name: Chaos Testing Pipeline
on:
schedule:
- cron: "0 2 * * 1" # 每周一凌晨2点
workflow_dispatch: # 支持手动触发
jobs:
chaos-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Kubernetes cluster
uses: helm/kind-action@v1
with:
cluster_name: chaos-test
- name: Deploy application
run: |
kubectl apply -f k8s/
kubectl wait --for=condition=ready pod -l app=my-app --timeout=120s
- name: Install Litmus
run: |
helm repo add litmuschaos https://litmuschaos.github.io/litmus-helm/
helm install litmus litmuschaos/litmus --namespace litmus --create-namespace
kubectl wait --for=condition=ready pod -l app=chaos-operator --timeout=60s -n litmus
- name: Verify steady state (before)
run: |
# 记录基线指标
RESPONSE_CODE=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:8080/health)
if [ "$RESPONSE_CODE" != "200" ]; then
echo "❌ Pre-chaos health check failed"
exit 1
fi
echo "✅ Pre-chaos steady state verified"
- name: Run Pod Kill experiment
run: |
kubectl apply -f chaos-experiments/pod-kill.yaml
# 等待实验完成
kubectl wait --for=condition=complete chaosresult/pod-kill-chaos --timeout=300s
- name: Verify steady state (after)
run: |
sleep 30 # 等待系统恢复
RESPONSE_CODE=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:8080/health)
if [ "$RESPONSE_CODE" != "200" ]; then
echo "❌ Post-chaos health check failed — system did not recover"
exit 1
fi
echo "✅ System recovered successfully"
- name: Collect chaos results
if: always()
run: |
kubectl get chaosresult -o yaml > chaos-results.yaml
kubectl logs -l app=chaos-operator -n litmus > chaos-operator.log
- name: Upload results
if: always()
uses: actions/upload-artifact@v4
with:
name: chaos-results
path: |
chaos-results.yaml
chaos-operator.log
4.2 渐进式混沌策略¶
CI/CD 混沌注入策略:
Stage 1: 开发环境(每次 PR)
├── 基础健康检查
├── 单 Pod 重启验证
└── 通过后合并
Stage 2: 预发布环境(每次部署)
├── Pod Kill(单实例)
├── 网络延迟(100ms)
├── 验证服务降级机制
└── 通过后发布
Stage 3: 生产环境(每周定期)
├── Pod Kill(多实例,30%)
├── 网络延迟(500ms)+ 丢包(10%)
├── CPU/Memory 压力
├── 依赖服务故障
└── 全链路验证
Stage 4: GameDay(每月/每季度)
├── AZ 级别故障
├── 数据库故障转移
├── 全链路混沌
└── 事件响应流程演练
5. GameDay 演练流程¶
5.1 GameDay 完整流程¶
┌──────────────────────────────────────────────────┐
│ GameDay 演练流程 │
│ │
│ Phase 1: 准备(1-2周前) │
│ ├── 确定演练目标和范围 │
│ ├── 设计实验场景(基于风险评估) │
│ ├── 准备监控和告警 │
│ ├── 通知相关团队和利益相关者 │
│ ├── 准备回滚方案和紧急联系人 │
│ └── 安排值班人员 │
│ │
│ Phase 2: 执行(当天) │
│ ├── 09:00 集合,确认所有人就位 │
│ ├── 09:15 验证稳态基线指标 │
│ ├── 09:30 开始注入第1轮故障 │
│ ├── 10:00 观察系统行为,记录异常 │
│ ├── 10:30 验证自动恢复和告警 │
│ ├── 11:00 注入第2轮更大范围故障 │
│ ├── 11:30 事件响应团队演练 │
│ ├── 12:00 停止实验,验证系统恢复 │
│ └── 如遇紧急情况 → 立即执行回滚 │
│ │
│ Phase 3: 复盘(1-3天内) │
│ ├── 收集实验数据和监控截图 │
│ ├── 分析系统表现 vs 预期 │
│ ├── 识别弱点和改进项 │
│ ├── 按优先级排列修复任务 │
│ ├── 编写 GameDay 报告 │
│ └── 分享经验到全公司 │
└──────────────────────────────────────────────────┘
5.2 GameDay 报告模板¶
# GameDay 报告 — [日期]
## 基本信息
- **日期**: 2026-01-15
- **参与团队**: SRE、后端、运维、DBA
- **演练环境**: 生产环境(东区)
- **持续时间**: 09:00 - 12:00
## 实验场景
| # | 场景 | 预期影响 | 实际影响 | 结果 |
|---|------|---------|---------|------|
| 1 | 杀死 50% API Pod | 延迟升高,无错误 | p99 从 150ms → 280ms,无错误 | ✅ 通过 |
| 2 | 数据库主从切换 | < 5s 中断 | 8s 中断,3个超时请求 | ⚠️ 部分通过 |
| 3 | Redis 集群 1/3 节点下线 | 自动故障转移 | 故障转移成功但耗时 12s | ⚠️ 部分通过 |
## 发现的问题
1. **P1 - 数据库切换超时**:连接池未配置自动重连(负责人:@DBA团队,截止:01/22)
2. **P2 - Redis 故障转移慢**:Sentinel 超时配置过长(负责人:@SRE,截止:01/29)
3. **P3 - 告警延迟**:CPU 告警在故障后 3 分钟才触发(负责人:@运维,截止:02/05)
## 下次改进
- 扩大爆炸半径到跨 AZ 故障
- 增加消息队列故障场景
6. 面试题精选¶
面试题 1:什么是混沌工程?它与传统测试有什么区别?¶
参考答案: - 混沌工程通过主动注入故障验证系统弹性,传统测试验证功能正确性 - 混沌工程关注未知的未知(系统在非预期条件下的行为),测试关注已知的场景 - 混沌工程在接近生产的环境中运行,传统测试通常在测试环境 - 混沌工程是持续性活动,不是一次性测试
面试题 2:解释"最小化爆炸半径"原则¶
参考答案: - 从最小范围开始实验(单 Pod → 单节点 → 单 AZ → 多 AZ) - 设置自动终止条件(超时、错误率阈值触发回滚) - 确保有回滚机制(一键停止实验并恢复系统) - 有人值守:实验期间必须有人监控系统 - 逐步增加故障强度,确认系统在每个级别都能恢复
面试题 3:混沌工程中的"稳态假设"是什么?¶
参考答案: - 稳态假设是对系统正常行为的可量化定义 - 例:p99 延迟 < 200ms、错误率 < 0.1%、成功率 > 99.9% - 实验前测量基线,实验后对比——若指标偏离超过阈值,实验"失败"(发现了问题) - 好的稳态假设应该是面向业务的(订单成功率),而非纯技术的(CPU 使用率)
面试题 4:如何将混沌工程集成到 CI/CD?¶
参考答案: 1. 预发布阶段:部署后自动运行轻量混沌实验(Pod Kill、短暂网络延迟) 2. 定期触发:使用 cron 或调度器每周在生产环境运行 3. 渐进策略:开发环境 → 预发布 → 生产,故障强度逐级升级 4. 自动验证:实验后自动检查稳态假设,失败则阻止发布或告警 5. 结果归档:将实验结果存入 artifact,便于回溯和趋势分析
7. 检查清单¶
混沌工程原则¶
- 理解混沌工程的五大核心原则
- 能为系统定义合理的稳态假设
- 理解最小化爆炸半径的实践方法
工具使用¶
- 了解主流混沌工程工具的特点和适用场景
- 能安装和配置 Litmus
- 能编写 Pod Kill、Network Chaos、Stress Chaos 实验 YAML
- 理解 Probe 机制用于自动验证稳态假设
CI/CD 集成¶
- 能将混沌实验集成到 GitHub Actions
- 理解渐进式混沌策略(开发 → 预发布 → 生产)
- 能设计自动化的实验结果验证流程
GameDay¶
- 理解 GameDay 的完整流程(准备 → 执行 → 复盘)
- 能编写 GameDay 报告并追踪改进事项
- 了解如何逐步扩大 GameDay 的范围
上一章: 18-eBPF与可观测性 返回目录: README