
1. 这不是“花架子”为什么今天必须认真对待 Litmus 的这三个 CRD混沌工程不是新概念但真正把它从理论推到生产环境落地的Litmus 算是少有的、把“云原生基因”刻进骨子里的开源项目。我最早在某高校实验室做微服务稳定性验证时接触它当时团队还在用脚本手动模拟网络延迟、随机杀 Pod每次跑完都得手动翻日志比对指标波动——直到把 ChaosEngine、ChaosExperiment 和 ChaosResult 这三个自定义资源CRD串起来跑通第一轮自动化故障注入才真正意识到这不是又一个玩具工具而是一套可审计、可回溯、可嵌入 CI/CD 流水线的稳定性治理基础设施。你可能已经听过“混沌工程四步法”建立稳态假设 → 设计实验 → 扰动系统 → 验证稳态。但光有方法论没用关键在于“谁来执行怎么记录失败了归谁下次怎么复现”——这正是 Litmus 三大 CRD 的分工逻辑ChaosExperiment 是实验说明书ChaosEngine 是调度指挥官ChaosResult 是结案报告。它们不依赖外部数据库或中心化服务全部基于 Kubernetes 原生 API Server 存储状态所有操作可 kubectl get/watch/apply所有变更可 git commit所有结果可 Prometheus 抓取、Grafana 展示。这种设计不是为了炫技而是为了解决真实产线里最头疼的问题责任边界模糊、过程不可追溯、结果无法量化。比如某次线上订单超时率突增 0.8%运维说“可能是网关抖动”开发说“下游服务响应慢”SRE 拿不出证据。如果之前用 ChaosEngine 跑过针对网关连接池耗尽的 ChaosExperiment并生成了带时间戳、Pod UID、错误码分布、P99 延迟对比的 ChaosResult那复盘就不是开会扯皮而是直接打开 Kubernetes Dashboard 点开那个 Result YAML三秒定位根因。这才是混沌工程该有的样子不是制造混乱而是用可控的混乱暴露不可见的脆弱点。这三个 CRD 的命名看似平实实则暗藏设计哲学。ChaosExperiment 不叫 ChaosTemplate是因为它强调“一次性的实验意图”而非可复用的模板ChaosEngine 不叫 ChaosController是因为它不直接执行扰动而是协调多个 Experiment 的生命周期与依赖关系ChaosResult 不叫 ChaosReport是因为它必须是机器可解析的结构化输出而非人类阅读的 PDF。理解这层语义才能避免后续配置中常见的“把 Engine 当成执行器”“把 Experiment 当成全局配置”这类根本性误用。2. 核心设计逻辑为什么非得是这三个 CRD拆解 Litmus 的分层治理思想2.1 分层解耦从“单体脚本”到“声明式编排”的必然选择早期混沌工具比如某些基于 Shell curl 的方案最大的问题是“强耦合”。一个模拟 CPU 飙高的脚本既要写 cgroup 控制逻辑又要判断目标 Pod 是否就绪还要记录开始/结束时间戳最后还得发告警——所有这些混在一个文件里改一个参数就得全量测试。Litmus 的破局点就是把混沌实验彻底“Kubernetes 化”每个 CRD 承担单一职责通过 Kubernetes 的 Informer 机制自动联动。ChaosExperiment 是“不变的契约”它定义的是“这个实验在任何集群、任何时刻、任何环境下行为都应一致”。比如 litmuschaos.io/cpu-hog 实验其 spec 中的appinfo、duration、cpu-load字段描述的是业务无关的通用扰动能力。它被设计为 ClusterScope由集群管理员统一安装普通开发者只需引用无需关心底层如何实现。ChaosEngine 是“动态的上下文”它定义的是“这次实验在哪个命名空间、对哪些应用、按什么顺序、是否自动恢复”。比如你给订单服务配一个 Engine指定 target app 为deployment/order-api设置annotation-selector: litmuschaos.io/chaostrue再关联 cpu-hog Experiment。Engine 不执行任何命令只负责监听 Experiment 状态、创建 ChaosRunner Pod、注入 RBAC 权限、收集日志路径——它像 Kubernetes 的 Deployment Controller只管“编排”不管“干活”。ChaosResult 是“客观的事实存证”它不是日志聚合而是结构化快照。每次 Experiment 执行后ChaosRunner 会把verdict: Pass/Fail、failStep: Inject chaos、probeSuccessPercentage: 98.2、duration: 30s等字段写入 Result。这个对象自带ownerReferences指向 Engine天然形成血缘链路。你可以用kubectl get chaosresult -l chaosengineorder-api-cpu-test一键查出某次实验的所有结果也可以用 Prometheus 的litmus_chaos_result_verdict_count{verdictFail}做长期趋势分析。这种分层不是为了增加复杂度而是为了解决规模化落地的三个硬需求权限隔离开发只能创建 Engine不能改 Experiment、版本控制Experiment YAML 可 git tagEngine YAML 可 helm template、可观测性对齐Result 字段名与 SLO 指标命名一致如latency-p99-ms直接映射到 APM 系统。2.2 为什么不用 ConfigMap/Secret 存实验配置CRD 的不可替代性在哪有人问既然都是 YAML为啥不直接用 ConfigMap 存 Experiment 参数答案很现实Kubernetes 的原生资源不具备状态机语义和事件驱动能力。ConfigMap 修改后没有任何机制能触发 ChaosRunner 启动Secret 没有 status 字段无法记录experimentStatus: Running/Completed/Stopped更关键的是它们无法被 Kubernetes 的 admission webhook 拦截校验。Litmus 的 CRD 注册时会同时部署 ValidatingWebhookConfiguration。当你kubectl apply -f engine.yamlAdmission Controller 会实时检查spec.appinfo.applabels是否匹配集群中真实存在的 Pod Labelspec.chaosServiceAccount对应的 ServiceAccount 是否有patch pods/exec权限spec.engineState是否为合法值active/stop/completed这种校验发生在 API Server 层比任何客户端脚本都可靠。而 ConfigMap 一旦写错 labelChaosRunner 启动后才发现找不到目标 Pod此时实验已失败但没人知道是配置问题还是环境问题。CRD 的 status 字段还支持 subresource让 ChaosRunner 可以只 patchstatus.verdict而不 touchspec避免并发更新冲突——这是 ConfigMap 永远做不到的原子性保障。另一个常被忽略的优势是RBAC 细粒度控制。你可以为 QA 团队创建 Role只允许get/list/createChaosEngine他们只能发起实验禁止getChaosExperiment防止他们篡改核心实验逻辑同时限制 ChaosResult 的delete权限保证审计证据不可删。这种策略用原生资源根本无法实现。2.3 与 Chaos Mesh、Gremlin 的关键差异Litmus 的“轻量可信”定位对比主流混沌平台Litmus 的设计选择非常清醒不造轮子Chaos Mesh 自研 chaos-daemon 作为 DaemonSet 运行而 Litmus 全部基于标准 Kubernetes Job/Pod。这意味着它不需要修改 kubelet 配置不依赖特定 CNI 插件甚至能在 OpenShift、Rancher RKE2 等加固环境中运行。我实测过在某金融客户禁用 hostPID/hostNetwork 的集群里Chaos Mesh 的 network-delay 实验直接失败而 Litmus 的 pod-network-loss 通过 initContainer 注入 tc 命令完美兼容。不包办一切Gremlin 提供 Web UI 和商业 SaaS但 Litmus 默认不提供前端。它的 CLIlitmusctl只做 YAML 生成和状态查询所有交互回归kubectl。这种“反便利”设计恰恰保障了生产环境的安全基线——没有额外的 ingress controller、没有暴露的 dashboard token、没有需要定期轮换的 API Key。不牺牲可调试性Litmus 的每个 ChaosRunner Pod 启动后都会在容器内生成/tmp/chaos-log.txt和/tmp/chaos-result.json。你可以kubectl exec -it runner-pod -- cat /tmp/chaos-log.txt直接看到 tc 命令执行输出、curl 探针返回码、甚至 Python 脚本的 traceback。而 Chaos Mesh 的日志分散在 chaos-daemon 和 experiment pod 两个地方排查时要来回切换。这决定了 Litmus 的适用场景适合已有成熟 Kubernetes 运维体系、重视审计合规、需要将混沌实验深度集成到 GitOps 工作流的团队。如果你的团队还在用kubectl run手动起测试 Pod那 Chaos Mesh 的 UI 可能更友好但如果你的发布流水线已用 Argo CD 同步 200 个 Helm ReleaseLitmus 的 CRD 原生支持会让你少写 80% 的胶水代码。3. 实操详解从零构建一个可审计的订单服务混沌实验3.1 环境准备5 分钟完成最小可行验证MVV别急着部署全套 Litmus Operator先用kubectl apply快速验证核心 CRD 是否生效。以下步骤在任意 v1.20 Kubernetes 集群均可运行包括 Kind、Minikube、EKS# 1. 安装 Litmus CRD仅定义不启动控制器 kubectl apply -f https://raw.githubusercontent.com/litmuschaos/litmus/master/mkdocs/docs/2.6.0/litmus-crd.yaml # 2. 创建专用命名空间和权限 kubectl create ns litmus kubectl apply -f - EOF apiVersion: v1 kind: ServiceAccount metadata: name: litmus-admin namespace: litmus --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: litmus-admin roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-admin subjects: - kind: ServiceAccount name: litmus-admin namespace: litmus EOF # 3. 部署一个待测的订单服务模拟真实业务 kubectl create ns order-app kubectl apply -n order-app -f - EOF apiVersion: apps/v1 kind: Deployment metadata: name: order-api labels: app: order-api spec: replicas: 2 selector: matchLabels: app: order-api template: metadata: labels: app: order-api annotations: litmuschaos.io/chaos: true # Engine 将通过此 annotation 发现目标 spec: containers: - name: server image: gcr.io/google-samples/hello-app:1.0 ports: - containerPort: 8080 --- apiVersion: v1 kind: Service metadata: name: order-api spec: selector: app: order-api ports: - port: 80 targetPort: 8080 EOF提示这里故意不部署 Litmus Operator是为了证明 CRD 本身即可工作。后续所有 ChaosEngine/Experiment/Result 的创建都不依赖后台控制器——它们只是被 ChaosRunner Pod 消费的静态配置。验证 CRD 是否注册成功kubectl get crd | grep chaos # 应看到 chaosengines.litmuschaos.io、chaosexperiments.litmuschaos.io、chaosresults.litmuschaos.io3.2 创建 ChaosExperiment定义“CPU 飙高”实验的黄金标准ChaosExperiment 是整个链条的基石。我们不直接使用社区实验如cpu-hog而是手写一个精简版看清其本质# cpu-burn-experiment.yaml apiVersion: litmuschaos.io/v1alpha1 kind: ChaosExperiment metadata: name: cpu-burn-custom namespace: litmus labels: name: cpu-burn-custom category: platform spec: definition: # 这里定义实际执行的 Job 模板 jobTemplates: - name: runner spec: backoffLimit: 0 template: spec: serviceAccountName: litmus-admin restartPolicy: Never containers: - name: ansible-runner image: litmuschaos/ansible-runner:2.6.0 env: - name: ANSIBLE_HOST_KEY_CHECKING value: False - name: CHAOS_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace - name: APP_NS value: order-app - name: APP_LABEL value: apporder-api - name: TOTAL_CHAOS_DURATION value: 30 - name: CPU_LOAD value: 80 volumeMounts: - mountPath: /tmp name: tmp volumes: - name: tmp emptyDir: {} # 这里定义探针健康检查 probes: - name: application-health-check type: http-get httpGetProbe: url: http://order-api.order-app.svc.cluster.local:80/healthz timeoutSeconds: 3 intervalSeconds: 5 retry: 3 # 这里定义实验前后的动作 auxiliaryAppInfo: # 注意spec.definition 中不包含任何目标应用信息 # 它只描述“如何烧 CPU”不指定“烧谁的 CPU”关键点解析jobTemplates是真正的执行体它启动一个 Ansible Runner 容器通过环境变量传入参数。你完全可以用image: python:3.9-slim 自定义脚本替换只要最终效果是stress-ng --cpu 4 --cpu-load 80即可。probes定义了健康检查方式。这里用 HTTP 探针访问/healthz但你也可以换成exec类型执行curl -s http://... | jq .status或tcpSocket检查端口连通性。auxiliaryAppInfo留空因为我们不依赖辅助服务如 mock DB。真正的生产实验中这里会填入deployment/mock-db的信息用于模拟依赖故障。注意这个 Experiment 必须放在litmus命名空间且由集群管理员创建。普通开发者不应有权限修改它否则会破坏实验一致性。3.3 创建 ChaosEngine绑定实验到具体业务服务现在把抽象的实验“实例化”到订单服务上# order-api-cpu-engine.yaml apiVersion: litmuschaos.io/v1alpha1 kind: ChaosEngine metadata: name: order-api-cpu-test namespace: order-app # Engine 和目标应用在同一命名空间简化 RBAC spec: # 关键指定实验来源 experiment: - name: cpu-burn-custom spec: # 这里才是真正的业务上下文 appinfo: appns: order-app applabel: apporder-api appkind: deployment # 实验级参数覆盖优先级高于 Experiment 中的默认值 components: runnerProperties: imagePullPolicy: IfNotPresent chaosServiceAccount: litmus-admin # 持续时间、重试等 duration: 30 rampTime: 0 # 故障注入后是否自动恢复true 表示 chaos-runner 会在 duration 后清理 stress-ng 进程 restore: true # 引擎级开关 engineState: active # 审计标记 annotationCheck: true # 自动清理开关实验结束后是否删除 ChaosRunner Pod jobCleanUpPolicy: delete # 探针失败时的行为 monitoring: false # 最大容忍失败数当 probe 失败超过此值Result verdict 设为 Fail probeTimeout: 3 probeInterval: 5 probeRetry: 3核心逻辑spec.experiment[0].name指向前面创建的cpu-burn-custom建立引用关系。spec.experiment[0].spec.appinfo填充了真实的业务信息appns: order-app、applabel: apporder-api。这才是 Engine 的价值——它把通用实验和具体业务解耦。restore: true是安全底线。很多团队第一次用混沌工程时忘了设这个导致 stress-ng 进程一直跑着把节点 CPU 跑满。Litmus 的 restore 机制会确保无论实验成功失败最终都会执行killall stress-ng。部署并观察kubectl apply -f order-api-cpu-engine.yaml # 查看 Engine 状态 kubectl get chaosengine -n order-app # 应看到 STATUS 从 Initialized - Running - Completed3.4 解析 ChaosResult从“实验完成”到“结论可信”的最后一公里当 Engine 状态变为CompletedLitmus 会自动生成 ChaosResultkubectl get chaosresult -n order-app # NAME VERDICT FAIL STEP DURATION AGE # order-api-cpu-test-cpu-burn-pass Pass - 30s 2m查看详细内容kubectl get chaosresult order-api-cpu-test-cpu-burn-pass -n order-app -o yaml重点关注status字段status: experimentStatus: failStep: phase: Completed verdict: Pass probeStatuses: - name: application-health-check status: Passed type: http-get runnerStatus: Passed - name: application-latency-check status: Skipped type: http-get runnerStatus: Skipped startTime: 2024-06-15T08:23:11Z endTime: 2024-06-15T08:23:41Z duration: 30s probeSuccessPercentage: 100 appinfo: appns: order-app applabel: apporder-api appkind: deployment这个 Result 的价值在于verdict: Pass不是简单“没报错”而是基于probeSuccessPercentage: 100计算得出。如果健康探针在 30 秒内失败超过 3 次由probeRetry控制verdict 会变成Fail。probeStatuses列出了每个探针的详细结果支持多探针并行验证。你可以添加latency-check探针用curl -w %{time_total}\n -o /dev/null -s http://...记录 P99 延迟。startTime/endTime是 RFC3339 格式可直接导入时序数据库做长期分析。实操心得我曾遇到某次 Result 显示verdict: Fail但probeStatuses全是Passed。排查发现是probeTimeout设为 1 秒而/healthz接口在 CPU 飙高时平均耗时 1.2 秒导致探针超时被判定为失败。解决方案不是调大 timeout而是改用exec探针执行timeout 2s curl -s http://...把超时控制权交给 shell更精准。3.5 构建可复现的 GitOps 流水线用 Argo CD 管理混沌实验真正的生产级落地必须把 ChaosEngine 当作基础设施代码管理。以下是 Argo CD 的 Application YAML 示例# argocd-chaos-app.yaml apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: order-api-chaos namespace: argocd spec: project: default source: repoURL: https://github.com/your-org/chaos-manifests.git targetRevision: main path: chaos/order-api destination: server: https://kubernetes.default.svc namespace: order-app syncPolicy: automated: prune: true selfHeal: true syncOptions: - CreateNamespacetruechaos/order-api/目录结构├── chaosengine.yaml # 引用 cpu-burn-custom ├── chaosexperiment.yaml # 仅声明不部署由集群管理员统一管理 └── kustomization.yaml # patches for environment-specific params这样做的好处每次git push修改chaosengine.yaml中的duration: 60Argo CD 自动同步无需人工kubectl apply。chaosexperiment.yaml不在该目录下避免开发者误改核心实验逻辑。kustomization.yaml可以根据不同环境staging/prod打 patch比如 prod 环境duration设为 120staging 设为 30。注意Argo CD 默认不会监控 CRD 状态变化。要实现“实验失败自动告警”需配合 Argo Events 或自定义 webhook。我的做法是在 Argo CD 的Application上加 annotationnotify/chaos-fail: true然后用一个轻量 Go 程序监听ChaosResult的verdict: Fail事件触发企业微信机器人推送。4. 常见问题与避坑指南来自 37 次线上混沌实验的真实教训4.1 “Engine 一直卡在 RunningChaosRunner Pod 不启动” —— RBAC 权限的隐形陷阱现象kubectl get chaosengine显示STATUS: Running但kubectl get pod -n order-app | grep chaos无任何 ChaosRunner Pod。排查步骤kubectl describe chaosengine order-api-cpu-test -n order-app查看 EventsEvents: Type Reason Age From Message ---- ------ ---- ---- ------- Warning FailedToCreateJob 2m chaos-operator failed to create job: serviceaccounts litmus-admin not found检查chaosengine.spec.chaosServiceAccount指定的 SA 是否存在kubectl get sa litmus-admin -n order-app # ❌ 返回 NotFound kubectl get sa litmus-admin -n litmus # ✅ 存在修正将 Engine 的chaosServiceAccount改为litmus-admin因为 SA 在litmus命名空间并在litmus命名空间创建 RoleBinding授予order-app命名空间的 Pod 操作权限# fix-rbac.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: litmus-admin-order-app namespace: order-app roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-admin subjects: - kind: ServiceAccount name: litmus-admin namespace: litmus根本原因Litmus 的 ChaosRunner Pod 必须在目标应用所在命名空间order-app运行才能注入网络策略、读取 Pod 日志。但它需要litmus-adminSA 的权限去操作其他命名空间的资源如litmus下的 Experiment。因此RoleBinding 必须跨命名空间创建。4.2 “ChaosResult verdict: Fail但业务完全没感知” —— 探针设计失效的典型场景现象CPU 飙高实验后ChaosResult 显示verdict: Fail但订单服务的 Prometheus 指标QPS、Error Rate、Latency一切正常。深入分析chaosresultkubectl get chaosresult order-api-cpu-test-cpu-burn-fail -n order-app -o jsonpath{.status.probeStatuses[0].runnerStatus} # 输出Failed kubectl get chaosresult order-api-cpu-test-cpu-burn-fail -n order-app -o jsonpath{.status.probeStatuses[0].output} # 输出{error:Get \http://order-api.order-app.svc.cluster.local:80/healthz\: context deadline exceeded (Client.Timeout exceeded while awaiting headers)}问题定位/healthz接口在 CPU 飙高时Go runtime 的 GC 停顿导致请求超时。但这不代表业务不可用——真实用户请求走的是/api/v1/orders它有独立的连接池和超时设置。解决方案探针必须模拟真实业务流量。删除/healthz探针改为probes: - name: real-user-flow type: http-get httpGetProbe: url: http://order-api.order-app.svc.cluster.local:80/api/v1/orders?limit1 timeoutSeconds: 5 # 业务接口超时设为 5 秒而非 healthz 的 1 秒 intervalSeconds: 3 retry: 2更进一步用exec探针执行curl -s -w %{http_code} -o /dev/null http://...只关注 HTTP 状态码忽略响应体大小。我的教训在某电商大促前用/healthz探针验证了“服务可用”结果大促时/checkout接口因数据库连接池耗尽雪崩。后来强制规定所有混沌探针必须对应 SLO 中定义的 P99 延迟接口且超时时间 SLO timeout × 0.8。4.3 “实验执行后目标 Pod 被反复重启” —— 资源限制与 OOM Killer 的协同效应现象kubectl get pod -n order-app显示order-api-xxx的 RESTARTS 列从 0 突增至 5。检查 Pod 事件kubectl describe pod -n order-app -l apporder-api | grep -A 5 Events # Events: # Type Reason Age From Message # ---- ------ ---- ---- ------- # Normal Killing 3m kubelet Container order-api failed liveness probe, will be restarted根源order-api的 livenessProbe 设置为exec: curl -f http://localhost:8080/healthz而 CPU 飙高导致该命令执行超时触发 kubelet 重启容器。这不是混沌实验的 bug而是暴露了应用自身的脆弱性。修复方案分两层短期临时提高 livenessProbe 的initialDelaySeconds和timeoutSeconds避免干扰实验。长期重构健康检查逻辑区分liveness进程存活和readiness服务就绪。liveness改为exec: ps aux | grep serverreadiness保留/healthz并确保其超时小于业务接口。这正是混沌工程的价值它不制造故障只是让已有的脆弱点显形。我见过最典型的案例是一个 Java 应用的-Xms和-Xmx设为不同值CPU 飙高时 Full GC 频繁/healthz响应超时但ps aux仍显示进程存活——这说明应用没挂只是暂时不可服务。混沌实验帮你发现这个 gap。4.4 “ChaosResult 中 probeSuccessPercentage 为 0但所有探针都 Passed” —— 时间窗口计算的精度陷阱现象probeSuccessPercentage: 0但probeStatuses全是Passed。查看chaosresult.status.startTime和endTimekubectl get chaosresult ... -o jsonpath{.status.startTime}{\n}{.status.endTime} # 2024-06-15T08:23:11Z # 2024-06-15T08:23:12Z # 仅间隔 1 秒问题duration: 30被误解为“实验持续 30 秒”实际含义是“ChaosRunner Pod 的 activeDeadlineSeconds 为 30 秒”。如果 stress-ng 启动后立即触发探针而探针 1 秒内就完成那么整个实验窗口只有 1 秒probeSuccessPercentage按(成功次数 / 总探针次数) × 100计算但总次数为 0因为时间太短没来得及跑够intervalSeconds × retry次。正确做法明确区分duration实验总时长和probeInterval探针频率spec: duration: 120 # 实验总时长 2 分钟 components: runnerProperties: # 确保 ChaosRunner 至少运行 2 分钟 activeDeadlineSeconds: 180 probes: - name: real-user-flow type: http-get httpGetProbe: url: ... timeoutSeconds: 5 intervalSeconds: 10 # 每 10 秒探一次2 分钟内共 12 次 retry: 2实操技巧在 ChaosRunner 容器内加一行日志打印当前时间戳和探针结果用kubectl logs -f runner-pod实时观察比看 Result 更直观。5. 进阶实践让混沌实验真正驱动稳定性改进5.1 用 ChaosResult 数据反哺 SLO 体系SLOService Level Objective不是拍脑袋定的数字而应基于混沌实验的实证数据。例如对订单服务设定 SLOavailability 99.9%latency-p99 500ms。运行 10 次不同强度的 CPU 飙高实验CPU_LOAD: 50/60/70/80/90记录每次的probeSuccessPercentage和latency-p99-ms需在 Probe 中解析响应头X-Response-Time。绘制散点图X 轴为CPU_LOADY 轴为probeSuccessPercentage。找到probeSuccessPercentage首次跌破 99.9% 的临界点比如CPU_LOAD75这就是当前架构的 CPU 容忍上限。将此临界点写入 SLO 文档并作为容量规划依据当线上 CPU 平均使用率 70%即触发扩容流程。Litmus 本身不提供可视化但 ChaosResult 的结构化输出天生适配 Prometheus# prometheus-rule.yaml - record: litmus_chaos_result_probe_success_percentage expr: | avg by (experiment_name, appns, applabel) ( kube_pod_status_phase{phaseRunning, namespace~order-app} * on (pod) group_left(label_app) (count by (pod, label_app) ( kube_pod_labels{label_app~order-api} )) ) # 实际中需用 Prometheus 的 kube-state-metrics custom exporter 将 ChaosResult 字段转为 metrics5.2 构建“混沌实验即文档”的知识库每个 ChaosEngine YAML 都应成为活的文档。我们在chaos/order-api/目录下增加README.md# 订单服务混沌实验规范 ## 实验目的 验证订单服务在 CPU 资源受限 75%时的可用性与延迟表现 ## 关联 SLO - availability: 99.9% → 对应 probeSuccessPercentage 99.9 - latency-p99: 500ms → 对应 probe 中 X-Response-Time 500 ## 历史结果 | Date | CPU_LOAD | probeSuccessPercentage | latency-p99-ms | Verdict | Action | |------------|----------|------------------------|----------------|---------|--------| | 2024-06-01 | 70 | 100 | 420 | Pass | Baseline | | 2024-06-10 | 75 | 99.2 | 510 | Fail | 优化 GC 参数 | ## 下一步 - [ ] 评估升级 JVM 版本至 17u - [ ] 增加数据库连接池压力实验Git 提交时CI 流水线自动检查chaosengine.yaml中的duration是否大于等于 SLO 规定的最小观测窗口如 120 秒。probes中是否至少有一个探针的url匹配 SLO 文档中的 endpoint。这种做法让混沌工程从“一次性活动”变成“持续演进的稳定性资产”。某支付公司实施后SLO 达成率从 92% 提升至 99.5%根本原因是每个失败的 ChaosResult 都自动创建 Jira Issue关联到对应的服务负责人。5.3 安全红线生产环境混沌实验的五条铁律永远不在非预发布环境运行kill-process类实验pod-delete、node-drain等实验必须限定在staging或canary环境。生产环境只允许pod-network-loss、cpu-hog等可逆、低风险实验。所有 ChaosEngine 必须设置jobCleanUpPolicy: delete防止残留的 ChaosRunner Pod 占用资源。我见过最严重的事故是一个忘记清理