Chaos Mesh故障未自动恢复:排查、清理与预防实战指南 1. 项目概述当混沌实验“失控”之后在云原生微服务架构下混沌工程已经成为保障系统韧性的标准实践。Chaos Mesh 作为一款强大的云原生混沌工程平台让我们能够方便地在 Kubernetes 集群中模拟各类故障如网络延迟、Pod 被杀、IO 故障等。其核心魅力在于“自动化”实验创建、故障注入、以及实验结束后的自动恢复。然而在实际生产或测试环境中我们偶尔会遇到一个令人头疼的情况——实验明明已经结束或手动停止但被注入的故障却没有如预期般自动恢复。集群中某个服务依然网络不通或者某个 Pod 持续处于异常状态这无异于一场“人造事故”演变成了真实的线上故障。这种情况我遇到过不止一次。最初以为是偶发现象但后来发现其背后往往隐藏着资源残留、控制器异常、网络策略冲突或权限问题等深层次原因。本次分享的主题正是聚焦于“Chaos Mesh 注入实验后未自动恢复”这一典型问题。我将结合多次实战排查的经验为你梳理出一套从现象定位到根因分析再到安全清理的完整方法论。这不仅仅是解决一次故障更是深入理解 Chaos Mesh 运作机制、Kubernetes 控制循环以及相关资源生命周期的绝佳机会。无论你是正在被此类问题困扰的运维工程师还是希望深化对混沌工程底层原理理解的开发者接下来的内容都将提供直接的参考价值。简单来说当自动恢复失效我们的角色就从“混沌实验的设计者”转变为“集群异常的消防员”。目标很明确第一快速定位故障残留点恢复业务第二彻底清理异常资源避免复发第三复盘根因优化运维流程或实验配置。下面我们就按照这个逻辑一步步拆解。2. 故障现象深度解析与初步定位当接到“实验停了但服务没恢复”的告警时切忌盲目操作。一套系统化的排查思路能帮你事半功倍。首先我们需要对故障现象进行精确的“画像”。2.1 典型未恢复现象枚举根据我的经验未自动恢复的表现主要集中在这几个方面你可以对照检查网络类故障残留这是最常见的一类。你使用了NetworkChaos注入网络延迟、丢包或分区实验停止后目标 Pod 之间依然无法正常通信。ping不通或者应用层连接超时。Pod 生命周期类故障残留例如你使用了PodChaos中的pod-kill动作实验停止后预期的替换 Pod 没有成功启动或者原 Pod 没有被重建导致服务副本数不足。压力类故障残留使用StressChaos为 Pod 注入 CPU 或内存压力后实验结束但 Pod 的resource limit似乎依然被占用节点负载居高不下甚至 Pod 本身因为OOMKilled而无法启动。IO 类故障残留通过IOChaos模拟磁盘 IO 延迟或错误实验结束后相关容器的磁盘读写性能依然异常缓慢。内核类故障残留使用KernelChaos注入诸如fail_nth等内核级故障后即使实验删除系统调用层面的异常行为可能持续。注意首先需要确认实验是否真的“已停止”。通过kubectl get chaos查看实验状态是否为paused或已被删除。有时可能是实验暂停而非删除故障自然持续。2.2 第一步基于 Chaos Mesh 控制面的排查排查应从 Chaos Mesh 本身开始这是最直接的路径。检查 Chaos Mesh 控制器状态kubectl get pods -n chaos-mesh确保所有组件特别是chaos-controller-manager和chaos-daemon都处于Running状态。如果有CrashLoopBackOff或Error状态的 Pod需要先查看其日志。kubectl logs -f -n chaos-mesh deployment/chaos-controller-manager --tail100重点关注日志中是否有权限错误、连接 API Server 失败、或者处理具体实验时的报错如failed to apply chaos。审查实验资源对象 即使你在 Dashboard 上点击了停止也要通过命令行确认实验 CRD 对象的状态。# 查看所有混沌实验 kubectl get chaos -A # 查看某个特定实验的详细定义和状态 kubectl get networkchaos experiment-name -n namespace -o yaml在输出的 YAML 中你需要特别关注几个字段spec.paused: 是否为true。如果为true则实验是暂停状态故障会持续。metadata.deletionTimestamp: 如果这个字段存在说明资源正在删除中但可能遇到了阻塞Finalizer。status.experiment.phase: 理想状态应为Finished或空。如果是Running但实验理应结束则有问题。status.conditions: 查看最新的条件信息可能提示错误原因。检查 Finalizer关键步骤 Kubernetes 资源的 Finalizer 是导致资源无法被正常删除、进而阻止控制器执行清理操作的常见原因。查看实验对象的 Finalizer 字段kubectl get networkchaos experiment-name -n namespace -o jsonpath{.metadata.finalizers}如果输出类似[finalizers.chaos-mesh.org]且资源卡在删除中这通常是 Chaos Mesh 控制器未能成功执行清理逻辑所致。控制器需要先完成清理如恢复 iptables 规则才能移除 Finalizer。如果控制器异常这个步骤就会挂起。2.3 第二步深入目标工作负载与节点如果控制面看起来正常那么问题可能出在故障实际注入的目标上。检查目标 Pod 及其所在节点kubectl describe pod target-pod -n namespace查看 Events 部分是否有与 chaos-daemon 交互相关的错误。同时检查 Pod 是否运行在正常的节点上节点是否Ready。登录节点进行现场取证针对网络故障 对于NetworkChaos其本质是通过在目标 Pod 的 Network Namespace 中操作 iptables、tc 等工具来实现的。如果自动恢复失败这些规则可能残留。首先找到目标 Pod 所在的节点。登录该节点并找到目标 Pod 的容器 PID 和其网络命名空间。# 在节点上执行 crictl ps | grep target-pod-name # 获取容器ID后取得其PID crictl inspect container-id | grep pid # 进入该容器的网络命名空间 nsenter -n -t pid # 现在你就在Pod的网络空间里了。检查iptables规则和tc qdisc。 iptables-save | grep -i chaos tc qdisc show如果你看到了非预期的、带有chaos标签的 iptables 规则或 tc 队列这就是铁证。例如一个残留的tc filter规则可能导致网络延迟持续。检查 Chaos Daemon 的 Sidecar 注入针对 IO/Stress 故障 对于IOChaos或StressChaosChaos Mesh 可能会向目标 Pod 注入一个 sidecar 容器chaosfs或stress-ng。实验结束后这个 sidecar 应该被清理。检查目标 Pod 的容器列表kubectl get pod target-pod -n namespace -o jsonpath{.spec.containers[*].name}如果列表中仍然包含chaosfs等容器说明 sidecar 未被成功移除。3. 根因分析与分类应对策略通过上述排查我们通常能将问题定位到几个具体的场景。下面我将其归纳为几类根因并给出相应的解决思路。3.1 控制器异常或资源处理阻塞这是最可能的原因之一。表现实验 CRD 对象卡在删除中有deletionTimestampFinalizer 无法移除。Chaos Controller Manager 日志中有重复的错误信息。根因控制器 Pod 异常控制器可能因为内存不足OOM、与 Kubernetes API 服务器通信问题而重启或失效。权限问题Chaos Mesh 的 ServiceAccount 权限RBAC不足无法完成某些清理操作。依赖资源缺失例如清理网络规则时需要操作某个已不存在的网络设备。应对策略首先尝试恢复控制器重启chaos-controller-manager的 Pod。kubectl delete pod -n chaos-mesh -l app.kubernetes.io/componentcontroller-manager如果重启后问题依旧需要检查 RBAC。确保 Chaos Mesh 安装时使用的 ClusterRole 拥有对目标资源如 pods, networkpolicies的update和patch权限。对于卡死的实验对象可以尝试强制移除 Finalizer这是一个有风险的操作需谨慎并确保后续手动清理kubectl patch networkchaos/experiment-name -n namespace --type json --patch[{op: remove, path: /metadata/finalizers}]执行此操作前务必记录下残留的故障规则如上述节点取证步骤因为控制器将不再负责清理需要你手动处理。3.2 节点级故障规则残留这在网络混沌实验中尤为常见。表现实验对象已删除但目标 Pod 网络依然异常。通过nsenter在 Pod 网络命名空间内查看到残留的 iptables 规则或 tc 配置。根因chaos-daemon在节点上执行故障注入和恢复。如果 daemon 进程在处理恢复时崩溃、被杀死或者与控制器通信中断就可能留下“孤儿”规则。应对策略手动清理节点规则。这是本次分享的核心实操部分。对于 iptables 规则在 Pod 的网络命名空间内使用iptables -D chain rule-specification逐条删除标识为 chaos 的规则。更安全的方法是先备份再清空特定链。# 在Pod网络命名空间内执行 iptables-save | grep -v chaos /tmp/iptables.backup iptables-restore /tmp/iptables.backup # 或者更精准地删除CHAOS链如果存在 iptables -F CHAOS_INPUT # 清空链 iptables -X CHAOS_INPUT # 删除链对于 tc (Traffic Control) 规则使用tc qdisc del命令删除之前添加的队列规则。# 查看网卡上的qdisc通常设备是eth0 tc qdisc show dev eth0 # 删除根qdisc会恢复为默认的pfifo_fast请根据实际情况替换handle tc qdisc del dev eth0 root3.3 Sidecar 容器残留表现目标 Pod 的容器数量多于预期包含chaosfs等容器。Pod 可能无法正常终止或重建。根因负责注入和清理 sidecar 的 Kubernetes Mutating Webhook由 Chaos Mesh 提供可能未正常工作或者 Pod 的更新请求被拒绝。应对策略最直接的方法是重建目标 Pod。kubectl delete pod target-pod -n namespaceKubernetes 控制器如 Deployment会自动创建一个新的、干净的 Pod。如果 Pod 非常重要不能删除可以尝试手动编辑 Pod 配置移除 sidecar 容器定义。但注意直接kubectl edit一个由 Deployment 管理的 Pod 是无效的需要修改对应的 Deployment 模板并让 Pod 滚动更新。kubectl edit deployment deployment-name -n namespace在spec.template.spec.containers中移除与 chaos 相关的容器定义保存后触发滚动更新。3.4 资源竞争或状态不一致表现多个混沌实验同时作用于同一目标或者一个实验的恢复过程与另一个实验的注入过程产生竞争。根因Chaos Mesh 控制器是并发处理事件的在极端情况下可能产生状态竞争。应对策略暂停所有针对同一目标的混沌实验。按顺序逐个删除实验并观察恢复情况。在设计混沌实验时尽量避免对同一资源对象的复杂、交叉干扰。4. 标准化清理操作流程与实操脚本基于以上分析我总结了一套标准化的清理流程并附上可操作的脚本片段。请务必按照顺序进行并在操作前做好备份。4.1 流程总览确认与记录确认故障现象记录受影响的命名空间、Pod、实验名称。检查控制面检查 Chaos Mesh 组件状态和实验对象状态。尝试优雅恢复重启控制器等待其自动恢复。强制移除阻塞若优雅恢复失败备份后强制移除实验对象的 Finalizer。手动清理节点登录节点清理残留的网络或内核规则。清理工作负载重建 Pod 或更新工作负载以移除残留 sidecar。验证与复盘验证业务恢复并复盘根本原因。4.2 实操脚本节点网络规则清理假设我们已经定位到node-1上的 Podapp-1-abcde存在残留网络规则。#!/bin/bash # 清理节点上指定Pod的残留Chaos Mesh网络规则 # 使用方法./cleanup_chaos_residue.sh node-name pod-name namespace NODE$1 POD$2 NAMESPACE$3 if [ -z $NODE ] || [ -z $POD ] || [ -z $NAMESPACE ]; then echo Usage: $0 node-name pod-name namespace exit 1 fi echo 开始清理 $NAMESPACE/$POD 在节点 $NODE 上的残留规则 # 1. 获取Pod在节点上的容器ID和PID通过kubectl debug node或假设你有节点ssh权限 # 这里以通过crictl在节点上执行为例。你需要先ssh到目标节点或者使用kubectl debug node。 # 以下命令需要在目标节点上运行。 # 通过crictl找到容器注意节点上需安装crictl CONTAINER_ID$(crictl ps --name $POD -o json | jq -r .containers[0].id) if [ -z $CONTAINER_ID ] || [ $CONTAINER_ID null ]; then echo 错误未在节点 $NODE 上找到Pod $POD 的容器。 exit 1 fi PID$(crictl inspect $CONTAINER_ID | jq -r .info.pid) if [ -z $PID ] || [ $PID null ]; then echo 错误无法获取容器 $CONTAINER_ID 的PID。 exit 1 fi echo 找到容器PID: $PID # 2. 进入网络命名空间清理iptables # 创建一个临时脚本来在Pod网络空间内执行 CLEANUP_SCRIPT$(mktemp) cat $CLEANUP_SCRIPT EOF #!/bin/sh echo 正在Pod网络命名空间内清理iptables规则... # 备份当前规则 iptables-save /tmp/iptables_backup_$(date %s).rules # 删除所有包含chaos关键词的规则谨慎请先确认grep结果 iptables-save | grep -i chaos | while read line; do # 这里简化处理实际生产环境应更精确地解析和删除每条规则 echo 发现规则: $line # 示例对于 -A CHAOS_INPUT 这样的规则需要更复杂的解析来删除 # 更安全的方式是清空自定义的CHAOS链如果存在 done # 尝试清空和删除常见的Chaos Mesh链 for chain in CHAOS_INPUT CHAOS_OUTPUT CHAOS_FORWARD; do if iptables -L $chain /dev/null 21; then echo 清空并删除链: $chain iptables -F $chain iptables -X $chain fi done echo iptables清理完成。 echo 正在检查并清理tc qdisc... # 清理tc规则通常针对eth0但可能是其他接口 DEVICEeth0 if tc qdisc show dev $DEVICE | grep -q chaos; then echo 发现残留的tc qdisc正在清理... # 删除根qdisc这会恢复默认设置。请确保这是你想要的操作。 tc qdisc del dev $DEVICE root 2/dev/null || echo 删除根qdisc失败可能已不存在。 fi echo tc清理完成。 EOF chmod x $CLEANUP_SCRIPT # 3. 在Pod的网络命名空间中执行清理脚本 nsenter -n -t $PID -- $CLEANUP_SCRIPT # 4. 清理临时文件 rm -f $CLEANUP_SCRIPT echo 清理流程执行完毕 echo **请务必手动验证Pod的网络连接是否恢复。**重要提示此脚本为示例模板直接在生产环境运行前必须在测试环境验证并根据你的实际集群环境容器运行时、网络插件进行调整。尤其是tc qdisc del命令操作不当可能导致网络中断。4.3 集群级批量检查与清理对于大规模集群你可能需要一种批量检查 Chaos 实验残留的方法。#!/bin/bash # 检查所有命名空间中状态异常的Chaos实验 for chaos_type in networkchaos podchaos stresschaos iochaos kernelchaos; do echo 检查 $chaos_type... # 查找所有非Finished、非空状态的实验 kubectl get $chaos_type -A -o jsonpath{range .items[?(.status.experiment.phase!Finished .status.experiment.phase)]}{.metadata.namespace}/{.metadata.name}: {.status.experiment.phase}{\n}{end} done # 查找所有带有删除时间戳但未消失的实验卡在Finalizer kubectl get chaos -A -o json | jq -r .items[] | select(.metadata.deletionTimestamp!null) | \(.metadata.namespace)/\(.metadata.name) (\(.metadata.deletionTimestamp))5. 预防措施与最佳实践排查和清理是“亡羊补牢”更重要的是“防患于未然”。根据我的踩坑经验遵循以下实践能极大降低自动恢复失败的概率升级到稳定版本始终使用 Chaos Mesh 的稳定版本并关注其 Release Notes 中关于 Bug 修复的部分。社区活跃很多已知的恢复问题在新版本中已修复。精细化 RBAC 权限为 Chaos Mesh 的 ServiceAccount 配置足够但不过度的权限。确保其能够对目标资源Pod、NetworkPolicy等进行create、patch、update、delete操作。权限不足是控制器操作失败的常见原因。设置合理的实验范围与时长避免“核弹”实验不要一开始就对核心生产服务进行破坏性极强的实验。从小范围、非关键服务开始。使用duration和terminationGracePeriodSeconds为实验设置明确的持续时间并为 Pod 故障实验设置合理的优雅终止周期给恢复留出时间窗口。考虑使用paused属性先创建paused: true的实验检查注入目标是否正确然后再启用。加强监控与告警监控 Chaos Mesh 控制器将chaos-controller-manager和chaos-daemon的 Pod 状态、日志错误率纳入监控。监控实验状态对 Chaos 实验 CRD 的状态字段status.experiment.phase进行监控如果Running状态超过预期时长或出现Failed状态立即告警。监控目标应用在注入混沌故障时同步加强对目标应用关键指标延迟、错误率、吞吐量的监控确保能第一时间感知到“未恢复”的异常。制定并演练应急预案将本文所述的排查和清理步骤固化为团队的应急预案。定期进行混沌工程演练不仅要演练故障注入也要演练故障恢复包括自动恢复失败的手动干预。在非生产环境充分测试任何新的混沌实验类型或复杂场景先在开发或测试集群进行充分验证观察其注入和恢复的全过程是否平滑确认无误后再应用于生产环境。混沌工程的目的不是制造混乱而是通过受控的实验来建立对系统韧性的信心。当自动恢复失效时冷静、系统化的排查能力正是这种信心的最后一道坚实防线。掌握这些手动干预的技能并不意味着自动化的失败而是意味着你对系统的理解更深了一层对生产环境的掌控力更强了一分。每一次成功的“救火”都是对系统行为和运维流程的一次宝贵复盘其价值不亚于一次成功的混沌实验本身。

本月热点