DigitalOcean Kubernetes混沌工程实战:用ChaosMesh精准验证NVMe与网络亚健康

📅 2026/6/23 17:33:06
DigitalOcean Kubernetes混沌工程实战:用ChaosMesh精准验证NVMe与网络亚健康
1. 为什么在 DigitalOcean 上跑 Kubernetes 不能只靠“祈祷”——从一次凌晨三点的告警说起凌晨三点十七分手机震了三下。不是微信消息是 PagerDuty 的红色告警core-api-service: Latency 2s (99th percentile)紧接着是payment-gateway: Connection refused。我抓起电脑连上跳板机kubectl get pods -n production一敲——所有 Pod 状态都是Runningkubectl get nodes显示三台 Droplet 全部Ready。监控图表上 CPU、内存、网络带宽都平滑得像湖面。可用户订单正在失败支付链路彻底卡死。查了四十分钟最终发现是其中一台 worker 节点的磁盘 I/O 队列深度在凌晨两点四十五分开始持续飙升到 200而 Prometheus 没配 I/O wait 的告警阈值Kubernetes 自身也根本不感知底层块设备的“假死”状态——它只看 kubelet 心跳和 Pod 进程是否存在。那个节点上的容器进程全活着但所有读写请求都在内核队列里排队直到超时。我们花了六小时回溯日志、复现路径、打补丁最后才确认是 DigitalOcean 的 NVMe SSD 在高负载下触发了某次固件静默降速firmware throttling而这个行为完全不报错、不中断、不触发任何标准健康检查。这件事之后我删掉了所有“集群稳定运行中”的 Slack 状态。真正的稳定性不是所有组件都显示绿色而是当某个组件以一种你从未预料的方式悄悄变慢、变卡、变不可靠时你的系统依然能扛住、降级、自愈。这就是混沌工程存在的根本理由——它不测试“能不能跑”而测试“崩成什么样时还能活”。ChaosMesh 不是玩具它是我在 DigitalOcean Kubernetes 集群上部署的第一道“压力探针”也是唯一能提前半年发现上述 NVMe 固件问题的工具。它不依赖厂商文档里的“理论 SLA”只认真实硬件在真实流量下的反应。如果你还在用kubectl rollout restart当“重启大法”来验证高可用那你离下一次凌晨三点的告警只差一次未被模拟的磁盘抖动。2. ChaosMesh 在 DigitalOcean 环境中的不可替代性不是“能用”而是“必须用”很多人第一次接触 ChaosMesh会把它当成一个高级版的kill -9工具——不就是随机杀 Pod 吗DigitalOcean 的 Kubernetes 服务DOKS本身已经提供了自动节点恢复、Pod 水平伸缩、托管 etcd 备份为什么还要额外引入一个“制造故障”的系统这个问题的答案藏在 DigitalOcean 的基础设施抽象层级里。DOKS 是一个托管 Kubernetes 控制平面的服务但它不托管你的工作节点worker nodes的底层硬件行为。它保证kube-apiserver可用但不保证你选的s-2vcpu-4gbDroplet 上的 NVMe SSD 在 80% I/O 压力下会不会固件降速它保证kubelet能上报心跳但不保证该节点的网络驱动在内核更新后会不会出现微秒级的 TX 队列锁死它提供“自动修复”功能但其触发条件仅限于节点NotReady或kubelet进程崩溃——而上面提到的 I/O 队列深度飙升节点状态全程Readykubelet进程 PID 甚至没变过。这种“亚健康”状态正是生产环境故障的温床也是传统监控和 Kubernetes 健康检查的盲区。ChaosMesh 的价值恰恰在于它能精准刺入这个盲区。它不是在应用层模拟错误比如 HTTP 503而是在基础设施与 Kubernetes 的交界处注入可控扰动。例如NetworkChaos可以对特定 Pod 的 egress 流量注入netem规则模拟 DigitalOcean 数据中心内部网络的微突发丢包1% 丢包 50ms 延迟抖动这比单纯curl -I测试更能暴露服务间调用的脆弱性IOChaos直接在目标 Pod 的容器根文件系统层挂载fio模拟高 I/O 压力触发真实的磁盘队列堆积从而提前验证你的监控是否配置了node_disk_io_time_weighted_seconds_total的 P99 阈值StressChaos在指定 Pod 内启动stress-ng让 CPU 使用率虚假拉满但不真正计算专门用来检验你的 HPA 是否被错误指标误导——DigitalOcean 的top和htop在容器内看到的 CPU 利用率和cgroup统计的cpuacct.usage_percpu并不总是一致。更重要的是ChaosMesh 的实验定义是Kubernetes Native 的。一个NetworkChaos对象其spec.selector可以精确匹配到由app.kubernetes.io/instance: payment-gateway标签标识的 Pod而这个标签正是你用helm install payment-gateway ...部署时自动生成的。这意味着你的混沌实验可以和 CI/CD 流水线深度集成每次 Helm Chart 版本发布前自动运行一组基础网络扰动实验每次 Node Pool 升级后自动对新节点上的所有关键服务执行 IO 压力测试。这种“基础设施即代码”式的可靠性验证是任何外部脚本或手动kubectl exec都无法提供的确定性。提示在 DigitalOcean 上务必关闭 DOKS 控制台里的 “Automatically repair unhealthy nodes” 功能否则 ChaosMesh 注入的PodChaos如pod-failure可能被平台误判为节点故障触发不必要的节点重建干扰实验结果。真正的可靠性验证需要你亲手控制“坏”的节奏而不是交给平台自动擦屁股。3. 从零部署 ChaosMesh 到 DigitalOcean Kubernetes绕开三个最坑的“默认值”ChaosMesh 官方文档推荐使用 Helm 安装这没错。但在 DigitalOcean 环境下直接helm install chaos-mesh chaos-mesh/chaos-mesh --namespacechaos-testing --create-namespace会立刻掉进三个深坑。我踩过两次第二次重装时把每个参数都记在了笔记本上。下面是你必须手动覆盖的三个核心配置项以及它们背后的物理意义。3.1 镜像仓库必须显式指定为ghcr.io/chaos-mesh/chaos-meshDigitalOcean 的默认镜像拉取策略是IfNotPresent而 ChaosMesh 的 Helm Chart 默认使用的镜像是quay.io/chaos-mesh/chaos-mesh:v2.6.1。问题在于Quay.io 在亚太地区的 CDN 节点响应极不稳定尤其是在新加坡sgp1或班加罗尔blr1区域创建的 DOKS 集群。kubectl get pods -n chaos-testing会看到chaos-controller-managerPod 卡在ImagePullBackOffEvents里全是Failed to pull image quay.io/...: rpc error: code Unknown desc failed to pull and unpack image quay.io/...: failed to resolve reference quay.io/...: failed to do request: Head https://quay.io/v2/...: dial tcp 34.227.176.111:443: i/o timeout。解决方案极其简单但官方文档没强调强制使用 GitHub Container RegistryGHCR它的全球分发更可靠。执行以下命令helm repo add chaos-mesh https://charts.chaos-mesh.org helm repo update helm install chaos-mesh chaos-mesh/chaos-mesh \ --namespacechaos-testing \ --create-namespace \ --set chaosDaemon.runtimecontainerd \ --set chaosDaemon.socketPath/run/containerd/containerd.sock \ --set dashboard.createtrue \ --set dashboard.ingress.enabledtrue \ --set dashboard.ingress.hosts[0].hostchaos-dashboard.yourdomain.com \ --set chaosControllerManager.image.registryghcr.io \ --set chaosControllerManager.image.repositorychaos-mesh/chaos-mesh \ --set chaosControllerManager.image.tagv2.6.1 \ --set chaosDaemon.image.registryghcr.io \ --set chaosDaemon.image.repositorychaos-mesh/chaos-mesh \ --set chaosDaemon.image.tagv2.6.1 \ --set dnsServer.image.registryghcr.io \ --set dnsServer.image.repositorychaos-mesh/chaos-mesh \ --set dnsServer.image.tagv2.6.1注意--set chaosDaemon.runtimecontainerd和--set chaosDaemon.socketPath/run/containerd/containerd.sock这两行。DigitalOcean 的 DOKS 底层使用 containerd 作为 CRI而非 Docker Engine。如果你漏掉这两项chaos-daemonDaemonSet 会在每个节点上尝试连接/var/run/docker.sock而这个 socket 根本不存在导致所有混沌实验尤其是NetworkChaos和IOChaos全部静默失败——Pod 状态一切正常但网络规则压根没注入。3.2 Dashboard Ingress 必须配置 TLS 并指向正确的 LoadBalancer IPChaosMesh Dashboard 默认通过 Ingress 暴露而 DOKS 的 Ingress ControllerNGINX需要你手动创建一个Service类型为LoadBalancer的入口。但直接kubectl apply -f dashboard-ingress.yaml会遇到一个经典问题Ingress 的spec.rules[0].host指向了一个域名而 DigitalOcean 的 LoadBalancer Service 创建后分配的公网 IP 是动态的DNS 解析需要时间。更糟的是如果你的域名 DNS 是 Cloudflare 代理模式那么 ChaosMesh Dashboard 的 WebSocket 连接用于实时实验状态推送会被 Cloudflare 中断页面永远显示“Connecting...”。我的实操方案是放弃域名直接用 LoadBalancer 的 IP NodePort 访问。首先获取 LoadBalancer 的 IPkubectl get service -n chaos-testing chaos-dashboard -o jsonpath{.status.loadBalancer.ingress[0].ip} # 输出类似159.203.123.45然后编辑 Dashboard Service将type: LoadBalancer改为type: NodePort并记录其nodePort通常是 30080kubectl edit service -n chaos-testing chaos-dashboard # 修改 spec.type 为 NodePort并确保 spec.ports[0].nodePort 设为 30080最后在浏览器中直接访问http://YOUR_DROPLET_PUBLIC_IP:30080。这里YOUR_DROPLET_PUBLIC_IP是你任意一台 worker 节点的公网 IP不是 LoadBalancer IP。因为NodePort会将端口映射到所有节点所以只要防火墙放行30080你就能绕过所有 DNS 和 Ingress 的复杂性直连 Dashboard。这个方案在测试和预发环境足够健壮且避免了 TLS 证书管理的麻烦。3.3 RBAC 权限必须扩展以支持NetworkChaos的 eBPF 模式这是最隐蔽的坑。ChaosMesh 的NetworkChaos实验有两种模式tcTraffic Control和eBPF。tc模式需要在宿主机上执行tc qdisc命令这要求chaos-daemon容器拥有CAP_NET_ADMIN权限而eBPF模式则需要加载 eBPF 程序这要求chaos-daemon拥有CAP_SYS_ADMIN权限并且内核版本 5.8DigitalOcean 的 Ubuntu 22.04 默认内核是 5.15满足条件。Helm Chart 默认只授予CAP_NET_ADMIN所以当你创建一个NetworkChaos对象时如果spec.mode是eBPF这是推荐模式性能更好、影响更小chaos-controller-manager日志里会出现failed to inject network chaos: no such file or directory的错误而实验状态却显示Running——它根本没生效。解决方法是在 Helm 安装时显式添加--set chaosDaemon.securityContext.capabilities.add[0]SYS_ADMINhelm upgrade chaos-mesh chaos-mesh/chaos-mesh \ --namespacechaos-testing \ --set chaosDaemon.securityContext.capabilities.add[0]SYS_ADMIN \ --reuse-values--reuse-values确保其他参数不变。这个SYS_ADMIN权限是eBPF模式加载程序所必需的没有它NetworkChaos就是聋子的耳朵——摆设。你可以用一个简单的实验验证是否生效apiVersion: chaos-mesh.org/v1alpha1 kind: NetworkChaos metadata: name: test-ebpf namespace: chaos-testing spec: action: delay mode: one value: selector: namespaces: - default delay: latency: 100ms duration: 30s scheduler: cron: every 1m创建后进入目标 Pod 执行tc qdisc show dev eth0如果看到qdisc tbf 8001: root refcnt 2 rate 1000Mbit burst 1250000b lat 100.0ms说明tc模式生效如果看到qdisc clsact ffff: root说明eBPF模式已接管。后者才是 DigitalOcean 环境下推荐的低开销模式。4. 面向 DigitalOcean 特性的四大核心实验设计不止于“杀 Pod”很多团队把混沌工程等同于“随机杀服务”这就像把外科手术等同于“拿刀乱捅”。在 DigitalOcean 的具体环境中我们必须设计能击中其基础设施特性的实验。以下是我在生产集群中长期运行的四个核心实验每一个都对应一个 DigitalOcean 用户高频遇到的真实故障场景。4.1 实验一IOChaos模拟 NVMe SSD 固件降速——专治“磁盘慢得离谱但监控全绿”故障背景DigitalOcean 的 NVMe SSD 性能卓越但其固件在持续高 I/O 压力尤其是大量小文件随机写下会触发热节流thermal throttling或写缓存刷新延迟write cache flush delay。此时iostat -x 1显示await平均 I/O 等待时间飙升至 200ms%util接近 100%但kubectl top nodes显示磁盘使用率diskio.io_service_bytes_recursive可能只有 30%Prometheus node_exporter的node_filesystem_usage也远未爆满。监控告警全无但数据库查询慢得像幻灯片。实验设计apiVersion: chaos-mesh.org/v1alpha1 kind: IOChaos metadata: name: nvme-throttling-sim namespace: chaos-testing spec: action: latency mode: all selector: labelSelectors: app.kubernetes.io/component: database volumePath: /var/lib/postgresql/data latency: time: 150ms correlation: 100 percent: 100 duration: 5m scheduler: cron: every 24h关键参数解析volumePath: /var/lib/postgresql/data必须精确指向数据库 Pod 挂载的持久卷PersistentVolume的实际路径。在 DigitalOcean 的 Block Storage 上这通常是/dev/disk/by-id/scsi-0DO_Volume_your-pv-name挂载到容器内的路径。latency.time: 150ms不是模拟“磁盘坏了”而是模拟“磁盘变慢了”。150ms 是 NVMe 降速后的典型await值足以让 PostgreSQL 的shared_buffers缓存失效迫使大量查询走磁盘。correlation: 100表示每次 I/O 请求都施加延迟不随机跳过。这是为了最大化复现“持续慢”的效果而非偶发抖动。scheduler.cron: every 24h每天凌晨 2 点执行避开业务高峰且频率足够低避免对存储造成永久性磨损。验证方式实验运行中登录数据库 Pod执行pg_isready -h localhost -U postgres观察返回时间是否从 5ms 变为 100ms同时在 Grafana 查看node_disk_io_time_weighted_seconds_total{device~sd.*|nvme.*}的 P99 值是否同步飙升。如果两者同步变化说明实验精准命中了目标。4.2 实验二NetworkChaos模拟数据中心内部网络微突发——专治“跨 AZ 调用超时”故障背景DigitalOcean 的多可用区AZ部署如 sgp1、sgp2、sgp3之间通过私有骨干网互联。这条网络并非“绝对可靠”。我们曾观测到在 sgp1 的 API 网关调用 sgp2 的用户服务时P99 延迟从 80ms 突然跳到 1200ms持续 3 分钟随后自动恢复。抓包发现是中间网络设备出现了微秒级的队列溢出micro-burst导致 TCP 重传。ping和mtr完全测不出因为 ICMP 包太小而业务流量是 HTTPS 大包。实验设计apiVersion: chaos-mesh.org/v1alpha1 kind: NetworkChaos metadata: name: az-microburst namespace: chaos-testing spec: action: loss mode: all selector: labelSelectors: app.kubernetes.io/name: user-service direction: to loss: loss: 1.5% correlation: 95 jitter: 20ms duration: 2m scheduler: cron: every 6h关键参数解析direction: to只对流入user-servicePod 的流量注入丢包。因为故障是“调用方收不到响应”根源在服务端接收路径。loss: 1.5%1.5% 的丢包率是微突发的典型特征。低于 0.5% 很难触发 TCP 重传高于 3% 则会引发连接重置偏离“微突发”场景。correlation: 95高相关性意味着丢包不是均匀分布而是集中在短时间窗口内如 100ms 内连续丢 5 个包完美模拟微突发。jitter: 20ms在丢包基础上增加 20ms 的延迟抖动模拟网络设备队列深度波动。验证方式在 API 网关 Pod 内用hey -z 5m -q 100 -c 50 https://user-service.default.svc.cluster.local/api/users/123持续压测。实验开启前hey报告的Latency distribution中 99th percentile 应 100ms实验开启后应能看到 99th percentile 瞬间跳至 1000ms且Error distribution中出现error: read tcp ...: i/o timeout。这证明你的服务调用链路对微突发是脆弱的需要增加客户端重试逻辑或调整 TCP keepalive 参数。4.3 实验三StressChaos模拟 CPU 资源争抢——专治“节点 CPU 100% 但 Pod 没被驱逐”故障背景DigitalOcean 的 Droplet 是共享宿主机资源的。当你在一个s-4vcpu-8gb节点上部署了 10 个 CPU limit 为500m的 Pod 时理论上最多用掉 5 个 vCPU。但如果其中一个 Pod 因 bug 进入无限循环while true; do :; done它的 CPU usage 会瞬间冲到4000m4 个 vCPU导致同节点上其他 Pod 的调度严重延迟kubectl top pods显示其 CPU usage 为0m因为 cgroup 统计被抢占但实际业务请求大量超时。Kubernetes 的kubelet驱逐机制--eviction-hardmemory.available500Mi,nodefs.available10%,nodefs.inodesFree5%默认不包含 CPU所以这个“CPU 虫子”可以肆虐数小时。实验设计apiVersion: chaos-mesh.org/v1alpha1 kind: StressChaos metadata: name: cpu-bug-sim namespace: chaos-testing spec: mode: one selector: labelSelectors: app.kubernetes.io/name: legacy-worker stressors: cpu: workers: 4 load: 100 duration: 3m scheduler: cron: every 12h关键参数解析workers: 4启动 4 个stress-ng --cpu 1进程精准占用 4 个 vCPU模拟一个 Pod 吃满整个节点。load: 100100% 的 CPU 占用率不是 50% 或 80%要达到“彻底饿死邻居”的效果。mode: one只在匹配到的一个 Pod 上执行。这样可以隔离影响避免整个节点瘫痪。验证方式实验运行中kubectl top nodes会显示该节点的 CPU usage 为4000m/4000m同时kubectl describe node node-name的Allocated resources下cpu一栏会显示4000m100%。此时观察同节点上其他 Pod 的kubectl logs应能看到大量context deadline exceeded错误。这证明你的应用缺乏对同节点资源争抢的防御能力需要在 Deployment 中设置合理的resources.requests和resources.limits并启用HorizontalPodAutoscaler基于 CPU usage 的扩缩容。4.4 实验四PodChaos模拟kubelet心跳丢失——专治“节点 Ready 但服务不可用”故障背景这是 DigitalOcean 上最诡异的故障之一。某次内核更新后kubelet进程仍在运行systemctl status kubelet显示 activekubectl get nodes显示Ready但kubelet向apiserver发送的心跳NodeStatus更新因 TLS 证书过期或网络策略变更而静默失败。结果是kubectl get pods能列出所有 Pod但kubectl exec、kubectl logs全部超时kubectl port-forward无法建立隧道。集群“看起来”完好实则完全丧失运维能力。实验设计apiVersion: chaos-mesh.org/v1alpha1 kind: PodChaos metadata: name: kubelet-heartbeat-loss namespace: chaos-testing spec: action: pod-failure mode: one selector: labelSelectors: component: kube-apiserver duration: 90s scheduler: cron: every 48h关键参数解析selector.labelSelectors.component: kube-apiserver直接针对kube-apiserverPod。这是 DOKS 托管的控制平面组件我们无法直接操作其节点但可以通过 ChaosMesh 对其 Pod 注入故障。action: pod-failure让kube-apiserverPod 进入CrashLoopBackOff状态模拟其与kubelet的通信中断。注意这不是杀死kubelet而是杀死apiserver因为kubelet的心跳是发给apiserver的apiserver不可用kubelet的状态就无法被集群感知。duration: 90s90 秒是 DOKS 自动恢复kube-apiserver的典型时间。短于 60s 可能来不及触发恢复长于 120s 则可能影响集群稳定性。验证方式实验开启后立即执行kubectl get componentstatuses应看到controller-manager和scheduler状态变为Unknown执行kubectl get nodes节点状态可能短暂变为NotReady然后在 90 秒内自动恢复为Ready。这验证了 DOKS 的控制平面自愈能力。更重要的是你要观察你的应用是否能在apiserver中断期间通过本地缓存如k8s.io/client-go的Informer继续提供只读服务或者是否有降级开关fallback。5. 实验结果分析与可靠性度量如何把“混沌”变成可量化的 SLO部署 ChaosMesh 不是为了看花里胡哨的仪表盘而是为了回答一个终极问题当 X 故障发生时Y 业务指标的 P99 延迟是否会超过 Z 毫秒如果答案是“会”那你的 SLOService Level Objective就名存实亡。因此每一次混沌实验都必须与你的核心业务指标绑定。在 DigitalOcean 环境下我建立了三层度量体系。5.1 第一层基础设施层 —— 验证 DOKS 的“承诺”是否兑现这一层的目标是验证 DigitalOcean 的托管服务 SLA。我们不关心业务只关心平台本身。关键指标包括指标名称查询 PromQL预期阈值实验关联sum(rate(kube_node_status_condition{conditionReady,statustrue}[5m])) by (node)sum(rate(kube_node_status_condition{conditionReady,statustrue}[5m])) by (node) 0.999 (99.9%)PodChaos模拟kube-apiserver故障后节点Ready状态恢复时间avg_over_time(node_network_receive_bytes_total{device~eth.*}[1h])avg_over_time(node_network_receive_bytes_total{device~eth.*}[1h])波动 ±15%NetworkChaos注入丢包后网络吞吐是否稳定max(node_disk_io_time_weighted_seconds_total{device~nvme.*})max(node_disk_io_time_weighted_seconds_total{device~nvme.*}) 50ms (P95)IOChaos注入延迟后磁盘 I/O 时间是否可控这些指标全部来自node_exporter和kube-state-metrics它们是 DOKS 开箱即用的监控组件。实验报告中必须截图对比“实验前 5 分钟”和“实验中 5 分钟”的指标曲线。如果node_disk_io_time_weighted_seconds_total在IOChaos开启后P95 值从 25ms 跳到 200ms那就证明你的数据库 Pod 所在的 NVMe 卷其 I/O 性能边界就是 200ms所有依赖该卷的服务其 P99 延迟 SLO 就不能定为 100ms。5.2 第二层平台层 —— 验证 Kubernetes 原生能力的鲁棒性这一层关注 Kubernetes 自身的编排和调度能力。我们假设基础设施是“可信”的测试 Kubernetes 如何应对组件故障。关键指标包括Pod 启动时间histogram_quantile(0.95, sum(rate(container_cpu_usage_seconds_total{container!,namespace~default|production}[5m])) by (le, namespace, container))。在PodChaos杀死一个关键 Deployment 的所有 Pod 后新 Pod 的container_cpu_usage_seconds_total从 0 上升到稳定值的时间应 30 秒。如果超过 60 秒说明你的initContainer或livenessProbe配置有问题。HPA 扩容延迟kube_hpa_status_current_replicas{hpayour-hpa-name}。在StressChaos注入 CPU 压力后HPA 从 2 副本扩容到 4 副本的时间应 2 分钟。如果延迟检查metrics-server的抓取间隔和horizontal-pod-autoscaler-sync-period参数。Service Endpoints 同步count(kube_endpoint_address_available{endpointyour-service} 1)。在NetworkChaos导致部分 Pod 网络不可达时Endpoints对象中的available地址数应实时减少且kube-proxyiptables 规则应同步更新剔除不可达地址。用iptables -t nat -L KUBE-SVC-* | grep DROP可验证。5.3 第三层业务层 —— 验证你的代码能否在混沌中存活这是最重要的一层也是最容易被忽视的。它不看 Kubernetes只看你自己的代码。我强制要求所有新上线的服务必须通过以下三个业务指标的混沌测试支付成功率Payment Success Rate在NetworkChaos模拟跨 AZ 丢包时支付网关的http_request_duration_seconds_count{code~2..,handlerpay}与http_request_duration_seconds_count{code~5..,handlerpay}的比值P95 应 99.5%。如果跌到 95%说明你的支付 SDK 缺少重试或熔断。搜索首屏时间Search FCP在StressChaos注入 CPU 压力时前端监控上报的performance.getEntriesByType(navigation)[0].domContentLoadedEventEndP95 应 2000ms。如果超时说明你的 SSR 渲染逻辑存在 CPU 密集型阻塞。库存扣减一致性Inventory Consistency在PodChaos随机杀死库存服务 Pod 时执行 1000 次并发扣减请求POST /inventory/deduct最终库存余额应等于初始值减去 1000。如果出现负数或不一致说明你的分布式锁或数据库事务隔离级别配置错误。每一次混沌实验的最终报告必须包含这三层指标的对比表格。例如一次IOChaos实验的结论可能是“NVMe 降速至 150ms 时支付成功率从 99.98% 降至 99.2%不满足 SLO根本原因是支付 SDK 的数据库连接池最大连接数maxOpen10过小导致连接等待超时。建议提升至 maxOpen50并增加连接超时重试。”注意所有实验必须在非生产环境staging先行运行至少一周收集基线数据。切勿在生产环境首次运行未经验证的混沌实验。我的原则是先用--dry-run模式生成实验 YAML再用kubectl create -f手动创建全程人工审核每一条selector和duration。6. 我的 DigitalOcean 混沌工程实践清单一份可直接打印贴在显示器边上的备忘录经过两年在 DigitalOcean Kubernetes 上的混沌工程实战我总结了一份极简但致命的实践清单。它不是理论而是我每天打开终端时脑子里自动浮现的 checklist。你可以把它打印出来贴在显示器边框上或者存为~/chaos-checklist.md。【部署前必做】✅ 确认 DOKS 集群的 Kubernetes 版本 ≥ v1.24ChaosMesh v2.6 要求执行doctl kubernetes cluster get your-cluster-name --format Version。✅ 确认所有 worker 节点的操作系统是 Ubuntu 22.04 LTS内核 5.15执行kubectl get nodes -o wide查看OS-IMAGE。✅ 关闭 DOKS 控制台的 “Automatically repair unhealthy nodes” 开关避免干扰实验。✅ 为chaos-testing命名空间单独创建 ResourceQuota限制其 CPU/Memory 总用量防止混沌实验本身耗尽集群资源。【实验设计必做】✅ 每个NetworkChaos实验selector必须精确到labelSelectors禁用mode: all除非你真想搞垮整个集群。✅ 每个IOChaos实验volumePath必须是 Pod 内实际挂载的路径可通过kubectl exec -it pod-name -- mount | grep on /获取。✅ 每个StressChaos实验workers数量必须 ≤ 该 Pod 的resources.limits.cpu避免触发cgroupOOM Killer。✅ 所有实验的duration必须 ≤scheduler.cron间隔的 1/3例如cron: every 6h则duration最长设为120m留出缓冲时间。【实验运行必做】✅ 实验开始前 5 分钟手动保存当前所有核心指标的 Grafana 快照Dashboard → Share → Direct link to snapshot。✅ 实验进行中每 30 秒