{"owner":"chaosblade-io","repo":"chaosblade","hasSkills":true,"totalSkillsCount":38,"totalTokensCount":39728,"categories":["anthropic-skill"],"hasMcp":false,"mcpConfig":null,"found":["blade-ai/skills/k8s-chaos-skills/SKILL.md","blade-ai/skills/k8s-chaos-skills/references/catalogue/DNS_解析失败/DNS_解析失败_CoreDNS异常.md","blade-ai/skills/k8s-chaos-skills/references/catalogue/DaemonSet_未完全调度/DaemonSet_未完全调度_节点不可调度.md","blade-ai/skills/k8s-chaos-skills/references/catalogue/HPA_副本达到上限/HPA_副本达到上限_资源饱和.md","blade-ai/skills/k8s-chaos-skills/references/catalogue/Node_CPU使用率过高/Node_CPU使用率过高_异常进程占用.md","blade-ai/skills/k8s-chaos-skills/references/catalogue/Node_不可用/Node_不可用_节点宕机.md","blade-ai/skills/k8s-chaos-skills/references/catalogue/Node_内存使用率过高/Node_内存使用率过高_异常进程占用.md","blade-ai/skills/k8s-chaos-skills/references/catalogue/Node_磁盘IO过高/Node_磁盘IO过高_异常IO占用.md","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_CPU_Throttling/Pod_CPU_Throttling_limits.cpu过低.md","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_ContainerCreating/Pod_ContainerCreating_CNI分配失败.md","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_ContainerCreating/Pod_ContainerCreating_Volume挂载超时CSI异常.md","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_ContainerCreating/Pod_ContainerCreating_云盘挂载超时或冲突.md","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_ContainerCreating/Pod_ContainerCreating_容器运行时异常.md","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_CrashLoopBackOff/Pod_CrashLoopBackOff_LivenessProbe配置不合理.md","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_CrashLoopBackOff/Pod_CrashLoopBackOff_StartupProbe配置不足.md","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_OOM内存异常/Pod_OOM内存异常_limit单位写错.md","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_OOM内存异常/Pod_OOM内存异常_内存压力过大.md","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_Pending/Pod_Pending_PVC未绑定.md","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_Pending/Pod_Pending_拓扑约束过严.md","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_Pending/Pod_Pending_节点Taint无对应Toleration.md","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_Terminating/Pod_Terminating_Finalizers未清理.md","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_Terminating/Pod_Terminating_Volume卸载失败.md","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_Terminating/Pod_Terminating_网卡卸载失败.md","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_Terminating/Pod_Terminating_节点宕机kubelet失联.md","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_cpu使用率过高/Pod_cpu使用率过高_应用性能问题.md","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_云盘空间打满/Pod_云盘空间打满_日志未清理.md","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_磁盘空间使用率过高/Pod_磁盘空间使用率过高_应用日志数据积累.md","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_网络丢包/Pod_网络丢包_服务依赖中断.md","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_被驱逐重建/Pod_被驱逐重建_DiskPressure.md","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_镜像拉取失败/Pod_镜像拉取失败_凭证缺失或过期.md","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_镜像拉取失败/Pod_镜像拉取失败_镜像不存在或标签错误.md","blade-ai/skills/k8s-chaos-skills/references/catalogue/Service_调用失败/Service_调用失败_ReadinessProbe配置不一致.md","blade-ai/skills/k8s-chaos-skills/references/catalogue/Service_调用失败/Service_调用失败_kube-proxy异常.md","blade-ai/skills/k8s-chaos-skills/references/catalogue/Service_调用失败/Service_调用失败_selector不匹配.md","blade-ai/skills/k8s-chaos-skills/references/catalogue/Service_负载均衡异常/Service_负载均衡异常_后端不可达.md","blade-ai/skills/k8s-chaos-skills/references/catalogue/workload_副本被缩容/workload_副本被缩容_人为误操作.md","blade-ai/skills/k8s-chaos-skills/references/catalogue/节点容器运行时磁盘使用率过高/节点容器运行时磁盘使用率过高_日志或临时文件堆积.md","blade-ai/skills/k8s-chaos-skills/references/chaosblade-commands.md"],"skills":{"blade-ai/skills/k8s-chaos-skills/SKILL.md":"---\nname: k8s-chaos-skills\ndescription: |\n  Kubernetes 故障演练与混沌工程专家。当用户需要进行 K8s 故障注入测试、混沌工程演练、系统韧性验证、故障场景模拟时，立即使用此 skill。\n\n  内置多个标准化故障注入用例，覆盖 Pod（Pending、CrashLoopBackOff、OOM、CPU 满载、内存接近 Limit、磁盘满、Terminating 卡住、镜像拉取失败等）、Workload（副本不一致、HPA 副本达到上限、DaemonSet 未完全调度）、Service（状态异常、负载均衡异常）、Node（宕机、磁盘使用率过高、磁盘 IO 过高、CPU 使用率过高、内存使用率过高）、存储（PVC 挂载 Pending）五个层级。\n\n  通过「意图识别 → 用例选择 → 用例执行」的决策树流程，精确匹配用户需求并执行对应演练方案。即使用户只是笼统地说「帮我做个故障演练」或「测试下应用的容错能力」，也应该触发此 skill 引导用户完成完整流程。\n\nscripts:\n  - name: list_scenarios.py\n    description: \"列出当前支持的所有故障演练场景（JSON 结构化输出）\"\n  - name: inject_cni_exhaust.py\n    description: \"CNI IP 耗尽注入 — 自动计算副本数，精确耗尽目标节点 IP 而不触发 OutOfpods。参数: --namespace <ns> --node <node> --kubeconfig <path>\"\n---\n\n# K8s 故障演练\n\n```\n意图识别 ──→ 用例选择 ──→ 用例执行\n(提取四维度)  (决策树匹配)  (读取文件并按步骤执行)\n```\n\n## 安全红线\n\n以下规则优先级高于一切操作指令，在任何步骤中都不得违反：\n\n- **隔离**：在隔离命名空间或测试集群演练，严禁在生产核心链路注入\n- **最小影响**：用精确标签选择器定位目标，范围尽可能小\n- **可回滚**：注入前明确回滚方案，确保 30 秒内可恢复\n- **有监控**：无监控不演练\n- **仅限已有用例**：只能执行 `references/catalogue/` 中已有的故障注入用例，严禁自行编造、拼凑或即兴发挥用例中未涉及的故障注入操作。无法匹配时必须明确告知用户「当前不支持该场景」并停止\n- **禁止**：业务高峰期演练 / 对 etcd、kube-apiserver 等控制平面注入 / 无备份对 StatefulSet 做破坏性实验\n\n---\n\n## 第一步：意图识别\n\n从用户输入中提取四个维度：\n\n| 维度 | 说明 | 示例 |\n|------|------|------|\n| **故障层级** | 作用在哪个层面 | Pod / Workload / Service / Node |\n| **故障现象** | 期望模拟的表现 | Pending、OOM、CPU 高 |\n| **故障原因** | 具体根因 | 资源不足、配置错误 |\n| **目标应用** | 注入目标 | 应用名、命名空间 |\n| **kubeconfig** | 集群凭证路径 | `~/.kube/config` |\n\n**层级判断关键词：**\n\n| 关键词 | 层级 |\n|--------|-----|\n| pod、容器、崩溃、重启、OOM、CPU高、内存高、镜像、挂载、磁盘空间、磁盘IO | Pod |\n| 副本、deployment、扩容、缩容 | Workload |\n| service、服务发现、负载均衡、端口、endpoints | Service |\n| 节点、node、磁盘、宿主机 | Node |\n\n**信息不全时的处理：**\n- 用户明确说出故障现象 → 直接进入第二步\n- 用户只说大致目标（如「测试容错」） → 提问引导确认四个维度\n- 用户描述生产问题要复现 → 从描述提取现象和原因，匹配用例\n- 匹配到多个用例 → 列出候选，让用户选择\n- 只说了现象没说根因 → 推荐该分类下最常见的用例，并列出其他选项\n- 不在覆盖范围 → 明确告知「当前不支持该场景」，停止操作，严禁自行构造用例外的故障注入\n\n---\n\n## 第二步：用例选择（动态发现）\n\n所有用例存储在 `references/catalogue/` 下，通过目录结构和文件命名规约自动发现，无需维护静态索引。\n\n### 命名规约\n\n```\nreferences/catalogue/\n├── <故障分类>/                         # 目录名 = 故障层级_故障现象（每个目录对应唯一的 Scope+Target+Action 组合）\n│   ├── <故障分类>_<根因A>.md           # 文件名 = 分类名_具体根因\n│   ├── <故障分类>_<根因B>.md\n│   └── ...\n└── ...\n```\n\n示例：\n- `references/catalogue/Pod_Pending/Pod_Pending_节点资源不足.md`\n- `references/catalogue/Pod_磁盘空间使用率过高/Pod_磁盘空间使用率过高_应用日志数据积累.md`（pod-disk fill）\n- `references/catalogue/Pod_磁盘IO过高/Pod_磁盘IO过高_异常IO占用.md`（pod-disk burn）\n\n### 发现流程\n\n**第 1 步：列出所有分类目录，匹配故障现象**\n\n```bash\nls references/catalogue/\n```\n\n从返回的目录名中，根据第一步识别的故障现象选择最匹配的目录。目录名本身已包含故障层级和故障现象信息（如 `Pod_Pending`、`service_conditions状态异常`、`节点容器运行时磁盘使用率过高`）。\n\n**第 2 步：列出该目录下所有用例文件，匹配根因**\n\n```bash\nls references/catalogue/<匹配的目录>/\n```\n\n从返回的文件名中，根据用户描述的根因选择最匹配的文件。文件名中 `_` 后的部分即为该用例对应的根因。\n\n- 如果用户明确了根因 → 直接选择对应文件\n- 如果用户未说明根因 → 将文件列表展示给用户，让用户选择\n- 如果没有匹配的文件 → 告知用户「当前不支持该场景」，停止操作\n\n### 新增/删除用例\n\n遵循命名规约即可，无需修改本文件：\n- **新增用例**：在对应分类目录下新建 `<分类>_<根因>.md`\n- **新增分类**：新建目录 `<故障层级>_<故障现象>/`，在其中添加用例文件\n- **删除用例**：直接删除对应 `.md` 文件\n\n### 辅助脚本\n\n- `scripts/list_scenarios.py`：一键列出所有已支持的演练场景（JSON 结构化输出），用于快速总览或对接外部系统\n  用法：`execute_skill_script(skill_name=\"k8s-chaos-skills\", script_name=\"list_scenarios.py\")`\n\n---\n\n## 第三步：用例执行\n\n1. 读取 `references/catalogue/<分类目录>/<用例文件>.md`\n2. 将用例中的占位符替换为用户实际参数（`应用 A` → 目标应用，`<namespace>` → 实际命名空间）\n3. 所有 `blade` 和 `kubectl` 命令必须显式指定 `--kubeconfig <路径>`，使用第一步中用户确认的 kubeconfig 路径，禁止依赖默认值\n4. 涉及 blade 命令时，查阅 `references/chaosblade-commands.md` 获取完整参数\n5. 严格按用例中的 **演练步骤 → 注入验证 → 注入恢复 → 恢复验证** 顺序执行\n6. 执行完毕后输出演练报告：\n\n```\n演练报告\n- 用例：[决策树路径，如 Pod > Pending > 节点资源不足]\n- 目标：[namespace/app-name]\n- 注入结果：[成功/失败] + 观察到的现象\n- 恢复结果：[成功/失败] + 是否符合基准事实\n- 发现的问题与改进建议\n```\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/DNS_解析失败/DNS_解析失败_CoreDNS异常.md":"**用例名称** CoreDNS异常 导致 DNS_解析失败\n\n**故障现象**：\n1. Pod 内 DNS 解析失败，应用报 `Name or service not known` 或 `NXDOMAIN` 错误\n2. CoreDNS Pod 异常（CrashLoopBackOff/不可用）\n3. 集群内服务间调用因 DNS 解析失败而中断\n\n**资源准备**：\n1. 确认应用 A 已正常运行，且依赖集群 DNS 进行服务发现\n2. 确认 CoreDNS Deployment 正常运行\n3. 确认监控系统可观测 DNS 请求指标\n\n**演练步骤**：\n1. 记录 CoreDNS Deployment 当前副本数和配置，并获取其 Pod 选择器标签：\n   ```bash\n   kubectl get deployment coredns -n kube-system -o jsonpath='{.spec.selector.matchLabels}'\n   ```\n   记录返回的标签（如 `component=coredns` 或 `k8s-app=kube-dns`），后续步骤中用 `<coredns-label>` 表示该标签\n2. 将 CoreDNS Deployment 的副本数缩为 0，模拟 CoreDNS 完全不可用：\n   ```bash\n   kubectl scale deployment coredns -n kube-system --replicas=0\n   ```\n3. 在应用 A 的 Pod 内尝试进行 DNS 解析\n4. 观察应用 A 的服务间调用行为\n\n**注入验证**：\n1. 执行 `kubectl get pods -n kube-system -l <coredns-label>`（使用演练步骤 1 中获取的实际标签），确认无 CoreDNS Pod 运行\n2. 在应用 A 的 Pod 内执行 DNS 解析测试：\n   ```bash\n   kubectl exec <pod-name> -- nslookup kubernetes.default.svc.cluster.local\n   ```\n   确认解析失败\n3. 确认应用 A 依赖 DNS 的服务调用出现错误\n\n**注入恢复**：\n1. 恢复 CoreDNS 副本数：\n   ```bash\n   kubectl scale deployment coredns -n kube-system --replicas=<原始副本数>\n   ```\n2. 等待 CoreDNS Pod 启动并就绪\n\n**恢复验证**：\n1. 执行 `kubectl get pods -n kube-system -l <coredns-label>`（使用演练步骤 1 中获取的实际标签），确认 CoreDNS Pod 全部 Running 且 Ready\n2. 在应用 A 的 Pod 内重新执行 DNS 解析，确认恢复正常\n3. 确认应用 A 的服务间调用恢复\n\n**基准事实**：\n- **根因**：CoreDNS Pod 异常或不可用，导致集群内 DNS 解析服务中断，依赖 DNS 的服务发现和调用全部失败\n- **必现现象**：Pod 内 DNS 解析超时或返回 NXDOMAIN；CoreDNS Pod 不可用；服务间调用失败\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/DaemonSet_未完全调度/DaemonSet_未完全调度_节点不可调度.md":"**用例名称** 节点不可调度 导致 DaemonSet_未完全调度\n\n**故障现象**：\n1. DaemonSet 的 Ready 副本数小于期望副本数\n2. 部分节点上没有运行 DaemonSet Pod\n3. `kubectl get daemonset` 显示 DESIRED 与 READY 数量不一致\n\n**资源准备**：\n1. 确认 DaemonSet 应用 A 已正常运行，且所有节点均有副本\n2. 确认监控系统可观测 DaemonSet 副本状态\n\n**演练步骤**：\n1. 选取一个运行 DaemonSet Pod 的节点\n2. 使用 kubectl 将该节点标记为不可调度（cordon）：`kubectl cordon <node>`\n3. 给该节点添加一个 DaemonSet 未配置容忍的自定义污点：`kubectl taint nodes <node> chaos-drill/unschedulable=true:NoSchedule`\n4. 删除该节点上的 DaemonSet Pod，观察 Pod 是否被重建\n5. 观察 DaemonSet 副本数变化\n\n**注入验证**：\n1. 执行 `kubectl get nodes`，确认目标节点标记为 SchedulingDisabled\n2. 执行 `kubectl describe node <node>`，确认自定义污点 `chaos-drill/unschedulable=true:NoSchedule` 存在\n3. 执行 `kubectl get daemonset`，确认 DESIRED 与 READY 数量不一致\n4. 确认目标节点上的 DaemonSet Pod 删除后无法被重建\n\n**注入恢复**：\n1. 使用 kubectl 取消节点不可调度标记（uncordon）：`kubectl uncordon <node>`\n2. 移除自定义污点：`kubectl taint nodes <node> chaos-drill/unschedulable=true:NoSchedule-`\n3. 等待 DaemonSet Pod 在该节点重建\n\n**恢复验证**：\n1. 执行 `kubectl get nodes`，确认目标节点恢复为可调度状态\n2. 执行 `kubectl describe node <node>`，确认自定义污点已被移除\n3. 执行 `kubectl get daemonset`，确认 DESIRED 与 READY 数量一致\n4. 确认目标节点上 DaemonSet Pod 已正常运行\n\n**注意事项**：\n- Kubernetes ≥ 1.12 的 DaemonSet 默认容忍 `node.kubernetes.io/unschedulable` 污点，因此 `kubectl cordon` 不会阻止 DaemonSet Pod 调度\n- 必须添加自定义污点（DaemonSet 未配置容忍的），才能有效阻止 Pod 调度\n- 恢复时需一并移除自定义污点，否则 Pod 仍无法调度\n\n**基准事实**：\n- **根因**：节点被标记为不可调度（cordon）且存在 DaemonSet 未容忍的自定义污点，导致 DaemonSet 无法在该节点创建 Pod，副本数小于期望数\n- **必现现象**：DaemonSet DESIRED 与 READY 不一致；节点 SchedulingDisabled；节点存在自定义污点；节点上缺少 DaemonSet Pod\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/HPA_副本达到上限/HPA_副本达到上限_资源饱和.md":"**用例名称** 资源饱和 导致 HPA_副本达到上限\n\n**故障现象**：\n1. HPA 的当前副本数达到 maxReplicas 上限，无法继续扩容\n2. 应用 CPU 或内存使用率仍持续高于 HPA 目标阈值\n3. 应用响应延迟增大，出现超时\n\n**资源准备**：\n1. 确认应用 A 已正常运行，且已配置 HPA（设置合适的 maxReplicas 以便快速触发上限）\n2. 确认监控系统可观测 HPA 状态和 Pod CPU/内存指标\n\n**演练步骤**：\n1. 定位应用 A 的 HPA，记录 maxReplicas 配置\n2. 使用 chaosblade 对应用 A 的所有 Pod 注入 CPU 压力，持续超过 HPA 扩容阈值\n3. 观察 HPA 扩容行为，等待副本数达到 maxReplicas 上限\n\n**注入验证**：\n1. 执行 `kubectl get hpa`，确认 REPLICAS 已达到 MAXPODS 上限\n2. 查看 HPA Event，确认出现 `FailedGetScale` 或 `DesiredReplicas` 超过 maxReplicas 的告警\n3. 查看 Pod CPU 使用率，确认仍持续高于目标阈值\n4. 确认应用 A 的请求延迟增大，出现超时\n\n**注入恢复**：\n1. 销毁 chaosblade CPU 压力实验\n2. 等待 HPA 自动缩容\n\n**恢复验证**：\n1. 执行 `kubectl get hpa`，确认 REPLICAS 回落至正常水平\n2. 查看 Pod CPU 使用率，确认恢复到 HPA 目标阈值以下\n3. 确认应用 A 的请求延迟恢复正常\n\n**基准事实**：\n- **根因**：应用负载超过 HPA 的 maxReplicas 能覆盖的处理能力，HPA 达到扩容上限后无法继续扩容，导致服务资源饱和\n- **必现现象**：HPA REPLICAS 达到 MAXPODS；HPA Event 有超限告警；CPU 使用率持续超过目标阈值；应用性能下降\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Node_CPU使用率过高/Node_CPU使用率过高_异常进程占用.md":"**用例名称** 异常进程占用 导致 Node_CPU使用率过高\n\n**故障现象**：\n1. 节点 CPU 使用率持续超过 90%\n2. 节点上 Pod 响应变慢，出现超时\n3. Load Average 显著升高\n\n**资源准备**：\n1. 确认应用 A 已正常运行\n2. 确认监控系统（如 Prometheus）已配置，可观测节点 CPU 指标\n\n**演练步骤**：\n1. 定位运行应用 A 的节点\n2. 使用 chaosblade 对该节点注入 CPU 满载，模拟异常进程占用节点 CPU\n3. 观察节点 CPU 使用率及 Pod 性能变化\n\n**注入验证**：\n1. 查看节点 CPU 使用率监控，确认持续超过 90%\n2. 查看 Load Average，确认显著升高\n3. 确认应用 A 的请求延迟增大\n\n**注入恢复**：\n1. 销毁 chaosblade 实验\n\n**恢复验证**：\n1. 查看节点 CPU 使用率监控，确认恢复到正常水平\n2. 确认应用 A 的请求延迟恢复正常\n\n**基准事实**：\n- **根因**：节点上存在异常进程大量占用 CPU，导致节点 CPU 使用率过高，影响同节点上所有 Pod 的性能\n- **必现现象**：节点 CPU 使用率持续超过 90%；Load Average 显著升高；同节点 Pod 响应变慢\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Node_不可用/Node_不可用_节点宕机.md":"**用例名称** 节点宕机 导致 Node_不可用\n\n**故障现象**：\n1. 节点状态变为 NotReady\n2. 节点上所有 Pod 无法访问\n3. kubelet 停止上报节点状态，NodeStatus 中 LastHeartbeatTime 停止更新\n4. Pod 在其他节点上被重建\n\n**资源准备**：\n1. 确认应用 A 已正常运行，且有多个副本分布在不同节点\n2. 确认监控系统可观测节点状态和 Pod 状态\n\n**演练步骤**：\n1. 定位运行应用 A 的节点\n2. 使用 chaosblade 对该节点注入网络完全丢包（node-network drop 即全量丢包，不需要 --percent），并设置 `--timeout 600`（600 秒后自动恢复），模拟节点与集群失联的宕机场景\n3. 观察节点状态和 Pod 调度行为变化\n\n**注入验证**：\n1. 执行 `kubectl get nodes`，确认目标节点状态变为 NotReady\n2. 查看 NodeStatus，确认 LastHeartbeatTime 停止更新\n3. 确认节点上应用 A 的 Pod 在其他节点上被重建\n4. 确认应用 A 的服务整体仍可访问（多副本场景）\n\n**注入恢复**：\n1. 等待 chaosblade 实验自动超时恢复（600 秒内），agent 本地定时器会自动清理网络规则\n2. 如超时后仍未恢复，通过 `blade destroy <UID>` 或重启节点强制恢复\n\n**恢复验证**：\n1. 执行 `kubectl get nodes`，确认目标节点恢复 Ready\n2. 确认 LastHeartbeatTime 恢复更新\n3. 确认应用 A 的 Pod 恢复正常运行\n\n**基准事实**：\n- **根因**：节点网络完全中断，导致 kubelet 无法与 API server 通信，停止上报节点状态\n- **必现现象**：节点 NotReady；LastHeartbeatTime 停止更新；Pod 在其他节点被重建\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Node_内存使用率过高/Node_内存使用率过高_异常进程占用.md":"**用例名称** 异常进程占用 导致 Node_内存使用率过高\n\n**故障现象**：\n1. 节点内存使用率持续超过 90%\n2. 节点上 Pod 出现 OOMKilled 或被驱逐\n3. 节点 Status 出现 MemoryPressure 条件为 True\n\n**资源准备**：\n1. 确认应用 A 已正常运行\n2. 确认监控系统（如 Prometheus）已配置，可观测节点内存指标\n\n**演练步骤**：\n1. 定位运行应用 A 的节点\n2. 使用 chaosblade 对该节点注入内存压力，模拟异常进程占用节点内存\n3. 观察节点内存使用率及 Pod 状态变化\n\n**注入验证**：\n1. 查看节点内存使用率监控，确认持续超过 90%\n2. 执行 `kubectl describe node <节点名>`，确认 MemoryPressure 条件为 True\n3. 确认应用 A 的 Pod 出现 OOMKilled 或被驱逐\n\n**注入恢复**：\n1. 销毁 chaosblade 实验\n\n**恢复验证**：\n1. 查看节点内存使用率监控，确认恢复到正常水平\n2. 执行 `kubectl describe node <节点名>`，确认 MemoryPressure 条件为 False\n3. 确认应用 A 的 Pod 恢复正常运行\n\n**基准事实**：\n- **根因**：节点上存在异常进程大量占用内存，导致节点内存使用率过高，触发 MemoryPressure，Pod 被 OOMKilled 或驱逐\n- **必现现象**：节点内存使用率持续超过 90%；MemoryPressure 条件为 True；Pod 出现 OOMKilled 或被驱逐\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Node_磁盘IO过高/Node_磁盘IO过高_异常IO占用.md":"**用例名称** 异常IO占用 导致 Node_磁盘IO过高\n\n**故障现象**：\n1. 节点磁盘 IO 使用率持续过高（iostat 显示 %util 接近 100%）\n2. 节点上 Pod 的磁盘读写延迟增大，应用响应变慢\n3. iowait 占比升高\n\n**资源准备**：\n1. 确认应用 A 已正常运行\n2. 确认监控系统可观测节点磁盘 IO 指标\n\n**演练步骤**：\n1. 定位运行应用 A 的节点\n2. **路径校验（必须）**：注入前验证目标路径存在且可写：\n   - 通过 `kubectl exec <tool-pod> -n chaosblade -- ls -ld <磁盘路径>` 确认路径存在\n   - 如路径不存在，通过 `df -h` 查看可用挂载点，选择已存在的可写目录\n   - 常见可用路径：`/var/lib/containerd`、`/var/lib/docker`、`/tmp`、`/var/log`\n   - **禁止使用未校验的路径** — ChaosBlade 接受任意路径但底层 dd 进程会静默失败\n   - 不同路径可能对应不同的物理磁盘分区，注入前可通过 `df -h <路径>` 确认路径所在的设备\n3. 使用 chaosblade 对该节点注入磁盘 IO 负载：`blade create k8s node-disk burn --read --write --names <节点名> --path <已校验的磁盘路径> --timeout <秒> --kubeconfig <路径>`\n4. 观察节点磁盘 IO 指标及 Pod 性能变化\n\n**注入验证**：\n1. 查看节点磁盘 IO 负载指标：\n   - 优先：`iostat -xd 1 3`（关注 %util 接近 100%）\n   - BusyBox 备选：`iostat -d -k 1 3`（关注 tps 和 kB_wrtn/s/kB_read/s 异常升高）+ `iostat -c 1 3`（关注 %iowait 显著升高）\n   - 进程确认：`ps | grep dd` 确认 ChaosBlade 的 dd 压测进程在运行（若 dd 不存在，说明路径无效导致注入静默失败，需检查路径是否存在）\n   - **多磁盘注意**：`iostat` 显示节点上所有物理磁盘的 IO 指标。如果节点有多个磁盘（如 vda 用于 nodefs，vdb 用于 imagefs），需根据 `--path` 参数判断目标路径对应的物理磁盘，只关注该磁盘的指标变化\n2. 查看 iowait 占比，确认显著升高（`iostat -c` 或节点监控）\n3. 确认应用 A 的磁盘读写延迟增大（见下方 Pod 级验证方法）\n\n**Pod 级磁盘 IO 验证方法**：\n- 方法 1（推荐）：在目标节点上选一个 Running Pod，`kubectl exec <pod> -- dd if=/dev/zero of=/tmp/disk-io-test bs=1M count=100`，对比注入前后写入耗时\n- 方法 2：`kubectl exec <pod> -- df -h` 确认 Pod 所在容器的磁盘使用率（注意：显示的是 overlay 文件系统，非宿主机），`kubectl describe pod <pod>` 检查 Events 中是否有磁盘相关告警\n- 方法 3（容器无 dd 时）：`kubectl get events -n <ns> --field-selector involvedObject.name=<pod>` 观察是否有 IO 相关事件\n\n**注入恢复**：\n1. 销毁 chaosblade 实验\n\n**恢复验证**：\n1. 查看节点磁盘 IO 监控，确认 %util 恢复正常：\n   - 优先：`iostat -xd 1 3`\n   - BusyBox 备选：`iostat -d -k 1 3`（确认 tps/吞吐量回落）+ `iostat -c 1 3`（确认 %iowait 恢复基线）\n2. 确认 iowait 占比恢复正常\n3. 确认应用 A 的磁盘读写延迟恢复正常（使用 Pod 级验证方法中的 dd 写入测试，确认耗时恢复）\n\n**基准事实**：\n- **根因**：节点上存在异常进程大量占用磁盘 IO，导致磁盘 IO 使用率过高，影响同节点上所有 Pod 的磁盘读写性能\n- **必现现象**：节点磁盘 IO %util 接近 100%；iowait 占比升高；同节点 Pod 磁盘读写延迟增大\n\n**CRD 模式 overlay 文件系统关键说明**：\n- ChaosBlade K8s CRD 模式下，`node-disk burn --path /tmp` 的 dd 进程运行在 DaemonSet tool pod 内，\n  写入的是**容器 overlay 文件系统**（通常由 imagefs/vdb 支持），**而非宿主机 /tmp**（通常由 nodefs/vda3 支持）\n- **验证 burn 时不应该检查 /host/tmp/ 下的文件**：burn 产生的临时文件在 overlay 中，不会出现在宿主机路径\n- **df -h 对 burn 验证无效**：burn 产生的是 I/O 压力（临时文件会被自动清理），不会造成磁盘使用量持续增长。\n  用 df -h 验证 burn 可能导致误判为\"注入失败\"\n- **正确的 burn 验证方法**：通过 `/proc/diskstats` 两次采样（间隔 3-5 秒），计算写入吞吐量增量：\n  - 读取方法：`cat /proc/diskstats`，格式为 `major minor name reads reads_merged sectors_read ... sectors_written writes_merged sectors_written ...`\n  - 计算方式：delta(sectors_written) × 512 / 间隔秒数 / 1048576 = MB/s\n  - 判断标准：任何分区持续写入 >10MB/s 即表示 burn 在生效\n  - 注意跳过分区条目（如 vda1、vda3），只关注整盘设备（如 vda、vdb）\n- **fill 与 burn 的验证方法差异**：\n  - fill（空间填充）：df -h 是主要验证手段（填充产生持久数据，磁盘使用量增加）\n  - burn（IO 压力）：/proc/diskstats 是主要验证手段（burn 产生 IO 压力，不产生持久数据）\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_CPU_Throttling/Pod_CPU_Throttling_limits.cpu过低.md":"**用例名称** limits.cpu过低 导致 Pod_CPU_Throttling\n\n**故障现象**：\n1. Pod 内进程频繁被内核 CPU 节流（throttle），`cpu.stat` 中 `nr_throttled` 持续增长\n2. 应用请求延迟显著增大，P99 延迟飙升\n3. `kubectl top pod` 显示 CPU 使用率接近 limits 但实际未满载\n\n**资源准备**：\n1. 确认应用 A 已正常运行，且 Pod 配置了 resources.limits.cpu\n2. 确认监控系统可观测 Pod CPU 使用率及 throttle 指标\n\n**演练步骤**：\n1. 定位应用 A 的 Deployment\n2. 使用 kubectl patch 将应用 A 的 CPU limits 调低为极小值（如 50m），模拟 limits.cpu 配置过低的场景\n3. 使用 chaosblade 对应用 A 的 Pod 注入 CPU 负载，确保实际 CPU 需求超过 limits，触发内核 throttle\n4. 观察 Pod CPU throttle 指标变化及应用响应延迟\n\n**注入验证**：\n1. 进入容器查看 `/sys/fs/cgroup/cpu/cpu.stat`，确认 `nr_throttled` 和 `throttled_time` 持续增长\n2. 查看监控指标，确认 Pod CPU 使用率接近 limits\n3. 确认应用 A 的请求延迟显著增大\n\n**注入恢复**：\n1. 销毁 chaosblade CPU 负载实验\n2. 使用 kubectl patch 将应用 A 的 CPU limits 恢复为原始合理值\n\n**恢复验证**：\n1. 查看 `cpu.stat`，确认 `nr_throttled` 停止增长\n2. 确认应用 A 的请求延迟恢复正常\n\n**基准事实**：\n- **根因**：容器 limits.cpu 设置过低，实际 CPU 需求超过 limit，内核对容器 CPU 时间片进行 throttle，导致应用性能下降\n- **必现现象**：cpu.stat 中 nr_throttled 持续增长；应用延迟飙升；CPU 使用率接近 limits 上限\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_ContainerCreating/Pod_ContainerCreating_CNI分配失败.md":"**用例名称** CNI分配失败 导致 Pod_ContainerCreating\n\n**故障现象**：\n1. Pod 长时间停留在 ContainerCreating 状态\n2. Pod Events 中显示 `failed to allocate for ENI` 或 `no available IP in subnet` 或 CNI 相关错误\n3. 节点上的 IP 资源池耗尽或 ENI 数量达到上限\n\n**资源准备**：\n1. 确认应用 A 已正常运行\n2. 确认集群使用 ENI 或 vSwitch 分配 Pod IP 的 CNI 插件（如 Terway）\n\n**演练步骤**：\n1. 查看目标节点的 ENI 和 IP 分配情况，确认目标应用 Pod 所在节点（记为 `<目标节点>`）\n2. 给目标节点添加标签，并给应用 A 的 Deployment 添加 nodeSelector，确保新 Pod 只能调度到目标节点（防止调度器规避耗尽节点）：\n   ```bash\n   kubectl label node <目标节点> chaos-cni-target=true\n   kubectl patch deployment <deployment-name> -n <namespace> --type='merge' \\\n     -p='{\"spec\":{\"template\":{\"spec\":{\"nodeSelector\":{\"chaos-cni-target\":\"true\"}}}}}'\n   ```\n   等待 rollout 完成（Pod 仍在原节点运行，因为目标节点已有此标签）。\n   记录原始 nodeSelector 值，恢复时还原。\n3. 使用 `execute_skill_script` 在目标节点批量创建 Pod 耗尽 IP/ENI 资源（**`kubectl create/apply` 不可用，必须使用脚本**）：\n   ```\n   execute_skill_script(\n     skill_name=\"k8s-chaos-skills\",\n     script_name=\"inject_cni_exhaust.py\",\n     params=\"--namespace <namespace> --node <目标节点> --kubeconfig <kubeconfig路径>\"\n   )\n   ```\n   脚本会创建 `chaos-ip-exhaust` Deployment 并绑定到目标节点。\n4. 删除应用 A 在目标节点上的 Pod，触发重建。由于 nodeSelector 约束，新 Pod 只能调度到已耗尽的目标节点，将进入 ContainerCreating 状态\n5. 观察新 Pod 的 ContainerCreating 状态\n\n**注入验证**：\n1. 执行 `kubectl get pods`，确认应用 A 新 Pod 状态为 ContainerCreating\n2. 执行 `kubectl describe pod <pod-name>`，确认 Events 显示 CNI/IP 分配失败相关错误\n3. 查看节点 ENI/IP 使用情况，确认资源已耗尽\n\n**注入恢复**：\n1. 删除批量创建的 Deployment：`kubectl delete deployment chaos-ip-exhaust -n <namespace>`\n2. 移除应用 A 的 Deployment 上添加的 nodeSelector（还原为原始值，若原本无 nodeSelector 则移除整个 nodeSelector）\n3. 移除目标节点上添加的标签：`kubectl label node <目标节点> chaos-cni-target-`\n4. 等待 IP/ENI 资源释放和 Pod 滚动更新完成\n\n**恢复验证**：\n1. 执行 `kubectl get pods`，确认应用 A 的 Pod 状态恢复为 Running\n2. 确认节点 IP/ENI 资源恢复可用\n3. 确认应用 A 网络连通正常\n\n**基准事实**：\n- **根因**：节点可用 IP 池耗尽或 ENI 数量达到上限或 vSwitch IP 不足，CNI 插件无法为新 Pod 分配网络资源\n- **必现现象**：Pod ContainerCreating；Events 显示 CNI/IP/ENI 分配失败；节点网络资源耗尽\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_ContainerCreating/Pod_ContainerCreating_Volume挂载超时CSI异常.md":"**用例名称** Volume挂载超时CSI异常 导致 Pod_ContainerCreating\n\n**故障现象**：\n1. Pod 长时间停留在 ContainerCreating 状态\n2. Pod Events 中显示 `FailedMount` 或 `FailedAttachVolume`，提示 CSI driver 超时或可用区不匹配\n3. PV 对应的云盘与 Pod 调度的节点不在同一可用区\n\n**资源准备**：\n1. 确认应用 A 已正常运行，且使用了 CSI 驱动管理的存储卷\n2. 确认集群跨多个可用区部署\n\n**演练步骤**：\n1. 记录 Deployment 当前 maxUnavailable 值，并临时设为 100%（确保滚动更新能完成，故障注入的新 Pod 不会 Ready，默认策略下 K8s 不会终止旧 Pod，导致滚动更新死锁）：\n   ```bash\n   kubectl get deployment <deployment-name> -n <namespace> \\\n     -o jsonpath='{.spec.strategy.rollingUpdate.maxUnavailable}'\n   kubectl patch deployment <deployment-name> -n <namespace> --type='json' \\\n     -p='[{\"op\":\"replace\",\"path\":\"/spec/strategy/rollingUpdate/maxUnavailable\",\"value\":\"100%\"}]'\n   ```\n2. 使用 `kubectl(subcommand=\"apply\", v_args=\"-f -\", stdin_data=\"...\")` 创建跨可用区的 PV 和 PVC（**必须使用 `stdin_data` 参数传入 YAML，不要用 exec heredoc 或其他方式**）：\n   PV YAML:\n   ```yaml\n   apiVersion: v1\n   kind: PersistentVolume\n   metadata:\n     name: chaos-az-mismatch-pv\n   spec:\n     capacity:\n       storage: 20Gi\n     accessModes: [\"ReadWriteOnce\"]\n     csi:\n       driver: diskplugin.csi.alibabacloud.com\n       volumeHandle: <其他可用区的云盘ID>\n     nodeAffinity:\n       required:\n         nodeSelectorTerms:\n         - matchExpressions:\n           - key: topology.kubernetes.io/zone\n             operator: In\n             values: [\"<其他可用区>\"]\n   ```\n   PVC YAML:\n   ```yaml\n   apiVersion: v1\n   kind: PersistentVolumeClaim\n   metadata:\n     name: chaos-csi-mismatch-pvc\n     namespace: <namespace>\n   spec:\n     accessModes: [\"ReadWriteOnce\"]\n     resources:\n       requests:\n         storage: 20Gi\n     volumeName: chaos-az-mismatch-pv\n   ```\n3. 修改应用 A 的 Deployment，添加引用该 PVC 的 volume，并确保 Pod 调度到不同可用区的节点\n4. 等待 Pod 滚动更新完成，确认所有旧 Pod 已被替换\n5. 滚动更新完成后，立即还原 maxUnavailable 为原始值（maxUnavailable 只是使滚动更新完成的手段，不是故障本身，不应泄漏到恢复阶段）\n6. 观察 Pod 的 ContainerCreating 状态\n\n**注入验证**：\n1. 执行 `kubectl rollout status deployment <deployment-name>`，确认滚动更新已完成（所有旧 Pod 已被替换）。如果滚动更新未完成（卡死），则故障未完全生效，不可判定为 verified\n2. 执行 `kubectl get pods`，确认**所有**目标 Pod 状态为 ContainerCreating（不是仅一个新 Pod，而是全部副本）\n3. 执行 `kubectl describe pod <pod-name>`，确认 Events 显示 FailedMount 或 CSI attach 超时\n4. 确认错误信息包含可用区不匹配或 CSI 异常相关描述\n\n**注入恢复**：\n1. 恢复应用 A 的 Deployment，移除注入时添加的 volumes 和 volumeMounts（两者都需移除，只移除其中一个会导致 Deployment 配置错误）\n2. 等待 Pod 滚动更新完成，确认 Pod 恢复 Running\n3. 清理测试 PVC：`kubectl delete pvc chaos-csi-mismatch-pvc -n <namespace>`\n4. 清理测试 PV：`kubectl delete pv chaos-az-mismatch-pv`\n\n**恢复验证**：\n1. 执行 `kubectl get pods`，确认 Pod 状态恢复为 Running\n2. 确认测试资源已清理\n3. 确认应用 A 存储功能正常\n\n**基准事实**：\n- **根因**：CSI 驱动异常或云盘与节点可用区不匹配，导致 Volume attach/mount 操作超时，Pod 无法完成存储卷挂载\n- **必现现象**：Pod ContainerCreating；Events 显示 FailedMount/FailedAttachVolume/CSI 超时；可用区不匹配\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_ContainerCreating/Pod_ContainerCreating_云盘挂载超时或冲突.md":"**用例名称** 云盘挂载超时或冲突 导致 Pod_ContainerCreating\n\n**故障现象**：\n1. Pod 长时间停留在 ContainerCreating 状态\n2. Pod Events 中显示 `Multi-Attach error` 或 `AttachVolume.Attach failed`\n3. 云盘被其他节点占用，无法 attach 到当前节点\n\n**资源准备**：\n1. 确认应用 A 已正常运行，且使用了云盘类型的 PVC（accessMode 为 ReadWriteOnce）\n2. 确认集群中有多个节点\n\n**演练步骤**：\n1. 定位应用 A 使用的 PVC 及其对应的 PV\n2. 在另一个节点上创建一个临时 Pod，强制挂载同一个 PVC（通过直接指定 PV 的 volumeHandle 创建新 PV/PVC 对），模拟 Multi-Attach 冲突：\n   ```yaml\n   apiVersion: v1\n   kind: Pod\n   metadata:\n     name: chaos-volume-holder\n     namespace: <namespace>\n   spec:\n     nodeName: <另一节点>\n     containers:\n     - name: holder\n       image: busybox\n       command: [\"sleep\", \"3600\"]\n       volumeMounts:\n       - name: data\n         mountPath: /data\n     volumes:\n     - name: data\n       persistentVolumeClaim:\n         claimName: <应用A的PVC名称>\n   ```\n3. 删除应用 A 原来的 Pod，触发在其他节点重建\n4. 观察新 Pod 的 ContainerCreating 状态\n\n**注入验证**：\n1. 执行 `kubectl get pods`，确认应用 A 的新 Pod 状态为 ContainerCreating\n2. 执行 `kubectl describe pod <pod-name>`，确认 Events 显示 Multi-Attach error 或 volume attach 失败\n3. 确认 PV 仍 attach 在占用它的节点上\n\n**注入恢复**：\n1. 删除临时 Pod：`kubectl delete pod chaos-volume-holder --force --grace-period=0`\n2. 等待云盘从原节点 detach\n3. 等待应用 A 的 Pod 自动完成 volume attach\n\n**恢复验证**：\n1. 执行 `kubectl get pods`，确认应用 A 的 Pod 状态恢复为 Running\n2. 确认 volume 成功 attach 并 mount\n3. 确认应用 A 数据读写正常\n\n**基准事实**：\n- **根因**：云盘（ReadWriteOnce）被其他节点/Pod 占用，新 Pod 无法 attach 该云盘，导致 volume mount 阶段阻塞\n- **必现现象**：Pod ContainerCreating；Events 显示 Multi-Attach error 或 AttachVolume 失败；PV 被其他节点占用\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_ContainerCreating/Pod_ContainerCreating_容器运行时异常.md":"**用例名称** 容器运行时异常 导致 Pod_ContainerCreating\n\n**故障现象**：\n1. Pod 长时间停留在 ContainerCreating 状态\n2. Pod Events 中显示 `container runtime is not ready` 或 `rpc error` 相关错误\n3. 节点上的 containerd/docker 进程异常或 hang，无法响应容器创建请求\n\n**资源准备**：\n1. 确认应用 A 已正常运行\n2. 确认目标节点上有多个应用副本（避免单点影响）\n3. 确认监控系统可观测节点和容器运行时状态\n\n**演练步骤**：\n1. 定位应用 A 所在的目标节点\n2. 使用 chaosblade 挂起（stop）目标节点上的 containerd 进程，模拟容器运行时 hang：\n   ```bash\n   blade create k8s node-process stop \\\n     --names <节点名> \\\n     --process containerd \\\n     --timeout 120 \\\n     --kubeconfig <路径>\n   ```\n3. 删除应用 A 在目标节点上的 Pod，触发重建\n4. 观察新 Pod 的 ContainerCreating 状态\n\n**注入验证**：\n1. 执行 `kubectl get pods`，确认新 Pod 状态为 ContainerCreating\n2. 执行 `kubectl describe pod <pod-name>`，确认 Events 显示容器运行时相关错误\n3. 确认目标节点状态可能变为 NotReady（RuntimeNotReady condition）\n\n**注入恢复**：\n1. 等待 chaosblade 实验自动超时恢复（120 秒内），containerd 进程自动恢复\n2. 如超时后仍未恢复，通过 `blade destroy <UID>` 强制恢复\n3. 等待容器运行时恢复正常，Pod 自动完成创建\n\n**恢复验证**：\n1. 确认 containerd 进程恢复正常运行\n2. 执行 `kubectl get nodes`，确认目标节点恢复 Ready\n3. 执行 `kubectl get pods`，确认 Pod 状态恢复为 Running\n\n**基准事实**：\n- **根因**：容器运行时（containerd/docker）进程异常、hang 或状态不一致，无法响应 kubelet 的容器创建请求\n- **必现现象**：Pod ContainerCreating；Events 显示 runtime 相关 rpc error；节点可能 NotReady（RuntimeNotReady）\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_CrashLoopBackOff/Pod_CrashLoopBackOff_LivenessProbe配置不合理.md":"**用例名称** LivenessProbe配置不合理 导致 Pod_CrashLoopBackOff\n\n**故障现象**：\n1. Pod 反复重启，状态为 CrashLoopBackOff\n2. Pod Events 中显示 `Liveness probe failed` 后容器被杀\n3. 容器本身运行正常，但 Liveness Probe 配置参数不合理导致误判\n\n**RCA症状**：\n1. Pod 反复重启，状态为 CrashLoopBackOff\n2. Pod Events 中显示 `Liveness probe failed`，容器被反复杀死\n3. 容器日志无应用异常退出记录\n（以上为kubectl直接可观测的现象，不包含诊断结论）\n\n**资源准备**：\n1. 确认应用 A 已正常运行\n2. 确认应用 A 有健康检查接口\n\n**演练步骤**：\n1. 记录应用 A 当前的 livenessProbe 配置\n2. 记录 Deployment 当前 maxUnavailable 值，并临时设为 100%（确保滚动更新能完成，故障注入的新 Pod 不会 Ready，默认策略下 K8s 不会终止旧 Pod，导致滚动更新死锁）：\n   ```bash\n   kubectl get deployment <deployment-name> -n <namespace> \\\n     -o jsonpath='{.spec.strategy.rollingUpdate.maxUnavailable}'\n   kubectl patch deployment <deployment-name> -n <namespace> --type='json' \\\n     -p='[{\"op\":\"replace\",\"path\":\"/spec/strategy/rollingUpdate/maxUnavailable\",\"value\":\"100%\"}]'\n   ```\n3. 修改应用 A 的 Deployment，设置不合理的 livenessProbe 参数：\n   ```yaml\n   livenessProbe:\n     httpGet:\n       path: /healthz\n       port: 8080\n     initialDelaySeconds: 1\n     timeoutSeconds: 1\n     periodSeconds: 2\n     failureThreshold: 1\n   ```\n   （initialDelaySeconds 过短，应用未完成初始化；timeoutSeconds 过短，正常响应来不及返回；failureThreshold 为 1，无容错空间）\n4. 等待 Pod 滚动更新完成，确认所有旧 Pod 已被替换\n5. 滚动更新完成后，立即还原 maxUnavailable 为原始值（maxUnavailable 只是使滚动更新完成的手段，不是故障本身，不应泄漏到恢复阶段）\n6. 观察 Pod 重启行为\n\n**注入验证**：\n1. 执行 `kubectl rollout status deployment <deployment-name>`，确认滚动更新已完成（所有旧 Pod 已被替换）。如果滚动更新未完成（卡死），则故障未完全生效，不可判定为 verified\n2. 执行 `kubectl get pods`，确认**所有**目标 Pod 的 RESTARTS 数持续增长，状态为 CrashLoopBackOff（不是仅一个新 Pod，而是全部副本）\n3. 执行 `kubectl describe pod <pod-name>`，确认 Events 显示 `Liveness probe failed` 和 `Container will be killed`\n4. 查看容器日志，确认应用本身无异常退出（非应用 bug）\n\n**注入恢复**：\n1. 恢复应用 A 的 Deployment，将 livenessProbe 参数恢复为原始合理值（若原本无 livenessProbe，则移除）\n3. 等待 Pod 滚动更新完成\n\n**恢复验证**：\n1. 执行 `kubectl get pods`，确认 Pod 状态为 Running 且不再重启\n2. 确认 Liveness Probe 检查正常通过\n3. 确认应用 A 服务正常\n\n**基准事实**：\n- **根因**：Liveness Probe 的 initialDelaySeconds/timeoutSeconds/failureThreshold 配置不合理，导致健康检查在应用正常运行时误判为失败，kubelet 反复杀死并重启容器\n- **必现现象**：Pod CrashLoopBackOff；RESTARTS 持续增长；Events 显示 Liveness probe failed；容器日志无异常\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_CrashLoopBackOff/Pod_CrashLoopBackOff_StartupProbe配置不足.md":"**用例名称** StartupProbe配置不足 导致 Pod_CrashLoopBackOff\n\n**故障现象**：\n1. Pod 反复重启，状态为 CrashLoopBackOff\n2. Pod Events 中显示 `Startup probe failed` 后容器被杀\n3. 慢启动应用尚未完成初始化就被 StartupProbe 判定为失败\n\n**资源准备**：\n1. 确认应用 A 已正常运行（应用启动时间较长，如 Java 应用）\n2. 确认应用 A 启动过程中健康检查接口不可用\n\n**演练步骤**：\n1. 记录应用 A 当前的探针配置\n2. 记录 Deployment 当前 maxUnavailable 值，并临时设为 100%（确保滚动更新能完成，故障注入的新 Pod 不会 Ready，默认策略下 K8s 不会终止旧 Pod，导致滚动更新死锁）：\n   ```bash\n   kubectl get deployment <deployment-name> -n <namespace> \\\n     -o jsonpath='{.spec.strategy.rollingUpdate.maxUnavailable}'\n   kubectl patch deployment <deployment-name> -n <namespace> --type='json' \\\n     -p='[{\"op\":\"replace\",\"path\":\"/spec/strategy/rollingUpdate/maxUnavailable\",\"value\":\"100%\"}]'\n   ```\n3. 修改应用 A 的 Deployment，添加或修改 startupProbe 使其窗口不足以覆盖应用启动时间：\n   ```yaml\n   startupProbe:\n     httpGet:\n       path: /healthz\n       port: 8080\n     failureThreshold: 3\n     periodSeconds: 5\n   ```\n   （总等待时间 = failureThreshold × periodSeconds = 15 秒，远小于应用实际启动时间）\n4. 同时确保 livenessProbe 存在，使得 startupProbe 失败后触发容器重启\n5. 等待 Pod 滚动更新完成，确认所有旧 Pod 已被替换\n6. 滚动更新完成后，立即还原 maxUnavailable 为原始值（maxUnavailable 只是使滚动更新完成的手段，不是故障本身，不应泄漏到恢复阶段）\n7. 观察 Pod 启动行为\n\n**注入验证**：\n1. 执行 `kubectl rollout status deployment <deployment-name>`，确认滚动更新已完成（所有旧 Pod 已被替换）。如果滚动更新未完成（卡死），则故障未完全生效，不可判定为 verified\n2. 执行 `kubectl get pods`，确认**所有**目标 Pod 的 RESTARTS 持续增长，状态为 CrashLoopBackOff（不是仅一个新 Pod，而是全部副本）\n3. 执行 `kubectl describe pod <pod-name>`，确认 Events 显示 `Startup probe failed`\n4. 查看容器日志，确认应用正在启动但未完成初始化就被杀\n\n**注入恢复**：\n1. 恢复应用 A 的 Deployment，增大 startupProbe 的窗口时间（若原本无 startupProbe，则移除）\n2. 等待 Pod 滚动更新完成\n\n**恢复验证**：\n1. 执行 `kubectl get pods`，确认 Pod 状态为 Running 且不再重启\n2. 确认 StartupProbe 和 LivenessProbe 检查均正常通过\n3. 确认应用 A 完成初始化并正常服务\n\n**基准事实**：\n- **根因**：StartupProbe 未配置或 failureThreshold × periodSeconds 总窗口不足以覆盖应用启动时间，慢启动应用在初始化完成前被判定为启动失败，反复被杀重启\n- **必现现象**：Pod CrashLoopBackOff；Events 显示 Startup probe failed；容器日志显示应用启动中被中断\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_OOM内存异常/Pod_OOM内存异常_limit单位写错.md":"**用例名称** limit单位写错 导致 Pod_OOM内存异常\n\n**故障现象**：\n1. Pod 启动后立即异常退出，状态为 CrashLoopBackOff\n2. Pod 的 lastState 显示 reason: OOMKilled 或 StartError（cgroup v2 环境下容器可能因内存配置过小无法启动）\n3. 容器 memory limit 值极小（如 100m = 0.1 字节），应用启动即超限或无法启动\n\n**资源准备**：\n1. 确认应用 A 已正常运行\n2. 确认应用 A 的正常内存使用量（如 200Mi 以上）\n\n**演练步骤**：\n1. 记录应用 A 当前的 resources.limits.memory 配置\n2. 记录 Deployment 当前 maxUnavailable 值，并临时设为 100%（确保滚动更新能完成，故障注入的新 Pod 不会 Ready，默认策略下 K8s 不会终止旧 Pod，导致滚动更新死锁）：\n   ```bash\n   kubectl get deployment <deployment-name> -n <namespace> \\\n     -o jsonpath='{.spec.strategy.rollingUpdate.maxUnavailable}'\n   kubectl patch deployment <deployment-name> -n <namespace> --type='json' \\\n     -p='[{\"op\":\"replace\",\"path\":\"/spec/strategy/rollingUpdate/maxUnavailable\",\"value\":\"100%\"}]'\n   ```\n3. 修改应用 A 的 Deployment，将 memory limit 单位写错：\n   ```yaml\n   resources:\n     limits:\n       memory: \"100m\"    # 错误！100m = 0.1 字节（milli），应为 100Mi\n     requests:\n       memory: \"100m\"\n   ```\n   注意：在 Kubernetes 中，`m` 表示 milli（千分之一），`100m` = 0.1 字节；正确应为 `Mi`（Mebibyte）\n4. 等待 Pod 滚动更新完成，确认所有旧 Pod 已被替换\n5. 滚动更新完成后，立即还原 maxUnavailable 为原始值（maxUnavailable 只是使滚动更新完成的手段，不是故障本身，不应泄漏到恢复阶段）\n6. 观察 Pod 启动行为\n\n**注入验证**：\n1. 执行 `kubectl rollout status deployment <deployment-name>`，确认滚动更新已完成（所有旧 Pod 已被替换）。如果滚动更新未完成（卡死），则故障未完全生效，不可判定为 verified\n2. 执行 `kubectl get pods`，确认**所有**目标 Pod 状态为 CrashLoopBackOff，RESTARTS 持续增长（不是仅一个新 Pod，而是全部副本）\n3. 执行 `kubectl get pod <pod-name> -o jsonpath='{.status.containerStatuses[0].lastState}'`，确认 reason 为 OOMKilled 或 StartError（cgroup v2 环境下极小 limit 可能导致容器无法启动而非 OOMKill）\n4. 执行 `kubectl describe pod <pod-name>`，确认 limits.memory 为极小值\n5. 确认容器启动后立即异常退出（运行时间极短或无法启动）\n\n**注入恢复**：\n1. 恢复应用 A 的 Deployment，将 memory limit 修正为正确单位（如 `256Mi`）\n3. 等待 Pod 滚动更新完成\n\n**恢复验证**：\n1. 执行 `kubectl get pods`，确认 Pod 状态为 Running 且不再重启\n2. 确认容器正常运行，内存使用率在合理范围\n3. 确认应用 A 服务正常\n\n**基准事实**：\n- **根因**：memory limit 单位写错（如 `100m` 而非 `100Mi`），导致 limit 值极小，容器启动后内存使用立即超过 limit 被 OOMKill，或在 cgroup v2 环境下因内存配置过小无法启动\n- **必现现象**：Pod 异常退出（OOMKilled 或 StartError）；CrashLoopBackOff；limits.memory 值不合理（如 100m）；容器运行时间极短或无法启动\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_OOM内存异常/Pod_OOM内存异常_内存压力过大.md":"**用例名称** 内存压力过大 导致 Pod_OOM内存异常\n\n**故障现象**：\n1. Pod 内存使用率接近 Limit 上限\n2. 应用响应变慢，出现延迟\n3. 存在被 OOMKill 的风险\n\n**资源准备**：\n1. 确认应用 A 已正常运行\n2. 确认应用 A 的 Pod 已配置 resources.limits.memory\n\n**演练步骤**：\n1. 定位应用 A 的 Pod\n2. 使用 chaosblade 对应用 A 的 Pod 注入内存压力，模拟内存占用增长接近 Limit 的场景\n3. 观察 Pod 内存使用率变化\n\n**注入验证**：\n1. 查看监控指标，确认 Pod 内存使用率接近 Limit 上限\n2. 查看 Pod Event，确认存在内存相关告警\n3. 确认应用 A 的响应延迟增大\n\n**注入恢复**：\n1. 销毁 chaosblade 内存压力注入实验\n\n**恢复验证**：\n1. 查看监控指标，确认 Pod 内存使用率恢复正常\n2. 确认应用性能恢复正常\n\n**基准事实**：\n- **根因**：应用内存使用增长或注入内存压力，导致 Pod 内存使用率接近 Limit，存在被 OOMKill 的风险\n- **必现现象**：Pod 内存使用率接近 Limit；应用响应变慢；存在 OOMKill 风险\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_Pending/Pod_Pending_PVC未绑定.md":"**用例名称** PVC未绑定 导致 Pod_Pending\n\n**故障现象**：\n1. Pod 状态为 Pending，无法启动\n2. Pod Events 中显示 `pod has unbound immediate PersistentVolumeClaims`\n3. PVC 状态为 Pending，无法绑定到 PV\n\n**资源准备**：\n1. 确认应用 A 已正常运行\n2. 确认集群中 StorageClass 和 CSI 插件正常工作\n\n**演练步骤**（注意：本用例需要临时修改 Deployment 添加 volume 引用，这是故障注入的必要操作，不违反安全红线。目标应用无需预先配置 PVC——注入的目的就是添加一个无法绑定的 PVC 依赖。恢复步骤会还原所有修改）：\n1. 记录 Deployment 当前 maxUnavailable 值，并临时设为 100%（确保滚动更新能完成，故障注入的新 Pod 不会 Ready，默认策略下 K8s 不会终止旧 Pod，导致滚动更新死锁）：\n   ```bash\n   kubectl get deployment <deployment-name> -n <namespace> \\\n     -o jsonpath='{.spec.strategy.rollingUpdate.maxUnavailable}'\n   kubectl patch deployment <deployment-name> -n <namespace> --type='json' \\\n     -p='[{\"op\":\"replace\",\"path\":\"/spec/strategy/rollingUpdate/maxUnavailable\",\"value\":\"100%\"}]'\n   ```\n2. 使用 `kubectl apply -f` 创建一个引用不存在的 StorageClass 的 PVC（通过 `stdin_data` 传入 YAML）：\n   ```yaml\n   apiVersion: v1\n   kind: PersistentVolumeClaim\n   metadata:\n     name: chaos-test-pvc\n     namespace: <namespace>\n   spec:\n     accessModes: [\"ReadWriteOnce\"]\n     storageClassName: \"non-existent-sc\"\n     resources:\n       requests:\n         storage: 10Gi\n   ```\n3. 使用 `kubectl patch` 修改应用 A 的 Deployment，添加引用该 PVC 的 volume 和 volumeMount\n4. 等待 Pod 滚动更新完成，确认所有旧 Pod 已被替换\n5. 滚动更新完成后，立即还原 maxUnavailable 为原始值（maxUnavailable 只是使滚动更新完成的手段，不是故障本身，不应泄漏到恢复阶段）\n6. 观察新 Pod 的状态\n\n**注入验证**：\n1. 执行 `kubectl rollout status deployment <deployment-name>`，确认滚动更新已完成（所有旧 Pod 已被替换）。如果滚动更新未完成（卡死），则故障未完全生效，不可判定为 verified\n2. 执行 `kubectl get pvc`，确认 PVC 状态为 Pending\n3. 执行 `kubectl get pods`，确认**所有**目标 Pod 状态为 Pending（不是仅一个新 Pod，而是全部副本）\n4. 执行 `kubectl describe pod <pod-name>`，确认 Events 显示 unbound PVC 相关信息\n5. 执行 `kubectl describe pvc chaos-test-pvc`，确认 StorageClass 不存在或 Provisioner 异常\n\n**注入恢复**：\n1. 恢复应用 A 的 Deployment 定义，移除引用 chaos-test-pvc 的 volume\n2. 删除测试用 PVC：`kubectl delete pvc chaos-test-pvc`\n3. 等待 Pod 滚动更新完成\n\n**恢复验证**：\n1. 执行 `kubectl get pods`，确认 Pod 状态恢复为 Running\n2. 确认测试 PVC 已被清理\n\n**基准事实**：\n- **根因**：Pod 引用的 PVC 无法绑定，原因为 StorageClass 不存在或 Provisioner 异常，导致 Pod 无法挂载所需存储卷而 Pending\n- **必现现象**：Pod Pending；PVC Pending；Events 显示 unbound PersistentVolumeClaims\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_Pending/Pod_Pending_拓扑约束过严.md":"**用例名称** 拓扑约束过严 导致 Pod_Pending\n\n**故障现象**：\n1. Pod 状态为 Pending，无法被调度\n2. Pod Events 中显示 `didn't match pod topology spread constraints` 或 `didn't match pod anti-affinity rules`\n3. 由于拓扑分布约束或反亲和规则过严，调度器无法找到满足条件的节点\n\n**资源准备**：\n1. 确认应用 A 已正常运行\n2. 确认集群节点数量有限（便于触发约束冲突）\n\n**演练步骤**：\n1. 记录 Deployment 当前 maxUnavailable 值，并临时设为 100%（确保滚动更新能完成，故障注入的新 Pod 不会 Ready，默认策略下 K8s 不会终止旧 Pod，导致滚动更新死锁）：\n   ```bash\n   kubectl get deployment <deployment-name> -n <namespace> \\\n     -o jsonpath='{.spec.strategy.rollingUpdate.maxUnavailable}'\n   kubectl patch deployment <deployment-name> -n <namespace> --type='json' \\\n     -p='[{\"op\":\"replace\",\"path\":\"/spec/strategy/rollingUpdate/maxUnavailable\",\"value\":\"100%\"}]'\n   ```\n2. 修改应用 A 的 Deployment，添加过严的拓扑约束：\n   ```yaml\n   topologySpreadConstraints:\n   - maxSkew: 1\n     topologyKey: kubernetes.io/hostname\n     whenUnsatisfiable: DoNotSchedule\n     labelSelector:\n       matchLabels:\n         app: <app-name>\n   ```\n   或添加过严的反亲和规则：\n   ```yaml\n   affinity:\n     podAntiAffinity:\n       requiredDuringSchedulingIgnoredDuringExecution:\n       - labelSelector:\n           matchLabels:\n             app: <app-name>\n         topologyKey: kubernetes.io/hostname\n   ```\n3. 等待 Pod 滚动更新完成，确认所有旧 Pod 已被替换\n4. 滚动更新完成后，立即还原 maxUnavailable 为原始值（maxUnavailable 只是使滚动更新完成的手段，不是故障本身，不应泄漏到恢复阶段）\n5. 将应用 A 的副本数扩大到超过集群节点数\n6. 观察无法调度的 Pod 状态\n\n**注入验证**：\n1. 执行 `kubectl rollout status deployment <deployment-name>`，确认滚动更新已完成（所有旧 Pod 已被替换）。如果滚动更新未完成（卡死），则故障未完全生效，不可判定为 verified\n2. 执行 `kubectl get pods`，确认部分或全部 Pod 状态为 Pending\n3. 执行 `kubectl describe pod <pending-pod>`，确认 Events 显示拓扑约束或反亲和相关的调度失败原因\n\n**注入恢复**：\n1. 恢复应用 A 的 Deployment 定义，移除或放宽拓扑约束/反亲和规则\n2. 将副本数恢复为原始值\n3. 等待 Pod 滚动更新完成\n\n**恢复验证**：\n1. 执行 `kubectl get pods`，确认所有 Pod 状态为 Running\n2. 确认副本数恢复正常\n\n**基准事实**：\n- **根因**：topologySpreadConstraints 或 podAntiAffinity 配置过严，当副本数超过可用拓扑域时，调度器无法满足约束条件\n- **必现现象**：部分 Pod Pending；Events 显示拓扑约束或反亲和规则不满足；已调度 Pod 严格按约束分布\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_Pending/Pod_Pending_节点Taint无对应Toleration.md":"**用例名称** 节点Taint无对应Toleration 导致 Pod_Pending\n\n**故障现象**：\n1. Pod 状态为 Pending，无法被调度到任何节点\n2. Pod Events 中显示 `N node(s) had untolerated taint {chaos-test: true}`\n3. 目标 Pod 可调度的所有节点均带有 Pod 无法容忍的污点\n\n**RCA症状**：\n1. Pod 状态为 Pending，无法被调度到任何节点\n2. Pod Events 中显示 `had untolerated taint`\n（以上为kubectl直接可观测的现象，不包含诊断结论）\n\n**资源准备**：\n1. 确认应用 A 已正常运行\n2. 确认集群中有多个可调度节点\n3. 记录应用 A 的 Pod 当前运行在哪些节点上（这些节点即为\"目标节点\"）\n\n**演练步骤**：\n\n> **爆炸半径控制**：本用例仅 taint 目标 Pod 所在的节点（而非全部集群节点），\n> 通过 nodeSelector 约束目标 Pod 只能调度到这些节点，从而在保证故障复现的同时\n> 避免影响集群中其他工作负载的调度。\n\n1. 记录目标节点的当前 taint 信息，以及 Deployment 的当前 nodeSelector（用于恢复）\n2. 记录 Deployment 当前 maxUnavailable 值，并临时设为 100%（确保滚动更新能完成，故障注入的新 Pod 不会 Ready，默认策略下 K8s 不会终止旧 Pod，导致滚动更新死锁）：\n   ```bash\n   kubectl get deployment <deployment-name> -n <namespace> \\\n     -o jsonpath='{.spec.strategy.rollingUpdate.maxUnavailable}'\n   kubectl patch deployment <deployment-name> -n <namespace> --type='json' \\\n     -p='[{\"op\":\"replace\",\"path\":\"/spec/strategy/rollingUpdate/maxUnavailable\",\"value\":\"100%\"}]'\n   ```\n3. 给目标节点添加标签：`kubectl label node <node> chaos-target=<app-name>`（仅目标 Pod 所在节点）\n4. 给应用 A 的 Deployment 添加 nodeSelector，约束 Pod 只能调度到目标节点：\n   `kubectl patch deployment <name> -n <ns> -p '{\"spec\":{\"template\":{\"spec\":{\"nodeSelector\":{\"chaos-target\":\"<app-name>\"}}}}}'`\n5. 等待 rollout 完成（Pod 仍在原节点上运行，因为只有目标节点有此标签）\n6. 滚动更新完成后，立即还原 maxUnavailable 为原始值（maxUnavailable 只是使滚动更新完成的手段，不是故障本身，不应泄漏到恢复阶段）\n7. 给目标节点添加污点：`kubectl taint node <node> chaos-test=true:NoSchedule`（仅目标节点）\n8. 删除应用 A 的一个 Pod，触发重建调度\n9. 观察新 Pod 的调度状态\n\n**注入验证**：\n1. 执行 `kubectl get pods`，确认新 Pod 状态为 Pending\n2. 执行 `kubectl describe pod <pod-name>`，确认 Events 中显示 `had untolerated taint {chaos-test: true}`\n3. 确认目标节点均有 chaos-test taint\n\n**注入恢复**：\n1. 移除目标节点上添加的污点：`kubectl taint node <node> chaos-test=true:NoSchedule-`\n2. 移除 Deployment 的 nodeSelector 中添加的 chaos-target 键（若原 Deployment 无 nodeSelector，则移除整个 nodeSelector）\n3. 移除目标节点上添加的标签：`kubectl label node <node> chaos-target-`\n4. 等待 Pod 滚动更新完成\n\n**恢复验证**：\n1. 执行 `kubectl get pods`，确认 Pod 状态变为 Running\n2. 确认目标节点 taint 已恢复到演练前状态\n3. 确认 Deployment spec 已恢复到演练前状态\n\n**基准事实**：\n- **根因**：目标 Pod 可调度的所有节点被标记了 Taint，而 Pod 未配置对应的 Toleration，导致调度器无法找到合适节点\n- **必现现象**：Pod Pending；Events 显示 untolerated taint；目标节点带有不可容忍的污点\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_Terminating/Pod_Terminating_Finalizers未清理.md":"**用例名称** Finalizers未清理 导致 Pod_Terminating\n\n**故障现象**：\n1. Pod 无法完成删除，`metadata.deletionTimestamp` 已设置但 Pod 对象仍存在于 API 中\n2. Pod 的 metadata 中存在 finalizers 字段，等待外部控制器清理\n3. kubectl 显示状态可能是 `Terminating`（容器仍在运行时）或 `Error`/`Failed`（容器已退出时）\n\n> **注意**：\"Terminating\" 是 kubectl 的显示状态，仅当 `deletionTimestamp` 已设置\n> 且容器仍在运行时才显示。如果容器在 delete 信号后已退出，kubectl 会按容器状态\n> 显示（如 Error/Completed），但 Pod 对象仍因 finalizer 滞留在 API 中。\n> 判定依据是 `deletionTimestamp` + `finalizers` 同时存在，而非 kubectl 显示状态。\n\n**RCA症状**：\n1. `kubectl get pod` 显示 Pod 状态为 Terminating 或 Error/Failed，但 Pod 对象持续存在\n2. `kubectl get pod -o jsonpath='{.metadata.deletionTimestamp}'` 返回非空时间戳\n3. `kubectl get pod -o jsonpath='{.metadata.finalizers}'` 返回非空列表\n（以上为kubectl直接可观测的现象，不包含诊断结论）\n\n**资源准备**：\n1. 确认目标应用已正常运行\n2. 确认目标 Pod 当前没有 finalizers（`kubectl get pod <name> -o jsonpath='{.metadata.finalizers}'` 返回空）\n\n**演练步骤**：\n1. 定位目标 Pod\n2. 使用 kubectl patch 给 Pod 添加自定义 finalizer：\n   `kubectl patch pod <pod-name> -n <namespace> -p '{\"metadata\":{\"finalizers\":[\"example.com/block-deletion\"]}}'`\n3. 使用 `--wait=false` 删除 Pod，触发终止流程：\n   `kubectl delete pod <pod-name> -n <namespace> --wait=false`\n   > 不加 `--wait=false` 会导致 kubectl 等待删除完成，因 finalizer 阻塞而超时。\n4. 观察 Pod 状态变化\n\n**注入验证**：\n1. 执行 `kubectl get pod <pod-name>`，确认 Pod 对象仍存在（显示 Terminating 或 Error）\n2. 执行 `kubectl get pod <pod-name> -o jsonpath='{.metadata.deletionTimestamp}'`，确认已设置\n3. 执行 `kubectl get pod <pod-name> -o jsonpath='{.metadata.finalizers}'`，确认包含注入的 finalizer\n4. 确认没有控制器在处理该 finalizer（`example.com/block-deletion` 是注入的假标识）\n\n**注入恢复**：\n1. 移除 Pod 上的 finalizer：\n   `kubectl patch pod <pod-name> -n <namespace> --type=json -p '[{\"op\":\"remove\",\"path\":\"/metadata/finalizers\"}]'`\n2. Pod 将被 Kubernetes GC 自动清除\n\n**恢复验证**：\n1. 执行 `kubectl get pod <pod-name>`，确认 Pod 已从集群中删除（返回 NotFound）\n2. 确认 ReplicaSet 已创建替代 Pod 且状态为 Running\n\n**基准事实**：\n- **根因**：Pod 的 metadata 中存在 finalizers，Kubernetes 在删除资源时会设置 deletionTimestamp 但不会从 etcd 中移除资源对象，直到所有 finalizer 被外部控制器清除\n- **必现现象**：Pod 对象持续存在于 API 中；deletionTimestamp 已设置；metadata.finalizers 非空\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_Terminating/Pod_Terminating_Volume卸载失败.md":"**用例名称** Volume卸载失败 导致 Pod_Terminating\n\n**故障现象**：\n1. Pod 状态长时间停留在 Terminating\n2. Pod Events 或 Node Events 中显示 `FailedMount`、`UnmountVolume failed`、`device is busy`\n3. Volume 无法从节点上正常 unmount/detach，阻塞 Pod 终止流程\n\n**资源准备**：\n1. 确认应用 A 已正常运行，且挂载了 PVC（云盘类型）\n2. 确认监控系统可观测 Pod 和 Volume 状态\n\n**演练步骤**：\n1. 定位应用 A 的 Pod 及其挂载的 Volume 路径\n2. 进入目标节点，在 Volume 的挂载目录下创建一个持续占用文件句柄的进程，模拟 device busy：\n   ```bash\n   # 在节点上执行（通过 nsenter 或 debug pod）\n   # 找到 volume 挂载路径\n   mount | grep <pv-name>\n   # 创建持续占用的进程\n   tail -f <挂载路径>/some-file &\n   ```\n   或使用 chaosblade 对节点注入 IO 负载，锁住磁盘操作：\n   ```bash\n   blade create k8s node-disk burn \\\n     --names <节点名> \\\n     --path <volume挂载路径> \\\n     --read --write \\\n     --timeout 180 \\\n     --kubeconfig <路径>\n   ```\n3. 删除应用 A 的 Pod，触发 Terminating 流程\n4. 观察 Pod Terminating 状态持续时间\n\n**注入验证**：\n1. 执行 `kubectl get pods`，确认 Pod 状态为 Terminating 且长时间未消失\n2. 查看 Node Events 或 `kubectl describe pod`，确认有 UnmountVolume 失败或 device busy 相关错误\n3. 在节点上确认 volume 挂载路径仍被占用\n\n**注入恢复**：\n1. 终止节点上占用 volume 的进程（kill tail 进程）\n2. 若使用 chaosblade：销毁 IO 实验 `blade destroy <UID>`\n3. 等待 kubelet 自动重试 unmount 操作\n\n**恢复验证**：\n1. 执行 `kubectl get pods`，确认 Terminating 的 Pod 已完成删除\n2. 确认 volume 已成功 unmount 和 detach\n3. 确认 PV 状态恢复为 Available 或被新 Pod 重新绑定\n\n**基准事实**：\n- **根因**：Volume unmount 时设备仍被占用（device busy）或 CSI 异常，导致 kubelet 无法完成卷卸载，Pod 终止流程被阻塞\n- **必现现象**：Pod Terminating 持续；Events 显示 UnmountVolume failed/device busy；Volume 挂载路径未释放\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_Terminating/Pod_Terminating_网卡卸载失败.md":"**用例名称** 网卡卸载失败 导致 Pod_Terminating\n\n**故障现象**：\n1. Pod 状态长时间停留在 Terminating\n2. 容器已停止，但 Pod sandbox 清理失败\n3. Events 或 kubelet 日志中显示 CNI DEL 调用失败或网络资源释放异常\n\n**资源准备**：\n1. 确认应用 A 已正常运行\n2. 确认集群使用 ENI/Terway 等需要显式清理网络资源的 CNI 插件\n3. 确认监控系统可观测 Pod 状态和 CNI 插件日志\n\n**演练步骤**：\n1. 定位应用 A 的 Pod 所在节点\n2. 使用 chaosblade 挂起节点上的 CNI 插件进程（如 terway-daemon），模拟 CNI 响应异常：\n   ```bash\n   blade create k8s node-process stop \\\n     --names <节点名> \\\n     --process terway \\\n     --timeout 120 \\\n     --kubeconfig <路径>\n   ```\n   或删除 CNI 插件 DaemonSet 中该节点的 Pod（先 cordon 节点防止重建）\n3. 删除应用 A 的 Pod，触发 Terminating 流程\n4. 观察 Pod Terminating 状态\n\n**注入验证**：\n1. 执行 `kubectl get pods`，确认 Pod 状态为 Terminating 且长时间未消失\n2. 查看 kubelet 日志（`journalctl -u kubelet`），确认有 CNI DEL 调用超时或失败的记录\n3. 确认 CNI 插件进程处于 stopped 状态或不可用\n\n**注入恢复**：\n1. 恢复 CNI 插件进程：等待 chaosblade 超时或执行 `blade destroy <UID>`\n2. 若删除了 CNI Pod：uncordon 节点，等待 CNI DaemonSet Pod 重建\n3. kubelet 将自动重试 sandbox 清理\n\n**恢复验证**：\n1. 确认 CNI 插件进程恢复正常\n2. 执行 `kubectl get pods`，确认 Terminating 的 Pod 已被完全清理\n3. 确认节点网络资源（ENI/IP）已释放\n4. 确认新 Pod 可以正常创建和分配网络\n\n**基准事实**：\n- **根因**：CNI 插件异常或不可用，导致 Pod 删除时网卡/ENI 资源无法正常释放，sandbox 清理失败，Pod 卡在 Terminating\n- **必现现象**：Pod Terminating 持续；kubelet 日志显示 CNI DEL 失败；网络资源未释放\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_Terminating/Pod_Terminating_节点宕机kubelet失联.md":"**用例名称** 节点宕机kubelet失联 导致 Pod_Terminating\n\n**故障现象**：\n1. Pod 状态长时间停留在 Terminating，无法完成删除\n2. 节点状态变为 NotReady，kubelet 停止上报\n3. API Server 已下发删除指令，但 kubelet 无法执行实际清理操作\n\n**资源准备**：\n1. 确认应用 A 已正常运行，至少有一个副本运行在目标节点上\n2. 确认监控系统可观测节点状态和 Pod 状态\n\n**演练步骤**：\n1. 定位运行应用 A 的目标节点\n2. 先通过 kubectl 删除应用 A 在目标节点上的 Pod（触发 Terminating）\n3. 立即使用 chaosblade 对目标节点注入网络完全丢包（node-network drop 即全量丢包，不需要 --percent），并设置 `--timeout 300`，模拟节点宕机导致 kubelet 失联\n4. 观察 Pod Terminating 状态持续时间\n\n**注入验证**：\n1. 执行 `kubectl get pods`，确认目标 Pod 状态为 Terminating 且长时间未消失\n2. 执行 `kubectl get nodes`，确认目标节点状态为 NotReady\n3. 查看 Pod 详情，确认 deletionTimestamp 已设置但 Pod 未被实际清理\n\n**注入恢复**：\n1. 等待 chaosblade 实验自动超时恢复（300 秒内）\n2. 如超时后仍未恢复，通过 `blade destroy <UID>` 或重启节点强制恢复\n3. kubelet 恢复后会自动清理 Terminating 状态的 Pod\n\n**恢复验证**：\n1. 执行 `kubectl get nodes`，确认目标节点恢复 Ready\n2. 执行 `kubectl get pods`，确认 Terminating 的 Pod 已被清理\n3. 确认应用 A 的新 Pod 在其他节点正常运行\n\n**基准事实**：\n- **根因**：节点宕机或 kubelet 失联，导致 API Server 下发的删除指令无法被执行，Pod 停留在 Terminating 状态\n- **必现现象**：Pod 状态为 Terminating 且长时间不消失；节点 NotReady；deletionTimestamp 已设置\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_cpu使用率过高/Pod_cpu使用率过高_应用性能问题.md":"**用例名称** 应用性能问题 导致 Pod_CPU使用率过高\n\n**故障现象**：\n1. Pod 的 CPU 使用率持续超过阈值\n2. CPU 使用率过高影响其他服务\n3. 应用响应变慢或发生超时\n\n**资源准备**：\n1. 确认应用 A/B 已正常运行\n2. 确认监控系统（如 Prometheus）已配置，可观测 Pod CPU 指标\n\n**演练步骤**：\n1. 定位应用 A 的 Pod 作为故障注入目标\n2. 使用 chaosblade 对目标 Pod 注入 CPU 压力（模拟死循环或高并发计算场景）\n3. 观察 Pod CPU 使用率变化\n\n**注入验证**：\n1. 查看 Pod CPU 使用率监控，确认持续高于阈值\n2. 进入容器查看 CPU 占用进程\n3. 通过 APM 工具分析 CPU 占用情况，定位问题代码\n4. 确认应用 A 对其他服务的调用出现延迟或超时\n\n**注入恢复**：\n1. 销毁 chaosblade CPU 压力实验\n2. 如 Pod 仍异常，可删除 Pod 触发重建\n\n**恢复验证**：\n1. 查看 Pod CPU 使用率监控，确认恢复到正常水平\n2. 确认应用 A 对其他服务的调用恢复正常\n\n**基准事实**：\n- **根因**：应用存在死循环、高并发计算或资源泄漏等性能问题，导致 CPU 使用率持续过高\n- **必现现象**：Pod CPU 使用率持续超过阈值，应用响应变慢或超时\n---\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_云盘空间打满/Pod_云盘空间打满_日志未清理.md":"**用例名称** 日志未清理 导致 Pod_云盘空间打满\n\n**故障现象**：\n1. Pod 挂载的云盘空间使用率达到 100%\n2. 应用写入操作失败，日志报 `No space left on device`\n3. 应用功能异常，数据无法持久化\n\n**资源准备**：\n1. 确认应用 A 已正常运行，且挂载了 PVC 用于数据存储\n2. 确认 PVC 对应的云盘容量已知\n3. 确认监控系统可观测 PVC 磁盘使用率\n\n**演练步骤**：\n1. 定位应用 A 的 Pod 及其 PVC 挂载路径\n2. 使用 chaosblade 对应用 A 的 Pod 注入磁盘填充，模拟日志堆积打满云盘：\n   ```bash\n   blade create k8s pod-disk fill \\\n     --namespace <namespace> \\\n     --labels \"app=<app>\" \\\n     --path <PVC挂载路径> \\\n     --percent 99 \\\n     --timeout 300 \\\n     --kubeconfig <路径>\n   ```\n3. 观察应用 A 的写入行为和错误日志\n\n**注入验证**：\n1. 进入 Pod 查看挂载路径磁盘使用率：`df -h <挂载路径>`，确认使用率接近 100%\n2. 在 Pod 内尝试写入文件，确认报 `No space left on device` 错误\n3. 查看应用 A 日志，确认有写入失败相关错误\n4. 确认应用 A 的业务功能受影响（如数据写入失败）\n\n**注入恢复**：\n1. 销毁 chaosblade 磁盘填充实验：`blade destroy <UID>`\n2. 确认填充的临时文件被清理\n3. 若空间未释放，手动清理注入的文件\n\n**恢复验证**：\n1. 进入 Pod 查看挂载路径磁盘使用率，确认恢复到正常水平\n2. 在 Pod 内尝试写入文件，确认成功\n3. 确认应用 A 的写入操作恢复正常\n4. 确认应用 A 业务功能恢复\n\n**基准事实**：\n- **根因**：云盘上的日志或数据文件持续增长且未配置清理策略，最终占满整个磁盘空间，导致新的写入操作失败\n- **必现现象**：磁盘使用率 100%；写入报 No space left on device；应用功能异常\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_磁盘空间使用率过高/Pod_磁盘空间使用率过高_应用日志数据积累.md":"**用例名称** 应用日志数据积累 导致 Pod_磁盘空间使用率过高\n\n**故障现象**：\n1. Pod 使用的存储空间接近上限，磁盘使用率告警\n2. 应用可能出现写入失败、响应变慢等问题\n3. 容器内日志目录（如 /var/log）文件过大\n\n**资源准备**：\n1. 确认应用 A/B 已正常运行\n2. 确认应用配置了日志输出（如输出到 /tmp 或挂载目录）\n\n**演练步骤**：\n1. 定位应用 A 的 Pod\n2. 使用 chaosblade 向应用 A 的 Pod 注入磁盘填充故障，模拟大量日志写入\n3. 持续向 Pod 写入大文件，填充磁盘空间至接近容量上限\n4. 观察 Pod 磁盘使用率变化及应用响应情况\n\n**注入验证**：\n1. 进入应用 A 的 Pod，使用 df -h 查看磁盘使用率，确认超过设定阈值\n2. 查看 Pod 状态，确认是否有磁盘相关异常事件\n3. 观察应用是否出现写入失败等异常表现\n\n**注入恢复**：\n1. 销毁 chaosblade 磁盘填充实验\n2. 删除 Pod 中产生的大文件，释放磁盘空间\n3. 或删除异常 Pod，触发重新调度创建新 Pod\n\n**恢复验证**：\n1. 查看 Pod 磁盘使用率，确认恢复到正常水平\n2. 查看应用是否恢复正常写入操作\n3. 确认 Pod 状态为 Running，无磁盘相关异常事件\n\n**基准事实**：\n- **根因**：应用日志未清理或数据写入过多，导致 Pod 存储空间被占满\n- **必现现象**：Pod 磁盘使用率超过设定阈值，应用出现写入失败\n\n---\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_网络丢包/Pod_网络丢包_服务依赖中断.md":"**用例名称** 服务依赖中断 导致 Pod_网络丢包\n\n**故障现象**：\n1. Pod 对外部服务或上下游依赖的网络请求超时或无响应\n2. 应用健康检查可能失败（如依赖外部探活）\n3. 服务间调用链路出现断裂，影响业务可用性\n\n**资源准备**：\n1. 确认目标应用已正常运行，且有对外网络调用（数据库、缓存、上下游服务等）\n2. 确认监控系统可观测网络请求成功率和延迟指标\n3. 确认目标 Pod 的标签选择器和命名空间\n\n**演练步骤**：\n1. 确认目标 Pod 的标签选择器和命名空间：\n   ```bash\n   kubectl get pods -n <namespace> -l <label-selector> -o wide\n   ```\n2. 使用 ChaosBlade 对目标 Pod 注入网络丢包故障：\n   ```bash\n   blade create k8s pod-network drop \\\n     --namespace <namespace> \\\n     --labels \"<label-key>=<label-value>\" \\\n     --source-port <port> \\\n     --kubeconfig <kubeconfig-path>\n   ```\n   - `--source-port`：限定丢包端口（如 3306 丢弃 MySQL 流量、53 丢弃 DNS 流量）\n   - 不指定端口时为全量丢包（慎用，影响所有流量包括监控和健康检查）\n3. 记录返回的 blade_uid，用于后续恢复\n\n**注入验证**：\n1. 在目标 Pod 内验证网络连通性丧失：\n   ```bash\n   kubectl exec <pod-name> -n <namespace> -- wget -qO- --timeout=5 <依赖服务地址>\n   ```\n   确认请求超时或无响应\n2. 查看应用日志确认出现连接超时错误：\n   ```bash\n   kubectl logs <pod-name> -n <namespace> --tail=20\n   ```\n3. 检查服务调用链路指标，确认目标端口流量中断\n\n**注入恢复**：\n1. 销毁 ChaosBlade 实验：\n   ```bash\n   blade destroy <blade_uid>\n   ```\n2. 如 Pod 因丢包导致健康检查失败被重启，等待新 Pod Ready\n\n**恢复验证**：\n1. 在目标 Pod 内重新验证网络连通性恢复：\n   ```bash\n   kubectl exec <pod-name> -n <namespace> -- wget -qO- --timeout=5 <依赖服务地址>\n   ```\n2. 确认应用日志不再出现连接超时错误\n3. 确认服务调用链路指标恢复正常\n\n**基准事实**：\n- **根因**：Pod 出方向网络流量被 iptables DROP 规则丢弃，导致对指定端口/地址的所有请求无响应\n- **必现现象**：目标端口的 TCP/UDP 请求超时；应用日志出现 connection timed out；依赖该连接的业务功能不可用\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_被驱逐重建/Pod_被驱逐重建_DiskPressure.md":"**用例名称** DiskPressure 导致 Pod_被驱逐重建\n\n**故障现象**：\n1. Pod 被 kubelet 驱逐（Evicted），状态为 Failed，reason 为 Evicted\n2. 节点 Conditions 中 DiskPressure 为 True\n3. 容器运行时目录（如 /var/lib/docker 或 /var/lib/containerd）磁盘使用超过 kubelet 驱逐阈值\n\n**资源准备**：\n1. 确认应用 A 已正常运行，有多个副本分布在不同节点\n2. 确认目标节点的容器运行时磁盘当前使用率距离驱逐阈值有一定空间\n3. 确认监控系统可观测节点磁盘使用率和 Pod 驱逐事件\n\n**演练步骤**：\n1. 查看目标节点 kubelet 配置的驱逐阈值（默认 `imagefs.available < 15%`）\n2. 使用 chaosblade 对目标节点的容器运行时目录注入磁盘填充，使其超过驱逐阈值：\n   ```bash\n   blade create k8s node-disk fill \\\n     --names <节点名> \\\n     --path /var/lib/containerd \\\n     --percent 90 \\\n     --timeout 300 \\\n     --kubeconfig <路径>\n   ```\n3. 等待 kubelet 检测到 DiskPressure 并触发 Pod 驱逐\n4. 观察应用 A 的 Pod 驱逐和重建行为\n\n**注入验证**：\n1. 执行 `kubectl describe node <节点名>`，确认 Conditions 中 DiskPressure 为 True\n2. 执行 `kubectl get pods --field-selector=status.phase=Failed`，确认有 Pod 被 Evicted\n3. 查看被驱逐 Pod 的详情，确认 reason 为 `The node was low on resource: ephemeral-storage`\n4. 确认应用 A 在其他节点重建 Pod\n\n**注入恢复**：\n1. 等待 chaosblade 实验自动超时恢复（300 秒内），或执行 `blade destroy <UID>`\n2. 等待节点磁盘空间释放\n3. 清理 Evicted Pod：`kubectl delete pods --field-selector=status.phase=Failed`\n\n**恢复验证**：\n1. 执行 `kubectl describe node <节点名>`，确认 DiskPressure 恢复为 False\n2. 确认应用 A 的 Pod 在正常节点上运行\n3. 确认节点磁盘使用率恢复到安全水位\n\n**基准事实**：\n- **根因**：容器运行时目录磁盘使用超过 kubelet 驱逐阈值（DiskPressure），kubelet 按优先级驱逐 Pod 以释放磁盘空间\n- **必现现象**：节点 DiskPressure=True；Pod 被 Evicted；reason 为 ephemeral-storage 不足\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_镜像拉取失败/Pod_镜像拉取失败_凭证缺失或过期.md":"**用例名称** 凭证缺失或过期 导致 Pod_镜像拉取失败\n\n**故障现象**：\n1. Pod 状态为 ImagePullBackOff 或 ErrImagePull\n2. Pod Events 中显示 `unauthorized` 或 `authentication required`\n3. 镜像仓库返回 401/403 认证错误\n\n**资源准备**：\n1. 确认应用 A 已正常运行，且使用私有镜像仓库\n2. 确认应用 A 的 Pod 配置了 imagePullSecrets\n\n**演练步骤**：\n1. 记录应用 A 当前的 imagePullSecrets 名称和 imagePullPolicy 值\n2. 记录 Deployment 当前 maxUnavailable 值，并临时设为 100%（确保滚动更新能完成，故障注入的新 Pod 不会 Ready，默认策略下 K8s 不会终止旧 Pod，导致滚动更新死锁）：\n   ```bash\n   kubectl get deployment <deployment-name> -n <namespace> \\\n     -o jsonpath='{.spec.strategy.rollingUpdate.maxUnavailable}'\n   kubectl patch deployment <deployment-name> -n <namespace> --type='json' \\\n     -p='[{\"op\":\"replace\",\"path\":\"/spec/strategy/rollingUpdate/maxUnavailable\",\"value\":\"100%\"}]'\n   ```\n3. 创建一个包含无效凭证的 Secret 来替换原有的有效凭证：\n   ```bash\n   kubectl create secret docker-registry chaos-invalid-secret \\\n     --docker-server=<registry-server> \\\n     --docker-username=invalid-user \\\n     --docker-password=invalid-password \\\n     --namespace <namespace>\n   ```\n4. 修改应用 A 的 Deployment，将 imagePullSecrets 指向无效 Secret（或直接移除 imagePullSecrets）。\n   同时检查 imagePullPolicy：如果当前为 `IfNotPresent`，需同时改为 `Always`，否则 K8s 直接使用本地缓存镜像启动 Pod，不会触发凭证校验，故障无法注入\n5. 等待 Pod 滚动更新完成，确认所有旧 Pod 已被替换\n6. 滚动更新完成后，立即还原 maxUnavailable 为原始值（maxUnavailable 只是使滚动更新完成的手段，不是故障本身，不应泄漏到恢复阶段）\n7. 观察 Pod 状态变化\n\n**注入验证**：\n1. 执行 `kubectl rollout status deployment <deployment-name>`，确认滚动更新已完成（所有旧 Pod 已被替换）。如果滚动更新未完成（卡死），则故障未完全生效，不可判定为 verified\n2. 执行 `kubectl get pods`，确认**所有**目标 Pod 状态为 ImagePullBackOff 或 ErrImagePull（不是仅一个新 Pod，而是全部副本）\n3. 执行 `kubectl describe pod <pod-name>`，确认 Events 中显示认证失败相关错误\n4. 确认错误信息包含 `unauthorized` 或 `authentication required`\n\n**注入恢复**：\n1. 恢复应用 A 的 Deployment，将 imagePullSecrets 指回原有的有效 Secret。如果注入时修改了 imagePullPolicy，需同时还原为原始值\n2. 删除测试用的无效 Secret：`kubectl delete secret chaos-invalid-secret`\n3. 等待 Pod 滚动更新完成\n\n**恢复验证**：\n1. 执行 `kubectl get pods`，确认 Pod 状态恢复为 Running\n2. 确认镜像拉取成功，无认证错误\n\n**基准事实**：\n- **根因**：imagePullSecrets 缺失或 Secret 中的凭证已过期/无效，导致向私有镜像仓库拉取镜像时认证失败\n- **必现现象**：Pod ImagePullBackOff；Events 显示 unauthorized/authentication required；镜像仓库返回 401/403\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_镜像拉取失败/Pod_镜像拉取失败_镜像不存在或标签错误.md":"**用例名称** 镜像不存在或标签错误 导致 Pod_镜像拉取失败\n\n**故障现象**：\n1. Pod 状态停留在 ImagePullBackOff 或 ErrImagePull\n2. Pod Event 显示镜像拉取失败，错误信息包含 `manifest for xxx not found`\n\n**资源准备**：\n1. 确认应用 A/B 所在节点正常运行\n2. 确认节点可正常访问镜像仓库\n\n**演练步骤**：\n1. 定位应用 A 的 Deployment\n2. 记录 Deployment 当前 maxUnavailable 值，并临时设为 100%（确保滚动更新能完成，故障注入的新 Pod 不会 Ready，默认策略下 K8s 不会终止旧 Pod，导致滚动更新死锁）：\n   ```bash\n   kubectl get deployment <deployment-name> -n <namespace> \\\n     -o jsonpath='{.spec.strategy.rollingUpdate.maxUnavailable}'\n   kubectl patch deployment <deployment-name> -n <namespace> --type='json' \\\n     -p='[{\"op\":\"replace\",\"path\":\"/spec/strategy/rollingUpdate/maxUnavailable\",\"value\":\"100%\"}]'\n   ```\n3. 修改应用 A 的镜像地址为不存在的镜像名称或标签\n4. 等待 Pod 滚动更新完成，确认所有旧 Pod 已被替换\n5. 滚动更新完成后，立即还原 maxUnavailable 为原始值（maxUnavailable 只是使滚动更新完成的手段，不是故障本身，不应泄漏到恢复阶段）\n6. 观察 Pod 的镜像拉取状态\n\n**注入验证**：\n1. 执行 `kubectl rollout status deployment <deployment-name>`，确认滚动更新已完成（所有旧 Pod 已被替换）。如果滚动更新未完成（卡死），则故障未完全生效，不可判定为 verified\n2. 执行 `kubectl get pods`，确认**所有**目标 Pod 状态停留在 ImagePullBackOff 或 ErrImagePull（不是仅一个新 Pod，而是全部副本）\n3. 执行 `kubectl describe pod <pod-name>`，确认 Events 包含镜像不存在相关信息，如 `manifest for xxx not found`\n\n**注入恢复**：\n1. 恢复应用 A 的镜像地址为正确的镜像名称和标签\n2. 等待 Pod 滚动更新完成\n\n**恢复验证**：\n1. 查看 Pod 状态，确认恢复为 Running\n2. 查看 Pod Event，确认镜像拉取成功\n\n**基准事实**：\n- **根因**：Pod 配置的镜像名称拼写错误或标签在镜像仓库中不存在\n- **必现现象**：Pod 状态为 ImagePullBackOff 或 ErrImagePull，日志显示 `manifest for xxx not found`\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Service_调用失败/Service_调用失败_ReadinessProbe配置不一致.md":"**用例名称** ReadinessProbe配置不一致 导致 Service_调用失败\n\n**故障现象**：\n1. Pod 状态为 Running 但 READY 为 0/1\n2. Service 的 Endpoints 列表为空或逐渐减少\n3. Readiness Probe 持续失败，Pod 从 Service 后端移除\n\n**资源准备**：\n1. 确认应用 A 已正常运行，对外暴露 Service\n2. 确认应用 A 实际监听的端口和健康检查路径\n\n**演练步骤**：\n1. 记录应用 A 当前的 readinessProbe 配置\n2. 记录 Deployment 当前 maxUnavailable 值，并临时设为 100%（确保滚动更新能完成，故障注入的新 Pod 不会 Ready，默认策略下 K8s 不会终止旧 Pod，导致滚动更新死锁）：\n   ```bash\n   kubectl get deployment <deployment-name> -n <namespace> \\\n     -o jsonpath='{.spec.strategy.rollingUpdate.maxUnavailable}'\n   kubectl patch deployment <deployment-name> -n <namespace> --type='json' \\\n     -p='[{\"op\":\"replace\",\"path\":\"/spec/strategy/rollingUpdate/maxUnavailable\",\"value\":\"100%\"}]'\n   ```\n3. 修改应用 A 的 Deployment，将 readinessProbe 路径或端口设置为与实际不一致：\n   ```yaml\n   readinessProbe:\n     httpGet:\n       path: /non-existent-health-path\n       port: 9999    # 应用实际不监听此端口\n     periodSeconds: 5\n     failureThreshold: 3\n   ```\n4. 等待 Pod 滚动更新完成，确认所有旧 Pod 已被替换\n5. 滚动更新完成后，立即还原 maxUnavailable 为原始值（maxUnavailable 只是使滚动更新完成的手段，不是故障本身，不应泄漏到恢复阶段）\n6. 观察 Pod Ready 状态和 Service Endpoints 变化\n\n**注入验证**：\n1. 执行 `kubectl rollout status deployment <deployment-name>`，确认滚动更新已完成（所有旧 Pod 已被替换）。如果滚动更新未完成（卡死），则故障未完全生效，不可判定为 verified\n2. 执行 `kubectl get pods`，确认**所有** Pod 状态为 Running 但 READY 列显示 0/1（不是仅一个新 Pod 0/1，而是全部副本都 0/1）\n3. 执行 `kubectl get endpoints <service-name>`，确认 Endpoints 列表**为空**（无子集），而非仅新 Pod 不在列表中\n4. 执行 `kubectl describe pod <pod-name>`，确认 Events 显示 `Readiness probe failed`\n5. 向 Service 发送请求，确认返回 connection refused 或超时。注意：connection reset by peer 可能是应用自身行为而非故障效果，不可作为故障生效的充分证据\n\n**注入恢复**：\n1. 恢复应用 A 的 Deployment，将 readinessProbe 的路径和端口修正为正确值（若原本无 readinessProbe，则移除）\n2. 等待 Pod 滚动更新完成\n\n**恢复验证**：\n1. 执行 `kubectl get pods`，确认 Pod READY 为 1/1\n2. 执行 `kubectl get endpoints <service-name>`，确认 Pod 重新加入 Endpoints\n3. 向 Service 发送请求，确认服务恢复正常\n\n**基准事实**：\n- **根因**：Readiness Probe 的路径或端口与应用实际监听不一致，Probe 持续失败导致 Pod 被标记为 Not Ready，从 Service Endpoints 中移除\n- **必现现象**：Pod Running 但 Not Ready（0/1）；Endpoints 为空；Events 显示 Readiness probe failed\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Service_调用失败/Service_调用失败_kube-proxy异常.md":"**用例名称** kube-proxy异常 导致 Service_调用失败\n\n**故障现象**：\n1. 通过 ClusterIP/NodePort 访问 Service 失败，连接超时\n2. 节点上 iptables/ipvs 规则未更新或被清空\n3. kube-proxy Pod 异常，无法维护 Service 转发规则\n\n**资源准备**：\n1. 确认应用 A 已正常运行，对外暴露 Service\n2. 确认 kube-proxy DaemonSet 正常运行\n3. 确认监控系统可观测 Service 请求指标\n\n**演练步骤**：\n1. 记录 kube-proxy DaemonSet 当前状态\n2. 选择目标节点，删除该节点上的 kube-proxy Pod 并临时阻止重建（通过 cordon 节点或修改 DaemonSet nodeSelector）：\n   ```bash\n   # 方式A：给目标节点添加标签排除 kube-proxy 调度\n   kubectl label node <目标节点> chaos-no-proxy=true\n   kubectl patch ds kube-proxy -n kube-system \\\n     -p '{\"spec\":{\"template\":{\"spec\":{\"affinity\":{\"nodeAffinity\":{\"requiredDuringSchedulingIgnoredDuringExecution\":{\"nodeSelectorTerms\":[{\"matchExpressions\":[{\"key\":\"chaos-no-proxy\",\"operator\":\"DoesNotExist\"}]}]}}}}}}}'\n   ```\n   或者直接使用 chaosblade 杀掉 kube-proxy 进程：\n   ```bash\n   blade create k8s node-process kill \\\n     --names <目标节点> \\\n     --process kube-proxy \\\n     --timeout 120 \\\n     --kubeconfig <路径>\n   ```\n3. 在目标节点上的 Pod 内通过 ClusterIP 访问 Service\n4. 观察 Service 访问结果\n\n**注入验证**：\n1. 确认目标节点上 kube-proxy 进程不存在或 Pod 处于异常状态\n2. 在目标节点的 Pod 内访问 Service ClusterIP，确认连接超时或失败\n3. 检查节点 iptables/ipvs 规则，确认 Service 相关转发规则缺失或过期\n\n**注入恢复**：\n1. 若使用标签方式：移除节点标签并恢复 DaemonSet 配置：\n   ```bash\n   kubectl label node <目标节点> chaos-no-proxy-\n   kubectl patch ds kube-proxy -n kube-system --type=json \\\n     -p='[{\"op\":\"remove\",\"path\":\"/spec/template/spec/affinity\"}]'\n   ```\n2. 若使用 chaosblade：等待实验超时或执行 `blade destroy <UID>`\n3. 等待 kube-proxy Pod 在目标节点重建\n\n**恢复验证**：\n1. 确认目标节点上 kube-proxy Pod 恢复 Running 且 Ready\n2. 在目标节点的 Pod 内重新访问 Service，确认恢复正常\n3. 检查 iptables/ipvs 规则已重新同步\n\n**基准事实**：\n- **根因**：kube-proxy Pod 异常或进程被杀，无法维护节点上的 iptables/ipvs 转发规则，导致 Service ClusterIP 流量无法被正确转发\n- **必现现象**：Service ClusterIP 访问超时；kube-proxy 不可用；节点 iptables/ipvs 规则缺失\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Service_调用失败/Service_调用失败_selector不匹配.md":"**用例名称** selector不匹配 导致 Service_调用失败\n\n**故障现象**：\n1. Service 的 Endpoints 列表为空\n2. 通过 Service 访问应用返回 connection refused 或无响应\n3. Pod 正常运行但未被 Service 选中\n\n**资源准备**：\n1. 确认应用 A 已正常运行，对外暴露 Service\n2. 确认监控系统可观测 Service 请求指标和 Endpoints 状态\n\n**演练步骤**：\n1. 记录应用 A 的 Service 当前 selector 配置\n2. 使用 kubectl patch 修改 Service 的 selector，使其不匹配任何 Pod：\n   ```bash\n   kubectl patch svc <service-name> -n <namespace> \\\n     -p '{\"spec\":{\"selector\":{\"app\":\"non-existent-app\"}}}'\n   ```\n3. 观察 Endpoints 变化和服务可用性\n\n**注入验证**：\n1. 执行 `kubectl get endpoints <service-name>`，确认 Endpoints 列表为空（无子集）\n2. 向 Service 发送请求，确认返回 connection refused 或超时\n3. 执行 `kubectl get pods -l app=<原标签>`，确认 Pod 实际正常运行\n4. 对比 Service selector 与 Pod labels，确认不匹配\n\n**注入恢复**：\n1. 使用 kubectl patch 将 Service selector 恢复为原始值：\n   ```bash\n   kubectl patch svc <service-name> -n <namespace> \\\n     -p '{\"spec\":{\"selector\":{\"app\":\"<原始标签>\"}}}'\n   ```\n2. 等待 Endpoints 自动更新\n\n**恢复验证**：\n1. 执行 `kubectl get endpoints <service-name>`，确认 Endpoints 列表恢复，包含后端 Pod IP\n2. 向 Service 发送请求，确认恢复正常\n3. 确认服务可用性恢复\n\n**基准事实**：\n- **根因**：Service 的 selector 与后端 Pod 的 label 不匹配，导致 Endpoints 控制器无法关联任何 Pod，Service 无后端可转发\n- **必现现象**：Endpoints 为空；Service 请求失败（connection refused/超时）；Pod 正常但未被选中\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Service_负载均衡异常/Service_负载均衡异常_后端不可达.md":"**用例名称** 后端不可达 导致 Service_负载均衡异常\n\n**故障现象**：\n1. Service 的 Endpoints 列表为空或部分后端不可用\n2. 请求到 Service 出现 5xx 错误或连接超时\n3. Ingress 后端健康检查失败\n\n**资源准备**：\n1. 确认应用 A 已正常运行，对外暴露 Service 和 Ingress\n2. 确认监控系统可观测 Service 请求指标和 Endpoints 状态\n\n**演练步骤**：\n1. 定位应用 A 的 Service 和后端 Pod\n2. 使用 chaosblade 对应用 A 的 Pod 注入故障，模拟后端不可达\n\n**注入方式选择（重要）**：\n- **推荐优先**：使用 `pod-process kill` 杀死后端 Pod 的主进程。优点：直接导致 Pod 重启或进入 CrashLoopBackOff，Endpoints 控制器会自动将其从 Endpoints 列表移除，故障效果明确且可观测\n- **备选方式**：使用 `pod-network drop` 断开 Pod 网络。注意：如果主机 blade 二进制与集群不兼容，会退化为 kubectl exec 方式注入，导致恢复阶段必须通过 kubectl exec 执行 blade destroy，增加恢复复杂度\n  - 如果目标是单个服务端口（如 MySQL 3306），推荐使用端口过滤以缩小爆炸半径：`pod-network drop --source-port 3306 --namespace <ns> --labels \"app=<app>\"`\n  - 如果需要完全断开 Pod 网络：`pod-network drop --namespace <ns> --labels \"app=<app>\"`，注意此方式会影响所有端口，包括 DNS 和监控\n- 选择原则：如果集群中已部署 ChaosBlade Operator 且主机 blade 可直接使用，两种方式均可；如果需要通过 kubectl exec 注入，优先选择 pod-process kill\n\n**Readiness Probe 兼容性**（选择注入方式前必须评估）：\n- 通过 `kubectl describe pod <pod>` 获取目标 Pod 的 Readiness Probe 类型\n- `exec` 类型 Probe：在容器内通过 localhost 执行，**不受** pod-network drop 的 tc 规则影响 → Pod 保持 Ready → Endpoints 不会移除\n- `httpGet/tcpSocket` 类型 Probe（端口在 Service 端口范围内）：**可能受** pod-network drop 影响 → 延迟后 Pod 变为 NotReady → Endpoints 会被移除\n- 选择原则：如果目标是\"Endpoints 移除\"，exec 类型 Probe 的 Pod 应使用 pod-process kill 而非 pod-network drop\n\n**注入验证**：\n1. 执行 `kubectl get endpoints <service-name>`，确认部分后端被移除或全不可用\n2. 向 Service 发送请求，确认出现 5xx 错误或连接超时\n3. 查看 Ingress 状态，确认后端健康检查失败\n4. 确认请求流量被调度到剩余可用后端（部分后端不可用时）\n\n**注入恢复**：\n1. 销毁 chaosblade 实验\n\n**恢复验证**：\n1. 执行 `kubectl get endpoints <service-name>`，确认所有后端恢复可用\n2. 向 Service 发送请求，确认恢复正常\n3. 查看 Ingress 状态，确认后端健康检查通过\n\n**基准事实**：\n- **根因**：Service 后端 Pod 异常或网络不通，导致负载均衡无法将请求转发到健康的后端，服务可用性下降\n- **必现现象**：Endpoints 列表部分为空或全部为空；请求出现 5xx 或超时；Ingress 后端健康检查失败\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/workload_副本被缩容/workload_副本被缩容_人为误操作.md":"**用例名称** 人为误操作 导致 workload_副本被缩容\n\n**故障现象**：\n1. Deployment/StatefulSet 的当前副本数小于期望副本数\n2. 应用可用实例减少，部分请求无法处理\n3. 服务响应延迟增大或出现超时\n\n**资源准备**：\n1. 确认应用 A 的 Deployment/StatefulSet 已正常运行，副本数大于 1\n2. 确认监控系统可观测 Pod 副本数和请求指标\n\n**演练步骤**：\n1. 定位应用 A 的 Deployment/StatefulSet\n2. 使用 kubectl 将 replicas 修改为较小的值，模拟人为误操作导致的意外缩容\n3. 观察 Pod 缩容过程和应用状态变化\n\n**标签选择器提示**：\n- Kubernetes 推荐标签格式为 `app.kubernetes.io/name=<name>`，而非简单的 `app=<name>`\n- 建议先不带 `-l` 过滤器查询 `kubectl get deployment <name> -n <ns>`，再从返回结果中提取实际标签\n- 若需用标签过滤，优先使用 `-l app.kubernetes.io/name=<name>` 或 `-l app.kubernetes.io/component=<name>`\n\n**注入验证**：\n1. 执行 `kubectl get pods`，确认 Pod 总数减少，部分 Pod 被终止\n2. 执行 `kubectl get deployment/statefulset <name>`，确认当前副本数小于缩容前的值\n3. 确认应用 A 的请求延迟增大或出现超时\n4. 确认服务可用性下降\n\n**注入恢复**：\n1. 使用 kubectl 将 replicas 恢复为原来的合理值\n2. 等待 Pod 自动扩容\n\n**恢复验证**：\n1. 执行 `kubectl get pods`，确认 Pod 总数恢复到缩容前的值\n2. 执行 `kubectl get deployment/statefulset <name>`，确认 READY 副本数等于 DESIRED\n3. 确认应用 A 的请求延迟恢复正常\n4. 确认服务可用性恢复\n\n**基准事实**：\n- **根因**：人为误操作（如 kubectl scale、修改 YAML 等）导致 Deployment/StatefulSet 的副本数被意外缩小，可用实例不足\n- **必现现象**：READY 副本数小于 DESIRED；Pod 被终止；服务可用性下降\n\n**注意事项**：\n- 若目标 Deployment/StatefulSet 由 Helm 管理（label `app.kubernetes.io/managed-by: Helm`），kubectl scale 修改会被 Helm reconciliation 覆盖\n- 注入期间应避免触发 Helm upgrade/rollback 操作，否则故障会被意外恢复\n- 反之，若需快速恢复，可通过 `helm rollback` 或 `helm upgrade` 强制还原\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/节点容器运行时磁盘使用率过高/节点容器运行时磁盘使用率过高_日志或临时文件堆积.md":"**用例名称** 日志或临时文件堆积 导致 节点容器运行时磁盘使用率过高\n\n**故障现象**：\n1. 节点磁盘使用率告警（大于85%）\n2. 容器无法写入数据\n3. `/var/log`、`/tmp` 目录占用空间大\n\n**资源准备**：\n1. 确认应用 A/B 已正常运行\n2. 确认节点磁盘空间充足\n\n**演练步骤**：\n1. 定位运行应用 A Pod 的节点\n2. 使用 chaosblade 或其他故障注入工具向节点 `/var/log` 或 `/tmp` 目录持续写入数据，模拟日志或临时文件堆积\n   - **路径语义**：在 K8s CRD 模式下（默认），`--path /tmp` 或 `--path /var/log` 是相对于容器 overlay 文件系统的路径，填充数据**通常**写入 imagefs 分区（需节点有独立 imagefs）；`--path /var/lib/docker` 等宿主机路径**通常**写入 nodefs 分区。实际分区取决于节点配置，验证时需确认检查的分区与填充目标分区一致\n3. 观察节点磁盘使用率变化\n\n**CRD 模式路径→分区映射表**：\n**注意**：下表为常见配置下的启发式映射。实际分区取决于节点的挂载配置：\n- 如果节点没有独立的 imagefs（容器运行时数据在根磁盘），所有路径都在 nodefs 上\n- `/var/lib/docker`、`/var/lib/containerd` 在独立磁盘时属于 imagefs（它们定义了 imagefs），不是 nodefs\n- 验证时以 `df -h`（无路径参数）的实际输出为准，而非下表\n\n在 K8s CRD 模式下（ChaosBlade Operator），`--path` 参数决定填充数据写入哪个分区。验证时**必须**检查对应分区，否则会产生假阴性。\n\n| `--path` 值 | 目标分区 | 典型后端设备 | 正确验证命令 | 常见假阴性命令 |\n|---|---|---|---|---|\n| `/tmp`, `/var/log`, `/var/run`, `/run` | imagefs（容器 overlay） | `/dev/vdb` 等独立磁盘 | `df -h`（无路径参数）列出所有挂载点，找 overlay 分区 | `df -h /host`（仅显示 nodefs） |\n| `/var/lib/docker`, `/var/lib/containerd`, `/var/lib/kubelet` | nodefs（根文件系统） | `/dev/vda3` 等根分区 | `df -h /host` 显示根分区使用率 | `df -h`（找错 overlay 分区） |\n| `/etc`, `/root`, `/home` | nodefs（根文件系统） | `/dev/vda3` 等根分区 | `df -h /host` 显示根分区使用率 | 同上 |\n| 其他路径 | 需 `df -h` 列出全部后判定 | 不确定 | `df -h`（无路径参数）识别哪个分区使用率变化 | 仅检查单一分区 |\n\n**注入验证**：\n0. **基线完整性检查**（验证阶段第一步，必须先于其他验证步骤执行）：\n   - **首条命令必须**是 `df -h`（无路径参数），列出所有分区使用率，标注与注入 `--path` 对应的分区（根据上方路径→分区映射表）。禁止先执行 `df -h /host` 或 `df -h /host/<path>` — 这些命令只显示 nodefs，会在 imagefs 场景下产生错误基线\n   - 后续验证中，只对比**同一分区**的使用率变化。禁止将 nodefs 基线与 imagefs 注入后数据做对比\n   - 若未在注入前记录目标分区基线，须在验证结论中注明\"No pre-injection baseline available for <分区类型>\"，并以首次检查值作为参考点\n   - 若首次检查值已接近注入参数预期值（如 `--percent 85` 对应 84%），此即故障生效的证据，无需等待\"变化\"\n1. 查看节点磁盘使用率，确认磁盘使用率变化。通过 `kubectl debug` 两步法查看宿主机磁盘使用率：\n   - Step 1：`kubectl debug node/<节点名> --image=busybox -- sleep 3600`（必须含 `-- sleep 3600` 保活，裸 busybox 会立即退出）\n   - Step 2：从 Step 1 输出找到 debug pod 名称，然后 `kubectl exec <debug-pod> -n default -- df -h`\n   - `df -h` 列出所有挂载的文件系统。如果节点有多个磁盘分区（如 nodefs 和 imagefs 分开），需检查**所有分区**的使用率变化。`df -h /host` 仅显示 nodefs（根分区）；imagefs 的变化需通过 `df -h` 列出所有挂载点来识别\n   - **注意**：otel-c-tool 不挂载 /host，`kubectl exec <otel-c-tool> -- df -h` 显示的是 overlay 文件系统，不能用于宿主机磁盘验证。禁止仅通过 `kubectl exec <Pod> -- df -h` 验证（容器 overlay 文件系统≠宿主机文件系统）\n2. 检查 `/var/log`、`/tmp` 目录大小，确认占用显著。需通过 kubectl debug 两步法进入 debug pod，路径加 `/host/` 前缀（如 `du -sh /host/tmp`、`du -sh /host/var/log`）\n\n   **CRD 模式重要提醒**：`du -sh /host/<path>` 检查的是宿主机文件系统（nodefs）。如果注入使用了 `--path /var/log` 或 `--path /tmp`（在 CRD 模式下写入容器 overlay/imagefs），`du` 将看到宿主机路径的**原始大小**，不会反映 fill 数据。此时 `df -h`（bare, 无路径参数）展示的 overlay/imagefs 使用率变化才是 fill 效果的正确证据。\n\n   - 若 `df -h` 已确认目标分区使用率达到预期 → Step 2 可标记为 `expected: du checks host nodefs, fill in imagefs overlay (confirmed by df -h)`，不要标记为 `failed`\n   - 若 fill 路径映射到 nodefs（如 `--path /var/lib/docker`）→ `du -sh /host/<path>` 应能观察到增长\n3. 使用容器运行时工具查看容器、镜像和日志占用\n4. 使用 `kubectl describe node <节点名>` 检查 DiskPressure 条件，确认 K8s 层面已检测到磁盘压力\n\n**验证语义说明**：区分两个概念：(1) 注入验证——填充数据是否写入成功（通过填充文件或磁盘增量判断）；(2) 场景验证——磁盘使用率是否达到 85%。注入验证通过但场景验证未达标时，Layer 2 应报告 'passed' 并在 Warnings 中注明阈值未达到。如果使用率未达 85%，说明 --size 参数过小，应增加 size 或改用 percent 参数。这不代表注入失败。\n\n**注入恢复**：\n1. 销毁 chaosblade 实验\n2. 停止数据写入或删除创建的大文件\n3. 清理日志文件\n\n**恢复验证**：\n1. 查看节点磁盘使用率，确认恢复到正常水平。使用 kubectl debug 两步法（同注入验证），执行 `df -h`（无路径参数）检查所有磁盘分区均恢复\n2. 确认应用 A/B 可正常写入数据\n3. 确认 `/var/log`、`/tmp` 目录大小恢复正常（需通过宿主机文件系统访问方式验证）\n\n**基准事实**：\n- **根因**：容器日志或临时文件未清理，导致磁盘空间被占满\n- **必现现象**：节点磁盘使用率大于85%，`/var/log` 或 `/tmp` 目录占用空间大\n","blade-ai/skills/k8s-chaos-skills/references/chaosblade-commands.md":"# Chaosblade K8s 命令速查表\n\n本文件提供 Chaosblade 在 Kubernetes 环境下常用故障注入命令的速查，减少执行过程中反复 `-h` 查看帮助。\n\n---\n\n## 通用语法\n\n```bash\nblade create k8s <scope>-<target> <action> [flags]\n```\n\n- `<scope>`: 作用范围，可选 `pod`、`node`、`container`\n- `<target>`: 故障目标，如 `cpu`、`network`、`disk`、`process`、`pod`(仅Pod级别)\n- `<action>`: 故障动作，如 `fullload`、`drop`、`dns`、`occupy`、`fill`、`kill`\n\n## Action 对照表（scope-target → 可用 action）\n\n| scope-target | 可用 action | 说明 |\n|---|---|---|\n| pod-cpu | `fullload` | CPU 满载 |\n| pod-mem | `load` | 内存占用 |\n| pod-network | `dns`, `drop`, `occupy` | 网络故障 (v1.8.0) |\n| pod-disk | `fill`, `burn` | 磁盘填充 / IO 负载 |\n| pod-process | `kill`, `stop` | 进程操作 |\n| pod-pod | `delete` | Pod 删除 |\n| pod-IO | `delay`, `errno` | 文件系统 IO 故障 |\n| node-cpu | `fullload` | CPU 满载 |\n| node-mem | `load` | 内存占用 |\n| node-network | `drop` | 网络故障 (v1.8.0: `delay`/`loss` → `drop`) |\n| node-disk | `fill`, `burn` | 磁盘填充 / IO 负载 (**无 fullload**) |\n| node-process | `kill`, `stop` | 进程操作 |\n| container-cpu | `fullload` | CPU 满载 |\n| container-network | `drop` | 网络故障 (v1.8.0: `delay`/`loss` → `drop`) |\n| container-process | `kill`, `stop` | 进程操作 |\n| container-container | `remove` | 容器删除 |\n\n> **⚠️ 常见错误警示**：\n> - `node-disk` **没有** `fullload` action！磁盘 IO 负载使用 `burn`，磁盘空间填充使用 `fill`\n> - `pod-disk` 同理，只有 `fill` 和 `burn`，没有 `fullload`\n> - `pod-mem` 的 action 是 `load`，不是 `fullload`\n> - `node-mem` 的 action 是 `load`，不是 `fullload`\n> - 只有 `cpu` target 才有 `fullload` action\n> - **注入前务必确认 scope-target-action 组合在上表中存在**，避免因 action 不存在导致注入失败\n\n## 通用 K8s Flags\n\n以下参数适用于所有 `blade create k8s` 命令：\n\n| Flag | 说明 | 示例 |\n|------|------|------|\n| `--namespace` | 目标命名空间 | `--namespace default` |\n| `--labels` | 按标签筛选资源 | `--labels \"app=nginx\"` |\n| `--names` | 按名称指定资源（逗号分隔） | `--names node-1,node-2` |\n| `--kubeconfig` | kubeconfig 文件路径 | `--kubeconfig ~/.kube/config` |\n| `--evict-count` | 限制影响的资源数量 | `--evict-count 1` |\n| `--evict-percent` | 限制影响的资源百分比 | `--evict-percent 50` |\n| `--waiting-time` | 等待结果的超时时间 | `--waiting-time 30s` |\n| `--timeout` | 实验自动过期时间（秒） | `--timeout 600` |\n\n---\n\n## 一、Pod 级别故障\n\n### 1. Pod CPU 满载\n\n```bash\nblade create k8s pod-cpu fullload \\\n  --namespace <ns> \\\n  --labels \"app=<app>\" \\\n  --cpu-percent <0-100> \\\n  --cpu-count <核数> \\\n  --kubeconfig ~/.kube/config\n```\n\n| Flag | 说明 | 默认值 |\n|------|------|--------|\n| `--cpu-percent` | CPU 使用率百分比 | 100 |\n| `--cpu-count` | 指定满载的 CPU 核数（不指定则全部） | 全部 |\n| `--cpu-list` | 指定满载的 CPU 核编号（如 0,1,2） | - |\n| `--timeout` | 自动恢复时间（秒） | - |\n\n### 2. Pod 内存压力\n\n```bash\nblade create k8s pod-mem load \\\n  --namespace <ns> \\\n  --labels \"app=<app>\" \\\n  --mode ram \\\n  --mem-percent <0-100> \\\n  --kubeconfig ~/.kube/config\n```\n\n| Flag | 说明 | 默认值 |\n|------|------|--------|\n| `--mode` | 内存占用模式：`ram`(物理内存) / `cache` | ram |\n| `--mem-percent` | 内存使用率百分比 | - |\n| `--reserve` | 保留的内存大小（如 `200m`） | - |\n| `--rate` | 内存增长速率（每秒MB） | - |\n\n### 3. Pod 网络延迟\n\n> **⚠️ v1.8.0 不可用**：`pod-network delay` 在 blade v1.8.0 中不存在（仅 `dns`/`drop`/`occupy`）。如需延迟效果，使用 Tier 2 kubectl-native 方案（tc qdisc）。以下为旧版参考：\n\n```bash\nblade create k8s pod-network delay \\\n  --namespace <ns> \\\n  --labels \"app=<app>\" \\\n  --time <毫秒> \\\n  --interface eth0 \\\n  --kubeconfig ~/.kube/config\n```\n\n| Flag | 说明 | 默认值 |\n|------|------|--------|\n| `--time` | 延迟时间（毫秒） | - |\n| `--offset` | 延迟波动范围（毫秒） | - |\n| `--interface` | 网络接口 | eth0 |\n| `--local-port` | 本地端口（逗号分隔） | 全部 |\n| `--remote-port` | 远程端口（逗号分隔） | 全部 |\n| `--destination-ip` | 目标 IP（逗号分隔） | 全部 |\n| `--exclude-port` | 排除端口 | - |\n| `--exclude-ip` | 排除 IP | - |\n\n### 4. Pod 网络丢包\n\n```bash\nblade create k8s pod-network drop \\\n  --namespace <ns> \\\n  --labels \"app=<app>\" \\\n  --kubeconfig ~/.kube/config\n```\n\n> **⚠️ drop 是全量丢包**（iptables DROP 语义），**不支持 `--percent` 和 `--interface`**。不带端口/IP 过滤时丢弃所有出方向流量。\n\n| Flag | 说明 | 默认值 |\n|------|------|--------|\n| `--source-port` | 源端口（逗号分隔） | 全部 |\n| `--destination-port` | 目标端口（逗号分隔） | 全部 |\n| `--source-ip` | 源 IP | 全部 |\n| `--destination-ip` | 目标 IP | 全部 |\n| `--network-traffic` | 流量方向：`in` / `out` | - |\n| `--string-pattern` | 匹配数据包内容 | - |\n\n> **爆炸半径控制提示**：drop 默认丢弃全部流量，**必须**使用 `--source-port` 或 `--destination-port` 或 `--destination-ip` 限制影响范围，避免丢弃 DNS、监控等非目标流量。仅在测试完全网络分区时使用不加过滤的注入。\n\n### 5. Pod DNS 故障\n\n```bash\nblade create k8s pod-network dns \\\n  --namespace <ns> \\\n  --labels \"app=<app>\" \\\n  --domain <域名> \\\n  --ip <伪造IP> \\\n  --kubeconfig ~/.kube/config\n```\n\n| Flag | 说明 | 默认值 |\n|------|------|--------|\n| `--domain` | 目标域名 | - |\n| `--ip` | 映射的伪造 IP | - |\n\n### 6. Pod 网络包损坏\n\n```bash\nblade create k8s pod-network corrupt \\\n  --namespace <ns> \\\n  --labels \"app=<app>\" \\\n  --percent <0-100> \\\n  --interface eth0 \\\n  --kubeconfig ~/.kube/config\n```\n\n### 7. Pod 网络包重复\n\n```bash\nblade create k8s pod-network duplicate \\\n  --namespace <ns> \\\n  --labels \"app=<app>\" \\\n  --percent <0-100> \\\n  --interface eth0 \\\n  --kubeconfig ~/.kube/config\n```\n\n### 8. Pod 磁盘填充\n\n```bash\nblade create k8s pod-disk fill \\\n  --namespace <ns> \\\n  --labels \"app=<app>\" \\\n  --path <目录> \\\n  --size <大小> \\\n  --kubeconfig ~/.kube/config\n```\n\n| Flag | 说明 | 默认值 |\n|------|------|--------|\n| `--path` | 填充的目标目录 | / |\n| `--size` | 填充大小（如 `1024m`、`10g`） | - |\n| `--percent` | 填充到磁盘使用率百分比 | - |\n| `--retain-handle` | 保留文件句柄（删除文件后不释放空间） | false |\n\n### 9. Pod 磁盘 IO 读写负载\n\n```bash\nblade create k8s pod-disk burn \\\n  --namespace <ns> \\\n  --labels \"app=<app>\" \\\n  --path <目录> \\\n  --read \\\n  --write \\\n  --kubeconfig ~/.kube/config\n```\n\n| Flag | 说明 | 默认值 |\n|------|------|--------|\n| `--path` | IO 负载目标目录 | / |\n| `--read` | 读 IO 负载 | false |\n| `--write` | 写 IO 负载 | false |\n| `--size` | 每次 IO 块大小（如 `10m`） | - |\n| `--count` | IO 次数 | - |\n\n### 10. Pod 文件系统 IO 故障\n\n```bash\nblade create k8s pod-IO delay \\\n  --namespace <ns> \\\n  --labels \"app=<app>\" \\\n  --time <毫秒> \\\n  --path <目录> \\\n  --kubeconfig ~/.kube/config\n```\n\n| Action | 说明 |\n|--------|------|\n| `delay` | 文件系统 IO 延迟 |\n| `errno` | 文件系统 IO 返回错误 |\n\n| Flag | 说明 | 默认值 |\n|------|------|--------|\n| `--time` | IO 延迟（毫秒），仅 `delay` | - |\n| `--errno` | 返回的错误码，仅 `errno` | 28 (ENOSPC) |\n| `--path` | 影响的文件路径 | - |\n| `--methods` | 拦截的系统调用（如 read,write） | 全部 |\n| `--percent` | 故障生效百分比 | 100 |\n\n### 11. Pod 进程操作\n\n```bash\nblade create k8s pod-process kill \\\n  --namespace <ns> \\\n  --labels \"app=<app>\" \\\n  --process <进程名> \\\n  --kubeconfig ~/.kube/config\n```\n\n| Action | 说明 |\n|--------|------|\n| `kill` | 杀掉进程 |\n| `stop` | 挂起进程（SIGSTOP） |\n\n| Flag | 说明 | 默认值 |\n|------|------|--------|\n| `--process` | 进程名 | - |\n| `--process-cmd` | 进程命令行关键词 | - |\n| `--signal` | 发送的信号（仅 kill） | 9 |\n| `--count` | 限制影响的进程数 | - |\n\n### 12. Pod 删除\n\n```bash\nblade create k8s pod-pod delete \\\n  --namespace <ns> \\\n  --labels \"app=<app>\" \\\n  --kubeconfig ~/.kube/config\n```\n\n| Flag | 说明 | 默认值 |\n|------|------|--------|\n| `--labels` | 标签筛选 | - |\n| `--names` | 指定 Pod 名称 | - |\n| `--evict-count` | 删除的 Pod 数量 | - |\n| `--evict-percent` | 删除的 Pod 百分比 | - |\n\n---\n\n## 二、Node 级别故障\n\n### 1. 节点 CPU 满载\n\n```bash\nblade create k8s node-cpu fullload \\\n  --names <节点名> \\\n  --cpu-percent <0-100> \\\n  --kubeconfig ~/.kube/config\n```\n\nFlags 与 Pod CPU 满载一致（`--cpu-percent`、`--cpu-count`、`--cpu-list`）。\n\n### 2. 节点内存压力\n\n```bash\nblade create k8s node-mem load \\\n  --names <节点名> \\\n  --mode ram \\\n  --mem-percent <0-100> \\\n  --kubeconfig ~/.kube/config\n```\n\nFlags 与 Pod 内存压力一致（`--mode`、`--mem-percent`、`--reserve`、`--rate`）。\n\n### 3. 节点网络延迟\n\n> **⚠️ v1.8.0 不可用**：`node-network delay` 在 blade v1.8.0 中不存在。以下为旧版参考：\n\n```bash\nblade create k8s node-network delay \\\n  --names <节点名> \\\n  --time <毫秒> \\\n  --interface eth0 \\\n  --kubeconfig ~/.kube/config\n```\n\n### 4. 节点网络丢包\n\n```bash\nblade create k8s node-network drop \\\n  --names <节点名> \\\n  --kubeconfig ~/.kube/config\n```\n\n> **⚠️ 同 Pod drop：全量丢包，不支持 `--percent` 和 `--interface`。** 用 `--source-port`/`--destination-ip` 缩小范围。\n\nNode 网络 Flags 与 Pod 网络一致（`--source-port`、`--destination-port`、`--source-ip`、`--destination-ip`、`--network-traffic` 等）。\n\n### 5. 节点磁盘填充\n\n```bash\nblade create k8s node-disk fill \\\n  --names <节点名> \\\n  --path <目录> \\\n  --size <大小> \\\n  --kubeconfig ~/.kube/config\n```\n\n| Flag | 说明 | 示例 |\n|------|------|------|\n| `--path` | 填充目标目录 | `/var/lib/docker` |\n| `--size` | 填充大小 | `50g` |\n| `--percent` | 填充到磁盘使用率 | `95` |\n\n### 6. 节点磁盘 IO 负载\n\n```bash\nblade create k8s node-disk burn \\\n  --names <节点名> \\\n  --read \\\n  --write \\\n  --path <目录> \\\n  --kubeconfig ~/.kube/config\n```\n\n| Flag | 说明 | 默认值 |\n|------|------|--------|\n| `--read` | 启用读 IO 负载 | false |\n| `--write` | 启用写 IO 负载 | false |\n| `--path` | IO 负载目标目录 | / |\n| `--size` | 每次 IO 块大小（如 `10m`） | - |\n| `--count` | IO 次数 | - |\n\n> **建议**：生产环境务必指定 `--path` 为非根分区目录（如 `/data`），避免影响根分区系统文件。\n\n### 7. 节点进程操作\n\n```bash\nblade create k8s node-process kill \\\n  --names <节点名> \\\n  --process <进程名> \\\n  --kubeconfig ~/.kube/config\n```\n\nActions 和 Flags 与 Pod 进程操作一致。\n\n---\n\n## 三、Container 级别故障\n\nContainer 级别命令在 Pod 内指定特定容器执行故障注入，适用于多容器 Pod（如有 sidecar 的场景）。\n\n### 通用 Container Flag\n\n| Flag | 说明 |\n|------|------|\n| `--container-names` | 目标容器名 |\n\n### 1. 容器 CPU 满载\n\n```bash\nblade create k8s container-cpu fullload \\\n  --namespace <ns> \\\n  --labels \"app=<app>\" \\\n  --container-names <容器名> \\\n  --cpu-percent <0-100> \\\n  --kubeconfig ~/.kube/config\n```\n\n### 2. 容器网络延迟\n\n> **⚠️ v1.8.0 不可用**：`container-network delay` 在 blade v1.8.0 中不存在。以下为旧版参考：\n\n```bash\nblade create k8s container-network delay \\\n  --namespace <ns> \\\n  --labels \"app=<app>\" \\\n  --container-names <容器名> \\\n  --time <毫秒> \\\n  --interface eth0 \\\n  --kubeconfig ~/.kube/config\n```\n\n### 3. 容器进程操作\n\n```bash\nblade create k8s container-process kill \\\n  --namespace <ns> \\\n  --labels \"app=<app>\" \\\n  --container-names <容器名> \\\n  --process <进程名> \\\n  --kubeconfig ~/.kube/config\n```\n\n### 4. 容器删除\n\n```bash\nblade create k8s container-container remove \\\n  --namespace <ns> \\\n  --labels \"app=<app>\" \\\n  --container-names <容器名> \\\n  --kubeconfig ~/.kube/config\n```\n\n---\n\n## 四、实验管理命令\n\n### 查看实验状态\n\n```bash\n# 查看所有进行中的实验\nblade status --type create\n\n# 查看指定实验详情\nblade status <UID>\n```\n\n### 销毁实验\n\n```bash\n# 销毁指定实验\nblade destroy <UID>\n\n# 批量销毁所有实验（紧急回滚用）\nblade status --type create | grep \"^UID\" | awk '{print $2}' | xargs -I {} blade destroy {}\n```\n\n### 版本与帮助\n\n```bash\n# 查看版本\nblade version\n\n# 查看所有支持的实验场景\nblade create -h\n\n# 查看某个场景的详细帮助\nblade create k8s pod-network drop -h\n```\n\n---\n\n## 五、常见演练场景速查\n\n按照 catalogue 中使用频率最高的故障场景，汇总对应的 blade 命令：\n\n### 资源压力类\n\n| 故障场景 | 命令 |\n|---------|------|\n| Pod CPU 满载 | `blade create k8s pod-cpu fullload --cpu-percent 80 --namespace <ns> --labels \"app=<app>\"` |\n| Pod 内存压力 | `blade create k8s pod-mem load --mode ram --mem-percent 90 --namespace <ns> --labels \"app=<app>\"` |\n| 节点 CPU 满载 | `blade create k8s node-cpu fullload --cpu-percent 90 --names <node>` |\n| 节点内存压力 | `blade create k8s node-mem load --mode ram --mem-percent 95 --names <node>` |\n\n### 网络故障类\n\n| 故障场景 | 命令 |\n|---------|------|\n| Pod 网络丢包(全量) | `blade create k8s pod-network drop --namespace <ns> --labels \"app=<app>\"` |\n| Pod 网络丢包(指定端口) | `blade create k8s pod-network drop --source-port 3306 --namespace <ns> --labels \"app=<app>\"` |\n| Pod DNS 故障 | `blade create k8s pod-network dns --domain example.com --ip 1.1.1.1 --namespace <ns> --labels \"app=<app>\"` |\n| 节点网络丢包 | `blade create k8s node-network drop --names <node>` |\n\n### 磁盘故障类\n\n| 故障场景 | 命令 |\n|---------|------|\n| Pod 磁盘填充 | `blade create k8s pod-disk fill --path /data --size 10g --namespace <ns> --labels \"app=<app>\"` |\n| 节点磁盘填充 | `blade create k8s node-disk fill --path /var/lib/docker --percent 95 --names <node>` |\n| 节点磁盘 IO 负载 | `blade create k8s node-disk burn --read --write --path /data --names <node>` |\n\n### 进程与 Pod 操作类\n\n| 故障场景 | 命令 |\n|---------|------|\n| 杀 Pod 内进程 | `blade create k8s pod-process kill --process <name> --namespace <ns> --labels \"app=<app>\"` |\n| 挂起 Pod 内进程 | `blade create k8s pod-process stop --process <name> --namespace <ns> --labels \"app=<app>\"` |\n| 删除 Pod | `blade create k8s pod-pod delete --namespace <ns> --labels \"app=<app>\" --evict-count 1` |\n| 杀节点进程 | `blade create k8s node-process kill --process <name> --names <node>` |\n\n---\n\n## 六、Operator YAML 模板\n\n当使用 Operator 方式（`kubectl apply`）执行持续化演练时，使用以下模板：\n\n```yaml\napiVersion: chaosblade.io/v1alpha1\nkind: ChaosBlade\nmetadata:\n  name: <experiment-name>\nspec:\n  experiments:\n    - scope: <pod|node|container>\n      target: <cpu|network|disk|process|pod|container>\n      action: <action>\n      desc: \"<实验描述>\"\n      matchers:\n        - name: namespace\n          value: [\"<namespace>\"]\n        - name: labels\n          value: [\"app=<app-name>\"]\n        # node 级别使用 names 而非 labels\n        # - name: names\n        #   value: [\"<node-name>\"]\n      flags:\n        - name: <flag-name>\n          value: \"<flag-value>\"\n```\n\n**Operator YAML 示例 - Pod CPU 满载：**\n\n```yaml\napiVersion: chaosblade.io/v1alpha1\nkind: ChaosBlade\nmetadata:\n  name: pod-cpu-fullload\nspec:\n  experiments:\n    - scope: pod\n      target: cpu\n      action: fullload\n      desc: \"Pod CPU 满载 80%\"\n      matchers:\n        - name: namespace\n          value: [\"default\"]\n        - name: labels\n          value: [\"app=nginx\"]\n      flags:\n        - name: cpu-percent\n          value: \"80\"\n```\n\n**Operator YAML 示例 - Pod 网络延迟：**\n\n```yaml\napiVersion: chaosblade.io/v1alpha1\nkind: ChaosBlade\nmetadata:\n  name: pod-network-delay\nspec:\n  experiments:\n    - scope: pod\n      target: network\n      action: delay\n      desc: \"Pod 网络延迟 3s\"\n      matchers:\n        - name: namespace\n          value: [\"default\"]\n        - name: labels\n          value: [\"app=nginx\"]\n      flags:\n        - name: time\n          value: \"3000\"\n        - name: interface\n          value: \"eth0\"\n```\n\n**Operator 管理命令：**\n\n```bash\n# 创建实验\nkubectl apply -f experiment.yaml\n\n# 查看实验状态\nkubectl get chaosblade <experiment-name> -o yaml\n\n# 销毁实验\nkubectl delete chaosblade <experiment-name>\n\n# 销毁所有实验\nkubectl delete chaosblade --all\n```\n\n---\n\n## 七、kubectl exec 注入路径\n\n当宿主机 blade CLI 不可用（未安装或版本不兼容，如报 `unknown flag` 错误）时，可通过 kubectl exec 在集群内的 tool Pod 中执行 blade 命令。\n\n### 前提条件\n- 集群中部署了 chaosblade-tool DaemonSet（如 otel-c-tool）\n- tool Pod 的 ServiceAccount 有操作目标资源的权限\n\n### 执行步骤\n\n1. 发现可用的 tool Pod：\n   ```bash\n   kubectl get pods -n chaosblade -l app=otel-c-tool --kubeconfig=<path>\n   ```\n2. 选择 STATUS=Running 的 Pod（任意一个均可，实验是集群级别的）\n3. 执行 blade 命令：\n   ```bash\n   kubectl exec <pod> -n chaosblade -- blade create k8s <scenario> [flags] --kubeconfig=<path>\n   ```\n4. 从 JSON 输出中提取 blade_uid 用于后续恢复\n\n### 示例：Pod 网络丢包\n\n```bash\n# 1. 发现 tool Pod\nkubectl get pods -n chaosblade -l app=otel-c-tool --kubeconfig=/path/to/config\n# 2. 通过 tool Pod 执行 blade create\nkubectl exec otel-c-tool-xxxxx -n chaosblade -- \\\n  blade create k8s pod-network drop \\\n  --namespace cms-demo \\\n  --labels \"app=myapp\" \\\n  --kubeconfig=/path/to/config\n# 3. 从输出中提取 blade_uid\n# {\"code\":200,\"success\":true,\"result\":\"abc123\"}\n# 4. 恢复时同样通过 tool Pod 执行 blade destroy\nkubectl exec otel-c-tool-xxxxx -n chaosblade -- \\\n  blade destroy abc123 --kubeconfig=/path/to/config\n```\n\n### 注意事项\n- 不同 tool Pod 可能运行在不同节点上，但 blade 命令通过 API Server 执行，任何健康 Pod 都可操作\n- tool Pod 可能因 DaemonSet 轮换而重启，恢复时需重新查找 Running 的 Pod\n- kubectl exec 中的 blade 命令参数与本地 blade CLI 完全一致\n"},"files":{"blade-ai/skills/k8s-chaos-skills/SKILL.md":"---\nname: k8s-chaos-skills\ndescription: |\n  Kubernetes 故障演练与混沌工程专家。当用户需要进行 K8s 故障注入测试、混沌工程演练、系统韧性验证、故障场景模拟时，立即使用此 skill。\n\n  内置多个标准化故障注入用例，覆盖 Pod（Pending、CrashLoopBackOff、OOM、CPU 满载、内存接近 Limit、磁盘满、Terminating 卡住、镜像拉取失败等）、Workload（副本不一致、HPA 副本达到上限、DaemonSet 未完全调度）、Service（状态异常、负载均衡异常）、Node（宕机、磁盘使用率过高、磁盘 IO 过高、CPU 使用率过高、内存使用率过高）、存储（PVC 挂载 Pending）五个层级。\n\n  通过「意图识别 → 用例选择 → 用例执行」的决策树流程，精确匹配用户需求并执行对应演练方案。即使用户只是笼统地说「帮我做个故障演练」或「测试下应用的容错能力」，也应该触发此 skill 引导用户完成完整流程。\n\nscripts:\n  - name: list_scenarios.py\n    description: \"列出当前支持的所有故障演练场景（JSON 结构化输出）\"\n  - name: inject_cni_exhaust.py\n    description: \"CNI IP 耗尽注入 — 自动计算副本数，精确耗尽目标节点 IP 而不触发 OutOfpods。参数: --namespace <ns> --node <node> --kubeconfig <path>\"\n---\n\n# K8s 故障演练\n\n```\n意图识别 ──→ 用例选择 ──→ 用例执行\n(提取四维度)  (决策树匹配)  (读取文件并按步骤执行)\n```\n\n## 安全红线\n\n以下规则优先级高于一切操作指令，在任何步骤中都不得违反：\n\n- **隔离**：在隔离命名空间或测试集群演练，严禁在生产核心链路注入\n- **最小影响**：用精确标签选择器定位目标，范围尽可能小\n- **可回滚**：注入前明确回滚方案，确保 30 秒内可恢复\n- **有监控**：无监控不演练\n- **仅限已有用例**：只能执行 `references/catalogue/` 中已有的故障注入用例，严禁自行编造、拼凑或即兴发挥用例中未涉及的故障注入操作。无法匹配时必须明确告知用户「当前不支持该场景」并停止\n- **禁止**：业务高峰期演练 / 对 etcd、kube-apiserver 等控制平面注入 / 无备份对 StatefulSet 做破坏性实验\n\n---\n\n## 第一步：意图识别\n\n从用户输入中提取四个维度：\n\n| 维度 | 说明 | 示例 |\n|------|------|------|\n| **故障层级** | 作用在哪个层面 | Pod / Workload / Service / Node |\n| **故障现象** | 期望模拟的表现 | Pending、OOM、CPU 高 |\n| **故障原因** | 具体根因 | 资源不足、配置错误 |\n| **目标应用** | 注入目标 | 应用名、命名空间 |\n| **kubeconfig** | 集群凭证路径 | `~/.kube/config` |\n\n**层级判断关键词：**\n\n| 关键词 | 层级 |\n|--------|-----|\n| pod、容器、崩溃、重启、OOM、CPU高、内存高、镜像、挂载、磁盘空间、磁盘IO | Pod |\n| 副本、deployment、扩容、缩容 | Workload |\n| service、服务发现、负载均衡、端口、endpoints | Service |\n| 节点、node、磁盘、宿主机 | Node |\n\n**信息不全时的处理：**\n- 用户明确说出故障现象 → 直接进入第二步\n- 用户只说大致目标（如「测试容错」） → 提问引导确认四个维度\n- 用户描述生产问题要复现 → 从描述提取现象和原因，匹配用例\n- 匹配到多个用例 → 列出候选，让用户选择\n- 只说了现象没说根因 → 推荐该分类下最常见的用例，并列出其他选项\n- 不在覆盖范围 → 明确告知「当前不支持该场景」，停止操作，严禁自行构造用例外的故障注入\n\n---\n\n## 第二步：用例选择（动态发现）\n\n所有用例存储在 `references/catalogue/` 下，通过目录结构和文件命名规约自动发现，无需维护静态索引。\n\n### 命名规约\n\n```\nreferences/catalogue/\n├── <故障分类>/                         # 目录名 = 故障层级_故障现象（每个目录对应唯一的 Scope+Target+Action 组合）\n│   ├── <故障分类>_<根因A>.md           # 文件名 = 分类名_具体根因\n│   ├── <故障分类>_<根因B>.md\n│   └── ...\n└── ...\n```\n\n示例：\n- `references/catalogue/Pod_Pending/Pod_Pending_节点资源不足.md`\n- `references/catalogue/Pod_磁盘空间使用率过高/Pod_磁盘空间使用率过高_应用日志数据积累.md`（pod-disk fill）\n- `references/catalogue/Pod_磁盘IO过高/Pod_磁盘IO过高_异常IO占用.md`（pod-disk burn）\n\n### 发现流程\n\n**第 1 步：列出所有分类目录，匹配故障现象**\n\n```bash\nls references/catalogue/\n```\n\n从返回的目录名中，根据第一步识别的故障现象选择最匹配的目录。目录名本身已包含故障层级和故障现象信息（如 `Pod_Pending`、`service_conditions状态异常`、`节点容器运行时磁盘使用率过高`）。\n\n**第 2 步：列出该目录下所有用例文件，匹配根因**\n\n```bash\nls references/catalogue/<匹配的目录>/\n```\n\n从返回的文件名中，根据用户描述的根因选择最匹配的文件。文件名中 `_` 后的部分即为该用例对应的根因。\n\n- 如果用户明确了根因 → 直接选择对应文件\n- 如果用户未说明根因 → 将文件列表展示给用户，让用户选择\n- 如果没有匹配的文件 → 告知用户「当前不支持该场景」，停止操作\n\n### 新增/删除用例\n\n遵循命名规约即可，无需修改本文件：\n- **新增用例**：在对应分类目录下新建 `<分类>_<根因>.md`\n- **新增分类**：新建目录 `<故障层级>_<故障现象>/`，在其中添加用例文件\n- **删除用例**：直接删除对应 `.md` 文件\n\n### 辅助脚本\n\n- `scripts/list_scenarios.py`：一键列出所有已支持的演练场景（JSON 结构化输出），用于快速总览或对接外部系统\n  用法：`execute_skill_script(skill_name=\"k8s-chaos-skills\", script_name=\"list_scenarios.py\")`\n\n---\n\n## 第三步：用例执行\n\n1. 读取 `references/catalogue/<分类目录>/<用例文件>.md`\n2. 将用例中的占位符替换为用户实际参数（`应用 A` → 目标应用，`<namespace>` → 实际命名空间）\n3. 所有 `blade` 和 `kubectl` 命令必须显式指定 `--kubeconfig <路径>`，使用第一步中用户确认的 kubeconfig 路径，禁止依赖默认值\n4. 涉及 blade 命令时，查阅 `references/chaosblade-commands.md` 获取完整参数\n5. 严格按用例中的 **演练步骤 → 注入验证 → 注入恢复 → 恢复验证** 顺序执行\n6. 执行完毕后输出演练报告：\n\n```\n演练报告\n- 用例：[决策树路径，如 Pod > Pending > 节点资源不足]\n- 目标：[namespace/app-name]\n- 注入结果：[成功/失败] + 观察到的现象\n- 恢复结果：[成功/失败] + 是否符合基准事实\n- 发现的问题与改进建议\n```\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/DNS_解析失败/DNS_解析失败_CoreDNS异常.md":"**用例名称** CoreDNS异常 导致 DNS_解析失败\n\n**故障现象**：\n1. Pod 内 DNS 解析失败，应用报 `Name or service not known` 或 `NXDOMAIN` 错误\n2. CoreDNS Pod 异常（CrashLoopBackOff/不可用）\n3. 集群内服务间调用因 DNS 解析失败而中断\n\n**资源准备**：\n1. 确认应用 A 已正常运行，且依赖集群 DNS 进行服务发现\n2. 确认 CoreDNS Deployment 正常运行\n3. 确认监控系统可观测 DNS 请求指标\n\n**演练步骤**：\n1. 记录 CoreDNS Deployment 当前副本数和配置，并获取其 Pod 选择器标签：\n   ```bash\n   kubectl get deployment coredns -n kube-system -o jsonpath='{.spec.selector.matchLabels}'\n   ```\n   记录返回的标签（如 `component=coredns` 或 `k8s-app=kube-dns`），后续步骤中用 `<coredns-label>` 表示该标签\n2. 将 CoreDNS Deployment 的副本数缩为 0，模拟 CoreDNS 完全不可用：\n   ```bash\n   kubectl scale deployment coredns -n kube-system --replicas=0\n   ```\n3. 在应用 A 的 Pod 内尝试进行 DNS 解析\n4. 观察应用 A 的服务间调用行为\n\n**注入验证**：\n1. 执行 `kubectl get pods -n kube-system -l <coredns-label>`（使用演练步骤 1 中获取的实际标签），确认无 CoreDNS Pod 运行\n2. 在应用 A 的 Pod 内执行 DNS 解析测试：\n   ```bash\n   kubectl exec <pod-name> -- nslookup kubernetes.default.svc.cluster.local\n   ```\n   确认解析失败\n3. 确认应用 A 依赖 DNS 的服务调用出现错误\n\n**注入恢复**：\n1. 恢复 CoreDNS 副本数：\n   ```bash\n   kubectl scale deployment coredns -n kube-system --replicas=<原始副本数>\n   ```\n2. 等待 CoreDNS Pod 启动并就绪\n\n**恢复验证**：\n1. 执行 `kubectl get pods -n kube-system -l <coredns-label>`（使用演练步骤 1 中获取的实际标签），确认 CoreDNS Pod 全部 Running 且 Ready\n2. 在应用 A 的 Pod 内重新执行 DNS 解析，确认恢复正常\n3. 确认应用 A 的服务间调用恢复\n\n**基准事实**：\n- **根因**：CoreDNS Pod 异常或不可用，导致集群内 DNS 解析服务中断，依赖 DNS 的服务发现和调用全部失败\n- **必现现象**：Pod 内 DNS 解析超时或返回 NXDOMAIN；CoreDNS Pod 不可用；服务间调用失败\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/DaemonSet_未完全调度/DaemonSet_未完全调度_节点不可调度.md":"**用例名称** 节点不可调度 导致 DaemonSet_未完全调度\n\n**故障现象**：\n1. DaemonSet 的 Ready 副本数小于期望副本数\n2. 部分节点上没有运行 DaemonSet Pod\n3. `kubectl get daemonset` 显示 DESIRED 与 READY 数量不一致\n\n**资源准备**：\n1. 确认 DaemonSet 应用 A 已正常运行，且所有节点均有副本\n2. 确认监控系统可观测 DaemonSet 副本状态\n\n**演练步骤**：\n1. 选取一个运行 DaemonSet Pod 的节点\n2. 使用 kubectl 将该节点标记为不可调度（cordon）：`kubectl cordon <node>`\n3. 给该节点添加一个 DaemonSet 未配置容忍的自定义污点：`kubectl taint nodes <node> chaos-drill/unschedulable=true:NoSchedule`\n4. 删除该节点上的 DaemonSet Pod，观察 Pod 是否被重建\n5. 观察 DaemonSet 副本数变化\n\n**注入验证**：\n1. 执行 `kubectl get nodes`，确认目标节点标记为 SchedulingDisabled\n2. 执行 `kubectl describe node <node>`，确认自定义污点 `chaos-drill/unschedulable=true:NoSchedule` 存在\n3. 执行 `kubectl get daemonset`，确认 DESIRED 与 READY 数量不一致\n4. 确认目标节点上的 DaemonSet Pod 删除后无法被重建\n\n**注入恢复**：\n1. 使用 kubectl 取消节点不可调度标记（uncordon）：`kubectl uncordon <node>`\n2. 移除自定义污点：`kubectl taint nodes <node> chaos-drill/unschedulable=true:NoSchedule-`\n3. 等待 DaemonSet Pod 在该节点重建\n\n**恢复验证**：\n1. 执行 `kubectl get nodes`，确认目标节点恢复为可调度状态\n2. 执行 `kubectl describe node <node>`，确认自定义污点已被移除\n3. 执行 `kubectl get daemonset`，确认 DESIRED 与 READY 数量一致\n4. 确认目标节点上 DaemonSet Pod 已正常运行\n\n**注意事项**：\n- Kubernetes ≥ 1.12 的 DaemonSet 默认容忍 `node.kubernetes.io/unschedulable` 污点，因此 `kubectl cordon` 不会阻止 DaemonSet Pod 调度\n- 必须添加自定义污点（DaemonSet 未配置容忍的），才能有效阻止 Pod 调度\n- 恢复时需一并移除自定义污点，否则 Pod 仍无法调度\n\n**基准事实**：\n- **根因**：节点被标记为不可调度（cordon）且存在 DaemonSet 未容忍的自定义污点，导致 DaemonSet 无法在该节点创建 Pod，副本数小于期望数\n- **必现现象**：DaemonSet DESIRED 与 READY 不一致；节点 SchedulingDisabled；节点存在自定义污点；节点上缺少 DaemonSet Pod\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/HPA_副本达到上限/HPA_副本达到上限_资源饱和.md":"**用例名称** 资源饱和 导致 HPA_副本达到上限\n\n**故障现象**：\n1. HPA 的当前副本数达到 maxReplicas 上限，无法继续扩容\n2. 应用 CPU 或内存使用率仍持续高于 HPA 目标阈值\n3. 应用响应延迟增大，出现超时\n\n**资源准备**：\n1. 确认应用 A 已正常运行，且已配置 HPA（设置合适的 maxReplicas 以便快速触发上限）\n2. 确认监控系统可观测 HPA 状态和 Pod CPU/内存指标\n\n**演练步骤**：\n1. 定位应用 A 的 HPA，记录 maxReplicas 配置\n2. 使用 chaosblade 对应用 A 的所有 Pod 注入 CPU 压力，持续超过 HPA 扩容阈值\n3. 观察 HPA 扩容行为，等待副本数达到 maxReplicas 上限\n\n**注入验证**：\n1. 执行 `kubectl get hpa`，确认 REPLICAS 已达到 MAXPODS 上限\n2. 查看 HPA Event，确认出现 `FailedGetScale` 或 `DesiredReplicas` 超过 maxReplicas 的告警\n3. 查看 Pod CPU 使用率，确认仍持续高于目标阈值\n4. 确认应用 A 的请求延迟增大，出现超时\n\n**注入恢复**：\n1. 销毁 chaosblade CPU 压力实验\n2. 等待 HPA 自动缩容\n\n**恢复验证**：\n1. 执行 `kubectl get hpa`，确认 REPLICAS 回落至正常水平\n2. 查看 Pod CPU 使用率，确认恢复到 HPA 目标阈值以下\n3. 确认应用 A 的请求延迟恢复正常\n\n**基准事实**：\n- **根因**：应用负载超过 HPA 的 maxReplicas 能覆盖的处理能力，HPA 达到扩容上限后无法继续扩容，导致服务资源饱和\n- **必现现象**：HPA REPLICAS 达到 MAXPODS；HPA Event 有超限告警；CPU 使用率持续超过目标阈值；应用性能下降\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Node_CPU使用率过高/Node_CPU使用率过高_异常进程占用.md":"**用例名称** 异常进程占用 导致 Node_CPU使用率过高\n\n**故障现象**：\n1. 节点 CPU 使用率持续超过 90%\n2. 节点上 Pod 响应变慢，出现超时\n3. Load Average 显著升高\n\n**资源准备**：\n1. 确认应用 A 已正常运行\n2. 确认监控系统（如 Prometheus）已配置，可观测节点 CPU 指标\n\n**演练步骤**：\n1. 定位运行应用 A 的节点\n2. 使用 chaosblade 对该节点注入 CPU 满载，模拟异常进程占用节点 CPU\n3. 观察节点 CPU 使用率及 Pod 性能变化\n\n**注入验证**：\n1. 查看节点 CPU 使用率监控，确认持续超过 90%\n2. 查看 Load Average，确认显著升高\n3. 确认应用 A 的请求延迟增大\n\n**注入恢复**：\n1. 销毁 chaosblade 实验\n\n**恢复验证**：\n1. 查看节点 CPU 使用率监控，确认恢复到正常水平\n2. 确认应用 A 的请求延迟恢复正常\n\n**基准事实**：\n- **根因**：节点上存在异常进程大量占用 CPU，导致节点 CPU 使用率过高，影响同节点上所有 Pod 的性能\n- **必现现象**：节点 CPU 使用率持续超过 90%；Load Average 显著升高；同节点 Pod 响应变慢\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Node_不可用/Node_不可用_节点宕机.md":"**用例名称** 节点宕机 导致 Node_不可用\n\n**故障现象**：\n1. 节点状态变为 NotReady\n2. 节点上所有 Pod 无法访问\n3. kubelet 停止上报节点状态，NodeStatus 中 LastHeartbeatTime 停止更新\n4. Pod 在其他节点上被重建\n\n**资源准备**：\n1. 确认应用 A 已正常运行，且有多个副本分布在不同节点\n2. 确认监控系统可观测节点状态和 Pod 状态\n\n**演练步骤**：\n1. 定位运行应用 A 的节点\n2. 使用 chaosblade 对该节点注入网络完全丢包（node-network drop 即全量丢包，不需要 --percent），并设置 `--timeout 600`（600 秒后自动恢复），模拟节点与集群失联的宕机场景\n3. 观察节点状态和 Pod 调度行为变化\n\n**注入验证**：\n1. 执行 `kubectl get nodes`，确认目标节点状态变为 NotReady\n2. 查看 NodeStatus，确认 LastHeartbeatTime 停止更新\n3. 确认节点上应用 A 的 Pod 在其他节点上被重建\n4. 确认应用 A 的服务整体仍可访问（多副本场景）\n\n**注入恢复**：\n1. 等待 chaosblade 实验自动超时恢复（600 秒内），agent 本地定时器会自动清理网络规则\n2. 如超时后仍未恢复，通过 `blade destroy <UID>` 或重启节点强制恢复\n\n**恢复验证**：\n1. 执行 `kubectl get nodes`，确认目标节点恢复 Ready\n2. 确认 LastHeartbeatTime 恢复更新\n3. 确认应用 A 的 Pod 恢复正常运行\n\n**基准事实**：\n- **根因**：节点网络完全中断，导致 kubelet 无法与 API server 通信，停止上报节点状态\n- **必现现象**：节点 NotReady；LastHeartbeatTime 停止更新；Pod 在其他节点被重建\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Node_内存使用率过高/Node_内存使用率过高_异常进程占用.md":"**用例名称** 异常进程占用 导致 Node_内存使用率过高\n\n**故障现象**：\n1. 节点内存使用率持续超过 90%\n2. 节点上 Pod 出现 OOMKilled 或被驱逐\n3. 节点 Status 出现 MemoryPressure 条件为 True\n\n**资源准备**：\n1. 确认应用 A 已正常运行\n2. 确认监控系统（如 Prometheus）已配置，可观测节点内存指标\n\n**演练步骤**：\n1. 定位运行应用 A 的节点\n2. 使用 chaosblade 对该节点注入内存压力，模拟异常进程占用节点内存\n3. 观察节点内存使用率及 Pod 状态变化\n\n**注入验证**：\n1. 查看节点内存使用率监控，确认持续超过 90%\n2. 执行 `kubectl describe node <节点名>`，确认 MemoryPressure 条件为 True\n3. 确认应用 A 的 Pod 出现 OOMKilled 或被驱逐\n\n**注入恢复**：\n1. 销毁 chaosblade 实验\n\n**恢复验证**：\n1. 查看节点内存使用率监控，确认恢复到正常水平\n2. 执行 `kubectl describe node <节点名>`，确认 MemoryPressure 条件为 False\n3. 确认应用 A 的 Pod 恢复正常运行\n\n**基准事实**：\n- **根因**：节点上存在异常进程大量占用内存，导致节点内存使用率过高，触发 MemoryPressure，Pod 被 OOMKilled 或驱逐\n- **必现现象**：节点内存使用率持续超过 90%；MemoryPressure 条件为 True；Pod 出现 OOMKilled 或被驱逐\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Node_磁盘IO过高/Node_磁盘IO过高_异常IO占用.md":"**用例名称** 异常IO占用 导致 Node_磁盘IO过高\n\n**故障现象**：\n1. 节点磁盘 IO 使用率持续过高（iostat 显示 %util 接近 100%）\n2. 节点上 Pod 的磁盘读写延迟增大，应用响应变慢\n3. iowait 占比升高\n\n**资源准备**：\n1. 确认应用 A 已正常运行\n2. 确认监控系统可观测节点磁盘 IO 指标\n\n**演练步骤**：\n1. 定位运行应用 A 的节点\n2. **路径校验（必须）**：注入前验证目标路径存在且可写：\n   - 通过 `kubectl exec <tool-pod> -n chaosblade -- ls -ld <磁盘路径>` 确认路径存在\n   - 如路径不存在，通过 `df -h` 查看可用挂载点，选择已存在的可写目录\n   - 常见可用路径：`/var/lib/containerd`、`/var/lib/docker`、`/tmp`、`/var/log`\n   - **禁止使用未校验的路径** — ChaosBlade 接受任意路径但底层 dd 进程会静默失败\n   - 不同路径可能对应不同的物理磁盘分区，注入前可通过 `df -h <路径>` 确认路径所在的设备\n3. 使用 chaosblade 对该节点注入磁盘 IO 负载：`blade create k8s node-disk burn --read --write --names <节点名> --path <已校验的磁盘路径> --timeout <秒> --kubeconfig <路径>`\n4. 观察节点磁盘 IO 指标及 Pod 性能变化\n\n**注入验证**：\n1. 查看节点磁盘 IO 负载指标：\n   - 优先：`iostat -xd 1 3`（关注 %util 接近 100%）\n   - BusyBox 备选：`iostat -d -k 1 3`（关注 tps 和 kB_wrtn/s/kB_read/s 异常升高）+ `iostat -c 1 3`（关注 %iowait 显著升高）\n   - 进程确认：`ps | grep dd` 确认 ChaosBlade 的 dd 压测进程在运行（若 dd 不存在，说明路径无效导致注入静默失败，需检查路径是否存在）\n   - **多磁盘注意**：`iostat` 显示节点上所有物理磁盘的 IO 指标。如果节点有多个磁盘（如 vda 用于 nodefs，vdb 用于 imagefs），需根据 `--path` 参数判断目标路径对应的物理磁盘，只关注该磁盘的指标变化\n2. 查看 iowait 占比，确认显著升高（`iostat -c` 或节点监控）\n3. 确认应用 A 的磁盘读写延迟增大（见下方 Pod 级验证方法）\n\n**Pod 级磁盘 IO 验证方法**：\n- 方法 1（推荐）：在目标节点上选一个 Running Pod，`kubectl exec <pod> -- dd if=/dev/zero of=/tmp/disk-io-test bs=1M count=100`，对比注入前后写入耗时\n- 方法 2：`kubectl exec <pod> -- df -h` 确认 Pod 所在容器的磁盘使用率（注意：显示的是 overlay 文件系统，非宿主机），`kubectl describe pod <pod>` 检查 Events 中是否有磁盘相关告警\n- 方法 3（容器无 dd 时）：`kubectl get events -n <ns> --field-selector involvedObject.name=<pod>` 观察是否有 IO 相关事件\n\n**注入恢复**：\n1. 销毁 chaosblade 实验\n\n**恢复验证**：\n1. 查看节点磁盘 IO 监控，确认 %util 恢复正常：\n   - 优先：`iostat -xd 1 3`\n   - BusyBox 备选：`iostat -d -k 1 3`（确认 tps/吞吐量回落）+ `iostat -c 1 3`（确认 %iowait 恢复基线）\n2. 确认 iowait 占比恢复正常\n3. 确认应用 A 的磁盘读写延迟恢复正常（使用 Pod 级验证方法中的 dd 写入测试，确认耗时恢复）\n\n**基准事实**：\n- **根因**：节点上存在异常进程大量占用磁盘 IO，导致磁盘 IO 使用率过高，影响同节点上所有 Pod 的磁盘读写性能\n- **必现现象**：节点磁盘 IO %util 接近 100%；iowait 占比升高；同节点 Pod 磁盘读写延迟增大\n\n**CRD 模式 overlay 文件系统关键说明**：\n- ChaosBlade K8s CRD 模式下，`node-disk burn --path /tmp` 的 dd 进程运行在 DaemonSet tool pod 内，\n  写入的是**容器 overlay 文件系统**（通常由 imagefs/vdb 支持），**而非宿主机 /tmp**（通常由 nodefs/vda3 支持）\n- **验证 burn 时不应该检查 /host/tmp/ 下的文件**：burn 产生的临时文件在 overlay 中，不会出现在宿主机路径\n- **df -h 对 burn 验证无效**：burn 产生的是 I/O 压力（临时文件会被自动清理），不会造成磁盘使用量持续增长。\n  用 df -h 验证 burn 可能导致误判为\"注入失败\"\n- **正确的 burn 验证方法**：通过 `/proc/diskstats` 两次采样（间隔 3-5 秒），计算写入吞吐量增量：\n  - 读取方法：`cat /proc/diskstats`，格式为 `major minor name reads reads_merged sectors_read ... sectors_written writes_merged sectors_written ...`\n  - 计算方式：delta(sectors_written) × 512 / 间隔秒数 / 1048576 = MB/s\n  - 判断标准：任何分区持续写入 >10MB/s 即表示 burn 在生效\n  - 注意跳过分区条目（如 vda1、vda3），只关注整盘设备（如 vda、vdb）\n- **fill 与 burn 的验证方法差异**：\n  - fill（空间填充）：df -h 是主要验证手段（填充产生持久数据，磁盘使用量增加）\n  - burn（IO 压力）：/proc/diskstats 是主要验证手段（burn 产生 IO 压力，不产生持久数据）\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_CPU_Throttling/Pod_CPU_Throttling_limits.cpu过低.md":"**用例名称** limits.cpu过低 导致 Pod_CPU_Throttling\n\n**故障现象**：\n1. Pod 内进程频繁被内核 CPU 节流（throttle），`cpu.stat` 中 `nr_throttled` 持续增长\n2. 应用请求延迟显著增大，P99 延迟飙升\n3. `kubectl top pod` 显示 CPU 使用率接近 limits 但实际未满载\n\n**资源准备**：\n1. 确认应用 A 已正常运行，且 Pod 配置了 resources.limits.cpu\n2. 确认监控系统可观测 Pod CPU 使用率及 throttle 指标\n\n**演练步骤**：\n1. 定位应用 A 的 Deployment\n2. 使用 kubectl patch 将应用 A 的 CPU limits 调低为极小值（如 50m），模拟 limits.cpu 配置过低的场景\n3. 使用 chaosblade 对应用 A 的 Pod 注入 CPU 负载，确保实际 CPU 需求超过 limits，触发内核 throttle\n4. 观察 Pod CPU throttle 指标变化及应用响应延迟\n\n**注入验证**：\n1. 进入容器查看 `/sys/fs/cgroup/cpu/cpu.stat`，确认 `nr_throttled` 和 `throttled_time` 持续增长\n2. 查看监控指标，确认 Pod CPU 使用率接近 limits\n3. 确认应用 A 的请求延迟显著增大\n\n**注入恢复**：\n1. 销毁 chaosblade CPU 负载实验\n2. 使用 kubectl patch 将应用 A 的 CPU limits 恢复为原始合理值\n\n**恢复验证**：\n1. 查看 `cpu.stat`，确认 `nr_throttled` 停止增长\n2. 确认应用 A 的请求延迟恢复正常\n\n**基准事实**：\n- **根因**：容器 limits.cpu 设置过低，实际 CPU 需求超过 limit，内核对容器 CPU 时间片进行 throttle，导致应用性能下降\n- **必现现象**：cpu.stat 中 nr_throttled 持续增长；应用延迟飙升；CPU 使用率接近 limits 上限\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_ContainerCreating/Pod_ContainerCreating_CNI分配失败.md":"**用例名称** CNI分配失败 导致 Pod_ContainerCreating\n\n**故障现象**：\n1. Pod 长时间停留在 ContainerCreating 状态\n2. Pod Events 中显示 `failed to allocate for ENI` 或 `no available IP in subnet` 或 CNI 相关错误\n3. 节点上的 IP 资源池耗尽或 ENI 数量达到上限\n\n**资源准备**：\n1. 确认应用 A 已正常运行\n2. 确认集群使用 ENI 或 vSwitch 分配 Pod IP 的 CNI 插件（如 Terway）\n\n**演练步骤**：\n1. 查看目标节点的 ENI 和 IP 分配情况，确认目标应用 Pod 所在节点（记为 `<目标节点>`）\n2. 给目标节点添加标签，并给应用 A 的 Deployment 添加 nodeSelector，确保新 Pod 只能调度到目标节点（防止调度器规避耗尽节点）：\n   ```bash\n   kubectl label node <目标节点> chaos-cni-target=true\n   kubectl patch deployment <deployment-name> -n <namespace> --type='merge' \\\n     -p='{\"spec\":{\"template\":{\"spec\":{\"nodeSelector\":{\"chaos-cni-target\":\"true\"}}}}}'\n   ```\n   等待 rollout 完成（Pod 仍在原节点运行，因为目标节点已有此标签）。\n   记录原始 nodeSelector 值，恢复时还原。\n3. 使用 `execute_skill_script` 在目标节点批量创建 Pod 耗尽 IP/ENI 资源（**`kubectl create/apply` 不可用，必须使用脚本**）：\n   ```\n   execute_skill_script(\n     skill_name=\"k8s-chaos-skills\",\n     script_name=\"inject_cni_exhaust.py\",\n     params=\"--namespace <namespace> --node <目标节点> --kubeconfig <kubeconfig路径>\"\n   )\n   ```\n   脚本会创建 `chaos-ip-exhaust` Deployment 并绑定到目标节点。\n4. 删除应用 A 在目标节点上的 Pod，触发重建。由于 nodeSelector 约束，新 Pod 只能调度到已耗尽的目标节点，将进入 ContainerCreating 状态\n5. 观察新 Pod 的 ContainerCreating 状态\n\n**注入验证**：\n1. 执行 `kubectl get pods`，确认应用 A 新 Pod 状态为 ContainerCreating\n2. 执行 `kubectl describe pod <pod-name>`，确认 Events 显示 CNI/IP 分配失败相关错误\n3. 查看节点 ENI/IP 使用情况，确认资源已耗尽\n\n**注入恢复**：\n1. 删除批量创建的 Deployment：`kubectl delete deployment chaos-ip-exhaust -n <namespace>`\n2. 移除应用 A 的 Deployment 上添加的 nodeSelector（还原为原始值，若原本无 nodeSelector 则移除整个 nodeSelector）\n3. 移除目标节点上添加的标签：`kubectl label node <目标节点> chaos-cni-target-`\n4. 等待 IP/ENI 资源释放和 Pod 滚动更新完成\n\n**恢复验证**：\n1. 执行 `kubectl get pods`，确认应用 A 的 Pod 状态恢复为 Running\n2. 确认节点 IP/ENI 资源恢复可用\n3. 确认应用 A 网络连通正常\n\n**基准事实**：\n- **根因**：节点可用 IP 池耗尽或 ENI 数量达到上限或 vSwitch IP 不足，CNI 插件无法为新 Pod 分配网络资源\n- **必现现象**：Pod ContainerCreating；Events 显示 CNI/IP/ENI 分配失败；节点网络资源耗尽\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_ContainerCreating/Pod_ContainerCreating_Volume挂载超时CSI异常.md":"**用例名称** Volume挂载超时CSI异常 导致 Pod_ContainerCreating\n\n**故障现象**：\n1. Pod 长时间停留在 ContainerCreating 状态\n2. Pod Events 中显示 `FailedMount` 或 `FailedAttachVolume`，提示 CSI driver 超时或可用区不匹配\n3. PV 对应的云盘与 Pod 调度的节点不在同一可用区\n\n**资源准备**：\n1. 确认应用 A 已正常运行，且使用了 CSI 驱动管理的存储卷\n2. 确认集群跨多个可用区部署\n\n**演练步骤**：\n1. 记录 Deployment 当前 maxUnavailable 值，并临时设为 100%（确保滚动更新能完成，故障注入的新 Pod 不会 Ready，默认策略下 K8s 不会终止旧 Pod，导致滚动更新死锁）：\n   ```bash\n   kubectl get deployment <deployment-name> -n <namespace> \\\n     -o jsonpath='{.spec.strategy.rollingUpdate.maxUnavailable}'\n   kubectl patch deployment <deployment-name> -n <namespace> --type='json' \\\n     -p='[{\"op\":\"replace\",\"path\":\"/spec/strategy/rollingUpdate/maxUnavailable\",\"value\":\"100%\"}]'\n   ```\n2. 使用 `kubectl(subcommand=\"apply\", v_args=\"-f -\", stdin_data=\"...\")` 创建跨可用区的 PV 和 PVC（**必须使用 `stdin_data` 参数传入 YAML，不要用 exec heredoc 或其他方式**）：\n   PV YAML:\n   ```yaml\n   apiVersion: v1\n   kind: PersistentVolume\n   metadata:\n     name: chaos-az-mismatch-pv\n   spec:\n     capacity:\n       storage: 20Gi\n     accessModes: [\"ReadWriteOnce\"]\n     csi:\n       driver: diskplugin.csi.alibabacloud.com\n       volumeHandle: <其他可用区的云盘ID>\n     nodeAffinity:\n       required:\n         nodeSelectorTerms:\n         - matchExpressions:\n           - key: topology.kubernetes.io/zone\n             operator: In\n             values: [\"<其他可用区>\"]\n   ```\n   PVC YAML:\n   ```yaml\n   apiVersion: v1\n   kind: PersistentVolumeClaim\n   metadata:\n     name: chaos-csi-mismatch-pvc\n     namespace: <namespace>\n   spec:\n     accessModes: [\"ReadWriteOnce\"]\n     resources:\n       requests:\n         storage: 20Gi\n     volumeName: chaos-az-mismatch-pv\n   ```\n3. 修改应用 A 的 Deployment，添加引用该 PVC 的 volume，并确保 Pod 调度到不同可用区的节点\n4. 等待 Pod 滚动更新完成，确认所有旧 Pod 已被替换\n5. 滚动更新完成后，立即还原 maxUnavailable 为原始值（maxUnavailable 只是使滚动更新完成的手段，不是故障本身，不应泄漏到恢复阶段）\n6. 观察 Pod 的 ContainerCreating 状态\n\n**注入验证**：\n1. 执行 `kubectl rollout status deployment <deployment-name>`，确认滚动更新已完成（所有旧 Pod 已被替换）。如果滚动更新未完成（卡死），则故障未完全生效，不可判定为 verified\n2. 执行 `kubectl get pods`，确认**所有**目标 Pod 状态为 ContainerCreating（不是仅一个新 Pod，而是全部副本）\n3. 执行 `kubectl describe pod <pod-name>`，确认 Events 显示 FailedMount 或 CSI attach 超时\n4. 确认错误信息包含可用区不匹配或 CSI 异常相关描述\n\n**注入恢复**：\n1. 恢复应用 A 的 Deployment，移除注入时添加的 volumes 和 volumeMounts（两者都需移除，只移除其中一个会导致 Deployment 配置错误）\n2. 等待 Pod 滚动更新完成，确认 Pod 恢复 Running\n3. 清理测试 PVC：`kubectl delete pvc chaos-csi-mismatch-pvc -n <namespace>`\n4. 清理测试 PV：`kubectl delete pv chaos-az-mismatch-pv`\n\n**恢复验证**：\n1. 执行 `kubectl get pods`，确认 Pod 状态恢复为 Running\n2. 确认测试资源已清理\n3. 确认应用 A 存储功能正常\n\n**基准事实**：\n- **根因**：CSI 驱动异常或云盘与节点可用区不匹配，导致 Volume attach/mount 操作超时，Pod 无法完成存储卷挂载\n- **必现现象**：Pod ContainerCreating；Events 显示 FailedMount/FailedAttachVolume/CSI 超时；可用区不匹配\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_ContainerCreating/Pod_ContainerCreating_云盘挂载超时或冲突.md":"**用例名称** 云盘挂载超时或冲突 导致 Pod_ContainerCreating\n\n**故障现象**：\n1. Pod 长时间停留在 ContainerCreating 状态\n2. Pod Events 中显示 `Multi-Attach error` 或 `AttachVolume.Attach failed`\n3. 云盘被其他节点占用，无法 attach 到当前节点\n\n**资源准备**：\n1. 确认应用 A 已正常运行，且使用了云盘类型的 PVC（accessMode 为 ReadWriteOnce）\n2. 确认集群中有多个节点\n\n**演练步骤**：\n1. 定位应用 A 使用的 PVC 及其对应的 PV\n2. 在另一个节点上创建一个临时 Pod，强制挂载同一个 PVC（通过直接指定 PV 的 volumeHandle 创建新 PV/PVC 对），模拟 Multi-Attach 冲突：\n   ```yaml\n   apiVersion: v1\n   kind: Pod\n   metadata:\n     name: chaos-volume-holder\n     namespace: <namespace>\n   spec:\n     nodeName: <另一节点>\n     containers:\n     - name: holder\n       image: busybox\n       command: [\"sleep\", \"3600\"]\n       volumeMounts:\n       - name: data\n         mountPath: /data\n     volumes:\n     - name: data\n       persistentVolumeClaim:\n         claimName: <应用A的PVC名称>\n   ```\n3. 删除应用 A 原来的 Pod，触发在其他节点重建\n4. 观察新 Pod 的 ContainerCreating 状态\n\n**注入验证**：\n1. 执行 `kubectl get pods`，确认应用 A 的新 Pod 状态为 ContainerCreating\n2. 执行 `kubectl describe pod <pod-name>`，确认 Events 显示 Multi-Attach error 或 volume attach 失败\n3. 确认 PV 仍 attach 在占用它的节点上\n\n**注入恢复**：\n1. 删除临时 Pod：`kubectl delete pod chaos-volume-holder --force --grace-period=0`\n2. 等待云盘从原节点 detach\n3. 等待应用 A 的 Pod 自动完成 volume attach\n\n**恢复验证**：\n1. 执行 `kubectl get pods`，确认应用 A 的 Pod 状态恢复为 Running\n2. 确认 volume 成功 attach 并 mount\n3. 确认应用 A 数据读写正常\n\n**基准事实**：\n- **根因**：云盘（ReadWriteOnce）被其他节点/Pod 占用，新 Pod 无法 attach 该云盘，导致 volume mount 阶段阻塞\n- **必现现象**：Pod ContainerCreating；Events 显示 Multi-Attach error 或 AttachVolume 失败；PV 被其他节点占用\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_ContainerCreating/Pod_ContainerCreating_容器运行时异常.md":"**用例名称** 容器运行时异常 导致 Pod_ContainerCreating\n\n**故障现象**：\n1. Pod 长时间停留在 ContainerCreating 状态\n2. Pod Events 中显示 `container runtime is not ready` 或 `rpc error` 相关错误\n3. 节点上的 containerd/docker 进程异常或 hang，无法响应容器创建请求\n\n**资源准备**：\n1. 确认应用 A 已正常运行\n2. 确认目标节点上有多个应用副本（避免单点影响）\n3. 确认监控系统可观测节点和容器运行时状态\n\n**演练步骤**：\n1. 定位应用 A 所在的目标节点\n2. 使用 chaosblade 挂起（stop）目标节点上的 containerd 进程，模拟容器运行时 hang：\n   ```bash\n   blade create k8s node-process stop \\\n     --names <节点名> \\\n     --process containerd \\\n     --timeout 120 \\\n     --kubeconfig <路径>\n   ```\n3. 删除应用 A 在目标节点上的 Pod，触发重建\n4. 观察新 Pod 的 ContainerCreating 状态\n\n**注入验证**：\n1. 执行 `kubectl get pods`，确认新 Pod 状态为 ContainerCreating\n2. 执行 `kubectl describe pod <pod-name>`，确认 Events 显示容器运行时相关错误\n3. 确认目标节点状态可能变为 NotReady（RuntimeNotReady condition）\n\n**注入恢复**：\n1. 等待 chaosblade 实验自动超时恢复（120 秒内），containerd 进程自动恢复\n2. 如超时后仍未恢复，通过 `blade destroy <UID>` 强制恢复\n3. 等待容器运行时恢复正常，Pod 自动完成创建\n\n**恢复验证**：\n1. 确认 containerd 进程恢复正常运行\n2. 执行 `kubectl get nodes`，确认目标节点恢复 Ready\n3. 执行 `kubectl get pods`，确认 Pod 状态恢复为 Running\n\n**基准事实**：\n- **根因**：容器运行时（containerd/docker）进程异常、hang 或状态不一致，无法响应 kubelet 的容器创建请求\n- **必现现象**：Pod ContainerCreating；Events 显示 runtime 相关 rpc error；节点可能 NotReady（RuntimeNotReady）\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_CrashLoopBackOff/Pod_CrashLoopBackOff_LivenessProbe配置不合理.md":"**用例名称** LivenessProbe配置不合理 导致 Pod_CrashLoopBackOff\n\n**故障现象**：\n1. Pod 反复重启，状态为 CrashLoopBackOff\n2. Pod Events 中显示 `Liveness probe failed` 后容器被杀\n3. 容器本身运行正常，但 Liveness Probe 配置参数不合理导致误判\n\n**RCA症状**：\n1. Pod 反复重启，状态为 CrashLoopBackOff\n2. Pod Events 中显示 `Liveness probe failed`，容器被反复杀死\n3. 容器日志无应用异常退出记录\n（以上为kubectl直接可观测的现象，不包含诊断结论）\n\n**资源准备**：\n1. 确认应用 A 已正常运行\n2. 确认应用 A 有健康检查接口\n\n**演练步骤**：\n1. 记录应用 A 当前的 livenessProbe 配置\n2. 记录 Deployment 当前 maxUnavailable 值，并临时设为 100%（确保滚动更新能完成，故障注入的新 Pod 不会 Ready，默认策略下 K8s 不会终止旧 Pod，导致滚动更新死锁）：\n   ```bash\n   kubectl get deployment <deployment-name> -n <namespace> \\\n     -o jsonpath='{.spec.strategy.rollingUpdate.maxUnavailable}'\n   kubectl patch deployment <deployment-name> -n <namespace> --type='json' \\\n     -p='[{\"op\":\"replace\",\"path\":\"/spec/strategy/rollingUpdate/maxUnavailable\",\"value\":\"100%\"}]'\n   ```\n3. 修改应用 A 的 Deployment，设置不合理的 livenessProbe 参数：\n   ```yaml\n   livenessProbe:\n     httpGet:\n       path: /healthz\n       port: 8080\n     initialDelaySeconds: 1\n     timeoutSeconds: 1\n     periodSeconds: 2\n     failureThreshold: 1\n   ```\n   （initialDelaySeconds 过短，应用未完成初始化；timeoutSeconds 过短，正常响应来不及返回；failureThreshold 为 1，无容错空间）\n4. 等待 Pod 滚动更新完成，确认所有旧 Pod 已被替换\n5. 滚动更新完成后，立即还原 maxUnavailable 为原始值（maxUnavailable 只是使滚动更新完成的手段，不是故障本身，不应泄漏到恢复阶段）\n6. 观察 Pod 重启行为\n\n**注入验证**：\n1. 执行 `kubectl rollout status deployment <deployment-name>`，确认滚动更新已完成（所有旧 Pod 已被替换）。如果滚动更新未完成（卡死），则故障未完全生效，不可判定为 verified\n2. 执行 `kubectl get pods`，确认**所有**目标 Pod 的 RESTARTS 数持续增长，状态为 CrashLoopBackOff（不是仅一个新 Pod，而是全部副本）\n3. 执行 `kubectl describe pod <pod-name>`，确认 Events 显示 `Liveness probe failed` 和 `Container will be killed`\n4. 查看容器日志，确认应用本身无异常退出（非应用 bug）\n\n**注入恢复**：\n1. 恢复应用 A 的 Deployment，将 livenessProbe 参数恢复为原始合理值（若原本无 livenessProbe，则移除）\n3. 等待 Pod 滚动更新完成\n\n**恢复验证**：\n1. 执行 `kubectl get pods`，确认 Pod 状态为 Running 且不再重启\n2. 确认 Liveness Probe 检查正常通过\n3. 确认应用 A 服务正常\n\n**基准事实**：\n- **根因**：Liveness Probe 的 initialDelaySeconds/timeoutSeconds/failureThreshold 配置不合理，导致健康检查在应用正常运行时误判为失败，kubelet 反复杀死并重启容器\n- **必现现象**：Pod CrashLoopBackOff；RESTARTS 持续增长；Events 显示 Liveness probe failed；容器日志无异常\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_CrashLoopBackOff/Pod_CrashLoopBackOff_StartupProbe配置不足.md":"**用例名称** StartupProbe配置不足 导致 Pod_CrashLoopBackOff\n\n**故障现象**：\n1. Pod 反复重启，状态为 CrashLoopBackOff\n2. Pod Events 中显示 `Startup probe failed` 后容器被杀\n3. 慢启动应用尚未完成初始化就被 StartupProbe 判定为失败\n\n**资源准备**：\n1. 确认应用 A 已正常运行（应用启动时间较长，如 Java 应用）\n2. 确认应用 A 启动过程中健康检查接口不可用\n\n**演练步骤**：\n1. 记录应用 A 当前的探针配置\n2. 记录 Deployment 当前 maxUnavailable 值，并临时设为 100%（确保滚动更新能完成，故障注入的新 Pod 不会 Ready，默认策略下 K8s 不会终止旧 Pod，导致滚动更新死锁）：\n   ```bash\n   kubectl get deployment <deployment-name> -n <namespace> \\\n     -o jsonpath='{.spec.strategy.rollingUpdate.maxUnavailable}'\n   kubectl patch deployment <deployment-name> -n <namespace> --type='json' \\\n     -p='[{\"op\":\"replace\",\"path\":\"/spec/strategy/rollingUpdate/maxUnavailable\",\"value\":\"100%\"}]'\n   ```\n3. 修改应用 A 的 Deployment，添加或修改 startupProbe 使其窗口不足以覆盖应用启动时间：\n   ```yaml\n   startupProbe:\n     httpGet:\n       path: /healthz\n       port: 8080\n     failureThreshold: 3\n     periodSeconds: 5\n   ```\n   （总等待时间 = failureThreshold × periodSeconds = 15 秒，远小于应用实际启动时间）\n4. 同时确保 livenessProbe 存在，使得 startupProbe 失败后触发容器重启\n5. 等待 Pod 滚动更新完成，确认所有旧 Pod 已被替换\n6. 滚动更新完成后，立即还原 maxUnavailable 为原始值（maxUnavailable 只是使滚动更新完成的手段，不是故障本身，不应泄漏到恢复阶段）\n7. 观察 Pod 启动行为\n\n**注入验证**：\n1. 执行 `kubectl rollout status deployment <deployment-name>`，确认滚动更新已完成（所有旧 Pod 已被替换）。如果滚动更新未完成（卡死），则故障未完全生效，不可判定为 verified\n2. 执行 `kubectl get pods`，确认**所有**目标 Pod 的 RESTARTS 持续增长，状态为 CrashLoopBackOff（不是仅一个新 Pod，而是全部副本）\n3. 执行 `kubectl describe pod <pod-name>`，确认 Events 显示 `Startup probe failed`\n4. 查看容器日志，确认应用正在启动但未完成初始化就被杀\n\n**注入恢复**：\n1. 恢复应用 A 的 Deployment，增大 startupProbe 的窗口时间（若原本无 startupProbe，则移除）\n2. 等待 Pod 滚动更新完成\n\n**恢复验证**：\n1. 执行 `kubectl get pods`，确认 Pod 状态为 Running 且不再重启\n2. 确认 StartupProbe 和 LivenessProbe 检查均正常通过\n3. 确认应用 A 完成初始化并正常服务\n\n**基准事实**：\n- **根因**：StartupProbe 未配置或 failureThreshold × periodSeconds 总窗口不足以覆盖应用启动时间，慢启动应用在初始化完成前被判定为启动失败，反复被杀重启\n- **必现现象**：Pod CrashLoopBackOff；Events 显示 Startup probe failed；容器日志显示应用启动中被中断\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_OOM内存异常/Pod_OOM内存异常_limit单位写错.md":"**用例名称** limit单位写错 导致 Pod_OOM内存异常\n\n**故障现象**：\n1. Pod 启动后立即异常退出，状态为 CrashLoopBackOff\n2. Pod 的 lastState 显示 reason: OOMKilled 或 StartError（cgroup v2 环境下容器可能因内存配置过小无法启动）\n3. 容器 memory limit 值极小（如 100m = 0.1 字节），应用启动即超限或无法启动\n\n**资源准备**：\n1. 确认应用 A 已正常运行\n2. 确认应用 A 的正常内存使用量（如 200Mi 以上）\n\n**演练步骤**：\n1. 记录应用 A 当前的 resources.limits.memory 配置\n2. 记录 Deployment 当前 maxUnavailable 值，并临时设为 100%（确保滚动更新能完成，故障注入的新 Pod 不会 Ready，默认策略下 K8s 不会终止旧 Pod，导致滚动更新死锁）：\n   ```bash\n   kubectl get deployment <deployment-name> -n <namespace> \\\n     -o jsonpath='{.spec.strategy.rollingUpdate.maxUnavailable}'\n   kubectl patch deployment <deployment-name> -n <namespace> --type='json' \\\n     -p='[{\"op\":\"replace\",\"path\":\"/spec/strategy/rollingUpdate/maxUnavailable\",\"value\":\"100%\"}]'\n   ```\n3. 修改应用 A 的 Deployment，将 memory limit 单位写错：\n   ```yaml\n   resources:\n     limits:\n       memory: \"100m\"    # 错误！100m = 0.1 字节（milli），应为 100Mi\n     requests:\n       memory: \"100m\"\n   ```\n   注意：在 Kubernetes 中，`m` 表示 milli（千分之一），`100m` = 0.1 字节；正确应为 `Mi`（Mebibyte）\n4. 等待 Pod 滚动更新完成，确认所有旧 Pod 已被替换\n5. 滚动更新完成后，立即还原 maxUnavailable 为原始值（maxUnavailable 只是使滚动更新完成的手段，不是故障本身，不应泄漏到恢复阶段）\n6. 观察 Pod 启动行为\n\n**注入验证**：\n1. 执行 `kubectl rollout status deployment <deployment-name>`，确认滚动更新已完成（所有旧 Pod 已被替换）。如果滚动更新未完成（卡死），则故障未完全生效，不可判定为 verified\n2. 执行 `kubectl get pods`，确认**所有**目标 Pod 状态为 CrashLoopBackOff，RESTARTS 持续增长（不是仅一个新 Pod，而是全部副本）\n3. 执行 `kubectl get pod <pod-name> -o jsonpath='{.status.containerStatuses[0].lastState}'`，确认 reason 为 OOMKilled 或 StartError（cgroup v2 环境下极小 limit 可能导致容器无法启动而非 OOMKill）\n4. 执行 `kubectl describe pod <pod-name>`，确认 limits.memory 为极小值\n5. 确认容器启动后立即异常退出（运行时间极短或无法启动）\n\n**注入恢复**：\n1. 恢复应用 A 的 Deployment，将 memory limit 修正为正确单位（如 `256Mi`）\n3. 等待 Pod 滚动更新完成\n\n**恢复验证**：\n1. 执行 `kubectl get pods`，确认 Pod 状态为 Running 且不再重启\n2. 确认容器正常运行，内存使用率在合理范围\n3. 确认应用 A 服务正常\n\n**基准事实**：\n- **根因**：memory limit 单位写错（如 `100m` 而非 `100Mi`），导致 limit 值极小，容器启动后内存使用立即超过 limit 被 OOMKill，或在 cgroup v2 环境下因内存配置过小无法启动\n- **必现现象**：Pod 异常退出（OOMKilled 或 StartError）；CrashLoopBackOff；limits.memory 值不合理（如 100m）；容器运行时间极短或无法启动\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_OOM内存异常/Pod_OOM内存异常_内存压力过大.md":"**用例名称** 内存压力过大 导致 Pod_OOM内存异常\n\n**故障现象**：\n1. Pod 内存使用率接近 Limit 上限\n2. 应用响应变慢，出现延迟\n3. 存在被 OOMKill 的风险\n\n**资源准备**：\n1. 确认应用 A 已正常运行\n2. 确认应用 A 的 Pod 已配置 resources.limits.memory\n\n**演练步骤**：\n1. 定位应用 A 的 Pod\n2. 使用 chaosblade 对应用 A 的 Pod 注入内存压力，模拟内存占用增长接近 Limit 的场景\n3. 观察 Pod 内存使用率变化\n\n**注入验证**：\n1. 查看监控指标，确认 Pod 内存使用率接近 Limit 上限\n2. 查看 Pod Event，确认存在内存相关告警\n3. 确认应用 A 的响应延迟增大\n\n**注入恢复**：\n1. 销毁 chaosblade 内存压力注入实验\n\n**恢复验证**：\n1. 查看监控指标，确认 Pod 内存使用率恢复正常\n2. 确认应用性能恢复正常\n\n**基准事实**：\n- **根因**：应用内存使用增长或注入内存压力，导致 Pod 内存使用率接近 Limit，存在被 OOMKill 的风险\n- **必现现象**：Pod 内存使用率接近 Limit；应用响应变慢；存在 OOMKill 风险\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_Pending/Pod_Pending_PVC未绑定.md":"**用例名称** PVC未绑定 导致 Pod_Pending\n\n**故障现象**：\n1. Pod 状态为 Pending，无法启动\n2. Pod Events 中显示 `pod has unbound immediate PersistentVolumeClaims`\n3. PVC 状态为 Pending，无法绑定到 PV\n\n**资源准备**：\n1. 确认应用 A 已正常运行\n2. 确认集群中 StorageClass 和 CSI 插件正常工作\n\n**演练步骤**（注意：本用例需要临时修改 Deployment 添加 volume 引用，这是故障注入的必要操作，不违反安全红线。目标应用无需预先配置 PVC——注入的目的就是添加一个无法绑定的 PVC 依赖。恢复步骤会还原所有修改）：\n1. 记录 Deployment 当前 maxUnavailable 值，并临时设为 100%（确保滚动更新能完成，故障注入的新 Pod 不会 Ready，默认策略下 K8s 不会终止旧 Pod，导致滚动更新死锁）：\n   ```bash\n   kubectl get deployment <deployment-name> -n <namespace> \\\n     -o jsonpath='{.spec.strategy.rollingUpdate.maxUnavailable}'\n   kubectl patch deployment <deployment-name> -n <namespace> --type='json' \\\n     -p='[{\"op\":\"replace\",\"path\":\"/spec/strategy/rollingUpdate/maxUnavailable\",\"value\":\"100%\"}]'\n   ```\n2. 使用 `kubectl apply -f` 创建一个引用不存在的 StorageClass 的 PVC（通过 `stdin_data` 传入 YAML）：\n   ```yaml\n   apiVersion: v1\n   kind: PersistentVolumeClaim\n   metadata:\n     name: chaos-test-pvc\n     namespace: <namespace>\n   spec:\n     accessModes: [\"ReadWriteOnce\"]\n     storageClassName: \"non-existent-sc\"\n     resources:\n       requests:\n         storage: 10Gi\n   ```\n3. 使用 `kubectl patch` 修改应用 A 的 Deployment，添加引用该 PVC 的 volume 和 volumeMount\n4. 等待 Pod 滚动更新完成，确认所有旧 Pod 已被替换\n5. 滚动更新完成后，立即还原 maxUnavailable 为原始值（maxUnavailable 只是使滚动更新完成的手段，不是故障本身，不应泄漏到恢复阶段）\n6. 观察新 Pod 的状态\n\n**注入验证**：\n1. 执行 `kubectl rollout status deployment <deployment-name>`，确认滚动更新已完成（所有旧 Pod 已被替换）。如果滚动更新未完成（卡死），则故障未完全生效，不可判定为 verified\n2. 执行 `kubectl get pvc`，确认 PVC 状态为 Pending\n3. 执行 `kubectl get pods`，确认**所有**目标 Pod 状态为 Pending（不是仅一个新 Pod，而是全部副本）\n4. 执行 `kubectl describe pod <pod-name>`，确认 Events 显示 unbound PVC 相关信息\n5. 执行 `kubectl describe pvc chaos-test-pvc`，确认 StorageClass 不存在或 Provisioner 异常\n\n**注入恢复**：\n1. 恢复应用 A 的 Deployment 定义，移除引用 chaos-test-pvc 的 volume\n2. 删除测试用 PVC：`kubectl delete pvc chaos-test-pvc`\n3. 等待 Pod 滚动更新完成\n\n**恢复验证**：\n1. 执行 `kubectl get pods`，确认 Pod 状态恢复为 Running\n2. 确认测试 PVC 已被清理\n\n**基准事实**：\n- **根因**：Pod 引用的 PVC 无法绑定，原因为 StorageClass 不存在或 Provisioner 异常，导致 Pod 无法挂载所需存储卷而 Pending\n- **必现现象**：Pod Pending；PVC Pending；Events 显示 unbound PersistentVolumeClaims\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_Pending/Pod_Pending_拓扑约束过严.md":"**用例名称** 拓扑约束过严 导致 Pod_Pending\n\n**故障现象**：\n1. Pod 状态为 Pending，无法被调度\n2. Pod Events 中显示 `didn't match pod topology spread constraints` 或 `didn't match pod anti-affinity rules`\n3. 由于拓扑分布约束或反亲和规则过严，调度器无法找到满足条件的节点\n\n**资源准备**：\n1. 确认应用 A 已正常运行\n2. 确认集群节点数量有限（便于触发约束冲突）\n\n**演练步骤**：\n1. 记录 Deployment 当前 maxUnavailable 值，并临时设为 100%（确保滚动更新能完成，故障注入的新 Pod 不会 Ready，默认策略下 K8s 不会终止旧 Pod，导致滚动更新死锁）：\n   ```bash\n   kubectl get deployment <deployment-name> -n <namespace> \\\n     -o jsonpath='{.spec.strategy.rollingUpdate.maxUnavailable}'\n   kubectl patch deployment <deployment-name> -n <namespace> --type='json' \\\n     -p='[{\"op\":\"replace\",\"path\":\"/spec/strategy/rollingUpdate/maxUnavailable\",\"value\":\"100%\"}]'\n   ```\n2. 修改应用 A 的 Deployment，添加过严的拓扑约束：\n   ```yaml\n   topologySpreadConstraints:\n   - maxSkew: 1\n     topologyKey: kubernetes.io/hostname\n     whenUnsatisfiable: DoNotSchedule\n     labelSelector:\n       matchLabels:\n         app: <app-name>\n   ```\n   或添加过严的反亲和规则：\n   ```yaml\n   affinity:\n     podAntiAffinity:\n       requiredDuringSchedulingIgnoredDuringExecution:\n       - labelSelector:\n           matchLabels:\n             app: <app-name>\n         topologyKey: kubernetes.io/hostname\n   ```\n3. 等待 Pod 滚动更新完成，确认所有旧 Pod 已被替换\n4. 滚动更新完成后，立即还原 maxUnavailable 为原始值（maxUnavailable 只是使滚动更新完成的手段，不是故障本身，不应泄漏到恢复阶段）\n5. 将应用 A 的副本数扩大到超过集群节点数\n6. 观察无法调度的 Pod 状态\n\n**注入验证**：\n1. 执行 `kubectl rollout status deployment <deployment-name>`，确认滚动更新已完成（所有旧 Pod 已被替换）。如果滚动更新未完成（卡死），则故障未完全生效，不可判定为 verified\n2. 执行 `kubectl get pods`，确认部分或全部 Pod 状态为 Pending\n3. 执行 `kubectl describe pod <pending-pod>`，确认 Events 显示拓扑约束或反亲和相关的调度失败原因\n\n**注入恢复**：\n1. 恢复应用 A 的 Deployment 定义，移除或放宽拓扑约束/反亲和规则\n2. 将副本数恢复为原始值\n3. 等待 Pod 滚动更新完成\n\n**恢复验证**：\n1. 执行 `kubectl get pods`，确认所有 Pod 状态为 Running\n2. 确认副本数恢复正常\n\n**基准事实**：\n- **根因**：topologySpreadConstraints 或 podAntiAffinity 配置过严，当副本数超过可用拓扑域时，调度器无法满足约束条件\n- **必现现象**：部分 Pod Pending；Events 显示拓扑约束或反亲和规则不满足；已调度 Pod 严格按约束分布\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_Pending/Pod_Pending_节点Taint无对应Toleration.md":"**用例名称** 节点Taint无对应Toleration 导致 Pod_Pending\n\n**故障现象**：\n1. Pod 状态为 Pending，无法被调度到任何节点\n2. Pod Events 中显示 `N node(s) had untolerated taint {chaos-test: true}`\n3. 目标 Pod 可调度的所有节点均带有 Pod 无法容忍的污点\n\n**RCA症状**：\n1. Pod 状态为 Pending，无法被调度到任何节点\n2. Pod Events 中显示 `had untolerated taint`\n（以上为kubectl直接可观测的现象，不包含诊断结论）\n\n**资源准备**：\n1. 确认应用 A 已正常运行\n2. 确认集群中有多个可调度节点\n3. 记录应用 A 的 Pod 当前运行在哪些节点上（这些节点即为\"目标节点\"）\n\n**演练步骤**：\n\n> **爆炸半径控制**：本用例仅 taint 目标 Pod 所在的节点（而非全部集群节点），\n> 通过 nodeSelector 约束目标 Pod 只能调度到这些节点，从而在保证故障复现的同时\n> 避免影响集群中其他工作负载的调度。\n\n1. 记录目标节点的当前 taint 信息，以及 Deployment 的当前 nodeSelector（用于恢复）\n2. 记录 Deployment 当前 maxUnavailable 值，并临时设为 100%（确保滚动更新能完成，故障注入的新 Pod 不会 Ready，默认策略下 K8s 不会终止旧 Pod，导致滚动更新死锁）：\n   ```bash\n   kubectl get deployment <deployment-name> -n <namespace> \\\n     -o jsonpath='{.spec.strategy.rollingUpdate.maxUnavailable}'\n   kubectl patch deployment <deployment-name> -n <namespace> --type='json' \\\n     -p='[{\"op\":\"replace\",\"path\":\"/spec/strategy/rollingUpdate/maxUnavailable\",\"value\":\"100%\"}]'\n   ```\n3. 给目标节点添加标签：`kubectl label node <node> chaos-target=<app-name>`（仅目标 Pod 所在节点）\n4. 给应用 A 的 Deployment 添加 nodeSelector，约束 Pod 只能调度到目标节点：\n   `kubectl patch deployment <name> -n <ns> -p '{\"spec\":{\"template\":{\"spec\":{\"nodeSelector\":{\"chaos-target\":\"<app-name>\"}}}}}'`\n5. 等待 rollout 完成（Pod 仍在原节点上运行，因为只有目标节点有此标签）\n6. 滚动更新完成后，立即还原 maxUnavailable 为原始值（maxUnavailable 只是使滚动更新完成的手段，不是故障本身，不应泄漏到恢复阶段）\n7. 给目标节点添加污点：`kubectl taint node <node> chaos-test=true:NoSchedule`（仅目标节点）\n8. 删除应用 A 的一个 Pod，触发重建调度\n9. 观察新 Pod 的调度状态\n\n**注入验证**：\n1. 执行 `kubectl get pods`，确认新 Pod 状态为 Pending\n2. 执行 `kubectl describe pod <pod-name>`，确认 Events 中显示 `had untolerated taint {chaos-test: true}`\n3. 确认目标节点均有 chaos-test taint\n\n**注入恢复**：\n1. 移除目标节点上添加的污点：`kubectl taint node <node> chaos-test=true:NoSchedule-`\n2. 移除 Deployment 的 nodeSelector 中添加的 chaos-target 键（若原 Deployment 无 nodeSelector，则移除整个 nodeSelector）\n3. 移除目标节点上添加的标签：`kubectl label node <node> chaos-target-`\n4. 等待 Pod 滚动更新完成\n\n**恢复验证**：\n1. 执行 `kubectl get pods`，确认 Pod 状态变为 Running\n2. 确认目标节点 taint 已恢复到演练前状态\n3. 确认 Deployment spec 已恢复到演练前状态\n\n**基准事实**：\n- **根因**：目标 Pod 可调度的所有节点被标记了 Taint，而 Pod 未配置对应的 Toleration，导致调度器无法找到合适节点\n- **必现现象**：Pod Pending；Events 显示 untolerated taint；目标节点带有不可容忍的污点\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_Terminating/Pod_Terminating_Finalizers未清理.md":"**用例名称** Finalizers未清理 导致 Pod_Terminating\n\n**故障现象**：\n1. Pod 无法完成删除，`metadata.deletionTimestamp` 已设置但 Pod 对象仍存在于 API 中\n2. Pod 的 metadata 中存在 finalizers 字段，等待外部控制器清理\n3. kubectl 显示状态可能是 `Terminating`（容器仍在运行时）或 `Error`/`Failed`（容器已退出时）\n\n> **注意**：\"Terminating\" 是 kubectl 的显示状态，仅当 `deletionTimestamp` 已设置\n> 且容器仍在运行时才显示。如果容器在 delete 信号后已退出，kubectl 会按容器状态\n> 显示（如 Error/Completed），但 Pod 对象仍因 finalizer 滞留在 API 中。\n> 判定依据是 `deletionTimestamp` + `finalizers` 同时存在，而非 kubectl 显示状态。\n\n**RCA症状**：\n1. `kubectl get pod` 显示 Pod 状态为 Terminating 或 Error/Failed，但 Pod 对象持续存在\n2. `kubectl get pod -o jsonpath='{.metadata.deletionTimestamp}'` 返回非空时间戳\n3. `kubectl get pod -o jsonpath='{.metadata.finalizers}'` 返回非空列表\n（以上为kubectl直接可观测的现象，不包含诊断结论）\n\n**资源准备**：\n1. 确认目标应用已正常运行\n2. 确认目标 Pod 当前没有 finalizers（`kubectl get pod <name> -o jsonpath='{.metadata.finalizers}'` 返回空）\n\n**演练步骤**：\n1. 定位目标 Pod\n2. 使用 kubectl patch 给 Pod 添加自定义 finalizer：\n   `kubectl patch pod <pod-name> -n <namespace> -p '{\"metadata\":{\"finalizers\":[\"example.com/block-deletion\"]}}'`\n3. 使用 `--wait=false` 删除 Pod，触发终止流程：\n   `kubectl delete pod <pod-name> -n <namespace> --wait=false`\n   > 不加 `--wait=false` 会导致 kubectl 等待删除完成，因 finalizer 阻塞而超时。\n4. 观察 Pod 状态变化\n\n**注入验证**：\n1. 执行 `kubectl get pod <pod-name>`，确认 Pod 对象仍存在（显示 Terminating 或 Error）\n2. 执行 `kubectl get pod <pod-name> -o jsonpath='{.metadata.deletionTimestamp}'`，确认已设置\n3. 执行 `kubectl get pod <pod-name> -o jsonpath='{.metadata.finalizers}'`，确认包含注入的 finalizer\n4. 确认没有控制器在处理该 finalizer（`example.com/block-deletion` 是注入的假标识）\n\n**注入恢复**：\n1. 移除 Pod 上的 finalizer：\n   `kubectl patch pod <pod-name> -n <namespace> --type=json -p '[{\"op\":\"remove\",\"path\":\"/metadata/finalizers\"}]'`\n2. Pod 将被 Kubernetes GC 自动清除\n\n**恢复验证**：\n1. 执行 `kubectl get pod <pod-name>`，确认 Pod 已从集群中删除（返回 NotFound）\n2. 确认 ReplicaSet 已创建替代 Pod 且状态为 Running\n\n**基准事实**：\n- **根因**：Pod 的 metadata 中存在 finalizers，Kubernetes 在删除资源时会设置 deletionTimestamp 但不会从 etcd 中移除资源对象，直到所有 finalizer 被外部控制器清除\n- **必现现象**：Pod 对象持续存在于 API 中；deletionTimestamp 已设置；metadata.finalizers 非空\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_Terminating/Pod_Terminating_Volume卸载失败.md":"**用例名称** Volume卸载失败 导致 Pod_Terminating\n\n**故障现象**：\n1. Pod 状态长时间停留在 Terminating\n2. Pod Events 或 Node Events 中显示 `FailedMount`、`UnmountVolume failed`、`device is busy`\n3. Volume 无法从节点上正常 unmount/detach，阻塞 Pod 终止流程\n\n**资源准备**：\n1. 确认应用 A 已正常运行，且挂载了 PVC（云盘类型）\n2. 确认监控系统可观测 Pod 和 Volume 状态\n\n**演练步骤**：\n1. 定位应用 A 的 Pod 及其挂载的 Volume 路径\n2. 进入目标节点，在 Volume 的挂载目录下创建一个持续占用文件句柄的进程，模拟 device busy：\n   ```bash\n   # 在节点上执行（通过 nsenter 或 debug pod）\n   # 找到 volume 挂载路径\n   mount | grep <pv-name>\n   # 创建持续占用的进程\n   tail -f <挂载路径>/some-file &\n   ```\n   或使用 chaosblade 对节点注入 IO 负载，锁住磁盘操作：\n   ```bash\n   blade create k8s node-disk burn \\\n     --names <节点名> \\\n     --path <volume挂载路径> \\\n     --read --write \\\n     --timeout 180 \\\n     --kubeconfig <路径>\n   ```\n3. 删除应用 A 的 Pod，触发 Terminating 流程\n4. 观察 Pod Terminating 状态持续时间\n\n**注入验证**：\n1. 执行 `kubectl get pods`，确认 Pod 状态为 Terminating 且长时间未消失\n2. 查看 Node Events 或 `kubectl describe pod`，确认有 UnmountVolume 失败或 device busy 相关错误\n3. 在节点上确认 volume 挂载路径仍被占用\n\n**注入恢复**：\n1. 终止节点上占用 volume 的进程（kill tail 进程）\n2. 若使用 chaosblade：销毁 IO 实验 `blade destroy <UID>`\n3. 等待 kubelet 自动重试 unmount 操作\n\n**恢复验证**：\n1. 执行 `kubectl get pods`，确认 Terminating 的 Pod 已完成删除\n2. 确认 volume 已成功 unmount 和 detach\n3. 确认 PV 状态恢复为 Available 或被新 Pod 重新绑定\n\n**基准事实**：\n- **根因**：Volume unmount 时设备仍被占用（device busy）或 CSI 异常，导致 kubelet 无法完成卷卸载，Pod 终止流程被阻塞\n- **必现现象**：Pod Terminating 持续；Events 显示 UnmountVolume failed/device busy；Volume 挂载路径未释放\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_Terminating/Pod_Terminating_网卡卸载失败.md":"**用例名称** 网卡卸载失败 导致 Pod_Terminating\n\n**故障现象**：\n1. Pod 状态长时间停留在 Terminating\n2. 容器已停止，但 Pod sandbox 清理失败\n3. Events 或 kubelet 日志中显示 CNI DEL 调用失败或网络资源释放异常\n\n**资源准备**：\n1. 确认应用 A 已正常运行\n2. 确认集群使用 ENI/Terway 等需要显式清理网络资源的 CNI 插件\n3. 确认监控系统可观测 Pod 状态和 CNI 插件日志\n\n**演练步骤**：\n1. 定位应用 A 的 Pod 所在节点\n2. 使用 chaosblade 挂起节点上的 CNI 插件进程（如 terway-daemon），模拟 CNI 响应异常：\n   ```bash\n   blade create k8s node-process stop \\\n     --names <节点名> \\\n     --process terway \\\n     --timeout 120 \\\n     --kubeconfig <路径>\n   ```\n   或删除 CNI 插件 DaemonSet 中该节点的 Pod（先 cordon 节点防止重建）\n3. 删除应用 A 的 Pod，触发 Terminating 流程\n4. 观察 Pod Terminating 状态\n\n**注入验证**：\n1. 执行 `kubectl get pods`，确认 Pod 状态为 Terminating 且长时间未消失\n2. 查看 kubelet 日志（`journalctl -u kubelet`），确认有 CNI DEL 调用超时或失败的记录\n3. 确认 CNI 插件进程处于 stopped 状态或不可用\n\n**注入恢复**：\n1. 恢复 CNI 插件进程：等待 chaosblade 超时或执行 `blade destroy <UID>`\n2. 若删除了 CNI Pod：uncordon 节点，等待 CNI DaemonSet Pod 重建\n3. kubelet 将自动重试 sandbox 清理\n\n**恢复验证**：\n1. 确认 CNI 插件进程恢复正常\n2. 执行 `kubectl get pods`，确认 Terminating 的 Pod 已被完全清理\n3. 确认节点网络资源（ENI/IP）已释放\n4. 确认新 Pod 可以正常创建和分配网络\n\n**基准事实**：\n- **根因**：CNI 插件异常或不可用，导致 Pod 删除时网卡/ENI 资源无法正常释放，sandbox 清理失败，Pod 卡在 Terminating\n- **必现现象**：Pod Terminating 持续；kubelet 日志显示 CNI DEL 失败；网络资源未释放\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_Terminating/Pod_Terminating_节点宕机kubelet失联.md":"**用例名称** 节点宕机kubelet失联 导致 Pod_Terminating\n\n**故障现象**：\n1. Pod 状态长时间停留在 Terminating，无法完成删除\n2. 节点状态变为 NotReady，kubelet 停止上报\n3. API Server 已下发删除指令，但 kubelet 无法执行实际清理操作\n\n**资源准备**：\n1. 确认应用 A 已正常运行，至少有一个副本运行在目标节点上\n2. 确认监控系统可观测节点状态和 Pod 状态\n\n**演练步骤**：\n1. 定位运行应用 A 的目标节点\n2. 先通过 kubectl 删除应用 A 在目标节点上的 Pod（触发 Terminating）\n3. 立即使用 chaosblade 对目标节点注入网络完全丢包（node-network drop 即全量丢包，不需要 --percent），并设置 `--timeout 300`，模拟节点宕机导致 kubelet 失联\n4. 观察 Pod Terminating 状态持续时间\n\n**注入验证**：\n1. 执行 `kubectl get pods`，确认目标 Pod 状态为 Terminating 且长时间未消失\n2. 执行 `kubectl get nodes`，确认目标节点状态为 NotReady\n3. 查看 Pod 详情，确认 deletionTimestamp 已设置但 Pod 未被实际清理\n\n**注入恢复**：\n1. 等待 chaosblade 实验自动超时恢复（300 秒内）\n2. 如超时后仍未恢复，通过 `blade destroy <UID>` 或重启节点强制恢复\n3. kubelet 恢复后会自动清理 Terminating 状态的 Pod\n\n**恢复验证**：\n1. 执行 `kubectl get nodes`，确认目标节点恢复 Ready\n2. 执行 `kubectl get pods`，确认 Terminating 的 Pod 已被清理\n3. 确认应用 A 的新 Pod 在其他节点正常运行\n\n**基准事实**：\n- **根因**：节点宕机或 kubelet 失联，导致 API Server 下发的删除指令无法被执行，Pod 停留在 Terminating 状态\n- **必现现象**：Pod 状态为 Terminating 且长时间不消失；节点 NotReady；deletionTimestamp 已设置\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_cpu使用率过高/Pod_cpu使用率过高_应用性能问题.md":"**用例名称** 应用性能问题 导致 Pod_CPU使用率过高\n\n**故障现象**：\n1. Pod 的 CPU 使用率持续超过阈值\n2. CPU 使用率过高影响其他服务\n3. 应用响应变慢或发生超时\n\n**资源准备**：\n1. 确认应用 A/B 已正常运行\n2. 确认监控系统（如 Prometheus）已配置，可观测 Pod CPU 指标\n\n**演练步骤**：\n1. 定位应用 A 的 Pod 作为故障注入目标\n2. 使用 chaosblade 对目标 Pod 注入 CPU 压力（模拟死循环或高并发计算场景）\n3. 观察 Pod CPU 使用率变化\n\n**注入验证**：\n1. 查看 Pod CPU 使用率监控，确认持续高于阈值\n2. 进入容器查看 CPU 占用进程\n3. 通过 APM 工具分析 CPU 占用情况，定位问题代码\n4. 确认应用 A 对其他服务的调用出现延迟或超时\n\n**注入恢复**：\n1. 销毁 chaosblade CPU 压力实验\n2. 如 Pod 仍异常，可删除 Pod 触发重建\n\n**恢复验证**：\n1. 查看 Pod CPU 使用率监控，确认恢复到正常水平\n2. 确认应用 A 对其他服务的调用恢复正常\n\n**基准事实**：\n- **根因**：应用存在死循环、高并发计算或资源泄漏等性能问题，导致 CPU 使用率持续过高\n- **必现现象**：Pod CPU 使用率持续超过阈值，应用响应变慢或超时\n---\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_云盘空间打满/Pod_云盘空间打满_日志未清理.md":"**用例名称** 日志未清理 导致 Pod_云盘空间打满\n\n**故障现象**：\n1. Pod 挂载的云盘空间使用率达到 100%\n2. 应用写入操作失败，日志报 `No space left on device`\n3. 应用功能异常，数据无法持久化\n\n**资源准备**：\n1. 确认应用 A 已正常运行，且挂载了 PVC 用于数据存储\n2. 确认 PVC 对应的云盘容量已知\n3. 确认监控系统可观测 PVC 磁盘使用率\n\n**演练步骤**：\n1. 定位应用 A 的 Pod 及其 PVC 挂载路径\n2. 使用 chaosblade 对应用 A 的 Pod 注入磁盘填充，模拟日志堆积打满云盘：\n   ```bash\n   blade create k8s pod-disk fill \\\n     --namespace <namespace> \\\n     --labels \"app=<app>\" \\\n     --path <PVC挂载路径> \\\n     --percent 99 \\\n     --timeout 300 \\\n     --kubeconfig <路径>\n   ```\n3. 观察应用 A 的写入行为和错误日志\n\n**注入验证**：\n1. 进入 Pod 查看挂载路径磁盘使用率：`df -h <挂载路径>`，确认使用率接近 100%\n2. 在 Pod 内尝试写入文件，确认报 `No space left on device` 错误\n3. 查看应用 A 日志，确认有写入失败相关错误\n4. 确认应用 A 的业务功能受影响（如数据写入失败）\n\n**注入恢复**：\n1. 销毁 chaosblade 磁盘填充实验：`blade destroy <UID>`\n2. 确认填充的临时文件被清理\n3. 若空间未释放，手动清理注入的文件\n\n**恢复验证**：\n1. 进入 Pod 查看挂载路径磁盘使用率，确认恢复到正常水平\n2. 在 Pod 内尝试写入文件，确认成功\n3. 确认应用 A 的写入操作恢复正常\n4. 确认应用 A 业务功能恢复\n\n**基准事实**：\n- **根因**：云盘上的日志或数据文件持续增长且未配置清理策略，最终占满整个磁盘空间，导致新的写入操作失败\n- **必现现象**：磁盘使用率 100%；写入报 No space left on device；应用功能异常\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_磁盘空间使用率过高/Pod_磁盘空间使用率过高_应用日志数据积累.md":"**用例名称** 应用日志数据积累 导致 Pod_磁盘空间使用率过高\n\n**故障现象**：\n1. Pod 使用的存储空间接近上限，磁盘使用率告警\n2. 应用可能出现写入失败、响应变慢等问题\n3. 容器内日志目录（如 /var/log）文件过大\n\n**资源准备**：\n1. 确认应用 A/B 已正常运行\n2. 确认应用配置了日志输出（如输出到 /tmp 或挂载目录）\n\n**演练步骤**：\n1. 定位应用 A 的 Pod\n2. 使用 chaosblade 向应用 A 的 Pod 注入磁盘填充故障，模拟大量日志写入\n3. 持续向 Pod 写入大文件，填充磁盘空间至接近容量上限\n4. 观察 Pod 磁盘使用率变化及应用响应情况\n\n**注入验证**：\n1. 进入应用 A 的 Pod，使用 df -h 查看磁盘使用率，确认超过设定阈值\n2. 查看 Pod 状态，确认是否有磁盘相关异常事件\n3. 观察应用是否出现写入失败等异常表现\n\n**注入恢复**：\n1. 销毁 chaosblade 磁盘填充实验\n2. 删除 Pod 中产生的大文件，释放磁盘空间\n3. 或删除异常 Pod，触发重新调度创建新 Pod\n\n**恢复验证**：\n1. 查看 Pod 磁盘使用率，确认恢复到正常水平\n2. 查看应用是否恢复正常写入操作\n3. 确认 Pod 状态为 Running，无磁盘相关异常事件\n\n**基准事实**：\n- **根因**：应用日志未清理或数据写入过多，导致 Pod 存储空间被占满\n- **必现现象**：Pod 磁盘使用率超过设定阈值，应用出现写入失败\n\n---\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_网络丢包/Pod_网络丢包_服务依赖中断.md":"**用例名称** 服务依赖中断 导致 Pod_网络丢包\n\n**故障现象**：\n1. Pod 对外部服务或上下游依赖的网络请求超时或无响应\n2. 应用健康检查可能失败（如依赖外部探活）\n3. 服务间调用链路出现断裂，影响业务可用性\n\n**资源准备**：\n1. 确认目标应用已正常运行，且有对外网络调用（数据库、缓存、上下游服务等）\n2. 确认监控系统可观测网络请求成功率和延迟指标\n3. 确认目标 Pod 的标签选择器和命名空间\n\n**演练步骤**：\n1. 确认目标 Pod 的标签选择器和命名空间：\n   ```bash\n   kubectl get pods -n <namespace> -l <label-selector> -o wide\n   ```\n2. 使用 ChaosBlade 对目标 Pod 注入网络丢包故障：\n   ```bash\n   blade create k8s pod-network drop \\\n     --namespace <namespace> \\\n     --labels \"<label-key>=<label-value>\" \\\n     --source-port <port> \\\n     --kubeconfig <kubeconfig-path>\n   ```\n   - `--source-port`：限定丢包端口（如 3306 丢弃 MySQL 流量、53 丢弃 DNS 流量）\n   - 不指定端口时为全量丢包（慎用，影响所有流量包括监控和健康检查）\n3. 记录返回的 blade_uid，用于后续恢复\n\n**注入验证**：\n1. 在目标 Pod 内验证网络连通性丧失：\n   ```bash\n   kubectl exec <pod-name> -n <namespace> -- wget -qO- --timeout=5 <依赖服务地址>\n   ```\n   确认请求超时或无响应\n2. 查看应用日志确认出现连接超时错误：\n   ```bash\n   kubectl logs <pod-name> -n <namespace> --tail=20\n   ```\n3. 检查服务调用链路指标，确认目标端口流量中断\n\n**注入恢复**：\n1. 销毁 ChaosBlade 实验：\n   ```bash\n   blade destroy <blade_uid>\n   ```\n2. 如 Pod 因丢包导致健康检查失败被重启，等待新 Pod Ready\n\n**恢复验证**：\n1. 在目标 Pod 内重新验证网络连通性恢复：\n   ```bash\n   kubectl exec <pod-name> -n <namespace> -- wget -qO- --timeout=5 <依赖服务地址>\n   ```\n2. 确认应用日志不再出现连接超时错误\n3. 确认服务调用链路指标恢复正常\n\n**基准事实**：\n- **根因**：Pod 出方向网络流量被 iptables DROP 规则丢弃，导致对指定端口/地址的所有请求无响应\n- **必现现象**：目标端口的 TCP/UDP 请求超时；应用日志出现 connection timed out；依赖该连接的业务功能不可用\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_被驱逐重建/Pod_被驱逐重建_DiskPressure.md":"**用例名称** DiskPressure 导致 Pod_被驱逐重建\n\n**故障现象**：\n1. Pod 被 kubelet 驱逐（Evicted），状态为 Failed，reason 为 Evicted\n2. 节点 Conditions 中 DiskPressure 为 True\n3. 容器运行时目录（如 /var/lib/docker 或 /var/lib/containerd）磁盘使用超过 kubelet 驱逐阈值\n\n**资源准备**：\n1. 确认应用 A 已正常运行，有多个副本分布在不同节点\n2. 确认目标节点的容器运行时磁盘当前使用率距离驱逐阈值有一定空间\n3. 确认监控系统可观测节点磁盘使用率和 Pod 驱逐事件\n\n**演练步骤**：\n1. 查看目标节点 kubelet 配置的驱逐阈值（默认 `imagefs.available < 15%`）\n2. 使用 chaosblade 对目标节点的容器运行时目录注入磁盘填充，使其超过驱逐阈值：\n   ```bash\n   blade create k8s node-disk fill \\\n     --names <节点名> \\\n     --path /var/lib/containerd \\\n     --percent 90 \\\n     --timeout 300 \\\n     --kubeconfig <路径>\n   ```\n3. 等待 kubelet 检测到 DiskPressure 并触发 Pod 驱逐\n4. 观察应用 A 的 Pod 驱逐和重建行为\n\n**注入验证**：\n1. 执行 `kubectl describe node <节点名>`，确认 Conditions 中 DiskPressure 为 True\n2. 执行 `kubectl get pods --field-selector=status.phase=Failed`，确认有 Pod 被 Evicted\n3. 查看被驱逐 Pod 的详情，确认 reason 为 `The node was low on resource: ephemeral-storage`\n4. 确认应用 A 在其他节点重建 Pod\n\n**注入恢复**：\n1. 等待 chaosblade 实验自动超时恢复（300 秒内），或执行 `blade destroy <UID>`\n2. 等待节点磁盘空间释放\n3. 清理 Evicted Pod：`kubectl delete pods --field-selector=status.phase=Failed`\n\n**恢复验证**：\n1. 执行 `kubectl describe node <节点名>`，确认 DiskPressure 恢复为 False\n2. 确认应用 A 的 Pod 在正常节点上运行\n3. 确认节点磁盘使用率恢复到安全水位\n\n**基准事实**：\n- **根因**：容器运行时目录磁盘使用超过 kubelet 驱逐阈值（DiskPressure），kubelet 按优先级驱逐 Pod 以释放磁盘空间\n- **必现现象**：节点 DiskPressure=True；Pod 被 Evicted；reason 为 ephemeral-storage 不足\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_镜像拉取失败/Pod_镜像拉取失败_凭证缺失或过期.md":"**用例名称** 凭证缺失或过期 导致 Pod_镜像拉取失败\n\n**故障现象**：\n1. Pod 状态为 ImagePullBackOff 或 ErrImagePull\n2. Pod Events 中显示 `unauthorized` 或 `authentication required`\n3. 镜像仓库返回 401/403 认证错误\n\n**资源准备**：\n1. 确认应用 A 已正常运行，且使用私有镜像仓库\n2. 确认应用 A 的 Pod 配置了 imagePullSecrets\n\n**演练步骤**：\n1. 记录应用 A 当前的 imagePullSecrets 名称和 imagePullPolicy 值\n2. 记录 Deployment 当前 maxUnavailable 值，并临时设为 100%（确保滚动更新能完成，故障注入的新 Pod 不会 Ready，默认策略下 K8s 不会终止旧 Pod，导致滚动更新死锁）：\n   ```bash\n   kubectl get deployment <deployment-name> -n <namespace> \\\n     -o jsonpath='{.spec.strategy.rollingUpdate.maxUnavailable}'\n   kubectl patch deployment <deployment-name> -n <namespace> --type='json' \\\n     -p='[{\"op\":\"replace\",\"path\":\"/spec/strategy/rollingUpdate/maxUnavailable\",\"value\":\"100%\"}]'\n   ```\n3. 创建一个包含无效凭证的 Secret 来替换原有的有效凭证：\n   ```bash\n   kubectl create secret docker-registry chaos-invalid-secret \\\n     --docker-server=<registry-server> \\\n     --docker-username=invalid-user \\\n     --docker-password=invalid-password \\\n     --namespace <namespace>\n   ```\n4. 修改应用 A 的 Deployment，将 imagePullSecrets 指向无效 Secret（或直接移除 imagePullSecrets）。\n   同时检查 imagePullPolicy：如果当前为 `IfNotPresent`，需同时改为 `Always`，否则 K8s 直接使用本地缓存镜像启动 Pod，不会触发凭证校验，故障无法注入\n5. 等待 Pod 滚动更新完成，确认所有旧 Pod 已被替换\n6. 滚动更新完成后，立即还原 maxUnavailable 为原始值（maxUnavailable 只是使滚动更新完成的手段，不是故障本身，不应泄漏到恢复阶段）\n7. 观察 Pod 状态变化\n\n**注入验证**：\n1. 执行 `kubectl rollout status deployment <deployment-name>`，确认滚动更新已完成（所有旧 Pod 已被替换）。如果滚动更新未完成（卡死），则故障未完全生效，不可判定为 verified\n2. 执行 `kubectl get pods`，确认**所有**目标 Pod 状态为 ImagePullBackOff 或 ErrImagePull（不是仅一个新 Pod，而是全部副本）\n3. 执行 `kubectl describe pod <pod-name>`，确认 Events 中显示认证失败相关错误\n4. 确认错误信息包含 `unauthorized` 或 `authentication required`\n\n**注入恢复**：\n1. 恢复应用 A 的 Deployment，将 imagePullSecrets 指回原有的有效 Secret。如果注入时修改了 imagePullPolicy，需同时还原为原始值\n2. 删除测试用的无效 Secret：`kubectl delete secret chaos-invalid-secret`\n3. 等待 Pod 滚动更新完成\n\n**恢复验证**：\n1. 执行 `kubectl get pods`，确认 Pod 状态恢复为 Running\n2. 确认镜像拉取成功，无认证错误\n\n**基准事实**：\n- **根因**：imagePullSecrets 缺失或 Secret 中的凭证已过期/无效，导致向私有镜像仓库拉取镜像时认证失败\n- **必现现象**：Pod ImagePullBackOff；Events 显示 unauthorized/authentication required；镜像仓库返回 401/403\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_镜像拉取失败/Pod_镜像拉取失败_镜像不存在或标签错误.md":"**用例名称** 镜像不存在或标签错误 导致 Pod_镜像拉取失败\n\n**故障现象**：\n1. Pod 状态停留在 ImagePullBackOff 或 ErrImagePull\n2. Pod Event 显示镜像拉取失败，错误信息包含 `manifest for xxx not found`\n\n**资源准备**：\n1. 确认应用 A/B 所在节点正常运行\n2. 确认节点可正常访问镜像仓库\n\n**演练步骤**：\n1. 定位应用 A 的 Deployment\n2. 记录 Deployment 当前 maxUnavailable 值，并临时设为 100%（确保滚动更新能完成，故障注入的新 Pod 不会 Ready，默认策略下 K8s 不会终止旧 Pod，导致滚动更新死锁）：\n   ```bash\n   kubectl get deployment <deployment-name> -n <namespace> \\\n     -o jsonpath='{.spec.strategy.rollingUpdate.maxUnavailable}'\n   kubectl patch deployment <deployment-name> -n <namespace> --type='json' \\\n     -p='[{\"op\":\"replace\",\"path\":\"/spec/strategy/rollingUpdate/maxUnavailable\",\"value\":\"100%\"}]'\n   ```\n3. 修改应用 A 的镜像地址为不存在的镜像名称或标签\n4. 等待 Pod 滚动更新完成，确认所有旧 Pod 已被替换\n5. 滚动更新完成后，立即还原 maxUnavailable 为原始值（maxUnavailable 只是使滚动更新完成的手段，不是故障本身，不应泄漏到恢复阶段）\n6. 观察 Pod 的镜像拉取状态\n\n**注入验证**：\n1. 执行 `kubectl rollout status deployment <deployment-name>`，确认滚动更新已完成（所有旧 Pod 已被替换）。如果滚动更新未完成（卡死），则故障未完全生效，不可判定为 verified\n2. 执行 `kubectl get pods`，确认**所有**目标 Pod 状态停留在 ImagePullBackOff 或 ErrImagePull（不是仅一个新 Pod，而是全部副本）\n3. 执行 `kubectl describe pod <pod-name>`，确认 Events 包含镜像不存在相关信息，如 `manifest for xxx not found`\n\n**注入恢复**：\n1. 恢复应用 A 的镜像地址为正确的镜像名称和标签\n2. 等待 Pod 滚动更新完成\n\n**恢复验证**：\n1. 查看 Pod 状态，确认恢复为 Running\n2. 查看 Pod Event，确认镜像拉取成功\n\n**基准事实**：\n- **根因**：Pod 配置的镜像名称拼写错误或标签在镜像仓库中不存在\n- **必现现象**：Pod 状态为 ImagePullBackOff 或 ErrImagePull，日志显示 `manifest for xxx not found`\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Service_调用失败/Service_调用失败_ReadinessProbe配置不一致.md":"**用例名称** ReadinessProbe配置不一致 导致 Service_调用失败\n\n**故障现象**：\n1. Pod 状态为 Running 但 READY 为 0/1\n2. Service 的 Endpoints 列表为空或逐渐减少\n3. Readiness Probe 持续失败，Pod 从 Service 后端移除\n\n**资源准备**：\n1. 确认应用 A 已正常运行，对外暴露 Service\n2. 确认应用 A 实际监听的端口和健康检查路径\n\n**演练步骤**：\n1. 记录应用 A 当前的 readinessProbe 配置\n2. 记录 Deployment 当前 maxUnavailable 值，并临时设为 100%（确保滚动更新能完成，故障注入的新 Pod 不会 Ready，默认策略下 K8s 不会终止旧 Pod，导致滚动更新死锁）：\n   ```bash\n   kubectl get deployment <deployment-name> -n <namespace> \\\n     -o jsonpath='{.spec.strategy.rollingUpdate.maxUnavailable}'\n   kubectl patch deployment <deployment-name> -n <namespace> --type='json' \\\n     -p='[{\"op\":\"replace\",\"path\":\"/spec/strategy/rollingUpdate/maxUnavailable\",\"value\":\"100%\"}]'\n   ```\n3. 修改应用 A 的 Deployment，将 readinessProbe 路径或端口设置为与实际不一致：\n   ```yaml\n   readinessProbe:\n     httpGet:\n       path: /non-existent-health-path\n       port: 9999    # 应用实际不监听此端口\n     periodSeconds: 5\n     failureThreshold: 3\n   ```\n4. 等待 Pod 滚动更新完成，确认所有旧 Pod 已被替换\n5. 滚动更新完成后，立即还原 maxUnavailable 为原始值（maxUnavailable 只是使滚动更新完成的手段，不是故障本身，不应泄漏到恢复阶段）\n6. 观察 Pod Ready 状态和 Service Endpoints 变化\n\n**注入验证**：\n1. 执行 `kubectl rollout status deployment <deployment-name>`，确认滚动更新已完成（所有旧 Pod 已被替换）。如果滚动更新未完成（卡死），则故障未完全生效，不可判定为 verified\n2. 执行 `kubectl get pods`，确认**所有** Pod 状态为 Running 但 READY 列显示 0/1（不是仅一个新 Pod 0/1，而是全部副本都 0/1）\n3. 执行 `kubectl get endpoints <service-name>`，确认 Endpoints 列表**为空**（无子集），而非仅新 Pod 不在列表中\n4. 执行 `kubectl describe pod <pod-name>`，确认 Events 显示 `Readiness probe failed`\n5. 向 Service 发送请求，确认返回 connection refused 或超时。注意：connection reset by peer 可能是应用自身行为而非故障效果，不可作为故障生效的充分证据\n\n**注入恢复**：\n1. 恢复应用 A 的 Deployment，将 readinessProbe 的路径和端口修正为正确值（若原本无 readinessProbe，则移除）\n2. 等待 Pod 滚动更新完成\n\n**恢复验证**：\n1. 执行 `kubectl get pods`，确认 Pod READY 为 1/1\n2. 执行 `kubectl get endpoints <service-name>`，确认 Pod 重新加入 Endpoints\n3. 向 Service 发送请求，确认服务恢复正常\n\n**基准事实**：\n- **根因**：Readiness Probe 的路径或端口与应用实际监听不一致，Probe 持续失败导致 Pod 被标记为 Not Ready，从 Service Endpoints 中移除\n- **必现现象**：Pod Running 但 Not Ready（0/1）；Endpoints 为空；Events 显示 Readiness probe failed\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Service_调用失败/Service_调用失败_kube-proxy异常.md":"**用例名称** kube-proxy异常 导致 Service_调用失败\n\n**故障现象**：\n1. 通过 ClusterIP/NodePort 访问 Service 失败，连接超时\n2. 节点上 iptables/ipvs 规则未更新或被清空\n3. kube-proxy Pod 异常，无法维护 Service 转发规则\n\n**资源准备**：\n1. 确认应用 A 已正常运行，对外暴露 Service\n2. 确认 kube-proxy DaemonSet 正常运行\n3. 确认监控系统可观测 Service 请求指标\n\n**演练步骤**：\n1. 记录 kube-proxy DaemonSet 当前状态\n2. 选择目标节点，删除该节点上的 kube-proxy Pod 并临时阻止重建（通过 cordon 节点或修改 DaemonSet nodeSelector）：\n   ```bash\n   # 方式A：给目标节点添加标签排除 kube-proxy 调度\n   kubectl label node <目标节点> chaos-no-proxy=true\n   kubectl patch ds kube-proxy -n kube-system \\\n     -p '{\"spec\":{\"template\":{\"spec\":{\"affinity\":{\"nodeAffinity\":{\"requiredDuringSchedulingIgnoredDuringExecution\":{\"nodeSelectorTerms\":[{\"matchExpressions\":[{\"key\":\"chaos-no-proxy\",\"operator\":\"DoesNotExist\"}]}]}}}}}}}'\n   ```\n   或者直接使用 chaosblade 杀掉 kube-proxy 进程：\n   ```bash\n   blade create k8s node-process kill \\\n     --names <目标节点> \\\n     --process kube-proxy \\\n     --timeout 120 \\\n     --kubeconfig <路径>\n   ```\n3. 在目标节点上的 Pod 内通过 ClusterIP 访问 Service\n4. 观察 Service 访问结果\n\n**注入验证**：\n1. 确认目标节点上 kube-proxy 进程不存在或 Pod 处于异常状态\n2. 在目标节点的 Pod 内访问 Service ClusterIP，确认连接超时或失败\n3. 检查节点 iptables/ipvs 规则，确认 Service 相关转发规则缺失或过期\n\n**注入恢复**：\n1. 若使用标签方式：移除节点标签并恢复 DaemonSet 配置：\n   ```bash\n   kubectl label node <目标节点> chaos-no-proxy-\n   kubectl patch ds kube-proxy -n kube-system --type=json \\\n     -p='[{\"op\":\"remove\",\"path\":\"/spec/template/spec/affinity\"}]'\n   ```\n2. 若使用 chaosblade：等待实验超时或执行 `blade destroy <UID>`\n3. 等待 kube-proxy Pod 在目标节点重建\n\n**恢复验证**：\n1. 确认目标节点上 kube-proxy Pod 恢复 Running 且 Ready\n2. 在目标节点的 Pod 内重新访问 Service，确认恢复正常\n3. 检查 iptables/ipvs 规则已重新同步\n\n**基准事实**：\n- **根因**：kube-proxy Pod 异常或进程被杀，无法维护节点上的 iptables/ipvs 转发规则，导致 Service ClusterIP 流量无法被正确转发\n- **必现现象**：Service ClusterIP 访问超时；kube-proxy 不可用；节点 iptables/ipvs 规则缺失\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Service_调用失败/Service_调用失败_selector不匹配.md":"**用例名称** selector不匹配 导致 Service_调用失败\n\n**故障现象**：\n1. Service 的 Endpoints 列表为空\n2. 通过 Service 访问应用返回 connection refused 或无响应\n3. Pod 正常运行但未被 Service 选中\n\n**资源准备**：\n1. 确认应用 A 已正常运行，对外暴露 Service\n2. 确认监控系统可观测 Service 请求指标和 Endpoints 状态\n\n**演练步骤**：\n1. 记录应用 A 的 Service 当前 selector 配置\n2. 使用 kubectl patch 修改 Service 的 selector，使其不匹配任何 Pod：\n   ```bash\n   kubectl patch svc <service-name> -n <namespace> \\\n     -p '{\"spec\":{\"selector\":{\"app\":\"non-existent-app\"}}}'\n   ```\n3. 观察 Endpoints 变化和服务可用性\n\n**注入验证**：\n1. 执行 `kubectl get endpoints <service-name>`，确认 Endpoints 列表为空（无子集）\n2. 向 Service 发送请求，确认返回 connection refused 或超时\n3. 执行 `kubectl get pods -l app=<原标签>`，确认 Pod 实际正常运行\n4. 对比 Service selector 与 Pod labels，确认不匹配\n\n**注入恢复**：\n1. 使用 kubectl patch 将 Service selector 恢复为原始值：\n   ```bash\n   kubectl patch svc <service-name> -n <namespace> \\\n     -p '{\"spec\":{\"selector\":{\"app\":\"<原始标签>\"}}}'\n   ```\n2. 等待 Endpoints 自动更新\n\n**恢复验证**：\n1. 执行 `kubectl get endpoints <service-name>`，确认 Endpoints 列表恢复，包含后端 Pod IP\n2. 向 Service 发送请求，确认恢复正常\n3. 确认服务可用性恢复\n\n**基准事实**：\n- **根因**：Service 的 selector 与后端 Pod 的 label 不匹配，导致 Endpoints 控制器无法关联任何 Pod，Service 无后端可转发\n- **必现现象**：Endpoints 为空；Service 请求失败（connection refused/超时）；Pod 正常但未被选中\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/Service_负载均衡异常/Service_负载均衡异常_后端不可达.md":"**用例名称** 后端不可达 导致 Service_负载均衡异常\n\n**故障现象**：\n1. Service 的 Endpoints 列表为空或部分后端不可用\n2. 请求到 Service 出现 5xx 错误或连接超时\n3. Ingress 后端健康检查失败\n\n**资源准备**：\n1. 确认应用 A 已正常运行，对外暴露 Service 和 Ingress\n2. 确认监控系统可观测 Service 请求指标和 Endpoints 状态\n\n**演练步骤**：\n1. 定位应用 A 的 Service 和后端 Pod\n2. 使用 chaosblade 对应用 A 的 Pod 注入故障，模拟后端不可达\n\n**注入方式选择（重要）**：\n- **推荐优先**：使用 `pod-process kill` 杀死后端 Pod 的主进程。优点：直接导致 Pod 重启或进入 CrashLoopBackOff，Endpoints 控制器会自动将其从 Endpoints 列表移除，故障效果明确且可观测\n- **备选方式**：使用 `pod-network drop` 断开 Pod 网络。注意：如果主机 blade 二进制与集群不兼容，会退化为 kubectl exec 方式注入，导致恢复阶段必须通过 kubectl exec 执行 blade destroy，增加恢复复杂度\n  - 如果目标是单个服务端口（如 MySQL 3306），推荐使用端口过滤以缩小爆炸半径：`pod-network drop --source-port 3306 --namespace <ns> --labels \"app=<app>\"`\n  - 如果需要完全断开 Pod 网络：`pod-network drop --namespace <ns> --labels \"app=<app>\"`，注意此方式会影响所有端口，包括 DNS 和监控\n- 选择原则：如果集群中已部署 ChaosBlade Operator 且主机 blade 可直接使用，两种方式均可；如果需要通过 kubectl exec 注入，优先选择 pod-process kill\n\n**Readiness Probe 兼容性**（选择注入方式前必须评估）：\n- 通过 `kubectl describe pod <pod>` 获取目标 Pod 的 Readiness Probe 类型\n- `exec` 类型 Probe：在容器内通过 localhost 执行，**不受** pod-network drop 的 tc 规则影响 → Pod 保持 Ready → Endpoints 不会移除\n- `httpGet/tcpSocket` 类型 Probe（端口在 Service 端口范围内）：**可能受** pod-network drop 影响 → 延迟后 Pod 变为 NotReady → Endpoints 会被移除\n- 选择原则：如果目标是\"Endpoints 移除\"，exec 类型 Probe 的 Pod 应使用 pod-process kill 而非 pod-network drop\n\n**注入验证**：\n1. 执行 `kubectl get endpoints <service-name>`，确认部分后端被移除或全不可用\n2. 向 Service 发送请求，确认出现 5xx 错误或连接超时\n3. 查看 Ingress 状态，确认后端健康检查失败\n4. 确认请求流量被调度到剩余可用后端（部分后端不可用时）\n\n**注入恢复**：\n1. 销毁 chaosblade 实验\n\n**恢复验证**：\n1. 执行 `kubectl get endpoints <service-name>`，确认所有后端恢复可用\n2. 向 Service 发送请求，确认恢复正常\n3. 查看 Ingress 状态，确认后端健康检查通过\n\n**基准事实**：\n- **根因**：Service 后端 Pod 异常或网络不通，导致负载均衡无法将请求转发到健康的后端，服务可用性下降\n- **必现现象**：Endpoints 列表部分为空或全部为空；请求出现 5xx 或超时；Ingress 后端健康检查失败\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/workload_副本被缩容/workload_副本被缩容_人为误操作.md":"**用例名称** 人为误操作 导致 workload_副本被缩容\n\n**故障现象**：\n1. Deployment/StatefulSet 的当前副本数小于期望副本数\n2. 应用可用实例减少，部分请求无法处理\n3. 服务响应延迟增大或出现超时\n\n**资源准备**：\n1. 确认应用 A 的 Deployment/StatefulSet 已正常运行，副本数大于 1\n2. 确认监控系统可观测 Pod 副本数和请求指标\n\n**演练步骤**：\n1. 定位应用 A 的 Deployment/StatefulSet\n2. 使用 kubectl 将 replicas 修改为较小的值，模拟人为误操作导致的意外缩容\n3. 观察 Pod 缩容过程和应用状态变化\n\n**标签选择器提示**：\n- Kubernetes 推荐标签格式为 `app.kubernetes.io/name=<name>`，而非简单的 `app=<name>`\n- 建议先不带 `-l` 过滤器查询 `kubectl get deployment <name> -n <ns>`，再从返回结果中提取实际标签\n- 若需用标签过滤，优先使用 `-l app.kubernetes.io/name=<name>` 或 `-l app.kubernetes.io/component=<name>`\n\n**注入验证**：\n1. 执行 `kubectl get pods`，确认 Pod 总数减少，部分 Pod 被终止\n2. 执行 `kubectl get deployment/statefulset <name>`，确认当前副本数小于缩容前的值\n3. 确认应用 A 的请求延迟增大或出现超时\n4. 确认服务可用性下降\n\n**注入恢复**：\n1. 使用 kubectl 将 replicas 恢复为原来的合理值\n2. 等待 Pod 自动扩容\n\n**恢复验证**：\n1. 执行 `kubectl get pods`，确认 Pod 总数恢复到缩容前的值\n2. 执行 `kubectl get deployment/statefulset <name>`，确认 READY 副本数等于 DESIRED\n3. 确认应用 A 的请求延迟恢复正常\n4. 确认服务可用性恢复\n\n**基准事实**：\n- **根因**：人为误操作（如 kubectl scale、修改 YAML 等）导致 Deployment/StatefulSet 的副本数被意外缩小，可用实例不足\n- **必现现象**：READY 副本数小于 DESIRED；Pod 被终止；服务可用性下降\n\n**注意事项**：\n- 若目标 Deployment/StatefulSet 由 Helm 管理（label `app.kubernetes.io/managed-by: Helm`），kubectl scale 修改会被 Helm reconciliation 覆盖\n- 注入期间应避免触发 Helm upgrade/rollback 操作，否则故障会被意外恢复\n- 反之，若需快速恢复，可通过 `helm rollback` 或 `helm upgrade` 强制还原\n","blade-ai/skills/k8s-chaos-skills/references/catalogue/节点容器运行时磁盘使用率过高/节点容器运行时磁盘使用率过高_日志或临时文件堆积.md":"**用例名称** 日志或临时文件堆积 导致 节点容器运行时磁盘使用率过高\n\n**故障现象**：\n1. 节点磁盘使用率告警（大于85%）\n2. 容器无法写入数据\n3. `/var/log`、`/tmp` 目录占用空间大\n\n**资源准备**：\n1. 确认应用 A/B 已正常运行\n2. 确认节点磁盘空间充足\n\n**演练步骤**：\n1. 定位运行应用 A Pod 的节点\n2. 使用 chaosblade 或其他故障注入工具向节点 `/var/log` 或 `/tmp` 目录持续写入数据，模拟日志或临时文件堆积\n   - **路径语义**：在 K8s CRD 模式下（默认），`--path /tmp` 或 `--path /var/log` 是相对于容器 overlay 文件系统的路径，填充数据**通常**写入 imagefs 分区（需节点有独立 imagefs）；`--path /var/lib/docker` 等宿主机路径**通常**写入 nodefs 分区。实际分区取决于节点配置，验证时需确认检查的分区与填充目标分区一致\n3. 观察节点磁盘使用率变化\n\n**CRD 模式路径→分区映射表**：\n**注意**：下表为常见配置下的启发式映射。实际分区取决于节点的挂载配置：\n- 如果节点没有独立的 imagefs（容器运行时数据在根磁盘），所有路径都在 nodefs 上\n- `/var/lib/docker`、`/var/lib/containerd` 在独立磁盘时属于 imagefs（它们定义了 imagefs），不是 nodefs\n- 验证时以 `df -h`（无路径参数）的实际输出为准，而非下表\n\n在 K8s CRD 模式下（ChaosBlade Operator），`--path` 参数决定填充数据写入哪个分区。验证时**必须**检查对应分区，否则会产生假阴性。\n\n| `--path` 值 | 目标分区 | 典型后端设备 | 正确验证命令 | 常见假阴性命令 |\n|---|---|---|---|---|\n| `/tmp`, `/var/log`, `/var/run`, `/run` | imagefs（容器 overlay） | `/dev/vdb` 等独立磁盘 | `df -h`（无路径参数）列出所有挂载点，找 overlay 分区 | `df -h /host`（仅显示 nodefs） |\n| `/var/lib/docker`, `/var/lib/containerd`, `/var/lib/kubelet` | nodefs（根文件系统） | `/dev/vda3` 等根分区 | `df -h /host` 显示根分区使用率 | `df -h`（找错 overlay 分区） |\n| `/etc`, `/root`, `/home` | nodefs（根文件系统） | `/dev/vda3` 等根分区 | `df -h /host` 显示根分区使用率 | 同上 |\n| 其他路径 | 需 `df -h` 列出全部后判定 | 不确定 | `df -h`（无路径参数）识别哪个分区使用率变化 | 仅检查单一分区 |\n\n**注入验证**：\n0. **基线完整性检查**（验证阶段第一步，必须先于其他验证步骤执行）：\n   - **首条命令必须**是 `df -h`（无路径参数），列出所有分区使用率，标注与注入 `--path` 对应的分区（根据上方路径→分区映射表）。禁止先执行 `df -h /host` 或 `df -h /host/<path>` — 这些命令只显示 nodefs，会在 imagefs 场景下产生错误基线\n   - 后续验证中，只对比**同一分区**的使用率变化。禁止将 nodefs 基线与 imagefs 注入后数据做对比\n   - 若未在注入前记录目标分区基线，须在验证结论中注明\"No pre-injection baseline available for <分区类型>\"，并以首次检查值作为参考点\n   - 若首次检查值已接近注入参数预期值（如 `--percent 85` 对应 84%），此即故障生效的证据，无需等待\"变化\"\n1. 查看节点磁盘使用率，确认磁盘使用率变化。通过 `kubectl debug` 两步法查看宿主机磁盘使用率：\n   - Step 1：`kubectl debug node/<节点名> --image=busybox -- sleep 3600`（必须含 `-- sleep 3600` 保活，裸 busybox 会立即退出）\n   - Step 2：从 Step 1 输出找到 debug pod 名称，然后 `kubectl exec <debug-pod> -n default -- df -h`\n   - `df -h` 列出所有挂载的文件系统。如果节点有多个磁盘分区（如 nodefs 和 imagefs 分开），需检查**所有分区**的使用率变化。`df -h /host` 仅显示 nodefs（根分区）；imagefs 的变化需通过 `df -h` 列出所有挂载点来识别\n   - **注意**：otel-c-tool 不挂载 /host，`kubectl exec <otel-c-tool> -- df -h` 显示的是 overlay 文件系统，不能用于宿主机磁盘验证。禁止仅通过 `kubectl exec <Pod> -- df -h` 验证（容器 overlay 文件系统≠宿主机文件系统）\n2. 检查 `/var/log`、`/tmp` 目录大小，确认占用显著。需通过 kubectl debug 两步法进入 debug pod，路径加 `/host/` 前缀（如 `du -sh /host/tmp`、`du -sh /host/var/log`）\n\n   **CRD 模式重要提醒**：`du -sh /host/<path>` 检查的是宿主机文件系统（nodefs）。如果注入使用了 `--path /var/log` 或 `--path /tmp`（在 CRD 模式下写入容器 overlay/imagefs），`du` 将看到宿主机路径的**原始大小**，不会反映 fill 数据。此时 `df -h`（bare, 无路径参数）展示的 overlay/imagefs 使用率变化才是 fill 效果的正确证据。\n\n   - 若 `df -h` 已确认目标分区使用率达到预期 → Step 2 可标记为 `expected: du checks host nodefs, fill in imagefs overlay (confirmed by df -h)`，不要标记为 `failed`\n   - 若 fill 路径映射到 nodefs（如 `--path /var/lib/docker`）→ `du -sh /host/<path>` 应能观察到增长\n3. 使用容器运行时工具查看容器、镜像和日志占用\n4. 使用 `kubectl describe node <节点名>` 检查 DiskPressure 条件，确认 K8s 层面已检测到磁盘压力\n\n**验证语义说明**：区分两个概念：(1) 注入验证——填充数据是否写入成功（通过填充文件或磁盘增量判断）；(2) 场景验证——磁盘使用率是否达到 85%。注入验证通过但场景验证未达标时，Layer 2 应报告 'passed' 并在 Warnings 中注明阈值未达到。如果使用率未达 85%，说明 --size 参数过小，应增加 size 或改用 percent 参数。这不代表注入失败。\n\n**注入恢复**：\n1. 销毁 chaosblade 实验\n2. 停止数据写入或删除创建的大文件\n3. 清理日志文件\n\n**恢复验证**：\n1. 查看节点磁盘使用率，确认恢复到正常水平。使用 kubectl debug 两步法（同注入验证），执行 `df -h`（无路径参数）检查所有磁盘分区均恢复\n2. 确认应用 A/B 可正常写入数据\n3. 确认 `/var/log`、`/tmp` 目录大小恢复正常（需通过宿主机文件系统访问方式验证）\n\n**基准事实**：\n- **根因**：容器日志或临时文件未清理，导致磁盘空间被占满\n- **必现现象**：节点磁盘使用率大于85%，`/var/log` 或 `/tmp` 目录占用空间大\n","blade-ai/skills/k8s-chaos-skills/references/chaosblade-commands.md":"# Chaosblade K8s 命令速查表\n\n本文件提供 Chaosblade 在 Kubernetes 环境下常用故障注入命令的速查，减少执行过程中反复 `-h` 查看帮助。\n\n---\n\n## 通用语法\n\n```bash\nblade create k8s <scope>-<target> <action> [flags]\n```\n\n- `<scope>`: 作用范围，可选 `pod`、`node`、`container`\n- `<target>`: 故障目标，如 `cpu`、`network`、`disk`、`process`、`pod`(仅Pod级别)\n- `<action>`: 故障动作，如 `fullload`、`drop`、`dns`、`occupy`、`fill`、`kill`\n\n## Action 对照表（scope-target → 可用 action）\n\n| scope-target | 可用 action | 说明 |\n|---|---|---|\n| pod-cpu | `fullload` | CPU 满载 |\n| pod-mem | `load` | 内存占用 |\n| pod-network | `dns`, `drop`, `occupy` | 网络故障 (v1.8.0) |\n| pod-disk | `fill`, `burn` | 磁盘填充 / IO 负载 |\n| pod-process | `kill`, `stop` | 进程操作 |\n| pod-pod | `delete` | Pod 删除 |\n| pod-IO | `delay`, `errno` | 文件系统 IO 故障 |\n| node-cpu | `fullload` | CPU 满载 |\n| node-mem | `load` | 内存占用 |\n| node-network | `drop` | 网络故障 (v1.8.0: `delay`/`loss` → `drop`) |\n| node-disk | `fill`, `burn` | 磁盘填充 / IO 负载 (**无 fullload**) |\n| node-process | `kill`, `stop` | 进程操作 |\n| container-cpu | `fullload` | CPU 满载 |\n| container-network | `drop` | 网络故障 (v1.8.0: `delay`/`loss` → `drop`) |\n| container-process | `kill`, `stop` | 进程操作 |\n| container-container | `remove` | 容器删除 |\n\n> **⚠️ 常见错误警示**：\n> - `node-disk` **没有** `fullload` action！磁盘 IO 负载使用 `burn`，磁盘空间填充使用 `fill`\n> - `pod-disk` 同理，只有 `fill` 和 `burn`，没有 `fullload`\n> - `pod-mem` 的 action 是 `load`，不是 `fullload`\n> - `node-mem` 的 action 是 `load`，不是 `fullload`\n> - 只有 `cpu` target 才有 `fullload` action\n> - **注入前务必确认 scope-target-action 组合在上表中存在**，避免因 action 不存在导致注入失败\n\n## 通用 K8s Flags\n\n以下参数适用于所有 `blade create k8s` 命令：\n\n| Flag | 说明 | 示例 |\n|------|------|------|\n| `--namespace` | 目标命名空间 | `--namespace default` |\n| `--labels` | 按标签筛选资源 | `--labels \"app=nginx\"` |\n| `--names` | 按名称指定资源（逗号分隔） | `--names node-1,node-2` |\n| `--kubeconfig` | kubeconfig 文件路径 | `--kubeconfig ~/.kube/config` |\n| `--evict-count` | 限制影响的资源数量 | `--evict-count 1` |\n| `--evict-percent` | 限制影响的资源百分比 | `--evict-percent 50` |\n| `--waiting-time` | 等待结果的超时时间 | `--waiting-time 30s` |\n| `--timeout` | 实验自动过期时间（秒） | `--timeout 600` |\n\n---\n\n## 一、Pod 级别故障\n\n### 1. Pod CPU 满载\n\n```bash\nblade create k8s pod-cpu fullload \\\n  --namespace <ns> \\\n  --labels \"app=<app>\" \\\n  --cpu-percent <0-100> \\\n  --cpu-count <核数> \\\n  --kubeconfig ~/.kube/config\n```\n\n| Flag | 说明 | 默认值 |\n|------|------|--------|\n| `--cpu-percent` | CPU 使用率百分比 | 100 |\n| `--cpu-count` | 指定满载的 CPU 核数（不指定则全部） | 全部 |\n| `--cpu-list` | 指定满载的 CPU 核编号（如 0,1,2） | - |\n| `--timeout` | 自动恢复时间（秒） | - |\n\n### 2. Pod 内存压力\n\n```bash\nblade create k8s pod-mem load \\\n  --namespace <ns> \\\n  --labels \"app=<app>\" \\\n  --mode ram \\\n  --mem-percent <0-100> \\\n  --kubeconfig ~/.kube/config\n```\n\n| Flag | 说明 | 默认值 |\n|------|------|--------|\n| `--mode` | 内存占用模式：`ram`(物理内存) / `cache` | ram |\n| `--mem-percent` | 内存使用率百分比 | - |\n| `--reserve` | 保留的内存大小（如 `200m`） | - |\n| `--rate` | 内存增长速率（每秒MB） | - |\n\n### 3. Pod 网络延迟\n\n> **⚠️ v1.8.0 不可用**：`pod-network delay` 在 blade v1.8.0 中不存在（仅 `dns`/`drop`/`occupy`）。如需延迟效果，使用 Tier 2 kubectl-native 方案（tc qdisc）。以下为旧版参考：\n\n```bash\nblade create k8s pod-network delay \\\n  --namespace <ns> \\\n  --labels \"app=<app>\" \\\n  --time <毫秒> \\\n  --interface eth0 \\\n  --kubeconfig ~/.kube/config\n```\n\n| Flag | 说明 | 默认值 |\n|------|------|--------|\n| `--time` | 延迟时间（毫秒） | - |\n| `--offset` | 延迟波动范围（毫秒） | - |\n| `--interface` | 网络接口 | eth0 |\n| `--local-port` | 本地端口（逗号分隔） | 全部 |\n| `--remote-port` | 远程端口（逗号分隔） | 全部 |\n| `--destination-ip` | 目标 IP（逗号分隔） | 全部 |\n| `--exclude-port` | 排除端口 | - |\n| `--exclude-ip` | 排除 IP | - |\n\n### 4. Pod 网络丢包\n\n```bash\nblade create k8s pod-network drop \\\n  --namespace <ns> \\\n  --labels \"app=<app>\" \\\n  --kubeconfig ~/.kube/config\n```\n\n> **⚠️ drop 是全量丢包**（iptables DROP 语义），**不支持 `--percent` 和 `--interface`**。不带端口/IP 过滤时丢弃所有出方向流量。\n\n| Flag | 说明 | 默认值 |\n|------|------|--------|\n| `--source-port` | 源端口（逗号分隔） | 全部 |\n| `--destination-port` | 目标端口（逗号分隔） | 全部 |\n| `--source-ip` | 源 IP | 全部 |\n| `--destination-ip` | 目标 IP | 全部 |\n| `--network-traffic` | 流量方向：`in` / `out` | - |\n| `--string-pattern` | 匹配数据包内容 | - |\n\n> **爆炸半径控制提示**：drop 默认丢弃全部流量，**必须**使用 `--source-port` 或 `--destination-port` 或 `--destination-ip` 限制影响范围，避免丢弃 DNS、监控等非目标流量。仅在测试完全网络分区时使用不加过滤的注入。\n\n### 5. Pod DNS 故障\n\n```bash\nblade create k8s pod-network dns \\\n  --namespace <ns> \\\n  --labels \"app=<app>\" \\\n  --domain <域名> \\\n  --ip <伪造IP> \\\n  --kubeconfig ~/.kube/config\n```\n\n| Flag | 说明 | 默认值 |\n|------|------|--------|\n| `--domain` | 目标域名 | - |\n| `--ip` | 映射的伪造 IP | - |\n\n### 6. Pod 网络包损坏\n\n```bash\nblade create k8s pod-network corrupt \\\n  --namespace <ns> \\\n  --labels \"app=<app>\" \\\n  --percent <0-100> \\\n  --interface eth0 \\\n  --kubeconfig ~/.kube/config\n```\n\n### 7. Pod 网络包重复\n\n```bash\nblade create k8s pod-network duplicate \\\n  --namespace <ns> \\\n  --labels \"app=<app>\" \\\n  --percent <0-100> \\\n  --interface eth0 \\\n  --kubeconfig ~/.kube/config\n```\n\n### 8. Pod 磁盘填充\n\n```bash\nblade create k8s pod-disk fill \\\n  --namespace <ns> \\\n  --labels \"app=<app>\" \\\n  --path <目录> \\\n  --size <大小> \\\n  --kubeconfig ~/.kube/config\n```\n\n| Flag | 说明 | 默认值 |\n|------|------|--------|\n| `--path` | 填充的目标目录 | / |\n| `--size` | 填充大小（如 `1024m`、`10g`） | - |\n| `--percent` | 填充到磁盘使用率百分比 | - |\n| `--retain-handle` | 保留文件句柄（删除文件后不释放空间） | false |\n\n### 9. Pod 磁盘 IO 读写负载\n\n```bash\nblade create k8s pod-disk burn \\\n  --namespace <ns> \\\n  --labels \"app=<app>\" \\\n  --path <目录> \\\n  --read \\\n  --write \\\n  --kubeconfig ~/.kube/config\n```\n\n| Flag | 说明 | 默认值 |\n|------|------|--------|\n| `--path` | IO 负载目标目录 | / |\n| `--read` | 读 IO 负载 | false |\n| `--write` | 写 IO 负载 | false |\n| `--size` | 每次 IO 块大小（如 `10m`） | - |\n| `--count` | IO 次数 | - |\n\n### 10. Pod 文件系统 IO 故障\n\n```bash\nblade create k8s pod-IO delay \\\n  --namespace <ns> \\\n  --labels \"app=<app>\" \\\n  --time <毫秒> \\\n  --path <目录> \\\n  --kubeconfig ~/.kube/config\n```\n\n| Action | 说明 |\n|--------|------|\n| `delay` | 文件系统 IO 延迟 |\n| `errno` | 文件系统 IO 返回错误 |\n\n| Flag | 说明 | 默认值 |\n|------|------|--------|\n| `--time` | IO 延迟（毫秒），仅 `delay` | - |\n| `--errno` | 返回的错误码，仅 `errno` | 28 (ENOSPC) |\n| `--path` | 影响的文件路径 | - |\n| `--methods` | 拦截的系统调用（如 read,write） | 全部 |\n| `--percent` | 故障生效百分比 | 100 |\n\n### 11. Pod 进程操作\n\n```bash\nblade create k8s pod-process kill \\\n  --namespace <ns> \\\n  --labels \"app=<app>\" \\\n  --process <进程名> \\\n  --kubeconfig ~/.kube/config\n```\n\n| Action | 说明 |\n|--------|------|\n| `kill` | 杀掉进程 |\n| `stop` | 挂起进程（SIGSTOP） |\n\n| Flag | 说明 | 默认值 |\n|------|------|--------|\n| `--process` | 进程名 | - |\n| `--process-cmd` | 进程命令行关键词 | - |\n| `--signal` | 发送的信号（仅 kill） | 9 |\n| `--count` | 限制影响的进程数 | - |\n\n### 12. Pod 删除\n\n```bash\nblade create k8s pod-pod delete \\\n  --namespace <ns> \\\n  --labels \"app=<app>\" \\\n  --kubeconfig ~/.kube/config\n```\n\n| Flag | 说明 | 默认值 |\n|------|------|--------|\n| `--labels` | 标签筛选 | - |\n| `--names` | 指定 Pod 名称 | - |\n| `--evict-count` | 删除的 Pod 数量 | - |\n| `--evict-percent` | 删除的 Pod 百分比 | - |\n\n---\n\n## 二、Node 级别故障\n\n### 1. 节点 CPU 满载\n\n```bash\nblade create k8s node-cpu fullload \\\n  --names <节点名> \\\n  --cpu-percent <0-100> \\\n  --kubeconfig ~/.kube/config\n```\n\nFlags 与 Pod CPU 满载一致（`--cpu-percent`、`--cpu-count`、`--cpu-list`）。\n\n### 2. 节点内存压力\n\n```bash\nblade create k8s node-mem load \\\n  --names <节点名> \\\n  --mode ram \\\n  --mem-percent <0-100> \\\n  --kubeconfig ~/.kube/config\n```\n\nFlags 与 Pod 内存压力一致（`--mode`、`--mem-percent`、`--reserve`、`--rate`）。\n\n### 3. 节点网络延迟\n\n> **⚠️ v1.8.0 不可用**：`node-network delay` 在 blade v1.8.0 中不存在。以下为旧版参考：\n\n```bash\nblade create k8s node-network delay \\\n  --names <节点名> \\\n  --time <毫秒> \\\n  --interface eth0 \\\n  --kubeconfig ~/.kube/config\n```\n\n### 4. 节点网络丢包\n\n```bash\nblade create k8s node-network drop \\\n  --names <节点名> \\\n  --kubeconfig ~/.kube/config\n```\n\n> **⚠️ 同 Pod drop：全量丢包，不支持 `--percent` 和 `--interface`。** 用 `--source-port`/`--destination-ip` 缩小范围。\n\nNode 网络 Flags 与 Pod 网络一致（`--source-port`、`--destination-port`、`--source-ip`、`--destination-ip`、`--network-traffic` 等）。\n\n### 5. 节点磁盘填充\n\n```bash\nblade create k8s node-disk fill \\\n  --names <节点名> \\\n  --path <目录> \\\n  --size <大小> \\\n  --kubeconfig ~/.kube/config\n```\n\n| Flag | 说明 | 示例 |\n|------|------|------|\n| `--path` | 填充目标目录 | `/var/lib/docker` |\n| `--size` | 填充大小 | `50g` |\n| `--percent` | 填充到磁盘使用率 | `95` |\n\n### 6. 节点磁盘 IO 负载\n\n```bash\nblade create k8s node-disk burn \\\n  --names <节点名> \\\n  --read \\\n  --write \\\n  --path <目录> \\\n  --kubeconfig ~/.kube/config\n```\n\n| Flag | 说明 | 默认值 |\n|------|------|--------|\n| `--read` | 启用读 IO 负载 | false |\n| `--write` | 启用写 IO 负载 | false |\n| `--path` | IO 负载目标目录 | / |\n| `--size` | 每次 IO 块大小（如 `10m`） | - |\n| `--count` | IO 次数 | - |\n\n> **建议**：生产环境务必指定 `--path` 为非根分区目录（如 `/data`），避免影响根分区系统文件。\n\n### 7. 节点进程操作\n\n```bash\nblade create k8s node-process kill \\\n  --names <节点名> \\\n  --process <进程名> \\\n  --kubeconfig ~/.kube/config\n```\n\nActions 和 Flags 与 Pod 进程操作一致。\n\n---\n\n## 三、Container 级别故障\n\nContainer 级别命令在 Pod 内指定特定容器执行故障注入，适用于多容器 Pod（如有 sidecar 的场景）。\n\n### 通用 Container Flag\n\n| Flag | 说明 |\n|------|------|\n| `--container-names` | 目标容器名 |\n\n### 1. 容器 CPU 满载\n\n```bash\nblade create k8s container-cpu fullload \\\n  --namespace <ns> \\\n  --labels \"app=<app>\" \\\n  --container-names <容器名> \\\n  --cpu-percent <0-100> \\\n  --kubeconfig ~/.kube/config\n```\n\n### 2. 容器网络延迟\n\n> **⚠️ v1.8.0 不可用**：`container-network delay` 在 blade v1.8.0 中不存在。以下为旧版参考：\n\n```bash\nblade create k8s container-network delay \\\n  --namespace <ns> \\\n  --labels \"app=<app>\" \\\n  --container-names <容器名> \\\n  --time <毫秒> \\\n  --interface eth0 \\\n  --kubeconfig ~/.kube/config\n```\n\n### 3. 容器进程操作\n\n```bash\nblade create k8s container-process kill \\\n  --namespace <ns> \\\n  --labels \"app=<app>\" \\\n  --container-names <容器名> \\\n  --process <进程名> \\\n  --kubeconfig ~/.kube/config\n```\n\n### 4. 容器删除\n\n```bash\nblade create k8s container-container remove \\\n  --namespace <ns> \\\n  --labels \"app=<app>\" \\\n  --container-names <容器名> \\\n  --kubeconfig ~/.kube/config\n```\n\n---\n\n## 四、实验管理命令\n\n### 查看实验状态\n\n```bash\n# 查看所有进行中的实验\nblade status --type create\n\n# 查看指定实验详情\nblade status <UID>\n```\n\n### 销毁实验\n\n```bash\n# 销毁指定实验\nblade destroy <UID>\n\n# 批量销毁所有实验（紧急回滚用）\nblade status --type create | grep \"^UID\" | awk '{print $2}' | xargs -I {} blade destroy {}\n```\n\n### 版本与帮助\n\n```bash\n# 查看版本\nblade version\n\n# 查看所有支持的实验场景\nblade create -h\n\n# 查看某个场景的详细帮助\nblade create k8s pod-network drop -h\n```\n\n---\n\n## 五、常见演练场景速查\n\n按照 catalogue 中使用频率最高的故障场景，汇总对应的 blade 命令：\n\n### 资源压力类\n\n| 故障场景 | 命令 |\n|---------|------|\n| Pod CPU 满载 | `blade create k8s pod-cpu fullload --cpu-percent 80 --namespace <ns> --labels \"app=<app>\"` |\n| Pod 内存压力 | `blade create k8s pod-mem load --mode ram --mem-percent 90 --namespace <ns> --labels \"app=<app>\"` |\n| 节点 CPU 满载 | `blade create k8s node-cpu fullload --cpu-percent 90 --names <node>` |\n| 节点内存压力 | `blade create k8s node-mem load --mode ram --mem-percent 95 --names <node>` |\n\n### 网络故障类\n\n| 故障场景 | 命令 |\n|---------|------|\n| Pod 网络丢包(全量) | `blade create k8s pod-network drop --namespace <ns> --labels \"app=<app>\"` |\n| Pod 网络丢包(指定端口) | `blade create k8s pod-network drop --source-port 3306 --namespace <ns> --labels \"app=<app>\"` |\n| Pod DNS 故障 | `blade create k8s pod-network dns --domain example.com --ip 1.1.1.1 --namespace <ns> --labels \"app=<app>\"` |\n| 节点网络丢包 | `blade create k8s node-network drop --names <node>` |\n\n### 磁盘故障类\n\n| 故障场景 | 命令 |\n|---------|------|\n| Pod 磁盘填充 | `blade create k8s pod-disk fill --path /data --size 10g --namespace <ns> --labels \"app=<app>\"` |\n| 节点磁盘填充 | `blade create k8s node-disk fill --path /var/lib/docker --percent 95 --names <node>` |\n| 节点磁盘 IO 负载 | `blade create k8s node-disk burn --read --write --path /data --names <node>` |\n\n### 进程与 Pod 操作类\n\n| 故障场景 | 命令 |\n|---------|------|\n| 杀 Pod 内进程 | `blade create k8s pod-process kill --process <name> --namespace <ns> --labels \"app=<app>\"` |\n| 挂起 Pod 内进程 | `blade create k8s pod-process stop --process <name> --namespace <ns> --labels \"app=<app>\"` |\n| 删除 Pod | `blade create k8s pod-pod delete --namespace <ns> --labels \"app=<app>\" --evict-count 1` |\n| 杀节点进程 | `blade create k8s node-process kill --process <name> --names <node>` |\n\n---\n\n## 六、Operator YAML 模板\n\n当使用 Operator 方式（`kubectl apply`）执行持续化演练时，使用以下模板：\n\n```yaml\napiVersion: chaosblade.io/v1alpha1\nkind: ChaosBlade\nmetadata:\n  name: <experiment-name>\nspec:\n  experiments:\n    - scope: <pod|node|container>\n      target: <cpu|network|disk|process|pod|container>\n      action: <action>\n      desc: \"<实验描述>\"\n      matchers:\n        - name: namespace\n          value: [\"<namespace>\"]\n        - name: labels\n          value: [\"app=<app-name>\"]\n        # node 级别使用 names 而非 labels\n        # - name: names\n        #   value: [\"<node-name>\"]\n      flags:\n        - name: <flag-name>\n          value: \"<flag-value>\"\n```\n\n**Operator YAML 示例 - Pod CPU 满载：**\n\n```yaml\napiVersion: chaosblade.io/v1alpha1\nkind: ChaosBlade\nmetadata:\n  name: pod-cpu-fullload\nspec:\n  experiments:\n    - scope: pod\n      target: cpu\n      action: fullload\n      desc: \"Pod CPU 满载 80%\"\n      matchers:\n        - name: namespace\n          value: [\"default\"]\n        - name: labels\n          value: [\"app=nginx\"]\n      flags:\n        - name: cpu-percent\n          value: \"80\"\n```\n\n**Operator YAML 示例 - Pod 网络延迟：**\n\n```yaml\napiVersion: chaosblade.io/v1alpha1\nkind: ChaosBlade\nmetadata:\n  name: pod-network-delay\nspec:\n  experiments:\n    - scope: pod\n      target: network\n      action: delay\n      desc: \"Pod 网络延迟 3s\"\n      matchers:\n        - name: namespace\n          value: [\"default\"]\n        - name: labels\n          value: [\"app=nginx\"]\n      flags:\n        - name: time\n          value: \"3000\"\n        - name: interface\n          value: \"eth0\"\n```\n\n**Operator 管理命令：**\n\n```bash\n# 创建实验\nkubectl apply -f experiment.yaml\n\n# 查看实验状态\nkubectl get chaosblade <experiment-name> -o yaml\n\n# 销毁实验\nkubectl delete chaosblade <experiment-name>\n\n# 销毁所有实验\nkubectl delete chaosblade --all\n```\n\n---\n\n## 七、kubectl exec 注入路径\n\n当宿主机 blade CLI 不可用（未安装或版本不兼容，如报 `unknown flag` 错误）时，可通过 kubectl exec 在集群内的 tool Pod 中执行 blade 命令。\n\n### 前提条件\n- 集群中部署了 chaosblade-tool DaemonSet（如 otel-c-tool）\n- tool Pod 的 ServiceAccount 有操作目标资源的权限\n\n### 执行步骤\n\n1. 发现可用的 tool Pod：\n   ```bash\n   kubectl get pods -n chaosblade -l app=otel-c-tool --kubeconfig=<path>\n   ```\n2. 选择 STATUS=Running 的 Pod（任意一个均可，实验是集群级别的）\n3. 执行 blade 命令：\n   ```bash\n   kubectl exec <pod> -n chaosblade -- blade create k8s <scenario> [flags] --kubeconfig=<path>\n   ```\n4. 从 JSON 输出中提取 blade_uid 用于后续恢复\n\n### 示例：Pod 网络丢包\n\n```bash\n# 1. 发现 tool Pod\nkubectl get pods -n chaosblade -l app=otel-c-tool --kubeconfig=/path/to/config\n# 2. 通过 tool Pod 执行 blade create\nkubectl exec otel-c-tool-xxxxx -n chaosblade -- \\\n  blade create k8s pod-network drop \\\n  --namespace cms-demo \\\n  --labels \"app=myapp\" \\\n  --kubeconfig=/path/to/config\n# 3. 从输出中提取 blade_uid\n# {\"code\":200,\"success\":true,\"result\":\"abc123\"}\n# 4. 恢复时同样通过 tool Pod 执行 blade destroy\nkubectl exec otel-c-tool-xxxxx -n chaosblade -- \\\n  blade destroy abc123 --kubeconfig=/path/to/config\n```\n\n### 注意事项\n- 不同 tool Pod 可能运行在不同节点上，但 blade 命令通过 API Server 执行，任何健康 Pod 都可操作\n- tool Pod 可能因 DaemonSet 轮换而重启，恢复时需重新查找 Running 的 Pod\n- kubectl exec 中的 blade 命令参数与本地 blade CLI 完全一致\n"},"items":[{"name":"DaemonSet_未完全调度_节点不可调度.md","path":"blade-ai/skills/k8s-chaos-skills/references/catalogue/DaemonSet_未完全调度/DaemonSet_未完全调度_节点不可调度.md","rawUrl":"https://raw.githubusercontent.com/chaosblade-io/chaosblade/HEAD/blade-ai/skills/k8s-chaos-skills/references/catalogue/DaemonSet_未完全调度/DaemonSet_未完全调度_节点不可调度.md","title":"DaemonSet_未完全调度 Skill","category":"anthropic-skill","format":"markdown","content":"**用例名称** 节点不可调度 导致 DaemonSet_未完全调度\n\n**故障现象**：\n1. DaemonSet 的 Ready 副本数小于期望副本数\n2. 部分节点上没有运行 DaemonSet Pod\n3. `kubectl get daemonset` 显示 DESIRED 与 READY 数量不一致\n\n**资源准备**：\n1. 确认 DaemonSet 应用 A 已正常运行，且所有节点均有副本\n2. 确认监控系统可观测 DaemonSet 副本状态\n\n**演练步骤**：\n1. 选取一个运行 DaemonSet Pod 的节点\n2. 使用 kubectl 将该节点标记为不可调度（cordon）：`kubectl cordon <node>`\n3. 给该节点添加一个 DaemonSet 未配置容忍的自定义污点：`kubectl taint nodes <node> chaos-drill/unschedulable=true:NoSchedule`\n4. 删除该节点上的 DaemonSet Pod，观察 Pod 是否被重建\n5. 观察 DaemonSet 副本数变化\n\n**注入验证**：\n1. 执行 `kubectl get nodes`，确认目标节点标记为 SchedulingDisabled\n2. 执行 `kubectl describe node <node>`，确认自定义污点 `chaos-drill/unschedulable=true:NoSchedule` 存在\n3. 执行 `kubectl get daemonset`，确认 DESIRED 与 READY 数量不一致\n4. 确认目标节点上的 DaemonSet Pod 删除后无法被重建\n\n**注入恢复**：\n1. 使用 kubectl 取消节点不可调度标记（uncordon）：`kubectl uncordon <node>`\n2. 移除自定义污点：`kubectl taint nodes <node> chaos-drill/unschedulable=true:NoSchedule-`\n3. 等待 DaemonSet Pod 在该节点重建\n\n**恢复验证**：\n1. 执行 `kubectl get nodes`，确认目标节点恢复为可调度状态\n2. 执行 `kubectl describe node <node>`，确认自定义污点已被移除\n3. 执行 `kubectl get daemonset`，确认 DESIRED 与 READY 数量一致\n4. 确认目标节点上 DaemonSet Pod 已正常运行\n\n**注意事项**：\n- Kubernetes ≥ 1.12 的 DaemonSet 默认容忍 `node.kubernetes.io/unschedulable` 污点，因此 `kubectl cordon` 不会阻止 DaemonSet Pod 调度\n- 必须添加自定义污点（DaemonSet 未配置容忍的），才能有效阻止 Pod 调度\n- 恢复时需一并移除自定义污点，否则 Pod 仍无法调度\n\n**基准事实**：\n- **根因**：节点被标记为不可调度（cordon）且存在 DaemonSet 未容忍的自定义污点，导致 DaemonSet 无法在该节点创建 Pod，副本数小于期望数\n- **必现现象**：DaemonSet DESIRED 与 READY 不一致；节点 SchedulingDisabled；节点存在自定义污点；节点上缺少 DaemonSet Pod\n","isInternal":false,"tokens":815,"sizeBytes":2418},{"name":"DNS_解析失败_CoreDNS异常.md","path":"blade-ai/skills/k8s-chaos-skills/references/catalogue/DNS_解析失败/DNS_解析失败_CoreDNS异常.md","rawUrl":"https://raw.githubusercontent.com/chaosblade-io/chaosblade/HEAD/blade-ai/skills/k8s-chaos-skills/references/catalogue/DNS_解析失败/DNS_解析失败_CoreDNS异常.md","title":"DNS_解析失败 Skill","category":"anthropic-skill","format":"markdown","content":"**用例名称** CoreDNS异常 导致 DNS_解析失败\n\n**故障现象**：\n1. Pod 内 DNS 解析失败，应用报 `Name or service not known` 或 `NXDOMAIN` 错误\n2. CoreDNS Pod 异常（CrashLoopBackOff/不可用）\n3. 集群内服务间调用因 DNS 解析失败而中断\n\n**资源准备**：\n1. 确认应用 A 已正常运行，且依赖集群 DNS 进行服务发现\n2. 确认 CoreDNS Deployment 正常运行\n3. 确认监控系统可观测 DNS 请求指标\n\n**演练步骤**：\n1. 记录 CoreDNS Deployment 当前副本数和配置，并获取其 Pod 选择器标签：\n   ```bash\n   kubectl get deployment coredns -n kube-system -o jsonpath='{.spec.selector.matchLabels}'\n   ```\n   记录返回的标签（如 `component=coredns` 或 `k8s-app=kube-dns`），后续步骤中用 `<coredns-label>` 表示该标签\n2. 将 CoreDNS Deployment 的副本数缩为 0，模拟 CoreDNS 完全不可用：\n   ```bash\n   kubectl scale deployment coredns -n kube-system --replicas=0\n   ```\n3. 在应用 A 的 Pod 内尝试进行 DNS 解析\n4. 观察应用 A 的服务间调用行为\n\n**注入验证**：\n1. 执行 `kubectl get pods -n kube-system -l <coredns-label>`（使用演练步骤 1 中获取的实际标签），确认无 CoreDNS Pod 运行\n2. 在应用 A 的 Pod 内执行 DNS 解析测试：\n   ```bash\n   kubectl exec <pod-name> -- nslookup kubernetes.default.svc.cluster.local\n   ```\n   确认解析失败\n3. 确认应用 A 依赖 DNS 的服务调用出现错误\n\n**注入恢复**：\n1. 恢复 CoreDNS 副本数：\n   ```bash\n   kubectl scale deployment coredns -n kube-system --replicas=<原始副本数>\n   ```\n2. 等待 CoreDNS Pod 启动并就绪\n\n**恢复验证**：\n1. 执行 `kubectl get pods -n kube-system -l <coredns-label>`（使用演练步骤 1 中获取的实际标签），确认 CoreDNS Pod 全部 Running 且 Ready\n2. 在应用 A 的 Pod 内重新执行 DNS 解析，确认恢复正常\n3. 确认应用 A 的服务间调用恢复\n\n**基准事实**：\n- **根因**：CoreDNS Pod 异常或不可用，导致集群内 DNS 解析服务中断，依赖 DNS 的服务发现和调用全部失败\n- **必现现象**：Pod 内 DNS 解析超时或返回 NXDOMAIN；CoreDNS Pod 不可用；服务间调用失败\n","isInternal":false,"tokens":761,"sizeBytes":2221},{"name":"HPA_副本达到上限_资源饱和.md","path":"blade-ai/skills/k8s-chaos-skills/references/catalogue/HPA_副本达到上限/HPA_副本达到上限_资源饱和.md","rawUrl":"https://raw.githubusercontent.com/chaosblade-io/chaosblade/HEAD/blade-ai/skills/k8s-chaos-skills/references/catalogue/HPA_副本达到上限/HPA_副本达到上限_资源饱和.md","title":"HPA_副本达到上限 Skill","category":"anthropic-skill","format":"markdown","content":"**用例名称** 资源饱和 导致 HPA_副本达到上限\n\n**故障现象**：\n1. HPA 的当前副本数达到 maxReplicas 上限，无法继续扩容\n2. 应用 CPU 或内存使用率仍持续高于 HPA 目标阈值\n3. 应用响应延迟增大，出现超时\n\n**资源准备**：\n1. 确认应用 A 已正常运行，且已配置 HPA（设置合适的 maxReplicas 以便快速触发上限）\n2. 确认监控系统可观测 HPA 状态和 Pod CPU/内存指标\n\n**演练步骤**：\n1. 定位应用 A 的 HPA，记录 maxReplicas 配置\n2. 使用 chaosblade 对应用 A 的所有 Pod 注入 CPU 压力，持续超过 HPA 扩容阈值\n3. 观察 HPA 扩容行为，等待副本数达到 maxReplicas 上限\n\n**注入验证**：\n1. 执行 `kubectl get hpa`，确认 REPLICAS 已达到 MAXPODS 上限\n2. 查看 HPA Event，确认出现 `FailedGetScale` 或 `DesiredReplicas` 超过 maxReplicas 的告警\n3. 查看 Pod CPU 使用率，确认仍持续高于目标阈值\n4. 确认应用 A 的请求延迟增大，出现超时\n\n**注入恢复**：\n1. 销毁 chaosblade CPU 压力实验\n2. 等待 HPA 自动缩容\n\n**恢复验证**：\n1. 执行 `kubectl get hpa`，确认 REPLICAS 回落至正常水平\n2. 查看 Pod CPU 使用率，确认恢复到 HPA 目标阈值以下\n3. 确认应用 A 的请求延迟恢复正常\n\n**基准事实**：\n- **根因**：应用负载超过 HPA 的 maxReplicas 能覆盖的处理能力，HPA 达到扩容上限后无法继续扩容，导致服务资源饱和\n- **必现现象**：HPA REPLICAS 达到 MAXPODS；HPA Event 有超限告警；CPU 使用率持续超过目标阈值；应用性能下降\n","isInternal":false,"tokens":634,"sizeBytes":1616},{"name":"Node_CPU使用率过高_异常进程占用.md","path":"blade-ai/skills/k8s-chaos-skills/references/catalogue/Node_CPU使用率过高/Node_CPU使用率过高_异常进程占用.md","rawUrl":"https://raw.githubusercontent.com/chaosblade-io/chaosblade/HEAD/blade-ai/skills/k8s-chaos-skills/references/catalogue/Node_CPU使用率过高/Node_CPU使用率过高_异常进程占用.md","title":"Node_CPU使用率过高 Skill","category":"anthropic-skill","format":"markdown","content":"**用例名称** 异常进程占用 导致 Node_CPU使用率过高\n\n**故障现象**：\n1. 节点 CPU 使用率持续超过 90%\n2. 节点上 Pod 响应变慢，出现超时\n3. Load Average 显著升高\n\n**资源准备**：\n1. 确认应用 A 已正常运行\n2. 确认监控系统（如 Prometheus）已配置，可观测节点 CPU 指标\n\n**演练步骤**：\n1. 定位运行应用 A 的节点\n2. 使用 chaosblade 对该节点注入 CPU 满载，模拟异常进程占用节点 CPU\n3. 观察节点 CPU 使用率及 Pod 性能变化\n\n**注入验证**：\n1. 查看节点 CPU 使用率监控，确认持续超过 90%\n2. 查看 Load Average，确认显著升高\n3. 确认应用 A 的请求延迟增大\n\n**注入恢复**：\n1. 销毁 chaosblade 实验\n\n**恢复验证**：\n1. 查看节点 CPU 使用率监控，确认恢复到正常水平\n2. 确认应用 A 的请求延迟恢复正常\n\n**基准事实**：\n- **根因**：节点上存在异常进程大量占用 CPU，导致节点 CPU 使用率过高，影响同节点上所有 Pod 的性能\n- **必现现象**：节点 CPU 使用率持续超过 90%；Load Average 显著升高；同节点 Pod 响应变慢\n","isInternal":false,"tokens":430,"sizeBytes":1149},{"name":"Node_不可用_节点宕机.md","path":"blade-ai/skills/k8s-chaos-skills/references/catalogue/Node_不可用/Node_不可用_节点宕机.md","rawUrl":"https://raw.githubusercontent.com/chaosblade-io/chaosblade/HEAD/blade-ai/skills/k8s-chaos-skills/references/catalogue/Node_不可用/Node_不可用_节点宕机.md","title":"Node_不可用 Skill","category":"anthropic-skill","format":"markdown","content":"**用例名称** 节点宕机 导致 Node_不可用\n\n**故障现象**：\n1. 节点状态变为 NotReady\n2. 节点上所有 Pod 无法访问\n3. kubelet 停止上报节点状态，NodeStatus 中 LastHeartbeatTime 停止更新\n4. Pod 在其他节点上被重建\n\n**资源准备**：\n1. 确认应用 A 已正常运行，且有多个副本分布在不同节点\n2. 确认监控系统可观测节点状态和 Pod 状态\n\n**演练步骤**：\n1. 定位运行应用 A 的节点\n2. 使用 chaosblade 对该节点注入网络完全丢包（node-network drop 即全量丢包，不需要 --percent），并设置 `--timeout 600`（600 秒后自动恢复），模拟节点与集群失联的宕机场景\n3. 观察节点状态和 Pod 调度行为变化\n\n**注入验证**：\n1. 执行 `kubectl get nodes`，确认目标节点状态变为 NotReady\n2. 查看 NodeStatus，确认 LastHeartbeatTime 停止更新\n3. 确认节点上应用 A 的 Pod 在其他节点上被重建\n4. 确认应用 A 的服务整体仍可访问（多副本场景）\n\n**注入恢复**：\n1. 等待 chaosblade 实验自动超时恢复（600 秒内），agent 本地定时器会自动清理网络规则\n2. 如超时后仍未恢复，通过 `blade destroy <UID>` 或重启节点强制恢复\n\n**恢复验证**：\n1. 执行 `kubectl get nodes`，确认目标节点恢复 Ready\n2. 确认 LastHeartbeatTime 恢复更新\n3. 确认应用 A 的 Pod 恢复正常运行\n\n**基准事实**：\n- **根因**：节点网络完全中断，导致 kubelet 无法与 API server 通信，停止上报节点状态\n- **必现现象**：节点 NotReady；LastHeartbeatTime 停止更新；Pod 在其他节点被重建\n","isInternal":false,"tokens":577,"sizeBytes":1645},{"name":"Node_内存使用率过高_异常进程占用.md","path":"blade-ai/skills/k8s-chaos-skills/references/catalogue/Node_内存使用率过高/Node_内存使用率过高_异常进程占用.md","rawUrl":"https://raw.githubusercontent.com/chaosblade-io/chaosblade/HEAD/blade-ai/skills/k8s-chaos-skills/references/catalogue/Node_内存使用率过高/Node_内存使用率过高_异常进程占用.md","title":"Node_内存使用率过高 Skill","category":"anthropic-skill","format":"markdown","content":"**用例名称** 异常进程占用 导致 Node_内存使用率过高\n\n**故障现象**：\n1. 节点内存使用率持续超过 90%\n2. 节点上 Pod 出现 OOMKilled 或被驱逐\n3. 节点 Status 出现 MemoryPressure 条件为 True\n\n**资源准备**：\n1. 确认应用 A 已正常运行\n2. 确认监控系统（如 Prometheus）已配置，可观测节点内存指标\n\n**演练步骤**：\n1. 定位运行应用 A 的节点\n2. 使用 chaosblade 对该节点注入内存压力，模拟异常进程占用节点内存\n3. 观察节点内存使用率及 Pod 状态变化\n\n**注入验证**：\n1. 查看节点内存使用率监控，确认持续超过 90%\n2. 执行 `kubectl describe node <节点名>`，确认 MemoryPressure 条件为 True\n3. 确认应用 A 的 Pod 出现 OOMKilled 或被驱逐\n\n**注入恢复**：\n1. 销毁 chaosblade 实验\n\n**恢复验证**：\n1. 查看节点内存使用率监控，确认恢复到正常水平\n2. 执行 `kubectl describe node <节点名>`，确认 MemoryPressure 条件为 False\n3. 确认应用 A 的 Pod 恢复正常运行\n\n**基准事实**：\n- **根因**：节点上存在异常进程大量占用内存，导致节点内存使用率过高，触发 MemoryPressure，Pod 被 OOMKilled 或驱逐\n- **必现现象**：节点内存使用率持续超过 90%；MemoryPressure 条件为 True；Pod 出现 OOMKilled 或被驱逐\n","isInternal":false,"tokens":489,"sizeBytes":1357},{"name":"Node_磁盘IO过高_异常IO占用.md","path":"blade-ai/skills/k8s-chaos-skills/references/catalogue/Node_磁盘IO过高/Node_磁盘IO过高_异常IO占用.md","rawUrl":"https://raw.githubusercontent.com/chaosblade-io/chaosblade/HEAD/blade-ai/skills/k8s-chaos-skills/references/catalogue/Node_磁盘IO过高/Node_磁盘IO过高_异常IO占用.md","title":"Node_磁盘IO过高 Skill","category":"anthropic-skill","format":"markdown","content":"**用例名称** 异常IO占用 导致 Node_磁盘IO过高\n\n**故障现象**：\n1. 节点磁盘 IO 使用率持续过高（iostat 显示 %util 接近 100%）\n2. 节点上 Pod 的磁盘读写延迟增大，应用响应变慢\n3. iowait 占比升高\n\n**资源准备**：\n1. 确认应用 A 已正常运行\n2. 确认监控系统可观测节点磁盘 IO 指标\n\n**演练步骤**：\n1. 定位运行应用 A 的节点\n2. **路径校验（必须）**：注入前验证目标路径存在且可写：\n   - 通过 `kubectl exec <tool-pod> -n chaosblade -- ls -ld <磁盘路径>` 确认路径存在\n   - 如路径不存在，通过 `df -h` 查看可用挂载点，选择已存在的可写目录\n   - 常见可用路径：`/var/lib/containerd`、`/var/lib/docker`、`/tmp`、`/var/log`\n   - **禁止使用未校验的路径** — ChaosBlade 接受任意路径但底层 dd 进程会静默失败\n   - 不同路径可能对应不同的物理磁盘分区，注入前可通过 `df -h <路径>` 确认路径所在的设备\n3. 使用 chaosblade 对该节点注入磁盘 IO 负载：`blade create k8s node-disk burn --read --write --names <节点名> --path <已校验的磁盘路径> --timeout <秒> --kubeconfig <路径>`\n4. 观察节点磁盘 IO 指标及 Pod 性能变化\n\n**注入验证**：\n1. 查看节点磁盘 IO 负载指标：\n   - 优先：`iostat -xd 1 3`（关注 %util 接近 100%）\n   - BusyBox 备选：`iostat -d -k 1 3`（关注 tps 和 kB_wrtn/s/kB_read/s 异常升高）+ `iostat -c 1 3`（关注 %iowait 显著升高）\n   - 进程确认：`ps | grep dd` 确认 ChaosBlade 的 dd 压测进程在运行（若 dd 不存在，说明路径无效导致注入静默失败，需检查路径是否存在）\n   - **多磁盘注意**：`iostat` 显示节点上所有物理磁盘的 IO 指标。如果节点有多个磁盘（如 vda 用于 nodefs，vdb 用于 imagefs），需根据 `--path` 参数判断目标路径对应的物理磁盘，只关注该磁盘的指标变化\n2. 查看 iowait 占比，确认显著升高（`iostat -c` 或节点监控）\n3. 确认应用 A 的磁盘读写延迟增大（见下方 Pod 级验证方法）\n\n**Pod 级磁盘 IO 验证方法**：\n- 方法 1（推荐）：在目标节点上选一个 Running Pod，`kubectl exec <pod> -- dd if=/dev/zero of=/tmp/disk-io-test bs=1M count=100`，对比注入前后写入耗时\n- 方法 2：`kubectl exec <pod> -- df -h` 确认 Pod 所在容器的磁盘使用率（注意：显示的是 overlay 文件系统，非宿主机），`kubectl describe pod <pod>` 检查 Events 中是否有磁盘相关告警\n- 方法 3（容器无 dd 时）：`kubectl get events -n <ns> --field-selector involvedObject.name=<pod>` 观察是否有 IO 相关事件\n\n**注入恢复**：\n1. 销毁 chaosblade 实验\n\n**恢复验证**：\n1. 查看节点磁盘 IO 监控，确认 %util 恢复正常：\n   - 优先：`iostat -xd 1 3`\n   - BusyBox 备选：`iostat -d -k 1 3`（确认 tps/吞吐量回落）+ `iostat -c 1 3`（确认 %iowait 恢复基线）\n2. 确认 iowait 占比恢复正常\n3. 确认应用 A 的磁盘读写延迟恢复正常（使用 Pod 级验证方法中的 dd 写入测试，确认耗时恢复）\n\n**基准事实**：\n- **根因**：节点上存在异常进程大量占用磁盘 IO，导致磁盘 IO 使用率过高，影响同节点上所有 Pod 的磁盘读写性能\n- **必现现象**：节点磁盘 IO %util 接近 100%；iowait 占比升高；同节点 Pod 磁盘读写延迟增大\n\n**CRD 模式 overlay 文件系统关键说明**：\n- ChaosBlade K8s CRD 模式下，`node-disk burn --path /tmp` 的 dd 进程运行在 DaemonSet tool pod 内，\n  写入的是**容器 overlay 文件系统**（通常由 imagefs/vdb 支持），**而非宿主机 /tmp**（通常由 nodefs/vda3 支持）\n- **验证 burn 时不应该检查 /host/tmp/ 下的文件**：burn 产生的临时文件在 overlay 中，不会出现在宿主机路径\n- **df -h 对 burn 验证无效**：burn 产生的是 I/O 压力（临时文件会被自动清理），不会造成磁盘使用量持续增长。\n  用 df -h 验证 burn 可能导致误判为\"注入失败\"\n- **正确的 burn 验证方法**：通过 `/proc/diskstats` 两次采样（间隔 3-5 秒），计算写入吞吐量增量：\n  - 读取方法：`cat /proc/diskstats`，格式为 `major minor name reads reads_merged sectors_read ... sectors_written writes_merged sectors_written ...`\n  - 计算方式：delta(sectors_written) × 512 / 间隔秒数 / 1048576 = MB/s\n  - 判断标准：任何分区持续写入 >10MB/s 即表示 burn 在生效\n  - 注意跳过分区条目（如 vda1、vda3），只关注整盘设备（如 vda、vdb）\n- **fill 与 burn 的验证方法差异**：\n  - fill（空间填充）：df -h 是主要验证手段（填充产生持久数据，磁盘使用量增加）\n  - burn（IO 压力）：/proc/diskstats 是主要验证手段（burn 产生 IO 压力，不产生持久数据）\n","isInternal":false,"tokens":1861,"sizeBytes":4896},{"name":"Pod_ContainerCreating_CNI分配失败.md","path":"blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_ContainerCreating/Pod_ContainerCreating_CNI分配失败.md","rawUrl":"https://raw.githubusercontent.com/chaosblade-io/chaosblade/HEAD/blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_ContainerCreating/Pod_ContainerCreating_CNI分配失败.md","title":"Pod_ContainerCreating Skill","category":"anthropic-skill","format":"markdown","content":"**用例名称** CNI分配失败 导致 Pod_ContainerCreating\n\n**故障现象**：\n1. Pod 长时间停留在 ContainerCreating 状态\n2. Pod Events 中显示 `failed to allocate for ENI` 或 `no available IP in subnet` 或 CNI 相关错误\n3. 节点上的 IP 资源池耗尽或 ENI 数量达到上限\n\n**资源准备**：\n1. 确认应用 A 已正常运行\n2. 确认集群使用 ENI 或 vSwitch 分配 Pod IP 的 CNI 插件（如 Terway）\n\n**演练步骤**：\n1. 查看目标节点的 ENI 和 IP 分配情况，确认目标应用 Pod 所在节点（记为 `<目标节点>`）\n2. 给目标节点添加标签，并给应用 A 的 Deployment 添加 nodeSelector，确保新 Pod 只能调度到目标节点（防止调度器规避耗尽节点）：\n   ```bash\n   kubectl label node <目标节点> chaos-cni-target=true\n   kubectl patch deployment <deployment-name> -n <namespace> --type='merge' \\\n     -p='{\"spec\":{\"template\":{\"spec\":{\"nodeSelector\":{\"chaos-cni-target\":\"true\"}}}}}'\n   ```\n   等待 rollout 完成（Pod 仍在原节点运行，因为目标节点已有此标签）。\n   记录原始 nodeSelector 值，恢复时还原。\n3. 使用 `execute_skill_script` 在目标节点批量创建 Pod 耗尽 IP/ENI 资源（**`kubectl create/apply` 不可用，必须使用脚本**）：\n   ```\n   execute_skill_script(\n     skill_name=\"k8s-chaos-skills\",\n     script_name=\"inject_cni_exhaust.py\",\n     params=\"--namespace <namespace> --node <目标节点> --kubeconfig <kubeconfig路径>\"\n   )\n   ```\n   脚本会创建 `chaos-ip-exhaust` Deployment 并绑定到目标节点。\n4. 删除应用 A 在目标节点上的 Pod，触发重建。由于 nodeSelector 约束，新 Pod 只能调度到已耗尽的目标节点，将进入 ContainerCreating 状态\n5. 观察新 Pod 的 ContainerCreating 状态\n\n**注入验证**：\n1. 执行 `kubectl get pods`，确认应用 A 新 Pod 状态为 ContainerCreating\n2. 执行 `kubectl describe pod <pod-name>`，确认 Events 显示 CNI/IP 分配失败相关错误\n3. 查看节点 ENI/IP 使用情况，确认资源已耗尽\n\n**注入恢复**：\n1. 删除批量创建的 Deployment：`kubectl delete deployment chaos-ip-exhaust -n <namespace>`\n2. 移除应用 A 的 Deployment 上添加的 nodeSelector（还原为原始值，若原本无 nodeSelector 则移除整个 nodeSelector）\n3. 移除目标节点上添加的标签：`kubectl label node <目标节点> chaos-cni-target-`\n4. 等待 IP/ENI 资源释放和 Pod 滚动更新完成\n\n**恢复验证**：\n1. 执行 `kubectl get pods`，确认应用 A 的 Pod 状态恢复为 Running\n2. 确认节点 IP/ENI 资源恢复可用\n3. 确认应用 A 网络连通正常\n\n**基准事实**：\n- **根因**：节点可用 IP 池耗尽或 ENI 数量达到上限或 vSwitch IP 不足，CNI 插件无法为新 Pod 分配网络资源\n- **必现现象**：Pod ContainerCreating；Events 显示 CNI/IP/ENI 分配失败；节点网络资源耗尽\n","isInternal":false,"tokens":936,"sizeBytes":2917},{"name":"Pod_ContainerCreating_Volume挂载超时CSI异常.md","path":"blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_ContainerCreating/Pod_ContainerCreating_Volume挂载超时CSI异常.md","rawUrl":"https://raw.githubusercontent.com/chaosblade-io/chaosblade/HEAD/blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_ContainerCreating/Pod_ContainerCreating_Volume挂载超时CSI异常.md","title":"Pod_ContainerCreating Skill","category":"anthropic-skill","format":"markdown","content":"**用例名称** Volume挂载超时CSI异常 导致 Pod_ContainerCreating\n\n**故障现象**：\n1. Pod 长时间停留在 ContainerCreating 状态\n2. Pod Events 中显示 `FailedMount` 或 `FailedAttachVolume`，提示 CSI driver 超时或可用区不匹配\n3. PV 对应的云盘与 Pod 调度的节点不在同一可用区\n\n**资源准备**：\n1. 确认应用 A 已正常运行，且使用了 CSI 驱动管理的存储卷\n2. 确认集群跨多个可用区部署\n\n**演练步骤**：\n1. 记录 Deployment 当前 maxUnavailable 值，并临时设为 100%（确保滚动更新能完成，故障注入的新 Pod 不会 Ready，默认策略下 K8s 不会终止旧 Pod，导致滚动更新死锁）：\n   ```bash\n   kubectl get deployment <deployment-name> -n <namespace> \\\n     -o jsonpath='{.spec.strategy.rollingUpdate.maxUnavailable}'\n   kubectl patch deployment <deployment-name> -n <namespace> --type='json' \\\n     -p='[{\"op\":\"replace\",\"path\":\"/spec/strategy/rollingUpdate/maxUnavailable\",\"value\":\"100%\"}]'\n   ```\n2. 使用 `kubectl(subcommand=\"apply\", v_args=\"-f -\", stdin_data=\"...\")` 创建跨可用区的 PV 和 PVC（**必须使用 `stdin_data` 参数传入 YAML，不要用 exec heredoc 或其他方式**）：\n   PV YAML:\n   ```yaml\n   apiVersion: v1\n   kind: PersistentVolume\n   metadata:\n     name: chaos-az-mismatch-pv\n   spec:\n     capacity:\n       storage: 20Gi\n     accessModes: [\"ReadWriteOnce\"]\n     csi:\n       driver: diskplugin.csi.alibabacloud.com\n       volumeHandle: <其他可用区的云盘ID>\n     nodeAffinity:\n       required:\n         nodeSelectorTerms:\n         - matchExpressions:\n           - key: topology.kubernetes.io/zone\n             operator: In\n             values: [\"<其他可用区>\"]\n   ```\n   PVC YAML:\n   ```yaml\n   apiVersion: v1\n   kind: PersistentVolumeClaim\n   metadata:\n     name: chaos-csi-mismatch-pvc\n     namespace: <namespace>\n   spec:\n     accessModes: [\"ReadWriteOnce\"]\n     resources:\n       requests:\n         storage: 20Gi\n     volumeName: chaos-az-mismatch-pv\n   ```\n3. 修改应用 A 的 Deployment，添加引用该 PVC 的 volume，并确保 Pod 调度到不同可用区的节点\n4. 等待 Pod 滚动更新完成，确认所有旧 Pod 已被替换\n5. 滚动更新完成后，立即还原 maxUnavailable 为原始值（maxUnavailable 只是使滚动更新完成的手段，不是故障本身，不应泄漏到恢复阶段）\n6. 观察 Pod 的 ContainerCreating 状态\n\n**注入验证**：\n1. 执行 `kubectl rollout status deployment <deployment-name>`，确认滚动更新已完成（所有旧 Pod 已被替换）。如果滚动更新未完成（卡死），则故障未完全生效，不可判定为 verified\n2. 执行 `kubectl get pods`，确认**所有**目标 Pod 状态为 ContainerCreating（不是仅一个新 Pod，而是全部副本）\n3. 执行 `kubectl describe pod <pod-name>`，确认 Events 显示 FailedMount 或 CSI attach 超时\n4. 确认错误信息包含可用区不匹配或 CSI 异常相关描述\n\n**注入恢复**：\n1. 恢复应用 A 的 Deployment，移除注入时添加的 volumes 和 volumeMounts（两者都需移除，只移除其中一个会导致 Deployment 配置错误）\n2. 等待 Pod 滚动更新完成，确认 Pod 恢复 Running\n3. 清理测试 PVC：`kubectl delete pvc chaos-csi-mismatch-pvc -n <namespace>`\n4. 清理测试 PV：`kubectl delete pv chaos-az-mismatch-pv`\n\n**恢复验证**：\n1. 执行 `kubectl get pods`，确认 Pod 状态恢复为 Running\n2. 确认测试资源已清理\n3. 确认应用 A 存储功能正常\n\n**基准事实**：\n- **根因**：CSI 驱动异常或云盘与节点可用区不匹配，导致 Volume attach/mount 操作超时，Pod 无法完成存储卷挂载\n- **必现现象**：Pod ContainerCreating；Events 显示 FailedMount/FailedAttachVolume/CSI 超时；可用区不匹配\n","isInternal":false,"tokens":1180,"sizeBytes":3813},{"name":"Pod_ContainerCreating_云盘挂载超时或冲突.md","path":"blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_ContainerCreating/Pod_ContainerCreating_云盘挂载超时或冲突.md","rawUrl":"https://raw.githubusercontent.com/chaosblade-io/chaosblade/HEAD/blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_ContainerCreating/Pod_ContainerCreating_云盘挂载超时或冲突.md","title":"Pod_ContainerCreating Skill","category":"anthropic-skill","format":"markdown","content":"**用例名称** 云盘挂载超时或冲突 导致 Pod_ContainerCreating\n\n**故障现象**：\n1. Pod 长时间停留在 ContainerCreating 状态\n2. Pod Events 中显示 `Multi-Attach error` 或 `AttachVolume.Attach failed`\n3. 云盘被其他节点占用，无法 attach 到当前节点\n\n**资源准备**：\n1. 确认应用 A 已正常运行，且使用了云盘类型的 PVC（accessMode 为 ReadWriteOnce）\n2. 确认集群中有多个节点\n\n**演练步骤**：\n1. 定位应用 A 使用的 PVC 及其对应的 PV\n2. 在另一个节点上创建一个临时 Pod，强制挂载同一个 PVC（通过直接指定 PV 的 volumeHandle 创建新 PV/PVC 对），模拟 Multi-Attach 冲突：\n   ```yaml\n   apiVersion: v1\n   kind: Pod\n   metadata:\n     name: chaos-volume-holder\n     namespace: <namespace>\n   spec:\n     nodeName: <另一节点>\n     containers:\n     - name: holder\n       image: busybox\n       command: [\"sleep\", \"3600\"]\n       volumeMounts:\n       - name: data\n         mountPath: /data\n     volumes:\n     - name: data\n       persistentVolumeClaim:\n         claimName: <应用A的PVC名称>\n   ```\n3. 删除应用 A 原来的 Pod，触发在其他节点重建\n4. 观察新 Pod 的 ContainerCreating 状态\n\n**注入验证**：\n1. 执行 `kubectl get pods`，确认应用 A 的新 Pod 状态为 ContainerCreating\n2. 执行 `kubectl describe pod <pod-name>`，确认 Events 显示 Multi-Attach error 或 volume attach 失败\n3. 确认 PV 仍 attach 在占用它的节点上\n\n**注入恢复**：\n1. 删除临时 Pod：`kubectl delete pod chaos-volume-holder --force --grace-period=0`\n2. 等待云盘从原节点 detach\n3. 等待应用 A 的 Pod 自动完成 volume attach\n\n**恢复验证**：\n1. 执行 `kubectl get pods`，确认应用 A 的 Pod 状态恢复为 Running\n2. 确认 volume 成功 attach 并 mount\n3. 确认应用 A 数据读写正常\n\n**基准事实**：\n- **根因**：云盘（ReadWriteOnce）被其他节点/Pod 占用，新 Pod 无法 attach 该云盘，导致 volume mount 阶段阻塞\n- **必现现象**：Pod ContainerCreating；Events 显示 Multi-Attach error 或 AttachVolume 失败；PV 被其他节点占用\n","isInternal":false,"tokens":686,"sizeBytes":2146},{"name":"Pod_ContainerCreating_容器运行时异常.md","path":"blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_ContainerCreating/Pod_ContainerCreating_容器运行时异常.md","rawUrl":"https://raw.githubusercontent.com/chaosblade-io/chaosblade/HEAD/blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_ContainerCreating/Pod_ContainerCreating_容器运行时异常.md","title":"Pod_ContainerCreating Skill","category":"anthropic-skill","format":"markdown","content":"**用例名称** 容器运行时异常 导致 Pod_ContainerCreating\n\n**故障现象**：\n1. Pod 长时间停留在 ContainerCreating 状态\n2. Pod Events 中显示 `container runtime is not ready` 或 `rpc error` 相关错误\n3. 节点上的 containerd/docker 进程异常或 hang，无法响应容器创建请求\n\n**资源准备**：\n1. 确认应用 A 已正常运行\n2. 确认目标节点上有多个应用副本（避免单点影响）\n3. 确认监控系统可观测节点和容器运行时状态\n\n**演练步骤**：\n1. 定位应用 A 所在的目标节点\n2. 使用 chaosblade 挂起（stop）目标节点上的 containerd 进程，模拟容器运行时 hang：\n   ```bash\n   blade create k8s node-process stop \\\n     --names <节点名> \\\n     --process containerd \\\n     --timeout 120 \\\n     --kubeconfig <路径>\n   ```\n3. 删除应用 A 在目标节点上的 Pod，触发重建\n4. 观察新 Pod 的 ContainerCreating 状态\n\n**注入验证**：\n1. 执行 `kubectl get pods`，确认新 Pod 状态为 ContainerCreating\n2. 执行 `kubectl describe pod <pod-name>`，确认 Events 显示容器运行时相关错误\n3. 确认目标节点状态可能变为 NotReady（RuntimeNotReady condition）\n\n**注入恢复**：\n1. 等待 chaosblade 实验自动超时恢复（120 秒内），containerd 进程自动恢复\n2. 如超时后仍未恢复，通过 `blade destroy <UID>` 强制恢复\n3. 等待容器运行时恢复正常，Pod 自动完成创建\n\n**恢复验证**：\n1. 确认 containerd 进程恢复正常运行\n2. 执行 `kubectl get nodes`，确认目标节点恢复 Ready\n3. 执行 `kubectl get pods`，确认 Pod 状态恢复为 Running\n\n**基准事实**：\n- **根因**：容器运行时（containerd/docker）进程异常、hang 或状态不一致，无法响应 kubelet 的容器创建请求\n- **必现现象**：Pod ContainerCreating；Events 显示 runtime 相关 rpc error；节点可能 NotReady（RuntimeNotReady）\n","isInternal":false,"tokens":619,"sizeBytes":1933},{"name":"Pod_CPU_Throttling_limits.cpu过低.md","path":"blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_CPU_Throttling/Pod_CPU_Throttling_limits.cpu过低.md","rawUrl":"https://raw.githubusercontent.com/chaosblade-io/chaosblade/HEAD/blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_CPU_Throttling/Pod_CPU_Throttling_limits.cpu过低.md","title":"Pod_CPU_Throttling Skill","category":"anthropic-skill","format":"markdown","content":"**用例名称** limits.cpu过低 导致 Pod_CPU_Throttling\n\n**故障现象**：\n1. Pod 内进程频繁被内核 CPU 节流（throttle），`cpu.stat` 中 `nr_throttled` 持续增长\n2. 应用请求延迟显著增大，P99 延迟飙升\n3. `kubectl top pod` 显示 CPU 使用率接近 limits 但实际未满载\n\n**资源准备**：\n1. 确认应用 A 已正常运行，且 Pod 配置了 resources.limits.cpu\n2. 确认监控系统可观测 Pod CPU 使用率及 throttle 指标\n\n**演练步骤**：\n1. 定位应用 A 的 Deployment\n2. 使用 kubectl patch 将应用 A 的 CPU limits 调低为极小值（如 50m），模拟 limits.cpu 配置过低的场景\n3. 使用 chaosblade 对应用 A 的 Pod 注入 CPU 负载，确保实际 CPU 需求超过 limits，触发内核 throttle\n4. 观察 Pod CPU throttle 指标变化及应用响应延迟\n\n**注入验证**：\n1. 进入容器查看 `/sys/fs/cgroup/cpu/cpu.stat`，确认 `nr_throttled` 和 `throttled_time` 持续增长\n2. 查看监控指标，确认 Pod CPU 使用率接近 limits\n3. 确认应用 A 的请求延迟显著增大\n\n**注入恢复**：\n1. 销毁 chaosblade CPU 负载实验\n2. 使用 kubectl patch 将应用 A 的 CPU limits 恢复为原始合理值\n\n**恢复验证**：\n1. 查看 `cpu.stat`，确认 `nr_throttled` 停止增长\n2. 确认应用 A 的请求延迟恢复正常\n\n**基准事实**：\n- **根因**：容器 limits.cpu 设置过低，实际 CPU 需求超过 limit，内核对容器 CPU 时间片进行 throttle，导致应用性能下降\n- **必现现象**：cpu.stat 中 nr_throttled 持续增长；应用延迟飙升；CPU 使用率接近 limits 上限\n","isInternal":false,"tokens":612,"sizeBytes":1625},{"name":"Pod_cpu使用率过高_应用性能问题.md","path":"blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_cpu使用率过高/Pod_cpu使用率过高_应用性能问题.md","rawUrl":"https://raw.githubusercontent.com/chaosblade-io/chaosblade/HEAD/blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_cpu使用率过高/Pod_cpu使用率过高_应用性能问题.md","title":"Pod_cpu使用率过高 Skill","category":"anthropic-skill","format":"markdown","content":"**用例名称** 应用性能问题 导致 Pod_CPU使用率过高\n\n**故障现象**：\n1. Pod 的 CPU 使用率持续超过阈值\n2. CPU 使用率过高影响其他服务\n3. 应用响应变慢或发生超时\n\n**资源准备**：\n1. 确认应用 A/B 已正常运行\n2. 确认监控系统（如 Prometheus）已配置，可观测 Pod CPU 指标\n\n**演练步骤**：\n1. 定位应用 A 的 Pod 作为故障注入目标\n2. 使用 chaosblade 对目标 Pod 注入 CPU 压力（模拟死循环或高并发计算场景）\n3. 观察 Pod CPU 使用率变化\n\n**注入验证**：\n1. 查看 Pod CPU 使用率监控，确认持续高于阈值\n2. 进入容器查看 CPU 占用进程\n3. 通过 APM 工具分析 CPU 占用情况，定位问题代码\n4. 确认应用 A 对其他服务的调用出现延迟或超时\n\n**注入恢复**：\n1. 销毁 chaosblade CPU 压力实验\n2. 如 Pod 仍异常，可删除 Pod 触发重建\n\n**恢复验证**：\n1. 查看 Pod CPU 使用率监控，确认恢复到正常水平\n2. 确认应用 A 对其他服务的调用恢复正常\n\n**基准事实**：\n- **根因**：应用存在死循环、高并发计算或资源泄漏等性能问题，导致 CPU 使用率持续过高\n- **必现现象**：Pod CPU 使用率持续超过阈值，应用响应变慢或超时\n---\n","isInternal":false,"tokens":483,"sizeBytes":1278},{"name":"Pod_CrashLoopBackOff_LivenessProbe配置不合理.md","path":"blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_CrashLoopBackOff/Pod_CrashLoopBackOff_LivenessProbe配置不合理.md","rawUrl":"https://raw.githubusercontent.com/chaosblade-io/chaosblade/HEAD/blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_CrashLoopBackOff/Pod_CrashLoopBackOff_LivenessProbe配置不合理.md","title":"Pod_CrashLoopBackOff Skill","category":"anthropic-skill","format":"markdown","content":"**用例名称** LivenessProbe配置不合理 导致 Pod_CrashLoopBackOff\n\n**故障现象**：\n1. Pod 反复重启，状态为 CrashLoopBackOff\n2. Pod Events 中显示 `Liveness probe failed` 后容器被杀\n3. 容器本身运行正常，但 Liveness Probe 配置参数不合理导致误判\n\n**RCA症状**：\n1. Pod 反复重启，状态为 CrashLoopBackOff\n2. Pod Events 中显示 `Liveness probe failed`，容器被反复杀死\n3. 容器日志无应用异常退出记录\n（以上为kubectl直接可观测的现象，不包含诊断结论）\n\n**资源准备**：\n1. 确认应用 A 已正常运行\n2. 确认应用 A 有健康检查接口\n\n**演练步骤**：\n1. 记录应用 A 当前的 livenessProbe 配置\n2. 记录 Deployment 当前 maxUnavailable 值，并临时设为 100%（确保滚动更新能完成，故障注入的新 Pod 不会 Ready，默认策略下 K8s 不会终止旧 Pod，导致滚动更新死锁）：\n   ```bash\n   kubectl get deployment <deployment-name> -n <namespace> \\\n     -o jsonpath='{.spec.strategy.rollingUpdate.maxUnavailable}'\n   kubectl patch deployment <deployment-name> -n <namespace> --type='json' \\\n     -p='[{\"op\":\"replace\",\"path\":\"/spec/strategy/rollingUpdate/maxUnavailable\",\"value\":\"100%\"}]'\n   ```\n3. 修改应用 A 的 Deployment，设置不合理的 livenessProbe 参数：\n   ```yaml\n   livenessProbe:\n     httpGet:\n       path: /healthz\n       port: 8080\n     initialDelaySeconds: 1\n     timeoutSeconds: 1\n     periodSeconds: 2\n     failureThreshold: 1\n   ```\n   （initialDelaySeconds 过短，应用未完成初始化；timeoutSeconds 过短，正常响应来不及返回；failureThreshold 为 1，无容错空间）\n4. 等待 Pod 滚动更新完成，确认所有旧 Pod 已被替换\n5. 滚动更新完成后，立即还原 maxUnavailable 为原始值（maxUnavailable 只是使滚动更新完成的手段，不是故障本身，不应泄漏到恢复阶段）\n6. 观察 Pod 重启行为\n\n**注入验证**：\n1. 执行 `kubectl rollout status deployment <deployment-name>`，确认滚动更新已完成（所有旧 Pod 已被替换）。如果滚动更新未完成（卡死），则故障未完全生效，不可判定为 verified\n2. 执行 `kubectl get pods`，确认**所有**目标 Pod 的 RESTARTS 数持续增长，状态为 CrashLoopBackOff（不是仅一个新 Pod，而是全部副本）\n3. 执行 `kubectl describe pod <pod-name>`，确认 Events 显示 `Liveness probe failed` 和 `Container will be killed`\n4. 查看容器日志，确认应用本身无异常退出（非应用 bug）\n\n**注入恢复**：\n1. 恢复应用 A 的 Deployment，将 livenessProbe 参数恢复为原始合理值（若原本无 livenessProbe，则移除）\n3. 等待 Pod 滚动更新完成\n\n**恢复验证**：\n1. 执行 `kubectl get pods`，确认 Pod 状态为 Running 且不再重启\n2. 确认 Liveness Probe 检查正常通过\n3. 确认应用 A 服务正常\n\n**基准事实**：\n- **根因**：Liveness Probe 的 initialDelaySeconds/timeoutSeconds/failureThreshold 配置不合理，导致健康检查在应用正常运行时误判为失败，kubelet 反复杀死并重启容器\n- **必现现象**：Pod CrashLoopBackOff；RESTARTS 持续增长；Events 显示 Liveness probe failed；容器日志无异常\n","isInternal":false,"tokens":1054,"sizeBytes":3247},{"name":"Pod_CrashLoopBackOff_StartupProbe配置不足.md","path":"blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_CrashLoopBackOff/Pod_CrashLoopBackOff_StartupProbe配置不足.md","rawUrl":"https://raw.githubusercontent.com/chaosblade-io/chaosblade/HEAD/blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_CrashLoopBackOff/Pod_CrashLoopBackOff_StartupProbe配置不足.md","title":"Pod_CrashLoopBackOff Skill","category":"anthropic-skill","format":"markdown","content":"**用例名称** StartupProbe配置不足 导致 Pod_CrashLoopBackOff\n\n**故障现象**：\n1. Pod 反复重启，状态为 CrashLoopBackOff\n2. Pod Events 中显示 `Startup probe failed` 后容器被杀\n3. 慢启动应用尚未完成初始化就被 StartupProbe 判定为失败\n\n**资源准备**：\n1. 确认应用 A 已正常运行（应用启动时间较长，如 Java 应用）\n2. 确认应用 A 启动过程中健康检查接口不可用\n\n**演练步骤**：\n1. 记录应用 A 当前的探针配置\n2. 记录 Deployment 当前 maxUnavailable 值，并临时设为 100%（确保滚动更新能完成，故障注入的新 Pod 不会 Ready，默认策略下 K8s 不会终止旧 Pod，导致滚动更新死锁）：\n   ```bash\n   kubectl get deployment <deployment-name> -n <namespace> \\\n     -o jsonpath='{.spec.strategy.rollingUpdate.maxUnavailable}'\n   kubectl patch deployment <deployment-name> -n <namespace> --type='json' \\\n     -p='[{\"op\":\"replace\",\"path\":\"/spec/strategy/rollingUpdate/maxUnavailable\",\"value\":\"100%\"}]'\n   ```\n3. 修改应用 A 的 Deployment，添加或修改 startupProbe 使其窗口不足以覆盖应用启动时间：\n   ```yaml\n   startupProbe:\n     httpGet:\n       path: /healthz\n       port: 8080\n     failureThreshold: 3\n     periodSeconds: 5\n   ```\n   （总等待时间 = failureThreshold × periodSeconds = 15 秒，远小于应用实际启动时间）\n4. 同时确保 livenessProbe 存在，使得 startupProbe 失败后触发容器重启\n5. 等待 Pod 滚动更新完成，确认所有旧 Pod 已被替换\n6. 滚动更新完成后，立即还原 maxUnavailable 为原始值（maxUnavailable 只是使滚动更新完成的手段，不是故障本身，不应泄漏到恢复阶段）\n7. 观察 Pod 启动行为\n\n**注入验证**：\n1. 执行 `kubectl rollout status deployment <deployment-name>`，确认滚动更新已完成（所有旧 Pod 已被替换）。如果滚动更新未完成（卡死），则故障未完全生效，不可判定为 verified\n2. 执行 `kubectl get pods`，确认**所有**目标 Pod 的 RESTARTS 持续增长，状态为 CrashLoopBackOff（不是仅一个新 Pod，而是全部副本）\n3. 执行 `kubectl describe pod <pod-name>`，确认 Events 显示 `Startup probe failed`\n4. 查看容器日志，确认应用正在启动但未完成初始化就被杀\n\n**注入恢复**：\n1. 恢复应用 A 的 Deployment，增大 startupProbe 的窗口时间（若原本无 startupProbe，则移除）\n2. 等待 Pod 滚动更新完成\n\n**恢复验证**：\n1. 执行 `kubectl get pods`，确认 Pod 状态为 Running 且不再重启\n2. 确认 StartupProbe 和 LivenessProbe 检查均正常通过\n3. 确认应用 A 完成初始化并正常服务\n\n**基准事实**：\n- **根因**：StartupProbe 未配置或 failureThreshold × periodSeconds 总窗口不足以覆盖应用启动时间，慢启动应用在初始化完成前被判定为启动失败，反复被杀重启\n- **必现现象**：Pod CrashLoopBackOff；Events 显示 Startup probe failed；容器日志显示应用启动中被中断\n","isInternal":false,"tokens":988,"sizeBytes":3045},{"name":"Pod_OOM内存异常_limit单位写错.md","path":"blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_OOM内存异常/Pod_OOM内存异常_limit单位写错.md","rawUrl":"https://raw.githubusercontent.com/chaosblade-io/chaosblade/HEAD/blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_OOM内存异常/Pod_OOM内存异常_limit单位写错.md","title":"Pod_OOM内存异常 Skill","category":"anthropic-skill","format":"markdown","content":"**用例名称** limit单位写错 导致 Pod_OOM内存异常\n\n**故障现象**：\n1. Pod 启动后立即异常退出，状态为 CrashLoopBackOff\n2. Pod 的 lastState 显示 reason: OOMKilled 或 StartError（cgroup v2 环境下容器可能因内存配置过小无法启动）\n3. 容器 memory limit 值极小（如 100m = 0.1 字节），应用启动即超限或无法启动\n\n**资源准备**：\n1. 确认应用 A 已正常运行\n2. 确认应用 A 的正常内存使用量（如 200Mi 以上）\n\n**演练步骤**：\n1. 记录应用 A 当前的 resources.limits.memory 配置\n2. 记录 Deployment 当前 maxUnavailable 值，并临时设为 100%（确保滚动更新能完成，故障注入的新 Pod 不会 Ready，默认策略下 K8s 不会终止旧 Pod，导致滚动更新死锁）：\n   ```bash\n   kubectl get deployment <deployment-name> -n <namespace> \\\n     -o jsonpath='{.spec.strategy.rollingUpdate.maxUnavailable}'\n   kubectl patch deployment <deployment-name> -n <namespace> --type='json' \\\n     -p='[{\"op\":\"replace\",\"path\":\"/spec/strategy/rollingUpdate/maxUnavailable\",\"value\":\"100%\"}]'\n   ```\n3. 修改应用 A 的 Deployment，将 memory limit 单位写错：\n   ```yaml\n   resources:\n     limits:\n       memory: \"100m\"    # 错误！100m = 0.1 字节（milli），应为 100Mi\n     requests:\n       memory: \"100m\"\n   ```\n   注意：在 Kubernetes 中，`m` 表示 milli（千分之一），`100m` = 0.1 字节；正确应为 `Mi`（Mebibyte）\n4. 等待 Pod 滚动更新完成，确认所有旧 Pod 已被替换\n5. 滚动更新完成后，立即还原 maxUnavailable 为原始值（maxUnavailable 只是使滚动更新完成的手段，不是故障本身，不应泄漏到恢复阶段）\n6. 观察 Pod 启动行为\n\n**注入验证**：\n1. 执行 `kubectl rollout status deployment <deployment-name>`，确认滚动更新已完成（所有旧 Pod 已被替换）。如果滚动更新未完成（卡死），则故障未完全生效，不可判定为 verified\n2. 执行 `kubectl get pods`，确认**所有**目标 Pod 状态为 CrashLoopBackOff，RESTARTS 持续增长（不是仅一个新 Pod，而是全部副本）\n3. 执行 `kubectl get pod <pod-name> -o jsonpath='{.status.containerStatuses[0].lastState}'`，确认 reason 为 OOMKilled 或 StartError（cgroup v2 环境下极小 limit 可能导致容器无法启动而非 OOMKill）\n4. 执行 `kubectl describe pod <pod-name>`，确认 limits.memory 为极小值\n5. 确认容器启动后立即异常退出（运行时间极短或无法启动）\n\n**注入恢复**：\n1. 恢复应用 A 的 Deployment，将 memory limit 修正为正确单位（如 `256Mi`）\n3. 等待 Pod 滚动更新完成\n\n**恢复验证**：\n1. 执行 `kubectl get pods`，确认 Pod 状态为 Running 且不再重启\n2. 确认容器正常运行，内存使用率在合理范围\n3. 确认应用 A 服务正常\n\n**基准事实**：\n- **根因**：memory limit 单位写错（如 `100m` 而非 `100Mi`），导致 limit 值极小，容器启动后内存使用立即超过 limit 被 OOMKill，或在 cgroup v2 环境下因内存配置过小无法启动\n- **必现现象**：Pod 异常退出（OOMKilled 或 StartError）；CrashLoopBackOff；limits.memory 值不合理（如 100m）；容器运行时间极短或无法启动\n","isInternal":false,"tokens":1102,"sizeBytes":3263},{"name":"Pod_OOM内存异常_内存压力过大.md","path":"blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_OOM内存异常/Pod_OOM内存异常_内存压力过大.md","rawUrl":"https://raw.githubusercontent.com/chaosblade-io/chaosblade/HEAD/blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_OOM内存异常/Pod_OOM内存异常_内存压力过大.md","title":"Pod_OOM内存异常 Skill","category":"anthropic-skill","format":"markdown","content":"**用例名称** 内存压力过大 导致 Pod_OOM内存异常\n\n**故障现象**：\n1. Pod 内存使用率接近 Limit 上限\n2. 应用响应变慢，出现延迟\n3. 存在被 OOMKill 的风险\n\n**资源准备**：\n1. 确认应用 A 已正常运行\n2. 确认应用 A 的 Pod 已配置 resources.limits.memory\n\n**演练步骤**：\n1. 定位应用 A 的 Pod\n2. 使用 chaosblade 对应用 A 的 Pod 注入内存压力，模拟内存占用增长接近 Limit 的场景\n3. 观察 Pod 内存使用率变化\n\n**注入验证**：\n1. 查看监控指标，确认 Pod 内存使用率接近 Limit 上限\n2. 查看 Pod Event，确认存在内存相关告警\n3. 确认应用 A 的响应延迟增大\n\n**注入恢复**：\n1. 销毁 chaosblade 内存压力注入实验\n\n**恢复验证**：\n1. 查看监控指标，确认 Pod 内存使用率恢复正常\n2. 确认应用性能恢复正常\n\n**基准事实**：\n- **根因**：应用内存使用增长或注入内存压力，导致 Pod 内存使用率接近 Limit，存在被 OOMKill 的风险\n- **必现现象**：Pod 内存使用率接近 Limit；应用响应变慢；存在 OOMKill 风险\n","isInternal":false,"tokens":430,"sizeBytes":1121},{"name":"Pod_Pending_PVC未绑定.md","path":"blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_Pending/Pod_Pending_PVC未绑定.md","rawUrl":"https://raw.githubusercontent.com/chaosblade-io/chaosblade/HEAD/blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_Pending/Pod_Pending_PVC未绑定.md","title":"Pod_Pending Skill","category":"anthropic-skill","format":"markdown","content":"**用例名称** PVC未绑定 导致 Pod_Pending\n\n**故障现象**：\n1. Pod 状态为 Pending，无法启动\n2. Pod Events 中显示 `pod has unbound immediate PersistentVolumeClaims`\n3. PVC 状态为 Pending，无法绑定到 PV\n\n**资源准备**：\n1. 确认应用 A 已正常运行\n2. 确认集群中 StorageClass 和 CSI 插件正常工作\n\n**演练步骤**（注意：本用例需要临时修改 Deployment 添加 volume 引用，这是故障注入的必要操作，不违反安全红线。目标应用无需预先配置 PVC——注入的目的就是添加一个无法绑定的 PVC 依赖。恢复步骤会还原所有修改）：\n1. 记录 Deployment 当前 maxUnavailable 值，并临时设为 100%（确保滚动更新能完成，故障注入的新 Pod 不会 Ready，默认策略下 K8s 不会终止旧 Pod，导致滚动更新死锁）：\n   ```bash\n   kubectl get deployment <deployment-name> -n <namespace> \\\n     -o jsonpath='{.spec.strategy.rollingUpdate.maxUnavailable}'\n   kubectl patch deployment <deployment-name> -n <namespace> --type='json' \\\n     -p='[{\"op\":\"replace\",\"path\":\"/spec/strategy/rollingUpdate/maxUnavailable\",\"value\":\"100%\"}]'\n   ```\n2. 使用 `kubectl apply -f` 创建一个引用不存在的 StorageClass 的 PVC（通过 `stdin_data` 传入 YAML）：\n   ```yaml\n   apiVersion: v1\n   kind: PersistentVolumeClaim\n   metadata:\n     name: chaos-test-pvc\n     namespace: <namespace>\n   spec:\n     accessModes: [\"ReadWriteOnce\"]\n     storageClassName: \"non-existent-sc\"\n     resources:\n       requests:\n         storage: 10Gi\n   ```\n3. 使用 `kubectl patch` 修改应用 A 的 Deployment，添加引用该 PVC 的 volume 和 volumeMount\n4. 等待 Pod 滚动更新完成，确认所有旧 Pod 已被替换\n5. 滚动更新完成后，立即还原 maxUnavailable 为原始值（maxUnavailable 只是使滚动更新完成的手段，不是故障本身，不应泄漏到恢复阶段）\n6. 观察新 Pod 的状态\n\n**注入验证**：\n1. 执行 `kubectl rollout status deployment <deployment-name>`，确认滚动更新已完成（所有旧 Pod 已被替换）。如果滚动更新未完成（卡死），则故障未完全生效，不可判定为 verified\n2. 执行 `kubectl get pvc`，确认 PVC 状态为 Pending\n3. 执行 `kubectl get pods`，确认**所有**目标 Pod 状态为 Pending（不是仅一个新 Pod，而是全部副本）\n4. 执行 `kubectl describe pod <pod-name>`，确认 Events 显示 unbound PVC 相关信息\n5. 执行 `kubectl describe pvc chaos-test-pvc`，确认 StorageClass 不存在或 Provisioner 异常\n\n**注入恢复**：\n1. 恢复应用 A 的 Deployment 定义，移除引用 chaos-test-pvc 的 volume\n2. 删除测试用 PVC：`kubectl delete pvc chaos-test-pvc`\n3. 等待 Pod 滚动更新完成\n\n**恢复验证**：\n1. 执行 `kubectl get pods`，确认 Pod 状态恢复为 Running\n2. 确认测试 PVC 已被清理\n\n**基准事实**：\n- **根因**：Pod 引用的 PVC 无法绑定，原因为 StorageClass 不存在或 Provisioner 异常，导致 Pod 无法挂载所需存储卷而 Pending\n- **必现现象**：Pod Pending；PVC Pending；Events 显示 unbound PersistentVolumeClaims\n","isInternal":false,"tokens":969,"sizeBytes":3149},{"name":"Pod_Pending_拓扑约束过严.md","path":"blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_Pending/Pod_Pending_拓扑约束过严.md","rawUrl":"https://raw.githubusercontent.com/chaosblade-io/chaosblade/HEAD/blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_Pending/Pod_Pending_拓扑约束过严.md","title":"Pod_Pending Skill","category":"anthropic-skill","format":"markdown","content":"**用例名称** 拓扑约束过严 导致 Pod_Pending\n\n**故障现象**：\n1. Pod 状态为 Pending，无法被调度\n2. Pod Events 中显示 `didn't match pod topology spread constraints` 或 `didn't match pod anti-affinity rules`\n3. 由于拓扑分布约束或反亲和规则过严，调度器无法找到满足条件的节点\n\n**资源准备**：\n1. 确认应用 A 已正常运行\n2. 确认集群节点数量有限（便于触发约束冲突）\n\n**演练步骤**：\n1. 记录 Deployment 当前 maxUnavailable 值，并临时设为 100%（确保滚动更新能完成，故障注入的新 Pod 不会 Ready，默认策略下 K8s 不会终止旧 Pod，导致滚动更新死锁）：\n   ```bash\n   kubectl get deployment <deployment-name> -n <namespace> \\\n     -o jsonpath='{.spec.strategy.rollingUpdate.maxUnavailable}'\n   kubectl patch deployment <deployment-name> -n <namespace> --type='json' \\\n     -p='[{\"op\":\"replace\",\"path\":\"/spec/strategy/rollingUpdate/maxUnavailable\",\"value\":\"100%\"}]'\n   ```\n2. 修改应用 A 的 Deployment，添加过严的拓扑约束：\n   ```yaml\n   topologySpreadConstraints:\n   - maxSkew: 1\n     topologyKey: kubernetes.io/hostname\n     whenUnsatisfiable: DoNotSchedule\n     labelSelector:\n       matchLabels:\n         app: <app-name>\n   ```\n   或添加过严的反亲和规则：\n   ```yaml\n   affinity:\n     podAntiAffinity:\n       requiredDuringSchedulingIgnoredDuringExecution:\n       - labelSelector:\n           matchLabels:\n             app: <app-name>\n         topologyKey: kubernetes.io/hostname\n   ```\n3. 等待 Pod 滚动更新完成，确认所有旧 Pod 已被替换\n4. 滚动更新完成后，立即还原 maxUnavailable 为原始值（maxUnavailable 只是使滚动更新完成的手段，不是故障本身，不应泄漏到恢复阶段）\n5. 将应用 A 的副本数扩大到超过集群节点数\n6. 观察无法调度的 Pod 状态\n\n**注入验证**：\n1. 执行 `kubectl rollout status deployment <deployment-name>`，确认滚动更新已完成（所有旧 Pod 已被替换）。如果滚动更新未完成（卡死），则故障未完全生效，不可判定为 verified\n2. 执行 `kubectl get pods`，确认部分或全部 Pod 状态为 Pending\n3. 执行 `kubectl describe pod <pending-pod>`，确认 Events 显示拓扑约束或反亲和相关的调度失败原因\n\n**注入恢复**：\n1. 恢复应用 A 的 Deployment 定义，移除或放宽拓扑约束/反亲和规则\n2. 将副本数恢复为原始值\n3. 等待 Pod 滚动更新完成\n\n**恢复验证**：\n1. 执行 `kubectl get pods`，确认所有 Pod 状态为 Running\n2. 确认副本数恢复正常\n\n**基准事实**：\n- **根因**：topologySpreadConstraints 或 podAntiAffinity 配置过严，当副本数超过可用拓扑域时，调度器无法满足约束条件\n- **必现现象**：部分 Pod Pending；Events 显示拓扑约束或反亲和规则不满足；已调度 Pod 严格按约束分布\n","isInternal":false,"tokens":953,"sizeBytes":2917},{"name":"Pod_Pending_节点Taint无对应Toleration.md","path":"blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_Pending/Pod_Pending_节点Taint无对应Toleration.md","rawUrl":"https://raw.githubusercontent.com/chaosblade-io/chaosblade/HEAD/blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_Pending/Pod_Pending_节点Taint无对应Toleration.md","title":"Pod_Pending Skill","category":"anthropic-skill","format":"markdown","content":"**用例名称** 节点Taint无对应Toleration 导致 Pod_Pending\n\n**故障现象**：\n1. Pod 状态为 Pending，无法被调度到任何节点\n2. Pod Events 中显示 `N node(s) had untolerated taint {chaos-test: true}`\n3. 目标 Pod 可调度的所有节点均带有 Pod 无法容忍的污点\n\n**RCA症状**：\n1. Pod 状态为 Pending，无法被调度到任何节点\n2. Pod Events 中显示 `had untolerated taint`\n（以上为kubectl直接可观测的现象，不包含诊断结论）\n\n**资源准备**：\n1. 确认应用 A 已正常运行\n2. 确认集群中有多个可调度节点\n3. 记录应用 A 的 Pod 当前运行在哪些节点上（这些节点即为\"目标节点\"）\n\n**演练步骤**：\n\n> **爆炸半径控制**：本用例仅 taint 目标 Pod 所在的节点（而非全部集群节点），\n> 通过 nodeSelector 约束目标 Pod 只能调度到这些节点，从而在保证故障复现的同时\n> 避免影响集群中其他工作负载的调度。\n\n1. 记录目标节点的当前 taint 信息，以及 Deployment 的当前 nodeSelector（用于恢复）\n2. 记录 Deployment 当前 maxUnavailable 值，并临时设为 100%（确保滚动更新能完成，故障注入的新 Pod 不会 Ready，默认策略下 K8s 不会终止旧 Pod，导致滚动更新死锁）：\n   ```bash\n   kubectl get deployment <deployment-name> -n <namespace> \\\n     -o jsonpath='{.spec.strategy.rollingUpdate.maxUnavailable}'\n   kubectl patch deployment <deployment-name> -n <namespace> --type='json' \\\n     -p='[{\"op\":\"replace\",\"path\":\"/spec/strategy/rollingUpdate/maxUnavailable\",\"value\":\"100%\"}]'\n   ```\n3. 给目标节点添加标签：`kubectl label node <node> chaos-target=<app-name>`（仅目标 Pod 所在节点）\n4. 给应用 A 的 Deployment 添加 nodeSelector，约束 Pod 只能调度到目标节点：\n   `kubectl patch deployment <name> -n <ns> -p '{\"spec\":{\"template\":{\"spec\":{\"nodeSelector\":{\"chaos-target\":\"<app-name>\"}}}}}'`\n5. 等待 rollout 完成（Pod 仍在原节点上运行，因为只有目标节点有此标签）\n6. 滚动更新完成后，立即还原 maxUnavailable 为原始值（maxUnavailable 只是使滚动更新完成的手段，不是故障本身，不应泄漏到恢复阶段）\n7. 给目标节点添加污点：`kubectl taint node <node> chaos-test=true:NoSchedule`（仅目标节点）\n8. 删除应用 A 的一个 Pod，触发重建调度\n9. 观察新 Pod 的调度状态\n\n**注入验证**：\n1. 执行 `kubectl get pods`，确认新 Pod 状态为 Pending\n2. 执行 `kubectl describe pod <pod-name>`，确认 Events 中显示 `had untolerated taint {chaos-test: true}`\n3. 确认目标节点均有 chaos-test taint\n\n**注入恢复**：\n1. 移除目标节点上添加的污点：`kubectl taint node <node> chaos-test=true:NoSchedule-`\n2. 移除 Deployment 的 nodeSelector 中添加的 chaos-target 键（若原 Deployment 无 nodeSelector，则移除整个 nodeSelector）\n3. 移除目标节点上添加的标签：`kubectl label node <node> chaos-target-`\n4. 等待 Pod 滚动更新完成\n\n**恢复验证**：\n1. 执行 `kubectl get pods`，确认 Pod 状态变为 Running\n2. 确认目标节点 taint 已恢复到演练前状态\n3. 确认 Deployment spec 已恢复到演练前状态\n\n**基准事实**：\n- **根因**：目标 Pod 可调度的所有节点被标记了 Taint，而 Pod 未配置对应的 Toleration，导致调度器无法找到合适节点\n- **必现现象**：Pod Pending；Events 显示 untolerated taint；目标节点带有不可容忍的污点\n","isInternal":false,"tokens":1150,"sizeBytes":3510},{"name":"Pod_Terminating_Finalizers未清理.md","path":"blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_Terminating/Pod_Terminating_Finalizers未清理.md","rawUrl":"https://raw.githubusercontent.com/chaosblade-io/chaosblade/HEAD/blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_Terminating/Pod_Terminating_Finalizers未清理.md","title":"Pod_Terminating Skill","category":"anthropic-skill","format":"markdown","content":"**用例名称** Finalizers未清理 导致 Pod_Terminating\n\n**故障现象**：\n1. Pod 无法完成删除，`metadata.deletionTimestamp` 已设置但 Pod 对象仍存在于 API 中\n2. Pod 的 metadata 中存在 finalizers 字段，等待外部控制器清理\n3. kubectl 显示状态可能是 `Terminating`（容器仍在运行时）或 `Error`/`Failed`（容器已退出时）\n\n> **注意**：\"Terminating\" 是 kubectl 的显示状态，仅当 `deletionTimestamp` 已设置\n> 且容器仍在运行时才显示。如果容器在 delete 信号后已退出，kubectl 会按容器状态\n> 显示（如 Error/Completed），但 Pod 对象仍因 finalizer 滞留在 API 中。\n> 判定依据是 `deletionTimestamp` + `finalizers` 同时存在，而非 kubectl 显示状态。\n\n**RCA症状**：\n1. `kubectl get pod` 显示 Pod 状态为 Terminating 或 Error/Failed，但 Pod 对象持续存在\n2. `kubectl get pod -o jsonpath='{.metadata.deletionTimestamp}'` 返回非空时间戳\n3. `kubectl get pod -o jsonpath='{.metadata.finalizers}'` 返回非空列表\n（以上为kubectl直接可观测的现象，不包含诊断结论）\n\n**资源准备**：\n1. 确认目标应用已正常运行\n2. 确认目标 Pod 当前没有 finalizers（`kubectl get pod <name> -o jsonpath='{.metadata.finalizers}'` 返回空）\n\n**演练步骤**：\n1. 定位目标 Pod\n2. 使用 kubectl patch 给 Pod 添加自定义 finalizer：\n   `kubectl patch pod <pod-name> -n <namespace> -p '{\"metadata\":{\"finalizers\":[\"example.com/block-deletion\"]}}'`\n3. 使用 `--wait=false` 删除 Pod，触发终止流程：\n   `kubectl delete pod <pod-name> -n <namespace> --wait=false`\n   > 不加 `--wait=false` 会导致 kubectl 等待删除完成，因 finalizer 阻塞而超时。\n4. 观察 Pod 状态变化\n\n**注入验证**：\n1. 执行 `kubectl get pod <pod-name>`，确认 Pod 对象仍存在（显示 Terminating 或 Error）\n2. 执行 `kubectl get pod <pod-name> -o jsonpath='{.metadata.deletionTimestamp}'`，确认已设置\n3. 执行 `kubectl get pod <pod-name> -o jsonpath='{.metadata.finalizers}'`，确认包含注入的 finalizer\n4. 确认没有控制器在处理该 finalizer（`example.com/block-deletion` 是注入的假标识）\n\n**注入恢复**：\n1. 移除 Pod 上的 finalizer：\n   `kubectl patch pod <pod-name> -n <namespace> --type=json -p '[{\"op\":\"remove\",\"path\":\"/metadata/finalizers\"}]'`\n2. Pod 将被 Kubernetes GC 自动清除\n\n**恢复验证**：\n1. 执行 `kubectl get pod <pod-name>`，确认 Pod 已从集群中删除（返回 NotFound）\n2. 确认 ReplicaSet 已创建替代 Pod 且状态为 Running\n\n**基准事实**：\n- **根因**：Pod 的 metadata 中存在 finalizers，Kubernetes 在删除资源时会设置 deletionTimestamp 但不会从 etcd 中移除资源对象，直到所有 finalizer 被外部控制器清除\n- **必现现象**：Pod 对象持续存在于 API 中；deletionTimestamp 已设置；metadata.finalizers 非空\n","isInternal":false,"tokens":908,"sizeBytes":2929},{"name":"Pod_Terminating_Volume卸载失败.md","path":"blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_Terminating/Pod_Terminating_Volume卸载失败.md","rawUrl":"https://raw.githubusercontent.com/chaosblade-io/chaosblade/HEAD/blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_Terminating/Pod_Terminating_Volume卸载失败.md","title":"Pod_Terminating Skill","category":"anthropic-skill","format":"markdown","content":"**用例名称** Volume卸载失败 导致 Pod_Terminating\n\n**故障现象**：\n1. Pod 状态长时间停留在 Terminating\n2. Pod Events 或 Node Events 中显示 `FailedMount`、`UnmountVolume failed`、`device is busy`\n3. Volume 无法从节点上正常 unmount/detach，阻塞 Pod 终止流程\n\n**资源准备**：\n1. 确认应用 A 已正常运行，且挂载了 PVC（云盘类型）\n2. 确认监控系统可观测 Pod 和 Volume 状态\n\n**演练步骤**：\n1. 定位应用 A 的 Pod 及其挂载的 Volume 路径\n2. 进入目标节点，在 Volume 的挂载目录下创建一个持续占用文件句柄的进程，模拟 device busy：\n   ```bash\n   # 在节点上执行（通过 nsenter 或 debug pod）\n   # 找到 volume 挂载路径\n   mount | grep <pv-name>\n   # 创建持续占用的进程\n   tail -f <挂载路径>/some-file &\n   ```\n   或使用 chaosblade 对节点注入 IO 负载，锁住磁盘操作：\n   ```bash\n   blade create k8s node-disk burn \\\n     --names <节点名> \\\n     --path <volume挂载路径> \\\n     --read --write \\\n     --timeout 180 \\\n     --kubeconfig <路径>\n   ```\n3. 删除应用 A 的 Pod，触发 Terminating 流程\n4. 观察 Pod Terminating 状态持续时间\n\n**注入验证**：\n1. 执行 `kubectl get pods`，确认 Pod 状态为 Terminating 且长时间未消失\n2. 查看 Node Events 或 `kubectl describe pod`，确认有 UnmountVolume 失败或 device busy 相关错误\n3. 在节点上确认 volume 挂载路径仍被占用\n\n**注入恢复**：\n1. 终止节点上占用 volume 的进程（kill tail 进程）\n2. 若使用 chaosblade：销毁 IO 实验 `blade destroy <UID>`\n3. 等待 kubelet 自动重试 unmount 操作\n\n**恢复验证**：\n1. 执行 `kubectl get pods`，确认 Terminating 的 Pod 已完成删除\n2. 确认 volume 已成功 unmount 和 detach\n3. 确认 PV 状态恢复为 Available 或被新 Pod 重新绑定\n\n**基准事实**：\n- **根因**：Volume unmount 时设备仍被占用（device busy）或 CSI 异常，导致 kubelet 无法完成卷卸载，Pod 终止流程被阻塞\n- **必现现象**：Pod Terminating 持续；Events 显示 UnmountVolume failed/device busy；Volume 挂载路径未释放\n","isInternal":false,"tokens":725,"sizeBytes":2177},{"name":"Pod_Terminating_网卡卸载失败.md","path":"blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_Terminating/Pod_Terminating_网卡卸载失败.md","rawUrl":"https://raw.githubusercontent.com/chaosblade-io/chaosblade/HEAD/blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_Terminating/Pod_Terminating_网卡卸载失败.md","title":"Pod_Terminating Skill","category":"anthropic-skill","format":"markdown","content":"**用例名称** 网卡卸载失败 导致 Pod_Terminating\n\n**故障现象**：\n1. Pod 状态长时间停留在 Terminating\n2. 容器已停止，但 Pod sandbox 清理失败\n3. Events 或 kubelet 日志中显示 CNI DEL 调用失败或网络资源释放异常\n\n**资源准备**：\n1. 确认应用 A 已正常运行\n2. 确认集群使用 ENI/Terway 等需要显式清理网络资源的 CNI 插件\n3. 确认监控系统可观测 Pod 状态和 CNI 插件日志\n\n**演练步骤**：\n1. 定位应用 A 的 Pod 所在节点\n2. 使用 chaosblade 挂起节点上的 CNI 插件进程（如 terway-daemon），模拟 CNI 响应异常：\n   ```bash\n   blade create k8s node-process stop \\\n     --names <节点名> \\\n     --process terway \\\n     --timeout 120 \\\n     --kubeconfig <路径>\n   ```\n   或删除 CNI 插件 DaemonSet 中该节点的 Pod（先 cordon 节点防止重建）\n3. 删除应用 A 的 Pod，触发 Terminating 流程\n4. 观察 Pod Terminating 状态\n\n**注入验证**：\n1. 执行 `kubectl get pods`，确认 Pod 状态为 Terminating 且长时间未消失\n2. 查看 kubelet 日志（`journalctl -u kubelet`），确认有 CNI DEL 调用超时或失败的记录\n3. 确认 CNI 插件进程处于 stopped 状态或不可用\n\n**注入恢复**：\n1. 恢复 CNI 插件进程：等待 chaosblade 超时或执行 `blade destroy <UID>`\n2. 若删除了 CNI Pod：uncordon 节点，等待 CNI DaemonSet Pod 重建\n3. kubelet 将自动重试 sandbox 清理\n\n**恢复验证**：\n1. 确认 CNI 插件进程恢复正常\n2. 执行 `kubectl get pods`，确认 Terminating 的 Pod 已被完全清理\n3. 确认节点网络资源（ENI/IP）已释放\n4. 确认新 Pod 可以正常创建和分配网络\n\n**基准事实**：\n- **根因**：CNI 插件异常或不可用，导致 Pod 删除时网卡/ENI 资源无法正常释放，sandbox 清理失败，Pod 卡在 Terminating\n- **必现现象**：Pod Terminating 持续；kubelet 日志显示 CNI DEL 失败；网络资源未释放\n","isInternal":false,"tokens":688,"sizeBytes":1970},{"name":"Pod_Terminating_节点宕机kubelet失联.md","path":"blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_Terminating/Pod_Terminating_节点宕机kubelet失联.md","rawUrl":"https://raw.githubusercontent.com/chaosblade-io/chaosblade/HEAD/blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_Terminating/Pod_Terminating_节点宕机kubelet失联.md","title":"Pod_Terminating Skill","category":"anthropic-skill","format":"markdown","content":"**用例名称** 节点宕机kubelet失联 导致 Pod_Terminating\n\n**故障现象**：\n1. Pod 状态长时间停留在 Terminating，无法完成删除\n2. 节点状态变为 NotReady，kubelet 停止上报\n3. API Server 已下发删除指令，但 kubelet 无法执行实际清理操作\n\n**资源准备**：\n1. 确认应用 A 已正常运行，至少有一个副本运行在目标节点上\n2. 确认监控系统可观测节点状态和 Pod 状态\n\n**演练步骤**：\n1. 定位运行应用 A 的目标节点\n2. 先通过 kubectl 删除应用 A 在目标节点上的 Pod（触发 Terminating）\n3. 立即使用 chaosblade 对目标节点注入网络完全丢包（node-network drop 即全量丢包，不需要 --percent），并设置 `--timeout 300`，模拟节点宕机导致 kubelet 失联\n4. 观察 Pod Terminating 状态持续时间\n\n**注入验证**：\n1. 执行 `kubectl get pods`，确认目标 Pod 状态为 Terminating 且长时间未消失\n2. 执行 `kubectl get nodes`，确认目标节点状态为 NotReady\n3. 查看 Pod 详情，确认 deletionTimestamp 已设置但 Pod 未被实际清理\n\n**注入恢复**：\n1. 等待 chaosblade 实验自动超时恢复（300 秒内）\n2. 如超时后仍未恢复，通过 `blade destroy <UID>` 或重启节点强制恢复\n3. kubelet 恢复后会自动清理 Terminating 状态的 Pod\n\n**恢复验证**：\n1. 执行 `kubectl get nodes`，确认目标节点恢复 Ready\n2. 执行 `kubectl get pods`，确认 Terminating 的 Pod 已被清理\n3. 确认应用 A 的新 Pod 在其他节点正常运行\n\n**基准事实**：\n- **根因**：节点宕机或 kubelet 失联，导致 API Server 下发的删除指令无法被执行，Pod 停留在 Terminating 状态\n- **必现现象**：Pod 状态为 Terminating 且长时间不消失；节点 NotReady；deletionTimestamp 已设置\n","isInternal":false,"tokens":611,"sizeBytes":1823},{"name":"Pod_云盘空间打满_日志未清理.md","path":"blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_云盘空间打满/Pod_云盘空间打满_日志未清理.md","rawUrl":"https://raw.githubusercontent.com/chaosblade-io/chaosblade/HEAD/blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_云盘空间打满/Pod_云盘空间打满_日志未清理.md","title":"Pod_云盘空间打满 Skill","category":"anthropic-skill","format":"markdown","content":"**用例名称** 日志未清理 导致 Pod_云盘空间打满\n\n**故障现象**：\n1. Pod 挂载的云盘空间使用率达到 100%\n2. 应用写入操作失败，日志报 `No space left on device`\n3. 应用功能异常，数据无法持久化\n\n**资源准备**：\n1. 确认应用 A 已正常运行，且挂载了 PVC 用于数据存储\n2. 确认 PVC 对应的云盘容量已知\n3. 确认监控系统可观测 PVC 磁盘使用率\n\n**演练步骤**：\n1. 定位应用 A 的 Pod 及其 PVC 挂载路径\n2. 使用 chaosblade 对应用 A 的 Pod 注入磁盘填充，模拟日志堆积打满云盘：\n   ```bash\n   blade create k8s pod-disk fill \\\n     --namespace <namespace> \\\n     --labels \"app=<app>\" \\\n     --path <PVC挂载路径> \\\n     --percent 99 \\\n     --timeout 300 \\\n     --kubeconfig <路径>\n   ```\n3. 观察应用 A 的写入行为和错误日志\n\n**注入验证**：\n1. 进入 Pod 查看挂载路径磁盘使用率：`df -h <挂载路径>`，确认使用率接近 100%\n2. 在 Pod 内尝试写入文件，确认报 `No space left on device` 错误\n3. 查看应用 A 日志，确认有写入失败相关错误\n4. 确认应用 A 的业务功能受影响（如数据写入失败）\n\n**注入恢复**：\n1. 销毁 chaosblade 磁盘填充实验：`blade destroy <UID>`\n2. 确认填充的临时文件被清理\n3. 若空间未释放，手动清理注入的文件\n\n**恢复验证**：\n1. 进入 Pod 查看挂载路径磁盘使用率，确认恢复到正常水平\n2. 在 Pod 内尝试写入文件，确认成功\n3. 确认应用 A 的写入操作恢复正常\n4. 确认应用 A 业务功能恢复\n\n**基准事实**：\n- **根因**：云盘上的日志或数据文件持续增长且未配置清理策略，最终占满整个磁盘空间，导致新的写入操作失败\n- **必现现象**：磁盘使用率 100%；写入报 No space left on device；应用功能异常\n","isInternal":false,"tokens":701,"sizeBytes":1870},{"name":"Pod_磁盘空间使用率过高_应用日志数据积累.md","path":"blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_磁盘空间使用率过高/Pod_磁盘空间使用率过高_应用日志数据积累.md","rawUrl":"https://raw.githubusercontent.com/chaosblade-io/chaosblade/HEAD/blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_磁盘空间使用率过高/Pod_磁盘空间使用率过高_应用日志数据积累.md","title":"Pod_磁盘空间使用率过高 Skill","category":"anthropic-skill","format":"markdown","content":"**用例名称** 应用日志数据积累 导致 Pod_磁盘空间使用率过高\n\n**故障现象**：\n1. Pod 使用的存储空间接近上限，磁盘使用率告警\n2. 应用可能出现写入失败、响应变慢等问题\n3. 容器内日志目录（如 /var/log）文件过大\n\n**资源准备**：\n1. 确认应用 A/B 已正常运行\n2. 确认应用配置了日志输出（如输出到 /tmp 或挂载目录）\n\n**演练步骤**：\n1. 定位应用 A 的 Pod\n2. 使用 chaosblade 向应用 A 的 Pod 注入磁盘填充故障，模拟大量日志写入\n3. 持续向 Pod 写入大文件，填充磁盘空间至接近容量上限\n4. 观察 Pod 磁盘使用率变化及应用响应情况\n\n**注入验证**：\n1. 进入应用 A 的 Pod，使用 df -h 查看磁盘使用率，确认超过设定阈值\n2. 查看 Pod 状态，确认是否有磁盘相关异常事件\n3. 观察应用是否出现写入失败等异常表现\n\n**注入恢复**：\n1. 销毁 chaosblade 磁盘填充实验\n2. 删除 Pod 中产生的大文件，释放磁盘空间\n3. 或删除异常 Pod，触发重新调度创建新 Pod\n\n**恢复验证**：\n1. 查看 Pod 磁盘使用率，确认恢复到正常水平\n2. 查看应用是否恢复正常写入操作\n3. 确认 Pod 状态为 Running，无磁盘相关异常事件\n\n**基准事实**：\n- **根因**：应用日志未清理或数据写入过多，导致 Pod 存储空间被占满\n- **必现现象**：Pod 磁盘使用率超过设定阈值，应用出现写入失败\n\n---\n","isInternal":false,"tokens":569,"sizeBytes":1483},{"name":"Pod_网络丢包_服务依赖中断.md","path":"blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_网络丢包/Pod_网络丢包_服务依赖中断.md","rawUrl":"https://raw.githubusercontent.com/chaosblade-io/chaosblade/HEAD/blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_网络丢包/Pod_网络丢包_服务依赖中断.md","title":"Pod_网络丢包 Skill","category":"anthropic-skill","format":"markdown","content":"**用例名称** 服务依赖中断 导致 Pod_网络丢包\n\n**故障现象**：\n1. Pod 对外部服务或上下游依赖的网络请求超时或无响应\n2. 应用健康检查可能失败（如依赖外部探活）\n3. 服务间调用链路出现断裂，影响业务可用性\n\n**资源准备**：\n1. 确认目标应用已正常运行，且有对外网络调用（数据库、缓存、上下游服务等）\n2. 确认监控系统可观测网络请求成功率和延迟指标\n3. 确认目标 Pod 的标签选择器和命名空间\n\n**演练步骤**：\n1. 确认目标 Pod 的标签选择器和命名空间：\n   ```bash\n   kubectl get pods -n <namespace> -l <label-selector> -o wide\n   ```\n2. 使用 ChaosBlade 对目标 Pod 注入网络丢包故障：\n   ```bash\n   blade create k8s pod-network drop \\\n     --namespace <namespace> \\\n     --labels \"<label-key>=<label-value>\" \\\n     --source-port <port> \\\n     --kubeconfig <kubeconfig-path>\n   ```\n   - `--source-port`：限定丢包端口（如 3306 丢弃 MySQL 流量、53 丢弃 DNS 流量）\n   - 不指定端口时为全量丢包（慎用，影响所有流量包括监控和健康检查）\n3. 记录返回的 blade_uid，用于后续恢复\n\n**注入验证**：\n1. 在目标 Pod 内验证网络连通性丧失：\n   ```bash\n   kubectl exec <pod-name> -n <namespace> -- wget -qO- --timeout=5 <依赖服务地址>\n   ```\n   确认请求超时或无响应\n2. 查看应用日志确认出现连接超时错误：\n   ```bash\n   kubectl logs <pod-name> -n <namespace> --tail=20\n   ```\n3. 检查服务调用链路指标，确认目标端口流量中断\n\n**注入恢复**：\n1. 销毁 ChaosBlade 实验：\n   ```bash\n   blade destroy <blade_uid>\n   ```\n2. 如 Pod 因丢包导致健康检查失败被重启，等待新 Pod Ready\n\n**恢复验证**：\n1. 在目标 Pod 内重新验证网络连通性恢复：\n   ```bash\n   kubectl exec <pod-name> -n <namespace> -- wget -qO- --timeout=5 <依赖服务地址>\n   ```\n2. 确认应用日志不再出现连接超时错误\n3. 确认服务调用链路指标恢复正常\n\n**基准事实**：\n- **根因**：Pod 出方向网络流量被 iptables DROP 规则丢弃，导致对指定端口/地址的所有请求无响应\n- **必现现象**：目标端口的 TCP/UDP 请求超时；应用日志出现 connection timed out；依赖该连接的业务功能不可用\n","isInternal":false,"tokens":828,"sizeBytes":2344},{"name":"Pod_被驱逐重建_DiskPressure.md","path":"blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_被驱逐重建/Pod_被驱逐重建_DiskPressure.md","rawUrl":"https://raw.githubusercontent.com/chaosblade-io/chaosblade/HEAD/blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_被驱逐重建/Pod_被驱逐重建_DiskPressure.md","title":"Pod_被驱逐重建 Skill","category":"anthropic-skill","format":"markdown","content":"**用例名称** DiskPressure 导致 Pod_被驱逐重建\n\n**故障现象**：\n1. Pod 被 kubelet 驱逐（Evicted），状态为 Failed，reason 为 Evicted\n2. 节点 Conditions 中 DiskPressure 为 True\n3. 容器运行时目录（如 /var/lib/docker 或 /var/lib/containerd）磁盘使用超过 kubelet 驱逐阈值\n\n**资源准备**：\n1. 确认应用 A 已正常运行，有多个副本分布在不同节点\n2. 确认目标节点的容器运行时磁盘当前使用率距离驱逐阈值有一定空间\n3. 确认监控系统可观测节点磁盘使用率和 Pod 驱逐事件\n\n**演练步骤**：\n1. 查看目标节点 kubelet 配置的驱逐阈值（默认 `imagefs.available < 15%`）\n2. 使用 chaosblade 对目标节点的容器运行时目录注入磁盘填充，使其超过驱逐阈值：\n   ```bash\n   blade create k8s node-disk fill \\\n     --names <节点名> \\\n     --path /var/lib/containerd \\\n     --percent 90 \\\n     --timeout 300 \\\n     --kubeconfig <路径>\n   ```\n3. 等待 kubelet 检测到 DiskPressure 并触发 Pod 驱逐\n4. 观察应用 A 的 Pod 驱逐和重建行为\n\n**注入验证**：\n1. 执行 `kubectl describe node <节点名>`，确认 Conditions 中 DiskPressure 为 True\n2. 执行 `kubectl get pods --field-selector=status.phase=Failed`，确认有 Pod 被 Evicted\n3. 查看被驱逐 Pod 的详情，确认 reason 为 `The node was low on resource: ephemeral-storage`\n4. 确认应用 A 在其他节点重建 Pod\n\n**注入恢复**：\n1. 等待 chaosblade 实验自动超时恢复（300 秒内），或执行 `blade destroy <UID>`\n2. 等待节点磁盘空间释放\n3. 清理 Evicted Pod：`kubectl delete pods --field-selector=status.phase=Failed`\n\n**恢复验证**：\n1. 执行 `kubectl describe node <节点名>`，确认 DiskPressure 恢复为 False\n2. 确认应用 A 的 Pod 在正常节点上运行\n3. 确认节点磁盘使用率恢复到安全水位\n\n**基准事实**：\n- **根因**：容器运行时目录磁盘使用超过 kubelet 驱逐阈值（DiskPressure），kubelet 按优先级驱逐 Pod 以释放磁盘空间\n- **必现现象**：节点 DiskPressure=True；Pod 被 Evicted；reason 为 ephemeral-storage 不足\n","isInternal":false,"tokens":756,"sizeBytes":2159},{"name":"Pod_镜像拉取失败_凭证缺失或过期.md","path":"blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_镜像拉取失败/Pod_镜像拉取失败_凭证缺失或过期.md","rawUrl":"https://raw.githubusercontent.com/chaosblade-io/chaosblade/HEAD/blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_镜像拉取失败/Pod_镜像拉取失败_凭证缺失或过期.md","title":"Pod_镜像拉取失败 Skill","category":"anthropic-skill","format":"markdown","content":"**用例名称** 凭证缺失或过期 导致 Pod_镜像拉取失败\n\n**故障现象**：\n1. Pod 状态为 ImagePullBackOff 或 ErrImagePull\n2. Pod Events 中显示 `unauthorized` 或 `authentication required`\n3. 镜像仓库返回 401/403 认证错误\n\n**资源准备**：\n1. 确认应用 A 已正常运行，且使用私有镜像仓库\n2. 确认应用 A 的 Pod 配置了 imagePullSecrets\n\n**演练步骤**：\n1. 记录应用 A 当前的 imagePullSecrets 名称和 imagePullPolicy 值\n2. 记录 Deployment 当前 maxUnavailable 值，并临时设为 100%（确保滚动更新能完成，故障注入的新 Pod 不会 Ready，默认策略下 K8s 不会终止旧 Pod，导致滚动更新死锁）：\n   ```bash\n   kubectl get deployment <deployment-name> -n <namespace> \\\n     -o jsonpath='{.spec.strategy.rollingUpdate.maxUnavailable}'\n   kubectl patch deployment <deployment-name> -n <namespace> --type='json' \\\n     -p='[{\"op\":\"replace\",\"path\":\"/spec/strategy/rollingUpdate/maxUnavailable\",\"value\":\"100%\"}]'\n   ```\n3. 创建一个包含无效凭证的 Secret 来替换原有的有效凭证：\n   ```bash\n   kubectl create secret docker-registry chaos-invalid-secret \\\n     --docker-server=<registry-server> \\\n     --docker-username=invalid-user \\\n     --docker-password=invalid-password \\\n     --namespace <namespace>\n   ```\n4. 修改应用 A 的 Deployment，将 imagePullSecrets 指向无效 Secret（或直接移除 imagePullSecrets）。\n   同时检查 imagePullPolicy：如果当前为 `IfNotPresent`，需同时改为 `Always`，否则 K8s 直接使用本地缓存镜像启动 Pod，不会触发凭证校验，故障无法注入\n5. 等待 Pod 滚动更新完成，确认所有旧 Pod 已被替换\n6. 滚动更新完成后，立即还原 maxUnavailable 为原始值（maxUnavailable 只是使滚动更新完成的手段，不是故障本身，不应泄漏到恢复阶段）\n7. 观察 Pod 状态变化\n\n**注入验证**：\n1. 执行 `kubectl rollout status deployment <deployment-name>`，确认滚动更新已完成（所有旧 Pod 已被替换）。如果滚动更新未完成（卡死），则故障未完全生效，不可判定为 verified\n2. 执行 `kubectl get pods`，确认**所有**目标 Pod 状态为 ImagePullBackOff 或 ErrImagePull（不是仅一个新 Pod，而是全部副本）\n3. 执行 `kubectl describe pod <pod-name>`，确认 Events 中显示认证失败相关错误\n4. 确认错误信息包含 `unauthorized` 或 `authentication required`\n\n**注入恢复**：\n1. 恢复应用 A 的 Deployment，将 imagePullSecrets 指回原有的有效 Secret。如果注入时修改了 imagePullPolicy，需同时还原为原始值\n2. 删除测试用的无效 Secret：`kubectl delete secret chaos-invalid-secret`\n3. 等待 Pod 滚动更新完成\n\n**恢复验证**：\n1. 执行 `kubectl get pods`，确认 Pod 状态恢复为 Running\n2. 确认镜像拉取成功，无认证错误\n\n**基准事实**：\n- **根因**：imagePullSecrets 缺失或 Secret 中的凭证已过期/无效，导致向私有镜像仓库拉取镜像时认证失败\n- **必现现象**：Pod ImagePullBackOff；Events 显示 unauthorized/authentication required；镜像仓库返回 401/403\n","isInternal":false,"tokens":991,"sizeBytes":3178},{"name":"Pod_镜像拉取失败_镜像不存在或标签错误.md","path":"blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_镜像拉取失败/Pod_镜像拉取失败_镜像不存在或标签错误.md","rawUrl":"https://raw.githubusercontent.com/chaosblade-io/chaosblade/HEAD/blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_镜像拉取失败/Pod_镜像拉取失败_镜像不存在或标签错误.md","title":"Pod_镜像拉取失败 Skill","category":"anthropic-skill","format":"markdown","content":"**用例名称** 镜像不存在或标签错误 导致 Pod_镜像拉取失败\n\n**故障现象**：\n1. Pod 状态停留在 ImagePullBackOff 或 ErrImagePull\n2. Pod Event 显示镜像拉取失败，错误信息包含 `manifest for xxx not found`\n\n**资源准备**：\n1. 确认应用 A/B 所在节点正常运行\n2. 确认节点可正常访问镜像仓库\n\n**演练步骤**：\n1. 定位应用 A 的 Deployment\n2. 记录 Deployment 当前 maxUnavailable 值，并临时设为 100%（确保滚动更新能完成，故障注入的新 Pod 不会 Ready，默认策略下 K8s 不会终止旧 Pod，导致滚动更新死锁）：\n   ```bash\n   kubectl get deployment <deployment-name> -n <namespace> \\\n     -o jsonpath='{.spec.strategy.rollingUpdate.maxUnavailable}'\n   kubectl patch deployment <deployment-name> -n <namespace> --type='json' \\\n     -p='[{\"op\":\"replace\",\"path\":\"/spec/strategy/rollingUpdate/maxUnavailable\",\"value\":\"100%\"}]'\n   ```\n3. 修改应用 A 的镜像地址为不存在的镜像名称或标签\n4. 等待 Pod 滚动更新完成，确认所有旧 Pod 已被替换\n5. 滚动更新完成后，立即还原 maxUnavailable 为原始值（maxUnavailable 只是使滚动更新完成的手段，不是故障本身，不应泄漏到恢复阶段）\n6. 观察 Pod 的镜像拉取状态\n\n**注入验证**：\n1. 执行 `kubectl rollout status deployment <deployment-name>`，确认滚动更新已完成（所有旧 Pod 已被替换）。如果滚动更新未完成（卡死），则故障未完全生效，不可判定为 verified\n2. 执行 `kubectl get pods`，确认**所有**目标 Pod 状态停留在 ImagePullBackOff 或 ErrImagePull（不是仅一个新 Pod，而是全部副本）\n3. 执行 `kubectl describe pod <pod-name>`，确认 Events 包含镜像不存在相关信息，如 `manifest for xxx not found`\n\n**注入恢复**：\n1. 恢复应用 A 的镜像地址为正确的镜像名称和标签\n2. 等待 Pod 滚动更新完成\n\n**恢复验证**：\n1. 查看 Pod 状态，确认恢复为 Running\n2. 查看 Pod Event，确认镜像拉取成功\n\n**基准事实**：\n- **根因**：Pod 配置的镜像名称拼写错误或标签在镜像仓库中不存在\n- **必现现象**：Pod 状态为 ImagePullBackOff 或 ErrImagePull，日志显示 `manifest for xxx not found`\n","isInternal":false,"tokens":736,"sizeBytes":2276},{"name":"Service_调用失败_kube-proxy异常.md","path":"blade-ai/skills/k8s-chaos-skills/references/catalogue/Service_调用失败/Service_调用失败_kube-proxy异常.md","rawUrl":"https://raw.githubusercontent.com/chaosblade-io/chaosblade/HEAD/blade-ai/skills/k8s-chaos-skills/references/catalogue/Service_调用失败/Service_调用失败_kube-proxy异常.md","title":"Service_调用失败 Skill","category":"anthropic-skill","format":"markdown","content":"**用例名称** kube-proxy异常 导致 Service_调用失败\n\n**故障现象**：\n1. 通过 ClusterIP/NodePort 访问 Service 失败，连接超时\n2. 节点上 iptables/ipvs 规则未更新或被清空\n3. kube-proxy Pod 异常，无法维护 Service 转发规则\n\n**资源准备**：\n1. 确认应用 A 已正常运行，对外暴露 Service\n2. 确认 kube-proxy DaemonSet 正常运行\n3. 确认监控系统可观测 Service 请求指标\n\n**演练步骤**：\n1. 记录 kube-proxy DaemonSet 当前状态\n2. 选择目标节点，删除该节点上的 kube-proxy Pod 并临时阻止重建（通过 cordon 节点或修改 DaemonSet nodeSelector）：\n   ```bash\n   # 方式A：给目标节点添加标签排除 kube-proxy 调度\n   kubectl label node <目标节点> chaos-no-proxy=true\n   kubectl patch ds kube-proxy -n kube-system \\\n     -p '{\"spec\":{\"template\":{\"spec\":{\"affinity\":{\"nodeAffinity\":{\"requiredDuringSchedulingIgnoredDuringExecution\":{\"nodeSelectorTerms\":[{\"matchExpressions\":[{\"key\":\"chaos-no-proxy\",\"operator\":\"DoesNotExist\"}]}]}}}}}}}'\n   ```\n   或者直接使用 chaosblade 杀掉 kube-proxy 进程：\n   ```bash\n   blade create k8s node-process kill \\\n     --names <目标节点> \\\n     --process kube-proxy \\\n     --timeout 120 \\\n     --kubeconfig <路径>\n   ```\n3. 在目标节点上的 Pod 内通过 ClusterIP 访问 Service\n4. 观察 Service 访问结果\n\n**注入验证**：\n1. 确认目标节点上 kube-proxy 进程不存在或 Pod 处于异常状态\n2. 在目标节点的 Pod 内访问 Service ClusterIP，确认连接超时或失败\n3. 检查节点 iptables/ipvs 规则，确认 Service 相关转发规则缺失或过期\n\n**注入恢复**：\n1. 若使用标签方式：移除节点标签并恢复 DaemonSet 配置：\n   ```bash\n   kubectl label node <目标节点> chaos-no-proxy-\n   kubectl patch ds kube-proxy -n kube-system --type=json \\\n     -p='[{\"op\":\"remove\",\"path\":\"/spec/template/spec/affinity\"}]'\n   ```\n2. 若使用 chaosblade：等待实验超时或执行 `blade destroy <UID>`\n3. 等待 kube-proxy Pod 在目标节点重建\n\n**恢复验证**：\n1. 确认目标节点上 kube-proxy Pod 恢复 Running 且 Ready\n2. 在目标节点的 Pod 内重新访问 Service，确认恢复正常\n3. 检查 iptables/ipvs 规则已重新同步\n\n**基准事实**：\n- **根因**：kube-proxy Pod 异常或进程被杀，无法维护节点上的 iptables/ipvs 转发规则，导致 Service ClusterIP 流量无法被正确转发\n- **必现现象**：Service ClusterIP 访问超时；kube-proxy 不可用；节点 iptables/ipvs 规则缺失\n","isInternal":false,"tokens":805,"sizeBytes":2561},{"name":"Service_调用失败_ReadinessProbe配置不一致.md","path":"blade-ai/skills/k8s-chaos-skills/references/catalogue/Service_调用失败/Service_调用失败_ReadinessProbe配置不一致.md","rawUrl":"https://raw.githubusercontent.com/chaosblade-io/chaosblade/HEAD/blade-ai/skills/k8s-chaos-skills/references/catalogue/Service_调用失败/Service_调用失败_ReadinessProbe配置不一致.md","title":"Service_调用失败 Skill","category":"anthropic-skill","format":"markdown","content":"**用例名称** ReadinessProbe配置不一致 导致 Service_调用失败\n\n**故障现象**：\n1. Pod 状态为 Running 但 READY 为 0/1\n2. Service 的 Endpoints 列表为空或逐渐减少\n3. Readiness Probe 持续失败，Pod 从 Service 后端移除\n\n**资源准备**：\n1. 确认应用 A 已正常运行，对外暴露 Service\n2. 确认应用 A 实际监听的端口和健康检查路径\n\n**演练步骤**：\n1. 记录应用 A 当前的 readinessProbe 配置\n2. 记录 Deployment 当前 maxUnavailable 值，并临时设为 100%（确保滚动更新能完成，故障注入的新 Pod 不会 Ready，默认策略下 K8s 不会终止旧 Pod，导致滚动更新死锁）：\n   ```bash\n   kubectl get deployment <deployment-name> -n <namespace> \\\n     -o jsonpath='{.spec.strategy.rollingUpdate.maxUnavailable}'\n   kubectl patch deployment <deployment-name> -n <namespace> --type='json' \\\n     -p='[{\"op\":\"replace\",\"path\":\"/spec/strategy/rollingUpdate/maxUnavailable\",\"value\":\"100%\"}]'\n   ```\n3. 修改应用 A 的 Deployment，将 readinessProbe 路径或端口设置为与实际不一致：\n   ```yaml\n   readinessProbe:\n     httpGet:\n       path: /non-existent-health-path\n       port: 9999    # 应用实际不监听此端口\n     periodSeconds: 5\n     failureThreshold: 3\n   ```\n4. 等待 Pod 滚动更新完成，确认所有旧 Pod 已被替换\n5. 滚动更新完成后，立即还原 maxUnavailable 为原始值（maxUnavailable 只是使滚动更新完成的手段，不是故障本身，不应泄漏到恢复阶段）\n6. 观察 Pod Ready 状态和 Service Endpoints 变化\n\n**注入验证**：\n1. 执行 `kubectl rollout status deployment <deployment-name>`，确认滚动更新已完成（所有旧 Pod 已被替换）。如果滚动更新未完成（卡死），则故障未完全生效，不可判定为 verified\n2. 执行 `kubectl get pods`，确认**所有** Pod 状态为 Running 但 READY 列显示 0/1（不是仅一个新 Pod 0/1，而是全部副本都 0/1）\n3. 执行 `kubectl get endpoints <service-name>`，确认 Endpoints 列表**为空**（无子集），而非仅新 Pod 不在列表中\n4. 执行 `kubectl describe pod <pod-name>`，确认 Events 显示 `Readiness probe failed`\n5. 向 Service 发送请求，确认返回 connection refused 或超时。注意：connection reset by peer 可能是应用自身行为而非故障效果，不可作为故障生效的充分证据\n\n**注入恢复**：\n1. 恢复应用 A 的 Deployment，将 readinessProbe 的路径和端口修正为正确值（若原本无 readinessProbe，则移除）\n2. 等待 Pod 滚动更新完成\n\n**恢复验证**：\n1. 执行 `kubectl get pods`，确认 Pod READY 为 1/1\n2. 执行 `kubectl get endpoints <service-name>`，确认 Pod 重新加入 Endpoints\n3. 向 Service 发送请求，确认服务恢复正常\n\n**基准事实**：\n- **根因**：Readiness Probe 的路径或端口与应用实际监听不一致，Probe 持续失败导致 Pod 被标记为 Not Ready，从 Service Endpoints 中移除\n- **必现现象**：Pod Running 但 Not Ready（0/1）；Endpoints 为空；Events 显示 Readiness probe failed\n","isInternal":false,"tokens":990,"sizeBytes":3116},{"name":"Service_调用失败_selector不匹配.md","path":"blade-ai/skills/k8s-chaos-skills/references/catalogue/Service_调用失败/Service_调用失败_selector不匹配.md","rawUrl":"https://raw.githubusercontent.com/chaosblade-io/chaosblade/HEAD/blade-ai/skills/k8s-chaos-skills/references/catalogue/Service_调用失败/Service_调用失败_selector不匹配.md","title":"Service_调用失败 Skill","category":"anthropic-skill","format":"markdown","content":"**用例名称** selector不匹配 导致 Service_调用失败\n\n**故障现象**：\n1. Service 的 Endpoints 列表为空\n2. 通过 Service 访问应用返回 connection refused 或无响应\n3. Pod 正常运行但未被 Service 选中\n\n**资源准备**：\n1. 确认应用 A 已正常运行，对外暴露 Service\n2. 确认监控系统可观测 Service 请求指标和 Endpoints 状态\n\n**演练步骤**：\n1. 记录应用 A 的 Service 当前 selector 配置\n2. 使用 kubectl patch 修改 Service 的 selector，使其不匹配任何 Pod：\n   ```bash\n   kubectl patch svc <service-name> -n <namespace> \\\n     -p '{\"spec\":{\"selector\":{\"app\":\"non-existent-app\"}}}'\n   ```\n3. 观察 Endpoints 变化和服务可用性\n\n**注入验证**：\n1. 执行 `kubectl get endpoints <service-name>`，确认 Endpoints 列表为空（无子集）\n2. 向 Service 发送请求，确认返回 connection refused 或超时\n3. 执行 `kubectl get pods -l app=<原标签>`，确认 Pod 实际正常运行\n4. 对比 Service selector 与 Pod labels，确认不匹配\n\n**注入恢复**：\n1. 使用 kubectl patch 将 Service selector 恢复为原始值：\n   ```bash\n   kubectl patch svc <service-name> -n <namespace> \\\n     -p '{\"spec\":{\"selector\":{\"app\":\"<原始标签>\"}}}'\n   ```\n2. 等待 Endpoints 自动更新\n\n**恢复验证**：\n1. 执行 `kubectl get endpoints <service-name>`，确认 Endpoints 列表恢复，包含后端 Pod IP\n2. 向 Service 发送请求，确认恢复正常\n3. 确认服务可用性恢复\n\n**基准事实**：\n- **根因**：Service 的 selector 与后端 Pod 的 label 不匹配，导致 Endpoints 控制器无法关联任何 Pod，Service 无后端可转发\n- **必现现象**：Endpoints 为空；Service 请求失败（connection refused/超时）；Pod 正常但未被选中\n","isInternal":false,"tokens":560,"sizeBytes":1790},{"name":"Service_负载均衡异常_后端不可达.md","path":"blade-ai/skills/k8s-chaos-skills/references/catalogue/Service_负载均衡异常/Service_负载均衡异常_后端不可达.md","rawUrl":"https://raw.githubusercontent.com/chaosblade-io/chaosblade/HEAD/blade-ai/skills/k8s-chaos-skills/references/catalogue/Service_负载均衡异常/Service_负载均衡异常_后端不可达.md","title":"Service_负载均衡异常 Skill","category":"anthropic-skill","format":"markdown","content":"**用例名称** 后端不可达 导致 Service_负载均衡异常\n\n**故障现象**：\n1. Service 的 Endpoints 列表为空或部分后端不可用\n2. 请求到 Service 出现 5xx 错误或连接超时\n3. Ingress 后端健康检查失败\n\n**资源准备**：\n1. 确认应用 A 已正常运行，对外暴露 Service 和 Ingress\n2. 确认监控系统可观测 Service 请求指标和 Endpoints 状态\n\n**演练步骤**：\n1. 定位应用 A 的 Service 和后端 Pod\n2. 使用 chaosblade 对应用 A 的 Pod 注入故障，模拟后端不可达\n\n**注入方式选择（重要）**：\n- **推荐优先**：使用 `pod-process kill` 杀死后端 Pod 的主进程。优点：直接导致 Pod 重启或进入 CrashLoopBackOff，Endpoints 控制器会自动将其从 Endpoints 列表移除，故障效果明确且可观测\n- **备选方式**：使用 `pod-network drop` 断开 Pod 网络。注意：如果主机 blade 二进制与集群不兼容，会退化为 kubectl exec 方式注入，导致恢复阶段必须通过 kubectl exec 执行 blade destroy，增加恢复复杂度\n  - 如果目标是单个服务端口（如 MySQL 3306），推荐使用端口过滤以缩小爆炸半径：`pod-network drop --source-port 3306 --namespace <ns> --labels \"app=<app>\"`\n  - 如果需要完全断开 Pod 网络：`pod-network drop --namespace <ns> --labels \"app=<app>\"`，注意此方式会影响所有端口，包括 DNS 和监控\n- 选择原则：如果集群中已部署 ChaosBlade Operator 且主机 blade 可直接使用，两种方式均可；如果需要通过 kubectl exec 注入，优先选择 pod-process kill\n\n**Readiness Probe 兼容性**（选择注入方式前必须评估）：\n- 通过 `kubectl describe pod <pod>` 获取目标 Pod 的 Readiness Probe 类型\n- `exec` 类型 Probe：在容器内通过 localhost 执行，**不受** pod-network drop 的 tc 规则影响 → Pod 保持 Ready → Endpoints 不会移除\n- `httpGet/tcpSocket` 类型 Probe（端口在 Service 端口范围内）：**可能受** pod-network drop 影响 → 延迟后 Pod 变为 NotReady → Endpoints 会被移除\n- 选择原则：如果目标是\"Endpoints 移除\"，exec 类型 Probe 的 Pod 应使用 pod-process kill 而非 pod-network drop\n\n**注入验证**：\n1. 执行 `kubectl get endpoints <service-name>`，确认部分后端被移除或全不可用\n2. 向 Service 发送请求，确认出现 5xx 错误或连接超时\n3. 查看 Ingress 状态，确认后端健康检查失败\n4. 确认请求流量被调度到剩余可用后端（部分后端不可用时）\n\n**注入恢复**：\n1. 销毁 chaosblade 实验\n\n**恢复验证**：\n1. 执行 `kubectl get endpoints <service-name>`，确认所有后端恢复可用\n2. 向 Service 发送请求，确认恢复正常\n3. 查看 Ingress 状态，确认后端健康检查通过\n\n**基准事实**：\n- **根因**：Service 后端 Pod 异常或网络不通，导致负载均衡无法将请求转发到健康的后端，服务可用性下降\n- **必现现象**：Endpoints 列表部分为空或全部为空；请求出现 5xx 或超时；Ingress 后端健康检查失败\n","isInternal":false,"tokens":1030,"sizeBytes":3097},{"name":"workload_副本被缩容_人为误操作.md","path":"blade-ai/skills/k8s-chaos-skills/references/catalogue/workload_副本被缩容/workload_副本被缩容_人为误操作.md","rawUrl":"https://raw.githubusercontent.com/chaosblade-io/chaosblade/HEAD/blade-ai/skills/k8s-chaos-skills/references/catalogue/workload_副本被缩容/workload_副本被缩容_人为误操作.md","title":"Workload_副本被缩容 Skill","category":"anthropic-skill","format":"markdown","content":"**用例名称** 人为误操作 导致 workload_副本被缩容\n\n**故障现象**：\n1. Deployment/StatefulSet 的当前副本数小于期望副本数\n2. 应用可用实例减少，部分请求无法处理\n3. 服务响应延迟增大或出现超时\n\n**资源准备**：\n1. 确认应用 A 的 Deployment/StatefulSet 已正常运行，副本数大于 1\n2. 确认监控系统可观测 Pod 副本数和请求指标\n\n**演练步骤**：\n1. 定位应用 A 的 Deployment/StatefulSet\n2. 使用 kubectl 将 replicas 修改为较小的值，模拟人为误操作导致的意外缩容\n3. 观察 Pod 缩容过程和应用状态变化\n\n**标签选择器提示**：\n- Kubernetes 推荐标签格式为 `app.kubernetes.io/name=<name>`，而非简单的 `app=<name>`\n- 建议先不带 `-l` 过滤器查询 `kubectl get deployment <name> -n <ns>`，再从返回结果中提取实际标签\n- 若需用标签过滤，优先使用 `-l app.kubernetes.io/name=<name>` 或 `-l app.kubernetes.io/component=<name>`\n\n**注入验证**：\n1. 执行 `kubectl get pods`，确认 Pod 总数减少，部分 Pod 被终止\n2. 执行 `kubectl get deployment/statefulset <name>`，确认当前副本数小于缩容前的值\n3. 确认应用 A 的请求延迟增大或出现超时\n4. 确认服务可用性下降\n\n**注入恢复**：\n1. 使用 kubectl 将 replicas 恢复为原来的合理值\n2. 等待 Pod 自动扩容\n\n**恢复验证**：\n1. 执行 `kubectl get pods`，确认 Pod 总数恢复到缩容前的值\n2. 执行 `kubectl get deployment/statefulset <name>`，确认 READY 副本数等于 DESIRED\n3. 确认应用 A 的请求延迟恢复正常\n4. 确认服务可用性恢复\n\n**基准事实**：\n- **根因**：人为误操作（如 kubectl scale、修改 YAML 等）导致 Deployment/StatefulSet 的副本数被意外缩小，可用实例不足\n- **必现现象**：READY 副本数小于 DESIRED；Pod 被终止；服务可用性下降\n\n**注意事项**：\n- 若目标 Deployment/StatefulSet 由 Helm 管理（label `app.kubernetes.io/managed-by: Helm`），kubectl scale 修改会被 Helm reconciliation 覆盖\n- 注入期间应避免触发 Helm upgrade/rollback 操作，否则故障会被意外恢复\n- 反之，若需快速恢复，可通过 `helm rollback` 或 `helm upgrade` 强制还原\n","isInternal":false,"tokens":807,"sizeBytes":2266},{"name":"节点容器运行时磁盘使用率过高_日志或临时文件堆积.md","path":"blade-ai/skills/k8s-chaos-skills/references/catalogue/节点容器运行时磁盘使用率过高/节点容器运行时磁盘使用率过高_日志或临时文件堆积.md","rawUrl":"https://raw.githubusercontent.com/chaosblade-io/chaosblade/HEAD/blade-ai/skills/k8s-chaos-skills/references/catalogue/节点容器运行时磁盘使用率过高/节点容器运行时磁盘使用率过高_日志或临时文件堆积.md","title":"节点容器运行时磁盘使用率过高 Skill","category":"anthropic-skill","format":"markdown","content":"**用例名称** 日志或临时文件堆积 导致 节点容器运行时磁盘使用率过高\n\n**故障现象**：\n1. 节点磁盘使用率告警（大于85%）\n2. 容器无法写入数据\n3. `/var/log`、`/tmp` 目录占用空间大\n\n**资源准备**：\n1. 确认应用 A/B 已正常运行\n2. 确认节点磁盘空间充足\n\n**演练步骤**：\n1. 定位运行应用 A Pod 的节点\n2. 使用 chaosblade 或其他故障注入工具向节点 `/var/log` 或 `/tmp` 目录持续写入数据，模拟日志或临时文件堆积\n   - **路径语义**：在 K8s CRD 模式下（默认），`--path /tmp` 或 `--path /var/log` 是相对于容器 overlay 文件系统的路径，填充数据**通常**写入 imagefs 分区（需节点有独立 imagefs）；`--path /var/lib/docker` 等宿主机路径**通常**写入 nodefs 分区。实际分区取决于节点配置，验证时需确认检查的分区与填充目标分区一致\n3. 观察节点磁盘使用率变化\n\n**CRD 模式路径→分区映射表**：\n**注意**：下表为常见配置下的启发式映射。实际分区取决于节点的挂载配置：\n- 如果节点没有独立的 imagefs（容器运行时数据在根磁盘），所有路径都在 nodefs 上\n- `/var/lib/docker`、`/var/lib/containerd` 在独立磁盘时属于 imagefs（它们定义了 imagefs），不是 nodefs\n- 验证时以 `df -h`（无路径参数）的实际输出为准，而非下表\n\n在 K8s CRD 模式下（ChaosBlade Operator），`--path` 参数决定填充数据写入哪个分区。验证时**必须**检查对应分区，否则会产生假阴性。\n\n| `--path` 值 | 目标分区 | 典型后端设备 | 正确验证命令 | 常见假阴性命令 |\n|---|---|---|---|---|\n| `/tmp`, `/var/log`, `/var/run`, `/run` | imagefs（容器 overlay） | `/dev/vdb` 等独立磁盘 | `df -h`（无路径参数）列出所有挂载点，找 overlay 分区 | `df -h /host`（仅显示 nodefs） |\n| `/var/lib/docker`, `/var/lib/containerd`, `/var/lib/kubelet` | nodefs（根文件系统） | `/dev/vda3` 等根分区 | `df -h /host` 显示根分区使用率 | `df -h`（找错 overlay 分区） |\n| `/etc`, `/root`, `/home` | nodefs（根文件系统） | `/dev/vda3` 等根分区 | `df -h /host` 显示根分区使用率 | 同上 |\n| 其他路径 | 需 `df -h` 列出全部后判定 | 不确定 | `df -h`（无路径参数）识别哪个分区使用率变化 | 仅检查单一分区 |\n\n**注入验证**：\n0. **基线完整性检查**（验证阶段第一步，必须先于其他验证步骤执行）：\n   - **首条命令必须**是 `df -h`（无路径参数），列出所有分区使用率，标注与注入 `--path` 对应的分区（根据上方路径→分区映射表）。禁止先执行 `df -h /host` 或 `df -h /host/<path>` — 这些命令只显示 nodefs，会在 imagefs 场景下产生错误基线\n   - 后续验证中，只对比**同一分区**的使用率变化。禁止将 nodefs 基线与 imagefs 注入后数据做对比\n   - 若未在注入前记录目标分区基线，须在验证结论中注明\"No pre-injection baseline available for <分区类型>\"，并以首次检查值作为参考点\n   - 若首次检查值已接近注入参数预期值（如 `--percent 85` 对应 84%），此即故障生效的证据，无需等待\"变化\"\n1. 查看节点磁盘使用率，确认磁盘使用率变化。通过 `kubectl debug` 两步法查看宿主机磁盘使用率：\n   - Step 1：`kubectl debug node/<节点名> --image=busybox -- sleep 3600`（必须含 `-- sleep 3600` 保活，裸 busybox 会立即退出）\n   - Step 2：从 Step 1 输出找到 debug pod 名称，然后 `kubectl exec <debug-pod> -n default -- df -h`\n   - `df -h` 列出所有挂载的文件系统。如果节点有多个磁盘分区（如 nodefs 和 imagefs 分开），需检查**所有分区**的使用率变化。`df -h /host` 仅显示 nodefs（根分区）；imagefs 的变化需通过 `df -h` 列出所有挂载点来识别\n   - **注意**：otel-c-tool 不挂载 /host，`kubectl exec <otel-c-tool> -- df -h` 显示的是 overlay 文件系统，不能用于宿主机磁盘验证。禁止仅通过 `kubectl exec <Pod> -- df -h` 验证（容器 overlay 文件系统≠宿主机文件系统）\n2. 检查 `/var/log`、`/tmp` 目录大小，确认占用显著。需通过 kubectl debug 两步法进入 debug pod，路径加 `/host/` 前缀（如 `du -sh /host/tmp`、`du -sh /host/var/log`）\n\n   **CRD 模式重要提醒**：`du -sh /host/<path>` 检查的是宿主机文件系统（nodefs）。如果注入使用了 `--path /var/log` 或 `--path /tmp`（在 CRD 模式下写入容器 overlay/imagefs），`du` 将看到宿主机路径的**原始大小**，不会反映 fill 数据。此时 `df -h`（bare, 无路径参数）展示的 overlay/imagefs 使用率变化才是 fill 效果的正确证据。\n\n   - 若 `df -h` 已确认目标分区使用率达到预期 → Step 2 可标记为 `expected: du checks host nodefs, fill in imagefs overlay (confirmed by df -h)`，不要标记为 `failed`\n   - 若 fill 路径映射到 nodefs（如 `--path /var/lib/docker`）→ `du -sh /host/<path>` 应能观察到增长\n3. 使用容器运行时工具查看容器、镜像和日志占用\n4. 使用 `kubectl describe node <节点名>` 检查 DiskPressure 条件，确认 K8s 层面已检测到磁盘压力\n\n**验证语义说明**：区分两个概念：(1) 注入验证——填充数据是否写入成功（通过填充文件或磁盘增量判断）；(2) 场景验证——磁盘使用率是否达到 85%。注入验证通过但场景验证未达标时，Layer 2 应报告 'passed' 并在 Warnings 中注明阈值未达到。如果使用率未达 85%，说明 --size 参数过小，应增加 size 或改用 percent 参数。这不代表注入失败。\n\n**注入恢复**：\n1. 销毁 chaosblade 实验\n2. 停止数据写入或删除创建的大文件\n3. 清理日志文件\n\n**恢复验证**：\n1. 查看节点磁盘使用率，确认恢复到正常水平。使用 kubectl debug 两步法（同注入验证），执行 `df -h`（无路径参数）检查所有磁盘分区均恢复\n2. 确认应用 A/B 可正常写入数据\n3. 确认 `/var/log`、`/tmp` 目录大小恢复正常（需通过宿主机文件系统访问方式验证）\n\n**基准事实**：\n- **根因**：容器日志或临时文件未清理，导致磁盘空间被占满\n- **必现现象**：节点磁盘使用率大于85%，`/var/log` 或 `/tmp` 目录占用空间大\n","isInternal":false,"tokens":2317,"sizeBytes":6449},{"name":"chaosblade-commands.md","path":"blade-ai/skills/k8s-chaos-skills/references/chaosblade-commands.md","rawUrl":"https://raw.githubusercontent.com/chaosblade-io/chaosblade/HEAD/blade-ai/skills/k8s-chaos-skills/references/chaosblade-commands.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Chaosblade K8s 命令速查表\n\n本文件提供 Chaosblade 在 Kubernetes 环境下常用故障注入命令的速查，减少执行过程中反复 `-h` 查看帮助。\n\n---\n\n## 通用语法\n\n```bash\nblade create k8s <scope>-<target> <action> [flags]\n```\n\n- `<scope>`: 作用范围，可选 `pod`、`node`、`container`\n- `<target>`: 故障目标，如 `cpu`、`network`、`disk`、`process`、`pod`(仅Pod级别)\n- `<action>`: 故障动作，如 `fullload`、`drop`、`dns`、`occupy`、`fill`、`kill`\n\n## Action 对照表（scope-target → 可用 action）\n\n| scope-target | 可用 action | 说明 |\n|---|---|---|\n| pod-cpu | `fullload` | CPU 满载 |\n| pod-mem | `load` | 内存占用 |\n| pod-network | `dns`, `drop`, `occupy` | 网络故障 (v1.8.0) |\n| pod-disk | `fill`, `burn` | 磁盘填充 / IO 负载 |\n| pod-process | `kill`, `stop` | 进程操作 |\n| pod-pod | `delete` | Pod 删除 |\n| pod-IO | `delay`, `errno` | 文件系统 IO 故障 |\n| node-cpu | `fullload` | CPU 满载 |\n| node-mem | `load` | 内存占用 |\n| node-network | `drop` | 网络故障 (v1.8.0: `delay`/`loss` → `drop`) |\n| node-disk | `fill`, `burn` | 磁盘填充 / IO 负载 (**无 fullload**) |\n| node-process | `kill`, `stop` | 进程操作 |\n| container-cpu | `fullload` | CPU 满载 |\n| container-network | `drop` | 网络故障 (v1.8.0: `delay`/`loss` → `drop`) |\n| container-process | `kill`, `stop` | 进程操作 |\n| container-container | `remove` | 容器删除 |\n\n> **⚠️ 常见错误警示**：\n> - `node-disk` **没有** `fullload` action！磁盘 IO 负载使用 `burn`，磁盘空间填充使用 `fill`\n> - `pod-disk` 同理，只有 `fill` 和 `burn`，没有 `fullload`\n> - `pod-mem` 的 action 是 `load`，不是 `fullload`\n> - `node-mem` 的 action 是 `load`，不是 `fullload`\n> - 只有 `cpu` target 才有 `fullload` action\n> - **注入前务必确认 scope-target-action 组合在上表中存在**，避免因 action 不存在导致注入失败\n\n## 通用 K8s Flags\n\n以下参数适用于所有 `blade create k8s` 命令：\n\n| Flag | 说明 | 示例 |\n|------|------|------|\n| `--namespace` | 目标命名空间 | `--namespace default` |\n| `--labels` | 按标签筛选资源 | `--labels \"app=nginx\"` |\n| `--names` | 按名称指定资源（逗号分隔） | `--names node-1,node-2` |\n| `--kubeconfig` | kubeconfig 文件路径 | `--kubeconfig ~/.kube/config` |\n| `--evict-count` | 限制影响的资源数量 | `--evict-count 1` |\n| `--evict-percent` | 限制影响的资源百分比 | `--evict-percent 50` |\n| `--waiting-time` | 等待结果的超时时间 | `--waiting-time 30s` |\n| `--timeout` | 实验自动过期时间（秒） | `--timeout 600` |\n\n---\n\n## 一、Pod 级别故障\n\n### 1. Pod CPU 满载\n\n```bash\nblade create k8s pod-cpu fullload \\\n  --namespace <ns> \\\n  --labels \"app=<app>\" \\\n  --cpu-percent <0-100> \\\n  --cpu-count <核数> \\\n  --kubeconfig ~/.kube/config\n```\n\n| Flag | 说明 | 默认值 |\n|------|------|--------|\n| `--cpu-percent` | CPU 使用率百分比 | 100 |\n| `--cpu-count` | 指定满载的 CPU 核数（不指定则全部） | 全部 |\n| `--cpu-list` | 指定满载的 CPU 核编号（如 0,1,2） | - |\n| `--timeout` | 自动恢复时间（秒） | - |\n\n### 2. Pod 内存压力\n\n```bash\nblade create k8s pod-mem load \\\n  --namespace <ns> \\\n  --labels \"app=<app>\" \\\n  --mode ram \\\n  --mem-percent <0-100> \\\n  --kubeconfig ~/.kube/config\n```\n\n| Flag | 说明 | 默认值 |\n|------|------|--------|\n| `--mode` | 内存占用模式：`ram`(物理内存) / `cache` | ram |\n| `--mem-percent` | 内存使用率百分比 | - |\n| `--reserve` | 保留的内存大小（如 `200m`） | - |\n| `--rate` | 内存增长速率（每秒MB） | - |\n\n### 3. Pod 网络延迟\n\n> **⚠️ v1.8.0 不可用**：`pod-network delay` 在 blade v1.8.0 中不存在（仅 `dns`/`drop`/`occupy`）。如需延迟效果，使用 Tier 2 kubectl-native 方案（tc qdisc）。以下为旧版参考：\n\n```bash\nblade create k8s pod-network delay \\\n  --namespace <ns> \\\n  --labels \"app=<app>\" \\\n  --time <毫秒> \\\n  --interface eth0 \\\n  --kubeconfig ~/.kube/config\n```\n\n| Flag | 说明 | 默认值 |\n|------|------|--------|\n| `--time` | 延迟时间（毫秒） | - |\n| `--offset` | 延迟波动范围（毫秒） | - |\n| `--interface` | 网络接口 | eth0 |\n| `--local-port` | 本地端口（逗号分隔） | 全部 |\n| `--remote-port` | 远程端口（逗号分隔） | 全部 |\n| `--destination-ip` | 目标 IP（逗号分隔） | 全部 |\n| `--exclude-port` | 排除端口 | - |\n| `--exclude-ip` | 排除 IP | - |\n\n### 4. Pod 网络丢包\n\n```bash\nblade create k8s pod-network drop \\\n  --namespace <ns> \\\n  --labels \"app=<app>\" \\\n  --kubeconfig ~/.kube/config\n```\n\n> **⚠️ drop 是全量丢包**（iptables DROP 语义），**不支持 `--percent` 和 `--interface`**。不带端口/IP 过滤时丢弃所有出方向流量。\n\n| Flag | 说明 | 默认值 |\n|------|------|--------|\n| `--source-port` | 源端口（逗号分隔） | 全部 |\n| `--destination-port` | 目标端口（逗号分隔） | 全部 |\n| `--source-ip` | 源 IP | 全部 |\n| `--destination-ip` | 目标 IP | 全部 |\n| `--network-traffic` | 流量方向：`in` / `out` | - |\n| `--string-pattern` | 匹配数据包内容 | - |\n\n> **爆炸半径控制提示**：drop 默认丢弃全部流量，**必须**使用 `--source-port` 或 `--destination-port` 或 `--destination-ip` 限制影响范围，避免丢弃 DNS、监控等非目标流量。仅在测试完全网络分区时使用不加过滤的注入。\n\n### 5. Pod DNS 故障\n\n```bash\nblade create k8s pod-network dns \\\n  --namespace <ns> \\\n  --labels \"app=<app>\" \\\n  --domain <域名> \\\n  --ip <伪造IP> \\\n  --kubeconfig ~/.kube/config\n```\n\n| Flag | 说明 | 默认值 |\n|------|------|--------|\n| `--domain` | 目标域名 | - |\n| `--ip` | 映射的伪造 IP | - |\n\n### 6. Pod 网络包损坏\n\n```bash\nblade create k8s pod-network corrupt \\\n  --namespace <ns> \\\n  --labels \"app=<app>\" \\\n  --percent <0-100> \\\n  --interface eth0 \\\n  --kubeconfig ~/.kube/config\n```\n\n### 7. Pod 网络包重复\n\n```bash\nblade create k8s pod-network duplicate \\\n  --namespace <ns> \\\n  --labels \"app=<app>\" \\\n  --percent <0-100> \\\n  --interface eth0 \\\n  --kubeconfig ~/.kube/config\n```\n\n### 8. Pod 磁盘填充\n\n```bash\nblade create k8s pod-disk fill \\\n  --namespace <ns> \\\n  --labels \"app=<app>\" \\\n  --path <目录> \\\n  --size <大小> \\\n  --kubeconfig ~/.kube/config\n```\n\n| Flag | 说明 | 默认值 |\n|------|------|--------|\n| `--path` | 填充的目标目录 | / |\n| `--size` | 填充大小（如 `1024m`、`10g`） | - |\n| `--percent` | 填充到磁盘使用率百分比 | - |\n| `--retain-handle` | 保留文件句柄（删除文件后不释放空间） | false |\n\n### 9. Pod 磁盘 IO 读写负载\n\n```bash\nblade create k8s pod-disk burn \\\n  --namespace <ns> \\\n  --labels \"app=<app>\" \\\n  --path <目录> \\\n  --read \\\n  --write \\\n  --kubeconfig ~/.kube/config\n```\n\n| Flag | 说明 | 默认值 |\n|------|------|--------|\n| `--path` | IO 负载目标目录 | / |\n| `--read` | 读 IO 负载 | false |\n| `--write` | 写 IO 负载 | false |\n| `--size` | 每次 IO 块大小（如 `10m`） | - |\n| `--count` | IO 次数 | - |\n\n### 10. Pod 文件系统 IO 故障\n\n```bash\nblade create k8s pod-IO delay \\\n  --namespace <ns> \\\n  --labels \"app=<app>\" \\\n  --time <毫秒> \\\n  --path <目录> \\\n  --kubeconfig ~/.kube/config\n```\n\n| Action | 说明 |\n|--------|------|\n| `delay` | 文件系统 IO 延迟 |\n| `errno` | 文件系统 IO 返回错误 |\n\n| Flag | 说明 | 默认值 |\n|------|------|--------|\n| `--time` | IO 延迟（毫秒），仅 `delay` | - |\n| `--errno` | 返回的错误码，仅 `errno` | 28 (ENOSPC) |\n| `--path` | 影响的文件路径 | - |\n| `--methods` | 拦截的系统调用（如 read,write） | 全部 |\n| `--percent` | 故障生效百分比 | 100 |\n\n### 11. Pod 进程操作\n\n```bash\nblade create k8s pod-process kill \\\n  --namespace <ns> \\\n  --labels \"app=<app>\" \\\n  --process <进程名> \\\n  --kubeconfig ~/.kube/config\n```\n\n| Action | 说明 |\n|--------|------|\n| `kill` | 杀掉进程 |\n| `stop` | 挂起进程（SIGSTOP） |\n\n| Flag | 说明 | 默认值 |\n|------|------|--------|\n| `--process` | 进程名 | - |\n| `--process-cmd` | 进程命令行关键词 | - |\n| `--signal` | 发送的信号（仅 kill） | 9 |\n| `--count` | 限制影响的进程数 | - |\n\n### 12. Pod 删除\n\n```bash\nblade create k8s pod-pod delete \\\n  --namespace <ns> \\\n  --labels \"app=<app>\" \\\n  --kubeconfig ~/.kube/config\n```\n\n| Flag | 说明 | 默认值 |\n|------|------|--------|\n| `--labels` | 标签筛选 | - |\n| `--names` | 指定 Pod 名称 | - |\n| `--evict-count` | 删除的 Pod 数量 | - |\n| `--evict-percent` | 删除的 Pod 百分比 | - |\n\n---\n\n## 二、Node 级别故障\n\n### 1. 节点 CPU 满载\n\n```bash\nblade create k8s node-cpu fullload \\\n  --names <节点名> \\\n  --cpu-percent <0-100> \\\n  --kubeconfig ~/.kube/config\n```\n\nFlags 与 Pod CPU 满载一致（`--cpu-percent`、`--cpu-count`、`--cpu-list`）。\n\n### 2. 节点内存压力\n\n```bash\nblade create k8s node-mem load \\\n  --names <节点名> \\\n  --mode ram \\\n  --mem-percent <0-100> \\\n  --kubeconfig ~/.kube/config\n```\n\nFlags 与 Pod 内存压力一致（`--mode`、`--mem-percent`、`--reserve`、`--rate`）。\n\n### 3. 节点网络延迟\n\n> **⚠️ v1.8.0 不可用**：`node-network delay` 在 blade v1.8.0 中不存在。以下为旧版参考：\n\n```bash\nblade create k8s node-network delay \\\n  --names <节点名> \\\n  --time <毫秒> \\\n  --interface eth0 \\\n  --kubeconfig ~/.kube/config\n```\n\n### 4. 节点网络丢包\n\n```bash\nblade create k8s node-network drop \\\n  --names <节点名> \\\n  --kubeconfig ~/.kube/config\n```\n\n> **⚠️ 同 Pod drop：全量丢包，不支持 `--percent` 和 `--interface`。** 用 `--source-port`/`--destination-ip` 缩小范围。\n\nNode 网络 Flags 与 Pod 网络一致（`--source-port`、`--destination-port`、`--source-ip`、`--destination-ip`、`--network-traffic` 等）。\n\n### 5. 节点磁盘填充\n\n```bash\nblade create k8s node-disk fill \\\n  --names <节点名> \\\n  --path <目录> \\\n  --size <大小> \\\n  --kubeconfig ~/.kube/config\n```\n\n| Flag | 说明 | 示例 |\n|------|------|------|\n| `--path` | 填充目标目录 | `/var/lib/docker` |\n| `--size` | 填充大小 | `50g` |\n| `--percent` | 填充到磁盘使用率 | `95` |\n\n### 6. 节点磁盘 IO 负载\n\n```bash\nblade create k8s node-disk burn \\\n  --names <节点名> \\\n  --read \\\n  --write \\\n  --path <目录> \\\n  --kubeconfig ~/.kube/config\n```\n\n| Flag | 说明 | 默认值 |\n|------|------|--------|\n| `--read` | 启用读 IO 负载 | false |\n| `--write` | 启用写 IO 负载 | false |\n| `--path` | IO 负载目标目录 | / |\n| `--size` | 每次 IO 块大小（如 `10m`） | - |\n| `--count` | IO 次数 | - |\n\n> **建议**：生产环境务必指定 `--path` 为非根分区目录（如 `/data`），避免影响根分区系统文件。\n\n### 7. 节点进程操作\n\n```bash\nblade create k8s node-process kill \\\n  --names <节点名> \\\n  --process <进程名> \\\n  --kubeconfig ~/.kube/config\n```\n\nActions 和 Flags 与 Pod 进程操作一致。\n\n---\n\n## 三、Container 级别故障\n\nContainer 级别命令在 Pod 内指定特定容器执行故障注入，适用于多容器 Pod（如有 sidecar 的场景）。\n\n### 通用 Container Flag\n\n| Flag | 说明 |\n|------|------|\n| `--container-names` | 目标容器名 |\n\n### 1. 容器 CPU 满载\n\n```bash\nblade create k8s container-cpu fullload \\\n  --namespace <ns> \\\n  --labels \"app=<app>\" \\\n  --container-names <容器名> \\\n  --cpu-percent <0-100> \\\n  --kubeconfig ~/.kube/config\n```\n\n### 2. 容器网络延迟\n\n> **⚠️ v1.8.0 不可用**：`container-network delay` 在 blade v1.8.0 中不存在。以下为旧版参考：\n\n```bash\nblade create k8s container-network delay \\\n  --namespace <ns> \\\n  --labels \"app=<app>\" \\\n  --container-names <容器名> \\\n  --time <毫秒> \\\n  --interface eth0 \\\n  --kubeconfig ~/.kube/config\n```\n\n### 3. 容器进程操作\n\n```bash\nblade create k8s container-process kill \\\n  --namespace <ns> \\\n  --labels \"app=<app>\" \\\n  --container-names <容器名> \\\n  --process <进程名> \\\n  --kubeconfig ~/.kube/config\n```\n\n### 4. 容器删除\n\n```bash\nblade create k8s container-container remove \\\n  --namespace <ns> \\\n  --labels \"app=<app>\" \\\n  --container-names <容器名> \\\n  --kubeconfig ~/.kube/config\n```\n\n---\n\n## 四、实验管理命令\n\n### 查看实验状态\n\n```bash\n# 查看所有进行中的实验\nblade status --type create\n\n# 查看指定实验详情\nblade status <UID>\n```\n\n### 销毁实验\n\n```bash\n# 销毁指定实验\nblade destroy <UID>\n\n# 批量销毁所有实验（紧急回滚用）\nblade status --type create | grep \"^UID\" | awk '{print $2}' | xargs -I {} blade destroy {}\n```\n\n### 版本与帮助\n\n```bash\n# 查看版本\nblade version\n\n# 查看所有支持的实验场景\nblade create -h\n\n# 查看某个场景的详细帮助\nblade create k8s pod-network drop -h\n```\n\n---\n\n## 五、常见演练场景速查\n\n按照 catalogue 中使用频率最高的故障场景，汇总对应的 blade 命令：\n\n### 资源压力类\n\n| 故障场景 | 命令 |\n|---------|------|\n| Pod CPU 满载 | `blade create k8s pod-cpu fullload --cpu-percent 80 --namespace <ns> --labels \"app=<app>\"` |\n| Pod 内存压力 | `blade create k8s pod-mem load --mode ram --mem-percent 90 --namespace <ns> --labels \"app=<app>\"` |\n| 节点 CPU 满载 | `blade create k8s node-cpu fullload --cpu-percent 90 --names <node>` |\n| 节点内存压力 | `blade create k8s node-mem load --mode ram --mem-percent 95 --names <node>` |\n\n### 网络故障类\n\n| 故障场景 | 命令 |\n|---------|------|\n| Pod 网络丢包(全量) | `blade create k8s pod-network drop --namespace <ns> --labels \"app=<app>\"` |\n| Pod 网络丢包(指定端口) | `blade create k8s pod-network drop --source-port 3306 --namespace <ns> --labels \"app=<app>\"` |\n| Pod DNS 故障 | `blade create k8s pod-network dns --domain example.com --ip 1.1.1.1 --namespace <ns> --labels \"app=<app>\"` |\n| 节点网络丢包 | `blade create k8s node-network drop --names <node>` |\n\n### 磁盘故障类\n\n| 故障场景 | 命令 |\n|---------|------|\n| Pod 磁盘填充 | `blade create k8s pod-disk fill --path /data --size 10g --namespace <ns> --labels \"app=<app>\"` |\n| 节点磁盘填充 | `blade create k8s node-disk fill --path /var/lib/docker --percent 95 --names <node>` |\n| 节点磁盘 IO 负载 | `blade create k8s node-disk burn --read --write --path /data --names <node>` |\n\n### 进程与 Pod 操作类\n\n| 故障场景 | 命令 |\n|---------|------|\n| 杀 Pod 内进程 | `blade create k8s pod-process kill --process <name> --namespace <ns> --labels \"app=<app>\"` |\n| 挂起 Pod 内进程 | `blade create k8s pod-process stop --process <name> --namespace <ns> --labels \"app=<app>\"` |\n| 删除 Pod | `blade create k8s pod-pod delete --namespace <ns> --labels \"app=<app>\" --evict-count 1` |\n| 杀节点进程 | `blade create k8s node-process kill --process <name> --names <node>` |\n\n---\n\n## 六、Operator YAML 模板\n\n当使用 Operator 方式（`kubectl apply`）执行持续化演练时，使用以下模板：\n\n```yaml\napiVersion: chaosblade.io/v1alpha1\nkind: ChaosBlade\nmetadata:\n  name: <experiment-name>\nspec:\n  experiments:\n    - scope: <pod|node|container>\n      target: <cpu|network|disk|process|pod|container>\n      action: <action>\n      desc: \"<实验描述>\"\n      matchers:\n        - name: namespace\n          value: [\"<namespace>\"]\n        - name: labels\n          value: [\"app=<app-name>\"]\n        # node 级别使用 names 而非 labels\n        # - name: names\n        #   value: [\"<node-name>\"]\n      flags:\n        - name: <flag-name>\n          value: \"<flag-value>\"\n```\n\n**Operator YAML 示例 - Pod CPU 满载：**\n\n```yaml\napiVersion: chaosblade.io/v1alpha1\nkind: ChaosBlade\nmetadata:\n  name: pod-cpu-fullload\nspec:\n  experiments:\n    - scope: pod\n      target: cpu\n      action: fullload\n      desc: \"Pod CPU 满载 80%\"\n      matchers:\n        - name: namespace\n          value: [\"default\"]\n        - name: labels\n          value: [\"app=nginx\"]\n      flags:\n        - name: cpu-percent\n          value: \"80\"\n```\n\n**Operator YAML 示例 - Pod 网络延迟：**\n\n```yaml\napiVersion: chaosblade.io/v1alpha1\nkind: ChaosBlade\nmetadata:\n  name: pod-network-delay\nspec:\n  experiments:\n    - scope: pod\n      target: network\n      action: delay\n      desc: \"Pod 网络延迟 3s\"\n      matchers:\n        - name: namespace\n          value: [\"default\"]\n        - name: labels\n          value: [\"app=nginx\"]\n      flags:\n        - name: time\n          value: \"3000\"\n        - name: interface\n          value: \"eth0\"\n```\n\n**Operator 管理命令：**\n\n```bash\n# 创建实验\nkubectl apply -f experiment.yaml\n\n# 查看实验状态\nkubectl get chaosblade <experiment-name> -o yaml\n\n# 销毁实验\nkubectl delete chaosblade <experiment-name>\n\n# 销毁所有实验\nkubectl delete chaosblade --all\n```\n\n---\n\n## 七、kubectl exec 注入路径\n\n当宿主机 blade CLI 不可用（未安装或版本不兼容，如报 `unknown flag` 错误）时，可通过 kubectl exec 在集群内的 tool Pod 中执行 blade 命令。\n\n### 前提条件\n- 集群中部署了 chaosblade-tool DaemonSet（如 otel-c-tool）\n- tool Pod 的 ServiceAccount 有操作目标资源的权限\n\n### 执行步骤\n\n1. 发现可用的 tool Pod：\n   ```bash\n   kubectl get pods -n chaosblade -l app=otel-c-tool --kubeconfig=<path>\n   ```\n2. 选择 STATUS=Running 的 Pod（任意一个均可，实验是集群级别的）\n3. 执行 blade 命令：\n   ```bash\n   kubectl exec <pod> -n chaosblade -- blade create k8s <scenario> [flags] --kubeconfig=<path>\n   ```\n4. 从 JSON 输出中提取 blade_uid 用于后续恢复\n\n### 示例：Pod 网络丢包\n\n```bash\n# 1. 发现 tool Pod\nkubectl get pods -n chaosblade -l app=otel-c-tool --kubeconfig=/path/to/config\n# 2. 通过 tool Pod 执行 blade create\nkubectl exec otel-c-tool-xxxxx -n chaosblade -- \\\n  blade create k8s pod-network drop \\\n  --namespace cms-demo \\\n  --labels \"app=myapp\" \\\n  --kubeconfig=/path/to/config\n# 3. 从输出中提取 blade_uid\n# {\"code\":200,\"success\":true,\"result\":\"abc123\"}\n# 4. 恢复时同样通过 tool Pod 执行 blade destroy\nkubectl exec otel-c-tool-xxxxx -n chaosblade -- \\\n  blade destroy abc123 --kubeconfig=/path/to/config\n```\n\n### 注意事项\n- 不同 tool Pod 可能运行在不同节点上，但 blade 命令通过 API Server 执行，任何健康 Pod 都可操作\n- tool Pod 可能因 DaemonSet 轮换而重启，恢复时需重新查找 Running 的 Pod\n- kubectl exec 中的 blade 命令参数与本地 blade CLI 完全一致\n","isInternal":false,"tokens":6498,"sizeBytes":18550},{"name":"SKILL.md","path":"blade-ai/skills/k8s-chaos-skills/SKILL.md","rawUrl":"https://raw.githubusercontent.com/chaosblade-io/chaosblade/HEAD/blade-ai/skills/k8s-chaos-skills/SKILL.md","title":"k8s-chaos-skills","category":"anthropic-skill","format":"markdown","content":"---\nname: k8s-chaos-skills\ndescription: |\n  Kubernetes 故障演练与混沌工程专家。当用户需要进行 K8s 故障注入测试、混沌工程演练、系统韧性验证、故障场景模拟时，立即使用此 skill。\n\n  内置多个标准化故障注入用例，覆盖 Pod（Pending、CrashLoopBackOff、OOM、CPU 满载、内存接近 Limit、磁盘满、Terminating 卡住、镜像拉取失败等）、Workload（副本不一致、HPA 副本达到上限、DaemonSet 未完全调度）、Service（状态异常、负载均衡异常）、Node（宕机、磁盘使用率过高、磁盘 IO 过高、CPU 使用率过高、内存使用率过高）、存储（PVC 挂载 Pending）五个层级。\n\n  通过「意图识别 → 用例选择 → 用例执行」的决策树流程，精确匹配用户需求并执行对应演练方案。即使用户只是笼统地说「帮我做个故障演练」或「测试下应用的容错能力」，也应该触发此 skill 引导用户完成完整流程。\n\nscripts:\n  - name: list_scenarios.py\n    description: \"列出当前支持的所有故障演练场景（JSON 结构化输出）\"\n  - name: inject_cni_exhaust.py\n    description: \"CNI IP 耗尽注入 — 自动计算副本数，精确耗尽目标节点 IP 而不触发 OutOfpods。参数: --namespace <ns> --node <node> --kubeconfig <path>\"\n---\n\n# K8s 故障演练\n\n```\n意图识别 ──→ 用例选择 ──→ 用例执行\n(提取四维度)  (决策树匹配)  (读取文件并按步骤执行)\n```\n\n## 安全红线\n\n以下规则优先级高于一切操作指令，在任何步骤中都不得违反：\n\n- **隔离**：在隔离命名空间或测试集群演练，严禁在生产核心链路注入\n- **最小影响**：用精确标签选择器定位目标，范围尽可能小\n- **可回滚**：注入前明确回滚方案，确保 30 秒内可恢复\n- **有监控**：无监控不演练\n- **仅限已有用例**：只能执行 `references/catalogue/` 中已有的故障注入用例，严禁自行编造、拼凑或即兴发挥用例中未涉及的故障注入操作。无法匹配时必须明确告知用户「当前不支持该场景」并停止\n- **禁止**：业务高峰期演练 / 对 etcd、kube-apiserver 等控制平面注入 / 无备份对 StatefulSet 做破坏性实验\n\n---\n\n## 第一步：意图识别\n\n从用户输入中提取四个维度：\n\n| 维度 | 说明 | 示例 |\n|------|------|------|\n| **故障层级** | 作用在哪个层面 | Pod / Workload / Service / Node |\n| **故障现象** | 期望模拟的表现 | Pending、OOM、CPU 高 |\n| **故障原因** | 具体根因 | 资源不足、配置错误 |\n| **目标应用** | 注入目标 | 应用名、命名空间 |\n| **kubeconfig** | 集群凭证路径 | `~/.kube/config` |\n\n**层级判断关键词：**\n\n| 关键词 | 层级 |\n|--------|-----|\n| pod、容器、崩溃、重启、OOM、CPU高、内存高、镜像、挂载、磁盘空间、磁盘IO | Pod |\n| 副本、deployment、扩容、缩容 | Workload |\n| service、服务发现、负载均衡、端口、endpoints | Service |\n| 节点、node、磁盘、宿主机 | Node |\n\n**信息不全时的处理：**\n- 用户明确说出故障现象 → 直接进入第二步\n- 用户只说大致目标（如「测试容错」） → 提问引导确认四个维度\n- 用户描述生产问题要复现 → 从描述提取现象和原因，匹配用例\n- 匹配到多个用例 → 列出候选，让用户选择\n- 只说了现象没说根因 → 推荐该分类下最常见的用例，并列出其他选项\n- 不在覆盖范围 → 明确告知「当前不支持该场景」，停止操作，严禁自行构造用例外的故障注入\n\n---\n\n## 第二步：用例选择（动态发现）\n\n所有用例存储在 `references/catalogue/` 下，通过目录结构和文件命名规约自动发现，无需维护静态索引。\n\n### 命名规约\n\n```\nreferences/catalogue/\n├── <故障分类>/                         # 目录名 = 故障层级_故障现象（每个目录对应唯一的 Scope+Target+Action 组合）\n│   ├── <故障分类>_<根因A>.md           # 文件名 = 分类名_具体根因\n│   ├── <故障分类>_<根因B>.md\n│   └── ...\n└── ...\n```\n\n示例：\n- `references/catalogue/Pod_Pending/Pod_Pending_节点资源不足.md`\n- `references/catalogue/Pod_磁盘空间使用率过高/Pod_磁盘空间使用率过高_应用日志数据积累.md`（pod-disk fill）\n- `references/catalogue/Pod_磁盘IO过高/Pod_磁盘IO过高_异常IO占用.md`（pod-disk burn）\n\n### 发现流程\n\n**第 1 步：列出所有分类目录，匹配故障现象**\n\n```bash\nls references/catalogue/\n```\n\n从返回的目录名中，根据第一步识别的故障现象选择最匹配的目录。目录名本身已包含故障层级和故障现象信息（如 `Pod_Pending`、`service_conditions状态异常`、`节点容器运行时磁盘使用率过高`）。\n\n**第 2 步：列出该目录下所有用例文件，匹配根因**\n\n```bash\nls references/catalogue/<匹配的目录>/\n```\n\n从返回的文件名中，根据用户描述的根因选择最匹配的文件。文件名中 `_` 后的部分即为该用例对应的根因。\n\n- 如果用户明确了根因 → 直接选择对应文件\n- 如果用户未说明根因 → 将文件列表展示给用户，让用户选择\n- 如果没有匹配的文件 → 告知用户「当前不支持该场景」，停止操作\n\n### 新增/删除用例\n\n遵循命名规约即可，无需修改本文件：\n- **新增用例**：在对应分类目录下新建 `<分类>_<根因>.md`\n- **新增分类**：新建目录 `<故障层级>_<故障现象>/`，在其中添加用例文件\n- **删除用例**：直接删除对应 `.md` 文件\n\n### 辅助脚本\n\n- `scripts/list_scenarios.py`：一键列出所有已支持的演练场景（JSON 结构化输出），用于快速总览或对接外部系统\n  用法：`execute_skill_script(skill_name=\"k8s-chaos-skills\", script_name=\"list_scenarios.py\")`\n\n---\n\n## 第三步：用例执行\n\n1. 读取 `references/catalogue/<分类目录>/<用例文件>.md`\n2. 将用例中的占位符替换为用户实际参数（`应用 A` → 目标应用，`<namespace>` → 实际命名空间）\n3. 所有 `blade` 和 `kubectl` 命令必须显式指定 `--kubeconfig <路径>`，使用第一步中用户确认的 kubeconfig 路径，禁止依赖默认值\n4. 涉及 blade 命令时，查阅 `references/chaosblade-commands.md` 获取完整参数\n5. 严格按用例中的 **演练步骤 → 注入验证 → 注入恢复 → 恢复验证** 顺序执行\n6. 执行完毕后输出演练报告：\n\n```\n演练报告\n- 用例：[决策树路径，如 Pod > Pending > 节点资源不足]\n- 目标：[namespace/app-name]\n- 注入结果：[成功/失败] + 观察到的现象\n- 恢复结果：[成功/失败] + 是否符合基准事实\n- 发现的问题与改进建议\n```\n","frontmatter":{"name":"k8s-chaos-skills","description":"Kubernetes 故障演练与混沌工程专家。当用户需要进行 K8s 故障注入测试、混沌工程演练、系统韧性验证、故障场景模拟时，立即使用此 skill。\n\n内置多个标准化故障注入用例，覆盖 Pod（Pending、CrashLoopBackOff、OOM、CPU 满载、内存接近 Limit、磁盘满、Terminating 卡住、镜像拉取失败等）、Workload（副本不一致、HPA 副本达到上限、DaemonSet 未完全调度）、Service（状态异常、负载均衡异常）、Node（宕机、磁盘使用率过高、磁盘 IO 过高、CPU 使用率过高、内存使用率过高）、存储（PVC 挂载 Pending）五个层级。\n\n通过「意图识别 → 用例选择 → 用例执行」的决策树流程，精确匹配用户需求并执行对应演练方案。即使用户只是笼统地说「帮我做个故障演练」或「测试下应用的容错能力」，也应该触发此 skill 引导用户完成完整流程。\n","scripts":[{"name":"list_scenarios.py","description":"列出当前支持的所有故障演练场景（JSON 结构化输出）"},{"name":"inject_cni_exhaust.py","description":"CNI IP 耗尽注入 — 自动计算副本数，精确耗尽目标节点 IP 而不触发 OutOfpods。参数: --namespace <ns> --node <node> --kubeconfig <path>"}]},"isInternal":false,"tokens":2479,"sizeBytes":6866}],"systemPromptSnippet":"<yakaai_skills repo=\"chaosblade-io/chaosblade\">\n<!-- File: blade-ai/skills/k8s-chaos-skills/references/catalogue/DaemonSet_未完全调度/DaemonSet_未完全调度_节点不可调度.md (Tokens: ~815 | Category: anthropic-skill) -->\n**用例名称** 节点不可调度 导致 DaemonSet_未完全调度\n\n**故障现象**：\n1. DaemonSet 的 Ready 副本数小于期望副本数\n2. 部分节点上没有运行 DaemonSet Pod\n3. `kubectl get daemonset` 显示 DESIRED 与 READY 数量不一致\n\n**资源准备**：\n1. 确认 DaemonSet 应用 A 已正常运行，且所有节点均有副本\n2. 确认监控系统可观测 DaemonSet 副本状态\n\n**演练步骤**：\n1. 选取一个运行 DaemonSet Pod 的节点\n2. 使用 kubectl 将该节点标记为不可调度（cordon）：`kubectl cordon <node>`\n3. 给该节点添加一个 DaemonSet 未配置容忍的自定义污点：`kubectl taint nodes <node> chaos-drill/unschedulable=true:NoSchedule`\n4. 删除该节点上的 DaemonSet Pod，观察 Pod 是否被重建\n5. 观察 DaemonSet 副本数变化\n\n**注入验证**：\n1. 执行 `kubectl get nodes`，确认目标节点标记为 SchedulingDisabled\n2. 执行 `kubectl describe node <node>`，确认自定义污点 `chaos-drill/unschedulable=true:NoSchedule` 存在\n3. 执行 `kubectl get daemonset`，确认 DESIRED 与 READY 数量不一致\n4. 确认目标节点上的 DaemonSet Pod 删除后无法被重建\n\n**注入恢复**：\n1. 使用 kubectl 取消节点不可调度标记（uncordon）：`kubectl uncordon <node>`\n2. 移除自定义污点：`kubectl taint nodes <node> chaos-drill/unschedulable=true:NoSchedule-`\n3. 等待 DaemonSet Pod 在该节点重建\n\n**恢复验证**：\n1. 执行 `kubectl get nodes`，确认目标节点恢复为可调度状态\n2. 执行 `kubectl describe node <node>`，确认自定义污点已被移除\n3. 执行 `kubectl get daemonset`，确认 DESIRED 与 READY 数量一致\n4. 确认目标节点上 DaemonSet Pod 已正常运行\n\n**注意事项**：\n- Kubernetes ≥ 1.12 的 DaemonSet 默认容忍 `node.kubernetes.io/unschedulable` 污点，因此 `kubectl cordon` 不会阻止 DaemonSet Pod 调度\n- 必须添加自定义污点（DaemonSet 未配置容忍的），才能有效阻止 Pod 调度\n- 恢复时需一并移除自定义污点，否则 Pod 仍无法调度\n\n**基准事实**：\n- **根因**：节点被标记为不可调度（cordon）且存在 DaemonSet 未容忍的自定义污点，导致 DaemonSet 无法在该节点创建 Pod，副本数小于期望数\n- **必现现象**：DaemonSet DESIRED 与 READY 不一致；节点 SchedulingDisabled；节点存在自定义污点；节点上缺少 DaemonSet Pod\n\n<!-- File: blade-ai/skills/k8s-chaos-skills/references/catalogue/DNS_解析失败/DNS_解析失败_CoreDNS异常.md (Tokens: ~761 | Category: anthropic-skill) -->\n**用例名称** CoreDNS异常 导致 DNS_解析失败\n\n**故障现象**：\n1. Pod 内 DNS 解析失败，应用报 `Name or service not known` 或 `NXDOMAIN` 错误\n2. CoreDNS Pod 异常（CrashLoopBackOff/不可用）\n3. 集群内服务间调用因 DNS 解析失败而中断\n\n**资源准备**：\n1. 确认应用 A 已正常运行，且依赖集群 DNS 进行服务发现\n2. 确认 CoreDNS Deployment 正常运行\n3. 确认监控系统可观测 DNS 请求指标\n\n**演练步骤**：\n1. 记录 CoreDNS Deployment 当前副本数和配置，并获取其 Pod 选择器标签：\n   ```bash\n   kubectl get deployment coredns -n kube-system -o jsonpath='{.spec.selector.matchLabels}'\n   ```\n   记录返回的标签（如 `component=coredns` 或 `k8s-app=kube-dns`），后续步骤中用 `<coredns-label>` 表示该标签\n2. 将 CoreDNS Deployment 的副本数缩为 0，模拟 CoreDNS 完全不可用：\n   ```bash\n   kubectl scale deployment coredns -n kube-system --replicas=0\n   ```\n3. 在应用 A 的 Pod 内尝试进行 DNS 解析\n4. 观察应用 A 的服务间调用行为\n\n**注入验证**：\n1. 执行 `kubectl get pods -n kube-system -l <coredns-label>`（使用演练步骤 1 中获取的实际标签），确认无 CoreDNS Pod 运行\n2. 在应用 A 的 Pod 内执行 DNS 解析测试：\n   ```bash\n   kubectl exec <pod-name> -- nslookup kubernetes.default.svc.cluster.local\n   ```\n   确认解析失败\n3. 确认应用 A 依赖 DNS 的服务调用出现错误\n\n**注入恢复**：\n1. 恢复 CoreDNS 副本数：\n   ```bash\n   kubectl scale deployment coredns -n kube-system --replicas=<原始副本数>\n   ```\n2. 等待 CoreDNS Pod 启动并就绪\n\n**恢复验证**：\n1. 执行 `kubectl get pods -n kube-system -l <coredns-label>`（使用演练步骤 1 中获取的实际标签），确认 CoreDNS Pod 全部 Running 且 Ready\n2. 在应用 A 的 Pod 内重新执行 DNS 解析，确认恢复正常\n3. 确认应用 A 的服务间调用恢复\n\n**基准事实**：\n- **根因**：CoreDNS Pod 异常或不可用，导致集群内 DNS 解析服务中断，依赖 DNS 的服务发现和调用全部失败\n- **必现现象**：Pod 内 DNS 解析超时或返回 NXDOMAIN；CoreDNS Pod 不可用；服务间调用失败\n\n<!-- File: blade-ai/skills/k8s-chaos-skills/references/catalogue/HPA_副本达到上限/HPA_副本达到上限_资源饱和.md (Tokens: ~634 | Category: anthropic-skill) -->\n**用例名称** 资源饱和 导致 HPA_副本达到上限\n\n**故障现象**：\n1. HPA 的当前副本数达到 maxReplicas 上限，无法继续扩容\n2. 应用 CPU 或内存使用率仍持续高于 HPA 目标阈值\n3. 应用响应延迟增大，出现超时\n\n**资源准备**：\n1. 确认应用 A 已正常运行，且已配置 HPA（设置合适的 maxReplicas 以便快速触发上限）\n2. 确认监控系统可观测 HPA 状态和 Pod CPU/内存指标\n\n**演练步骤**：\n1. 定位应用 A 的 HPA，记录 maxReplicas 配置\n2. 使用 chaosblade 对应用 A 的所有 Pod 注入 CPU 压力，持续超过 HPA 扩容阈值\n3. 观察 HPA 扩容行为，等待副本数达到 maxReplicas 上限\n\n**注入验证**：\n1. 执行 `kubectl get hpa`，确认 REPLICAS 已达到 MAXPODS 上限\n2. 查看 HPA Event，确认出现 `FailedGetScale` 或 `DesiredReplicas` 超过 maxReplicas 的告警\n3. 查看 Pod CPU 使用率，确认仍持续高于目标阈值\n4. 确认应用 A 的请求延迟增大，出现超时\n\n**注入恢复**：\n1. 销毁 chaosblade CPU 压力实验\n2. 等待 HPA 自动缩容\n\n**恢复验证**：\n1. 执行 `kubectl get hpa`，确认 REPLICAS 回落至正常水平\n2. 查看 Pod CPU 使用率，确认恢复到 HPA 目标阈值以下\n3. 确认应用 A 的请求延迟恢复正常\n\n**基准事实**：\n- **根因**：应用负载超过 HPA 的 maxReplicas 能覆盖的处理能力，HPA 达到扩容上限后无法继续扩容，导致服务资源饱和\n- **必现现象**：HPA REPLICAS 达到 MAXPODS；HPA Event 有超限告警；CPU 使用率持续超过目标阈值；应用性能下降\n\n<!-- File: blade-ai/skills/k8s-chaos-skills/references/catalogue/Node_CPU使用率过高/Node_CPU使用率过高_异常进程占用.md (Tokens: ~430 | Category: anthropic-skill) -->\n**用例名称** 异常进程占用 导致 Node_CPU使用率过高\n\n**故障现象**：\n1. 节点 CPU 使用率持续超过 90%\n2. 节点上 Pod 响应变慢，出现超时\n3. Load Average 显著升高\n\n**资源准备**：\n1. 确认应用 A 已正常运行\n2. 确认监控系统（如 Prometheus）已配置，可观测节点 CPU 指标\n\n**演练步骤**：\n1. 定位运行应用 A 的节点\n2. 使用 chaosblade 对该节点注入 CPU 满载，模拟异常进程占用节点 CPU\n3. 观察节点 CPU 使用率及 Pod 性能变化\n\n**注入验证**：\n1. 查看节点 CPU 使用率监控，确认持续超过 90%\n2. 查看 Load Average，确认显著升高\n3. 确认应用 A 的请求延迟增大\n\n**注入恢复**：\n1. 销毁 chaosblade 实验\n\n**恢复验证**：\n1. 查看节点 CPU 使用率监控，确认恢复到正常水平\n2. 确认应用 A 的请求延迟恢复正常\n\n**基准事实**：\n- **根因**：节点上存在异常进程大量占用 CPU，导致节点 CPU 使用率过高，影响同节点上所有 Pod 的性能\n- **必现现象**：节点 CPU 使用率持续超过 90%；Load Average 显著升高；同节点 Pod 响应变慢\n\n<!-- File: blade-ai/skills/k8s-chaos-skills/references/catalogue/Node_不可用/Node_不可用_节点宕机.md (Tokens: ~577 | Category: anthropic-skill) -->\n**用例名称** 节点宕机 导致 Node_不可用\n\n**故障现象**：\n1. 节点状态变为 NotReady\n2. 节点上所有 Pod 无法访问\n3. kubelet 停止上报节点状态，NodeStatus 中 LastHeartbeatTime 停止更新\n4. Pod 在其他节点上被重建\n\n**资源准备**：\n1. 确认应用 A 已正常运行，且有多个副本分布在不同节点\n2. 确认监控系统可观测节点状态和 Pod 状态\n\n**演练步骤**：\n1. 定位运行应用 A 的节点\n2. 使用 chaosblade 对该节点注入网络完全丢包（node-network drop 即全量丢包，不需要 --percent），并设置 `--timeout 600`（600 秒后自动恢复），模拟节点与集群失联的宕机场景\n3. 观察节点状态和 Pod 调度行为变化\n\n**注入验证**：\n1. 执行 `kubectl get nodes`，确认目标节点状态变为 NotReady\n2. 查看 NodeStatus，确认 LastHeartbeatTime 停止更新\n3. 确认节点上应用 A 的 Pod 在其他节点上被重建\n4. 确认应用 A 的服务整体仍可访问（多副本场景）\n\n**注入恢复**：\n1. 等待 chaosblade 实验自动超时恢复（600 秒内），agent 本地定时器会自动清理网络规则\n2. 如超时后仍未恢复，通过 `blade destroy <UID>` 或重启节点强制恢复\n\n**恢复验证**：\n1. 执行 `kubectl get nodes`，确认目标节点恢复 Ready\n2. 确认 LastHeartbeatTime 恢复更新\n3. 确认应用 A 的 Pod 恢复正常运行\n\n**基准事实**：\n- **根因**：节点网络完全中断，导致 kubelet 无法与 API server 通信，停止上报节点状态\n- **必现现象**：节点 NotReady；LastHeartbeatTime 停止更新；Pod 在其他节点被重建\n\n<!-- File: blade-ai/skills/k8s-chaos-skills/references/catalogue/Node_内存使用率过高/Node_内存使用率过高_异常进程占用.md (Tokens: ~489 | Category: anthropic-skill) -->\n**用例名称** 异常进程占用 导致 Node_内存使用率过高\n\n**故障现象**：\n1. 节点内存使用率持续超过 90%\n2. 节点上 Pod 出现 OOMKilled 或被驱逐\n3. 节点 Status 出现 MemoryPressure 条件为 True\n\n**资源准备**：\n1. 确认应用 A 已正常运行\n2. 确认监控系统（如 Prometheus）已配置，可观测节点内存指标\n\n**演练步骤**：\n1. 定位运行应用 A 的节点\n2. 使用 chaosblade 对该节点注入内存压力，模拟异常进程占用节点内存\n3. 观察节点内存使用率及 Pod 状态变化\n\n**注入验证**：\n1. 查看节点内存使用率监控，确认持续超过 90%\n2. 执行 `kubectl describe node <节点名>`，确认 MemoryPressure 条件为 True\n3. 确认应用 A 的 Pod 出现 OOMKilled 或被驱逐\n\n**注入恢复**：\n1. 销毁 chaosblade 实验\n\n**恢复验证**：\n1. 查看节点内存使用率监控，确认恢复到正常水平\n2. 执行 `kubectl describe node <节点名>`，确认 MemoryPressure 条件为 False\n3. 确认应用 A 的 Pod 恢复正常运行\n\n**基准事实**：\n- **根因**：节点上存在异常进程大量占用内存，导致节点内存使用率过高，触发 MemoryPressure，Pod 被 OOMKilled 或驱逐\n- **必现现象**：节点内存使用率持续超过 90%；MemoryPressure 条件为 True；Pod 出现 OOMKilled 或被驱逐\n\n<!-- File: blade-ai/skills/k8s-chaos-skills/references/catalogue/Node_磁盘IO过高/Node_磁盘IO过高_异常IO占用.md (Tokens: ~1861 | Category: anthropic-skill) -->\n**用例名称** 异常IO占用 导致 Node_磁盘IO过高\n\n**故障现象**：\n1. 节点磁盘 IO 使用率持续过高（iostat 显示 %util 接近 100%）\n2. 节点上 Pod 的磁盘读写延迟增大，应用响应变慢\n3. iowait 占比升高\n\n**资源准备**：\n1. 确认应用 A 已正常运行\n2. 确认监控系统可观测节点磁盘 IO 指标\n\n**演练步骤**：\n1. 定位运行应用 A 的节点\n2. **路径校验（必须）**：注入前验证目标路径存在且可写：\n   - 通过 `kubectl exec <tool-pod> -n chaosblade -- ls -ld <磁盘路径>` 确认路径存在\n   - 如路径不存在，通过 `df -h` 查看可用挂载点，选择已存在的可写目录\n   - 常见可用路径：`/var/lib/containerd`、`/var/lib/docker`、`/tmp`、`/var/log`\n   - **禁止使用未校验的路径** — ChaosBlade 接受任意路径但底层 dd 进程会静默失败\n   - 不同路径可能对应不同的物理磁盘分区，注入前可通过 `df -h <路径>` 确认路径所在的设备\n3. 使用 chaosblade 对该节点注入磁盘 IO 负载：`blade create k8s node-disk burn --read --write --names <节点名> --path <已校验的磁盘路径> --timeout <秒> --kubeconfig <路径>`\n4. 观察节点磁盘 IO 指标及 Pod 性能变化\n\n**注入验证**：\n1. 查看节点磁盘 IO 负载指标：\n   - 优先：`iostat -xd 1 3`（关注 %util 接近 100%）\n   - BusyBox 备选：`iostat -d -k 1 3`（关注 tps 和 kB_wrtn/s/kB_read/s 异常升高）+ `iostat -c 1 3`（关注 %iowait 显著升高）\n   - 进程确认：`ps | grep dd` 确认 ChaosBlade 的 dd 压测进程在运行（若 dd 不存在，说明路径无效导致注入静默失败，需检查路径是否存在）\n   - **多磁盘注意**：`iostat` 显示节点上所有物理磁盘的 IO 指标。如果节点有多个磁盘（如 vda 用于 nodefs，vdb 用于 imagefs），需根据 `--path` 参数判断目标路径对应的物理磁盘，只关注该磁盘的指标变化\n2. 查看 iowait 占比，确认显著升高（`iostat -c` 或节点监控）\n3. 确认应用 A 的磁盘读写延迟增大（见下方 Pod 级验证方法）\n\n**Pod 级磁盘 IO 验证方法**：\n- 方法 1（推荐）：在目标节点上选一个 Running Pod，`kubectl exec <pod> -- dd if=/dev/zero of=/tmp/disk-io-test bs=1M count=100`，对比注入前后写入耗时\n- 方法 2：`kubectl exec <pod> -- df -h` 确认 Pod 所在容器的磁盘使用率（注意：显示的是 overlay 文件系统，非宿主机），`kubectl describe pod <pod>` 检查 Events 中是否有磁盘相关告警\n- 方法 3（容器无 dd 时）：`kubectl get events -n <ns> --field-selector involvedObject.name=<pod>` 观察是否有 IO 相关事件\n\n**注入恢复**：\n1. 销毁 chaosblade 实验\n\n**恢复验证**：\n1. 查看节点磁盘 IO 监控，确认 %util 恢复正常：\n   - 优先：`iostat -xd 1 3`\n   - BusyBox 备选：`iostat -d -k 1 3`（确认 tps/吞吐量回落）+ `iostat -c 1 3`（确认 %iowait 恢复基线）\n2. 确认 iowait 占比恢复正常\n3. 确认应用 A 的磁盘读写延迟恢复正常（使用 Pod 级验证方法中的 dd 写入测试，确认耗时恢复）\n\n**基准事实**：\n- **根因**：节点上存在异常进程大量占用磁盘 IO，导致磁盘 IO 使用率过高，影响同节点上所有 Pod 的磁盘读写性能\n- **必现现象**：节点磁盘 IO %util 接近 100%；iowait 占比升高；同节点 Pod 磁盘读写延迟增大\n\n**CRD 模式 overlay 文件系统关键说明**：\n- ChaosBlade K8s CRD 模式下，`node-disk burn --path /tmp` 的 dd 进程运行在 DaemonSet tool pod 内，\n  写入的是**容器 overlay 文件系统**（通常由 imagefs/vdb 支持），**而非宿主机 /tmp**（通常由 nodefs/vda3 支持）\n- **验证 burn 时不应该检查 /host/tmp/ 下的文件**：burn 产生的临时文件在 overlay 中，不会出现在宿主机路径\n- **df -h 对 burn 验证无效**：burn 产生的是 I/O 压力（临时文件会被自动清理），不会造成磁盘使用量持续增长。\n  用 df -h 验证 burn 可能导致误判为\"注入失败\"\n- **正确的 burn 验证方法**：通过 `/proc/diskstats` 两次采样（间隔 3-5 秒），计算写入吞吐量增量：\n  - 读取方法：`cat /proc/diskstats`，格式为 `major minor name reads reads_merged sectors_read ... sectors_written writes_merged sectors_written ...`\n  - 计算方式：delta(sectors_written) × 512 / 间隔秒数 / 1048576 = MB/s\n  - 判断标准：任何分区持续写入 >10MB/s 即表示 burn 在生效\n  - 注意跳过分区条目（如 vda1、vda3），只关注整盘设备（如 vda、vdb）\n- **fill 与 burn 的验证方法差异**：\n  - fill（空间填充）：df -h 是主要验证手段（填充产生持久数据，磁盘使用量增加）\n  - burn（IO 压力）：/proc/diskstats 是主要验证手段（burn 产生 IO 压力，不产生持久数据）\n\n<!-- File: blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_ContainerCreating/Pod_ContainerCreating_CNI分配失败.md (Tokens: ~936 | Category: anthropic-skill) -->\n**用例名称** CNI分配失败 导致 Pod_ContainerCreating\n\n**故障现象**：\n1. Pod 长时间停留在 ContainerCreating 状态\n2. Pod Events 中显示 `failed to allocate for ENI` 或 `no available IP in subnet` 或 CNI 相关错误\n3. 节点上的 IP 资源池耗尽或 ENI 数量达到上限\n\n**资源准备**：\n1. 确认应用 A 已正常运行\n2. 确认集群使用 ENI 或 vSwitch 分配 Pod IP 的 CNI 插件（如 Terway）\n\n**演练步骤**：\n1. 查看目标节点的 ENI 和 IP 分配情况，确认目标应用 Pod 所在节点（记为 `<目标节点>`）\n2. 给目标节点添加标签，并给应用 A 的 Deployment 添加 nodeSelector，确保新 Pod 只能调度到目标节点（防止调度器规避耗尽节点）：\n   ```bash\n   kubectl label node <目标节点> chaos-cni-target=true\n   kubectl patch deployment <deployment-name> -n <namespace> --type='merge' \\\n     -p='{\"spec\":{\"template\":{\"spec\":{\"nodeSelector\":{\"chaos-cni-target\":\"true\"}}}}}'\n   ```\n   等待 rollout 完成（Pod 仍在原节点运行，因为目标节点已有此标签）。\n   记录原始 nodeSelector 值，恢复时还原。\n3. 使用 `execute_skill_script` 在目标节点批量创建 Pod 耗尽 IP/ENI 资源（**`kubectl create/apply` 不可用，必须使用脚本**）：\n   ```\n   execute_skill_script(\n     skill_name=\"k8s-chaos-skills\",\n     script_name=\"inject_cni_exhaust.py\",\n     params=\"--namespace <namespace> --node <目标节点> --kubeconfig <kubeconfig路径>\"\n   )\n   ```\n   脚本会创建 `chaos-ip-exhaust` Deployment 并绑定到目标节点。\n4. 删除应用 A 在目标节点上的 Pod，触发重建。由于 nodeSelector 约束，新 Pod 只能调度到已耗尽的目标节点，将进入 ContainerCreating 状态\n5. 观察新 Pod 的 ContainerCreating 状态\n\n**注入验证**：\n1. 执行 `kubectl get pods`，确认应用 A 新 Pod 状态为 ContainerCreating\n2. 执行 `kubectl describe pod <pod-name>`，确认 Events 显示 CNI/IP 分配失败相关错误\n3. 查看节点 ENI/IP 使用情况，确认资源已耗尽\n\n**注入恢复**：\n1. 删除批量创建的 Deployment：`kubectl delete deployment chaos-ip-exhaust -n <namespace>`\n2. 移除应用 A 的 Deployment 上添加的 nodeSelector（还原为原始值，若原本无 nodeSelector 则移除整个 nodeSelector）\n3. 移除目标节点上添加的标签：`kubectl label node <目标节点> chaos-cni-target-`\n4. 等待 IP/ENI 资源释放和 Pod 滚动更新完成\n\n**恢复验证**：\n1. 执行 `kubectl get pods`，确认应用 A 的 Pod 状态恢复为 Running\n2. 确认节点 IP/ENI 资源恢复可用\n3. 确认应用 A 网络连通正常\n\n**基准事实**：\n- **根因**：节点可用 IP 池耗尽或 ENI 数量达到上限或 vSwitch IP 不足，CNI 插件无法为新 Pod 分配网络资源\n- **必现现象**：Pod ContainerCreating；Events 显示 CNI/IP/ENI 分配失败；节点网络资源耗尽\n\n<!-- File: blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_ContainerCreating/Pod_ContainerCreating_Volume挂载超时CSI异常.md (Tokens: ~1180 | Category: anthropic-skill) -->\n**用例名称** Volume挂载超时CSI异常 导致 Pod_ContainerCreating\n\n**故障现象**：\n1. Pod 长时间停留在 ContainerCreating 状态\n2. Pod Events 中显示 `FailedMount` 或 `FailedAttachVolume`，提示 CSI driver 超时或可用区不匹配\n3. PV 对应的云盘与 Pod 调度的节点不在同一可用区\n\n**资源准备**：\n1. 确认应用 A 已正常运行，且使用了 CSI 驱动管理的存储卷\n2. 确认集群跨多个可用区部署\n\n**演练步骤**：\n1. 记录 Deployment 当前 maxUnavailable 值，并临时设为 100%（确保滚动更新能完成，故障注入的新 Pod 不会 Ready，默认策略下 K8s 不会终止旧 Pod，导致滚动更新死锁）：\n   ```bash\n   kubectl get deployment <deployment-name> -n <namespace> \\\n     -o jsonpath='{.spec.strategy.rollingUpdate.maxUnavailable}'\n   kubectl patch deployment <deployment-name> -n <namespace> --type='json' \\\n     -p='[{\"op\":\"replace\",\"path\":\"/spec/strategy/rollingUpdate/maxUnavailable\",\"value\":\"100%\"}]'\n   ```\n2. 使用 `kubectl(subcommand=\"apply\", v_args=\"-f -\", stdin_data=\"...\")` 创建跨可用区的 PV 和 PVC（**必须使用 `stdin_data` 参数传入 YAML，不要用 exec heredoc 或其他方式**）：\n   PV YAML:\n   ```yaml\n   apiVersion: v1\n   kind: PersistentVolume\n   metadata:\n     name: chaos-az-mismatch-pv\n   spec:\n     capacity:\n       storage: 20Gi\n     accessModes: [\"ReadWriteOnce\"]\n     csi:\n       driver: diskplugin.csi.alibabacloud.com\n       volumeHandle: <其他可用区的云盘ID>\n     nodeAffinity:\n       required:\n         nodeSelectorTerms:\n         - matchExpressions:\n           - key: topology.kubernetes.io/zone\n             operator: In\n             values: [\"<其他可用区>\"]\n   ```\n   PVC YAML:\n   ```yaml\n   apiVersion: v1\n   kind: PersistentVolumeClaim\n   metadata:\n     name: chaos-csi-mismatch-pvc\n     namespace: <namespace>\n   spec:\n     accessModes: [\"ReadWriteOnce\"]\n     resources:\n       requests:\n         storage: 20Gi\n     volumeName: chaos-az-mismatch-pv\n   ```\n3. 修改应用 A 的 Deployment，添加引用该 PVC 的 volume，并确保 Pod 调度到不同可用区的节点\n4. 等待 Pod 滚动更新完成，确认所有旧 Pod 已被替换\n5. 滚动更新完成后，立即还原 maxUnavailable 为原始值（maxUnavailable 只是使滚动更新完成的手段，不是故障本身，不应泄漏到恢复阶段）\n6. 观察 Pod 的 ContainerCreating 状态\n\n**注入验证**：\n1. 执行 `kubectl rollout status deployment <deployment-name>`，确认滚动更新已完成（所有旧 Pod 已被替换）。如果滚动更新未完成（卡死），则故障未完全生效，不可判定为 verified\n2. 执行 `kubectl get pods`，确认**所有**目标 Pod 状态为 ContainerCreating（不是仅一个新 Pod，而是全部副本）\n3. 执行 `kubectl describe pod <pod-name>`，确认 Events 显示 FailedMount 或 CSI attach 超时\n4. 确认错误信息包含可用区不匹配或 CSI 异常相关描述\n\n**注入恢复**：\n1. 恢复应用 A 的 Deployment，移除注入时添加的 volumes 和 volumeMounts（两者都需移除，只移除其中一个会导致 Deployment 配置错误）\n2. 等待 Pod 滚动更新完成，确认 Pod 恢复 Running\n3. 清理测试 PVC：`kubectl delete pvc chaos-csi-mismatch-pvc -n <namespace>`\n4. 清理测试 PV：`kubectl delete pv chaos-az-mismatch-pv`\n\n**恢复验证**：\n1. 执行 `kubectl get pods`，确认 Pod 状态恢复为 Running\n2. 确认测试资源已清理\n3. 确认应用 A 存储功能正常\n\n**基准事实**：\n- **根因**：CSI 驱动异常或云盘与节点可用区不匹配，导致 Volume attach/mount 操作超时，Pod 无法完成存储卷挂载\n- **必现现象**：Pod ContainerCreating；Events 显示 FailedMount/FailedAttachVolume/CSI 超时；可用区不匹配\n\n<!-- File: blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_ContainerCreating/Pod_ContainerCreating_云盘挂载超时或冲突.md (Tokens: ~686 | Category: anthropic-skill) -->\n**用例名称** 云盘挂载超时或冲突 导致 Pod_ContainerCreating\n\n**故障现象**：\n1. Pod 长时间停留在 ContainerCreating 状态\n2. Pod Events 中显示 `Multi-Attach error` 或 `AttachVolume.Attach failed`\n3. 云盘被其他节点占用，无法 attach 到当前节点\n\n**资源准备**：\n1. 确认应用 A 已正常运行，且使用了云盘类型的 PVC（accessMode 为 ReadWriteOnce）\n2. 确认集群中有多个节点\n\n**演练步骤**：\n1. 定位应用 A 使用的 PVC 及其对应的 PV\n2. 在另一个节点上创建一个临时 Pod，强制挂载同一个 PVC（通过直接指定 PV 的 volumeHandle 创建新 PV/PVC 对），模拟 Multi-Attach 冲突：\n   ```yaml\n   apiVersion: v1\n   kind: Pod\n   metadata:\n     name: chaos-volume-holder\n     namespace: <namespace>\n   spec:\n     nodeName: <另一节点>\n     containers:\n     - name: holder\n       image: busybox\n       command: [\"sleep\", \"3600\"]\n       volumeMounts:\n       - name: data\n         mountPath: /data\n     volumes:\n     - name: data\n       persistentVolumeClaim:\n         claimName: <应用A的PVC名称>\n   ```\n3. 删除应用 A 原来的 Pod，触发在其他节点重建\n4. 观察新 Pod 的 ContainerCreating 状态\n\n**注入验证**：\n1. 执行 `kubectl get pods`，确认应用 A 的新 Pod 状态为 ContainerCreating\n2. 执行 `kubectl describe pod <pod-name>`，确认 Events 显示 Multi-Attach error 或 volume attach 失败\n3. 确认 PV 仍 attach 在占用它的节点上\n\n**注入恢复**：\n1. 删除临时 Pod：`kubectl delete pod chaos-volume-holder --force --grace-period=0`\n2. 等待云盘从原节点 detach\n3. 等待应用 A 的 Pod 自动完成 volume attach\n\n**恢复验证**：\n1. 执行 `kubectl get pods`，确认应用 A 的 Pod 状态恢复为 Running\n2. 确认 volume 成功 attach 并 mount\n3. 确认应用 A 数据读写正常\n\n**基准事实**：\n- **根因**：云盘（ReadWriteOnce）被其他节点/Pod 占用，新 Pod 无法 attach 该云盘，导致 volume mount 阶段阻塞\n- **必现现象**：Pod ContainerCreating；Events 显示 Multi-Attach error 或 AttachVolume 失败；PV 被其他节点占用\n\n<!-- File: blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_ContainerCreating/Pod_ContainerCreating_容器运行时异常.md (Tokens: ~619 | Category: anthropic-skill) -->\n**用例名称** 容器运行时异常 导致 Pod_ContainerCreating\n\n**故障现象**：\n1. Pod 长时间停留在 ContainerCreating 状态\n2. Pod Events 中显示 `container runtime is not ready` 或 `rpc error` 相关错误\n3. 节点上的 containerd/docker 进程异常或 hang，无法响应容器创建请求\n\n**资源准备**：\n1. 确认应用 A 已正常运行\n2. 确认目标节点上有多个应用副本（避免单点影响）\n3. 确认监控系统可观测节点和容器运行时状态\n\n**演练步骤**：\n1. 定位应用 A 所在的目标节点\n2. 使用 chaosblade 挂起（stop）目标节点上的 containerd 进程，模拟容器运行时 hang：\n   ```bash\n   blade create k8s node-process stop \\\n     --names <节点名> \\\n     --process containerd \\\n     --timeout 120 \\\n     --kubeconfig <路径>\n   ```\n3. 删除应用 A 在目标节点上的 Pod，触发重建\n4. 观察新 Pod 的 ContainerCreating 状态\n\n**注入验证**：\n1. 执行 `kubectl get pods`，确认新 Pod 状态为 ContainerCreating\n2. 执行 `kubectl describe pod <pod-name>`，确认 Events 显示容器运行时相关错误\n3. 确认目标节点状态可能变为 NotReady（RuntimeNotReady condition）\n\n**注入恢复**：\n1. 等待 chaosblade 实验自动超时恢复（120 秒内），containerd 进程自动恢复\n2. 如超时后仍未恢复，通过 `blade destroy <UID>` 强制恢复\n3. 等待容器运行时恢复正常，Pod 自动完成创建\n\n**恢复验证**：\n1. 确认 containerd 进程恢复正常运行\n2. 执行 `kubectl get nodes`，确认目标节点恢复 Ready\n3. 执行 `kubectl get pods`，确认 Pod 状态恢复为 Running\n\n**基准事实**：\n- **根因**：容器运行时（containerd/docker）进程异常、hang 或状态不一致，无法响应 kubelet 的容器创建请求\n- **必现现象**：Pod ContainerCreating；Events 显示 runtime 相关 rpc error；节点可能 NotReady（RuntimeNotReady）\n\n<!-- File: blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_CPU_Throttling/Pod_CPU_Throttling_limits.cpu过低.md (Tokens: ~612 | Category: anthropic-skill) -->\n**用例名称** limits.cpu过低 导致 Pod_CPU_Throttling\n\n**故障现象**：\n1. Pod 内进程频繁被内核 CPU 节流（throttle），`cpu.stat` 中 `nr_throttled` 持续增长\n2. 应用请求延迟显著增大，P99 延迟飙升\n3. `kubectl top pod` 显示 CPU 使用率接近 limits 但实际未满载\n\n**资源准备**：\n1. 确认应用 A 已正常运行，且 Pod 配置了 resources.limits.cpu\n2. 确认监控系统可观测 Pod CPU 使用率及 throttle 指标\n\n**演练步骤**：\n1. 定位应用 A 的 Deployment\n2. 使用 kubectl patch 将应用 A 的 CPU limits 调低为极小值（如 50m），模拟 limits.cpu 配置过低的场景\n3. 使用 chaosblade 对应用 A 的 Pod 注入 CPU 负载，确保实际 CPU 需求超过 limits，触发内核 throttle\n4. 观察 Pod CPU throttle 指标变化及应用响应延迟\n\n**注入验证**：\n1. 进入容器查看 `/sys/fs/cgroup/cpu/cpu.stat`，确认 `nr_throttled` 和 `throttled_time` 持续增长\n2. 查看监控指标，确认 Pod CPU 使用率接近 limits\n3. 确认应用 A 的请求延迟显著增大\n\n**注入恢复**：\n1. 销毁 chaosblade CPU 负载实验\n2. 使用 kubectl patch 将应用 A 的 CPU limits 恢复为原始合理值\n\n**恢复验证**：\n1. 查看 `cpu.stat`，确认 `nr_throttled` 停止增长\n2. 确认应用 A 的请求延迟恢复正常\n\n**基准事实**：\n- **根因**：容器 limits.cpu 设置过低，实际 CPU 需求超过 limit，内核对容器 CPU 时间片进行 throttle，导致应用性能下降\n- **必现现象**：cpu.stat 中 nr_throttled 持续增长；应用延迟飙升；CPU 使用率接近 limits 上限\n\n<!-- File: blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_cpu使用率过高/Pod_cpu使用率过高_应用性能问题.md (Tokens: ~483 | Category: anthropic-skill) -->\n**用例名称** 应用性能问题 导致 Pod_CPU使用率过高\n\n**故障现象**：\n1. Pod 的 CPU 使用率持续超过阈值\n2. CPU 使用率过高影响其他服务\n3. 应用响应变慢或发生超时\n\n**资源准备**：\n1. 确认应用 A/B 已正常运行\n2. 确认监控系统（如 Prometheus）已配置，可观测 Pod CPU 指标\n\n**演练步骤**：\n1. 定位应用 A 的 Pod 作为故障注入目标\n2. 使用 chaosblade 对目标 Pod 注入 CPU 压力（模拟死循环或高并发计算场景）\n3. 观察 Pod CPU 使用率变化\n\n**注入验证**：\n1. 查看 Pod CPU 使用率监控，确认持续高于阈值\n2. 进入容器查看 CPU 占用进程\n3. 通过 APM 工具分析 CPU 占用情况，定位问题代码\n4. 确认应用 A 对其他服务的调用出现延迟或超时\n\n**注入恢复**：\n1. 销毁 chaosblade CPU 压力实验\n2. 如 Pod 仍异常，可删除 Pod 触发重建\n\n**恢复验证**：\n1. 查看 Pod CPU 使用率监控，确认恢复到正常水平\n2. 确认应用 A 对其他服务的调用恢复正常\n\n**基准事实**：\n- **根因**：应用存在死循环、高并发计算或资源泄漏等性能问题，导致 CPU 使用率持续过高\n- **必现现象**：Pod CPU 使用率持续超过阈值，应用响应变慢或超时\n---\n\n<!-- File: blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_CrashLoopBackOff/Pod_CrashLoopBackOff_LivenessProbe配置不合理.md (Tokens: ~1054 | Category: anthropic-skill) -->\n**用例名称** LivenessProbe配置不合理 导致 Pod_CrashLoopBackOff\n\n**故障现象**：\n1. Pod 反复重启，状态为 CrashLoopBackOff\n2. Pod Events 中显示 `Liveness probe failed` 后容器被杀\n3. 容器本身运行正常，但 Liveness Probe 配置参数不合理导致误判\n\n**RCA症状**：\n1. Pod 反复重启，状态为 CrashLoopBackOff\n2. Pod Events 中显示 `Liveness probe failed`，容器被反复杀死\n3. 容器日志无应用异常退出记录\n（以上为kubectl直接可观测的现象，不包含诊断结论）\n\n**资源准备**：\n1. 确认应用 A 已正常运行\n2. 确认应用 A 有健康检查接口\n\n**演练步骤**：\n1. 记录应用 A 当前的 livenessProbe 配置\n2. 记录 Deployment 当前 maxUnavailable 值，并临时设为 100%（确保滚动更新能完成，故障注入的新 Pod 不会 Ready，默认策略下 K8s 不会终止旧 Pod，导致滚动更新死锁）：\n   ```bash\n   kubectl get deployment <deployment-name> -n <namespace> \\\n     -o jsonpath='{.spec.strategy.rollingUpdate.maxUnavailable}'\n   kubectl patch deployment <deployment-name> -n <namespace> --type='json' \\\n     -p='[{\"op\":\"replace\",\"path\":\"/spec/strategy/rollingUpdate/maxUnavailable\",\"value\":\"100%\"}]'\n   ```\n3. 修改应用 A 的 Deployment，设置不合理的 livenessProbe 参数：\n   ```yaml\n   livenessProbe:\n     httpGet:\n       path: /healthz\n       port: 8080\n     initialDelaySeconds: 1\n     timeoutSeconds: 1\n     periodSeconds: 2\n     failureThreshold: 1\n   ```\n   （initialDelaySeconds 过短，应用未完成初始化；timeoutSeconds 过短，正常响应来不及返回；failureThreshold 为 1，无容错空间）\n4. 等待 Pod 滚动更新完成，确认所有旧 Pod 已被替换\n5. 滚动更新完成后，立即还原 maxUnavailable 为原始值（maxUnavailable 只是使滚动更新完成的手段，不是故障本身，不应泄漏到恢复阶段）\n6. 观察 Pod 重启行为\n\n**注入验证**：\n1. 执行 `kubectl rollout status deployment <deployment-name>`，确认滚动更新已完成（所有旧 Pod 已被替换）。如果滚动更新未完成（卡死），则故障未完全生效，不可判定为 verified\n2. 执行 `kubectl get pods`，确认**所有**目标 Pod 的 RESTARTS 数持续增长，状态为 CrashLoopBackOff（不是仅一个新 Pod，而是全部副本）\n3. 执行 `kubectl describe pod <pod-name>`，确认 Events 显示 `Liveness probe failed` 和 `Container will be killed`\n4. 查看容器日志，确认应用本身无异常退出（非应用 bug）\n\n**注入恢复**：\n1. 恢复应用 A 的 Deployment，将 livenessProbe 参数恢复为原始合理值（若原本无 livenessProbe，则移除）\n3. 等待 Pod 滚动更新完成\n\n**恢复验证**：\n1. 执行 `kubectl get pods`，确认 Pod 状态为 Running 且不再重启\n2. 确认 Liveness Probe 检查正常通过\n3. 确认应用 A 服务正常\n\n**基准事实**：\n- **根因**：Liveness Probe 的 initialDelaySeconds/timeoutSeconds/failureThreshold 配置不合理，导致健康检查在应用正常运行时误判为失败，kubelet 反复杀死并重启容器\n- **必现现象**：Pod CrashLoopBackOff；RESTARTS 持续增长；Events 显示 Liveness probe failed；容器日志无异常\n\n<!-- File: blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_CrashLoopBackOff/Pod_CrashLoopBackOff_StartupProbe配置不足.md (Tokens: ~988 | Category: anthropic-skill) -->\n**用例名称** StartupProbe配置不足 导致 Pod_CrashLoopBackOff\n\n**故障现象**：\n1. Pod 反复重启，状态为 CrashLoopBackOff\n2. Pod Events 中显示 `Startup probe failed` 后容器被杀\n3. 慢启动应用尚未完成初始化就被 StartupProbe 判定为失败\n\n**资源准备**：\n1. 确认应用 A 已正常运行（应用启动时间较长，如 Java 应用）\n2. 确认应用 A 启动过程中健康检查接口不可用\n\n**演练步骤**：\n1. 记录应用 A 当前的探针配置\n2. 记录 Deployment 当前 maxUnavailable 值，并临时设为 100%（确保滚动更新能完成，故障注入的新 Pod 不会 Ready，默认策略下 K8s 不会终止旧 Pod，导致滚动更新死锁）：\n   ```bash\n   kubectl get deployment <deployment-name> -n <namespace> \\\n     -o jsonpath='{.spec.strategy.rollingUpdate.maxUnavailable}'\n   kubectl patch deployment <deployment-name> -n <namespace> --type='json' \\\n     -p='[{\"op\":\"replace\",\"path\":\"/spec/strategy/rollingUpdate/maxUnavailable\",\"value\":\"100%\"}]'\n   ```\n3. 修改应用 A 的 Deployment，添加或修改 startupProbe 使其窗口不足以覆盖应用启动时间：\n   ```yaml\n   startupProbe:\n     httpGet:\n       path: /healthz\n       port: 8080\n     failureThreshold: 3\n     periodSeconds: 5\n   ```\n   （总等待时间 = failureThreshold × periodSeconds = 15 秒，远小于应用实际启动时间）\n4. 同时确保 livenessProbe 存在，使得 startupProbe 失败后触发容器重启\n5. 等待 Pod 滚动更新完成，确认所有旧 Pod 已被替换\n6. 滚动更新完成后，立即还原 maxUnavailable 为原始值（maxUnavailable 只是使滚动更新完成的手段，不是故障本身，不应泄漏到恢复阶段）\n7. 观察 Pod 启动行为\n\n**注入验证**：\n1. 执行 `kubectl rollout status deployment <deployment-name>`，确认滚动更新已完成（所有旧 Pod 已被替换）。如果滚动更新未完成（卡死），则故障未完全生效，不可判定为 verified\n2. 执行 `kubectl get pods`，确认**所有**目标 Pod 的 RESTARTS 持续增长，状态为 CrashLoopBackOff（不是仅一个新 Pod，而是全部副本）\n3. 执行 `kubectl describe pod <pod-name>`，确认 Events 显示 `Startup probe failed`\n4. 查看容器日志，确认应用正在启动但未完成初始化就被杀\n\n**注入恢复**：\n1. 恢复应用 A 的 Deployment，增大 startupProbe 的窗口时间（若原本无 startupProbe，则移除）\n2. 等待 Pod 滚动更新完成\n\n**恢复验证**：\n1. 执行 `kubectl get pods`，确认 Pod 状态为 Running 且不再重启\n2. 确认 StartupProbe 和 LivenessProbe 检查均正常通过\n3. 确认应用 A 完成初始化并正常服务\n\n**基准事实**：\n- **根因**：StartupProbe 未配置或 failureThreshold × periodSeconds 总窗口不足以覆盖应用启动时间，慢启动应用在初始化完成前被判定为启动失败，反复被杀重启\n- **必现现象**：Pod CrashLoopBackOff；Events 显示 Startup probe failed；容器日志显示应用启动中被中断\n\n<!-- File: blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_OOM内存异常/Pod_OOM内存异常_limit单位写错.md (Tokens: ~1102 | Category: anthropic-skill) -->\n**用例名称** limit单位写错 导致 Pod_OOM内存异常\n\n**故障现象**：\n1. Pod 启动后立即异常退出，状态为 CrashLoopBackOff\n2. Pod 的 lastState 显示 reason: OOMKilled 或 StartError（cgroup v2 环境下容器可能因内存配置过小无法启动）\n3. 容器 memory limit 值极小（如 100m = 0.1 字节），应用启动即超限或无法启动\n\n**资源准备**：\n1. 确认应用 A 已正常运行\n2. 确认应用 A 的正常内存使用量（如 200Mi 以上）\n\n**演练步骤**：\n1. 记录应用 A 当前的 resources.limits.memory 配置\n2. 记录 Deployment 当前 maxUnavailable 值，并临时设为 100%（确保滚动更新能完成，故障注入的新 Pod 不会 Ready，默认策略下 K8s 不会终止旧 Pod，导致滚动更新死锁）：\n   ```bash\n   kubectl get deployment <deployment-name> -n <namespace> \\\n     -o jsonpath='{.spec.strategy.rollingUpdate.maxUnavailable}'\n   kubectl patch deployment <deployment-name> -n <namespace> --type='json' \\\n     -p='[{\"op\":\"replace\",\"path\":\"/spec/strategy/rollingUpdate/maxUnavailable\",\"value\":\"100%\"}]'\n   ```\n3. 修改应用 A 的 Deployment，将 memory limit 单位写错：\n   ```yaml\n   resources:\n     limits:\n       memory: \"100m\"    # 错误！100m = 0.1 字节（milli），应为 100Mi\n     requests:\n       memory: \"100m\"\n   ```\n   注意：在 Kubernetes 中，`m` 表示 milli（千分之一），`100m` = 0.1 字节；正确应为 `Mi`（Mebibyte）\n4. 等待 Pod 滚动更新完成，确认所有旧 Pod 已被替换\n5. 滚动更新完成后，立即还原 maxUnavailable 为原始值（maxUnavailable 只是使滚动更新完成的手段，不是故障本身，不应泄漏到恢复阶段）\n6. 观察 Pod 启动行为\n\n**注入验证**：\n1. 执行 `kubectl rollout status deployment <deployment-name>`，确认滚动更新已完成（所有旧 Pod 已被替换）。如果滚动更新未完成（卡死），则故障未完全生效，不可判定为 verified\n2. 执行 `kubectl get pods`，确认**所有**目标 Pod 状态为 CrashLoopBackOff，RESTARTS 持续增长（不是仅一个新 Pod，而是全部副本）\n3. 执行 `kubectl get pod <pod-name> -o jsonpath='{.status.containerStatuses[0].lastState}'`，确认 reason 为 OOMKilled 或 StartError（cgroup v2 环境下极小 limit 可能导致容器无法启动而非 OOMKill）\n4. 执行 `kubectl describe pod <pod-name>`，确认 limits.memory 为极小值\n5. 确认容器启动后立即异常退出（运行时间极短或无法启动）\n\n**注入恢复**：\n1. 恢复应用 A 的 Deployment，将 memory limit 修正为正确单位（如 `256Mi`）\n3. 等待 Pod 滚动更新完成\n\n**恢复验证**：\n1. 执行 `kubectl get pods`，确认 Pod 状态为 Running 且不再重启\n2. 确认容器正常运行，内存使用率在合理范围\n3. 确认应用 A 服务正常\n\n**基准事实**：\n- **根因**：memory limit 单位写错（如 `100m` 而非 `100Mi`），导致 limit 值极小，容器启动后内存使用立即超过 limit 被 OOMKill，或在 cgroup v2 环境下因内存配置过小无法启动\n- **必现现象**：Pod 异常退出（OOMKilled 或 StartError）；CrashLoopBackOff；limits.memory 值不合理（如 100m）；容器运行时间极短或无法启动\n\n<!-- File: blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_OOM内存异常/Pod_OOM内存异常_内存压力过大.md (Tokens: ~430 | Category: anthropic-skill) -->\n**用例名称** 内存压力过大 导致 Pod_OOM内存异常\n\n**故障现象**：\n1. Pod 内存使用率接近 Limit 上限\n2. 应用响应变慢，出现延迟\n3. 存在被 OOMKill 的风险\n\n**资源准备**：\n1. 确认应用 A 已正常运行\n2. 确认应用 A 的 Pod 已配置 resources.limits.memory\n\n**演练步骤**：\n1. 定位应用 A 的 Pod\n2. 使用 chaosblade 对应用 A 的 Pod 注入内存压力，模拟内存占用增长接近 Limit 的场景\n3. 观察 Pod 内存使用率变化\n\n**注入验证**：\n1. 查看监控指标，确认 Pod 内存使用率接近 Limit 上限\n2. 查看 Pod Event，确认存在内存相关告警\n3. 确认应用 A 的响应延迟增大\n\n**注入恢复**：\n1. 销毁 chaosblade 内存压力注入实验\n\n**恢复验证**：\n1. 查看监控指标，确认 Pod 内存使用率恢复正常\n2. 确认应用性能恢复正常\n\n**基准事实**：\n- **根因**：应用内存使用增长或注入内存压力，导致 Pod 内存使用率接近 Limit，存在被 OOMKill 的风险\n- **必现现象**：Pod 内存使用率接近 Limit；应用响应变慢；存在 OOMKill 风险\n\n<!-- File: blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_Pending/Pod_Pending_PVC未绑定.md (Tokens: ~969 | Category: anthropic-skill) -->\n**用例名称** PVC未绑定 导致 Pod_Pending\n\n**故障现象**：\n1. Pod 状态为 Pending，无法启动\n2. Pod Events 中显示 `pod has unbound immediate PersistentVolumeClaims`\n3. PVC 状态为 Pending，无法绑定到 PV\n\n**资源准备**：\n1. 确认应用 A 已正常运行\n2. 确认集群中 StorageClass 和 CSI 插件正常工作\n\n**演练步骤**（注意：本用例需要临时修改 Deployment 添加 volume 引用，这是故障注入的必要操作，不违反安全红线。目标应用无需预先配置 PVC——注入的目的就是添加一个无法绑定的 PVC 依赖。恢复步骤会还原所有修改）：\n1. 记录 Deployment 当前 maxUnavailable 值，并临时设为 100%（确保滚动更新能完成，故障注入的新 Pod 不会 Ready，默认策略下 K8s 不会终止旧 Pod，导致滚动更新死锁）：\n   ```bash\n   kubectl get deployment <deployment-name> -n <namespace> \\\n     -o jsonpath='{.spec.strategy.rollingUpdate.maxUnavailable}'\n   kubectl patch deployment <deployment-name> -n <namespace> --type='json' \\\n     -p='[{\"op\":\"replace\",\"path\":\"/spec/strategy/rollingUpdate/maxUnavailable\",\"value\":\"100%\"}]'\n   ```\n2. 使用 `kubectl apply -f` 创建一个引用不存在的 StorageClass 的 PVC（通过 `stdin_data` 传入 YAML）：\n   ```yaml\n   apiVersion: v1\n   kind: PersistentVolumeClaim\n   metadata:\n     name: chaos-test-pvc\n     namespace: <namespace>\n   spec:\n     accessModes: [\"ReadWriteOnce\"]\n     storageClassName: \"non-existent-sc\"\n     resources:\n       requests:\n         storage: 10Gi\n   ```\n3. 使用 `kubectl patch` 修改应用 A 的 Deployment，添加引用该 PVC 的 volume 和 volumeMount\n4. 等待 Pod 滚动更新完成，确认所有旧 Pod 已被替换\n5. 滚动更新完成后，立即还原 maxUnavailable 为原始值（maxUnavailable 只是使滚动更新完成的手段，不是故障本身，不应泄漏到恢复阶段）\n6. 观察新 Pod 的状态\n\n**注入验证**：\n1. 执行 `kubectl rollout status deployment <deployment-name>`，确认滚动更新已完成（所有旧 Pod 已被替换）。如果滚动更新未完成（卡死），则故障未完全生效，不可判定为 verified\n2. 执行 `kubectl get pvc`，确认 PVC 状态为 Pending\n3. 执行 `kubectl get pods`，确认**所有**目标 Pod 状态为 Pending（不是仅一个新 Pod，而是全部副本）\n4. 执行 `kubectl describe pod <pod-name>`，确认 Events 显示 unbound PVC 相关信息\n5. 执行 `kubectl describe pvc chaos-test-pvc`，确认 StorageClass 不存在或 Provisioner 异常\n\n**注入恢复**：\n1. 恢复应用 A 的 Deployment 定义，移除引用 chaos-test-pvc 的 volume\n2. 删除测试用 PVC：`kubectl delete pvc chaos-test-pvc`\n3. 等待 Pod 滚动更新完成\n\n**恢复验证**：\n1. 执行 `kubectl get pods`，确认 Pod 状态恢复为 Running\n2. 确认测试 PVC 已被清理\n\n**基准事实**：\n- **根因**：Pod 引用的 PVC 无法绑定，原因为 StorageClass 不存在或 Provisioner 异常，导致 Pod 无法挂载所需存储卷而 Pending\n- **必现现象**：Pod Pending；PVC Pending；Events 显示 unbound PersistentVolumeClaims\n\n<!-- File: blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_Pending/Pod_Pending_拓扑约束过严.md (Tokens: ~953 | Category: anthropic-skill) -->\n**用例名称** 拓扑约束过严 导致 Pod_Pending\n\n**故障现象**：\n1. Pod 状态为 Pending，无法被调度\n2. Pod Events 中显示 `didn't match pod topology spread constraints` 或 `didn't match pod anti-affinity rules`\n3. 由于拓扑分布约束或反亲和规则过严，调度器无法找到满足条件的节点\n\n**资源准备**：\n1. 确认应用 A 已正常运行\n2. 确认集群节点数量有限（便于触发约束冲突）\n\n**演练步骤**：\n1. 记录 Deployment 当前 maxUnavailable 值，并临时设为 100%（确保滚动更新能完成，故障注入的新 Pod 不会 Ready，默认策略下 K8s 不会终止旧 Pod，导致滚动更新死锁）：\n   ```bash\n   kubectl get deployment <deployment-name> -n <namespace> \\\n     -o jsonpath='{.spec.strategy.rollingUpdate.maxUnavailable}'\n   kubectl patch deployment <deployment-name> -n <namespace> --type='json' \\\n     -p='[{\"op\":\"replace\",\"path\":\"/spec/strategy/rollingUpdate/maxUnavailable\",\"value\":\"100%\"}]'\n   ```\n2. 修改应用 A 的 Deployment，添加过严的拓扑约束：\n   ```yaml\n   topologySpreadConstraints:\n   - maxSkew: 1\n     topologyKey: kubernetes.io/hostname\n     whenUnsatisfiable: DoNotSchedule\n     labelSelector:\n       matchLabels:\n         app: <app-name>\n   ```\n   或添加过严的反亲和规则：\n   ```yaml\n   affinity:\n     podAntiAffinity:\n       requiredDuringSchedulingIgnoredDuringExecution:\n       - labelSelector:\n           matchLabels:\n             app: <app-name>\n         topologyKey: kubernetes.io/hostname\n   ```\n3. 等待 Pod 滚动更新完成，确认所有旧 Pod 已被替换\n4. 滚动更新完成后，立即还原 maxUnavailable 为原始值（maxUnavailable 只是使滚动更新完成的手段，不是故障本身，不应泄漏到恢复阶段）\n5. 将应用 A 的副本数扩大到超过集群节点数\n6. 观察无法调度的 Pod 状态\n\n**注入验证**：\n1. 执行 `kubectl rollout status deployment <deployment-name>`，确认滚动更新已完成（所有旧 Pod 已被替换）。如果滚动更新未完成（卡死），则故障未完全生效，不可判定为 verified\n2. 执行 `kubectl get pods`，确认部分或全部 Pod 状态为 Pending\n3. 执行 `kubectl describe pod <pending-pod>`，确认 Events 显示拓扑约束或反亲和相关的调度失败原因\n\n**注入恢复**：\n1. 恢复应用 A 的 Deployment 定义，移除或放宽拓扑约束/反亲和规则\n2. 将副本数恢复为原始值\n3. 等待 Pod 滚动更新完成\n\n**恢复验证**：\n1. 执行 `kubectl get pods`，确认所有 Pod 状态为 Running\n2. 确认副本数恢复正常\n\n**基准事实**：\n- **根因**：topologySpreadConstraints 或 podAntiAffinity 配置过严，当副本数超过可用拓扑域时，调度器无法满足约束条件\n- **必现现象**：部分 Pod Pending；Events 显示拓扑约束或反亲和规则不满足；已调度 Pod 严格按约束分布\n\n<!-- File: blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_Pending/Pod_Pending_节点Taint无对应Toleration.md (Tokens: ~1150 | Category: anthropic-skill) -->\n**用例名称** 节点Taint无对应Toleration 导致 Pod_Pending\n\n**故障现象**：\n1. Pod 状态为 Pending，无法被调度到任何节点\n2. Pod Events 中显示 `N node(s) had untolerated taint {chaos-test: true}`\n3. 目标 Pod 可调度的所有节点均带有 Pod 无法容忍的污点\n\n**RCA症状**：\n1. Pod 状态为 Pending，无法被调度到任何节点\n2. Pod Events 中显示 `had untolerated taint`\n（以上为kubectl直接可观测的现象，不包含诊断结论）\n\n**资源准备**：\n1. 确认应用 A 已正常运行\n2. 确认集群中有多个可调度节点\n3. 记录应用 A 的 Pod 当前运行在哪些节点上（这些节点即为\"目标节点\"）\n\n**演练步骤**：\n\n> **爆炸半径控制**：本用例仅 taint 目标 Pod 所在的节点（而非全部集群节点），\n> 通过 nodeSelector 约束目标 Pod 只能调度到这些节点，从而在保证故障复现的同时\n> 避免影响集群中其他工作负载的调度。\n\n1. 记录目标节点的当前 taint 信息，以及 Deployment 的当前 nodeSelector（用于恢复）\n2. 记录 Deployment 当前 maxUnavailable 值，并临时设为 100%（确保滚动更新能完成，故障注入的新 Pod 不会 Ready，默认策略下 K8s 不会终止旧 Pod，导致滚动更新死锁）：\n   ```bash\n   kubectl get deployment <deployment-name> -n <namespace> \\\n     -o jsonpath='{.spec.strategy.rollingUpdate.maxUnavailable}'\n   kubectl patch deployment <deployment-name> -n <namespace> --type='json' \\\n     -p='[{\"op\":\"replace\",\"path\":\"/spec/strategy/rollingUpdate/maxUnavailable\",\"value\":\"100%\"}]'\n   ```\n3. 给目标节点添加标签：`kubectl label node <node> chaos-target=<app-name>`（仅目标 Pod 所在节点）\n4. 给应用 A 的 Deployment 添加 nodeSelector，约束 Pod 只能调度到目标节点：\n   `kubectl patch deployment <name> -n <ns> -p '{\"spec\":{\"template\":{\"spec\":{\"nodeSelector\":{\"chaos-target\":\"<app-name>\"}}}}}'`\n5. 等待 rollout 完成（Pod 仍在原节点上运行，因为只有目标节点有此标签）\n6. 滚动更新完成后，立即还原 maxUnavailable 为原始值（maxUnavailable 只是使滚动更新完成的手段，不是故障本身，不应泄漏到恢复阶段）\n7. 给目标节点添加污点：`kubectl taint node <node> chaos-test=true:NoSchedule`（仅目标节点）\n8. 删除应用 A 的一个 Pod，触发重建调度\n9. 观察新 Pod 的调度状态\n\n**注入验证**：\n1. 执行 `kubectl get pods`，确认新 Pod 状态为 Pending\n2. 执行 `kubectl describe pod <pod-name>`，确认 Events 中显示 `had untolerated taint {chaos-test: true}`\n3. 确认目标节点均有 chaos-test taint\n\n**注入恢复**：\n1. 移除目标节点上添加的污点：`kubectl taint node <node> chaos-test=true:NoSchedule-`\n2. 移除 Deployment 的 nodeSelector 中添加的 chaos-target 键（若原 Deployment 无 nodeSelector，则移除整个 nodeSelector）\n3. 移除目标节点上添加的标签：`kubectl label node <node> chaos-target-`\n4. 等待 Pod 滚动更新完成\n\n**恢复验证**：\n1. 执行 `kubectl get pods`，确认 Pod 状态变为 Running\n2. 确认目标节点 taint 已恢复到演练前状态\n3. 确认 Deployment spec 已恢复到演练前状态\n\n**基准事实**：\n- **根因**：目标 Pod 可调度的所有节点被标记了 Taint，而 Pod 未配置对应的 Toleration，导致调度器无法找到合适节点\n- **必现现象**：Pod Pending；Events 显示 untolerated taint；目标节点带有不可容忍的污点\n\n<!-- File: blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_Terminating/Pod_Terminating_Finalizers未清理.md (Tokens: ~908 | Category: anthropic-skill) -->\n**用例名称** Finalizers未清理 导致 Pod_Terminating\n\n**故障现象**：\n1. Pod 无法完成删除，`metadata.deletionTimestamp` 已设置但 Pod 对象仍存在于 API 中\n2. Pod 的 metadata 中存在 finalizers 字段，等待外部控制器清理\n3. kubectl 显示状态可能是 `Terminating`（容器仍在运行时）或 `Error`/`Failed`（容器已退出时）\n\n> **注意**：\"Terminating\" 是 kubectl 的显示状态，仅当 `deletionTimestamp` 已设置\n> 且容器仍在运行时才显示。如果容器在 delete 信号后已退出，kubectl 会按容器状态\n> 显示（如 Error/Completed），但 Pod 对象仍因 finalizer 滞留在 API 中。\n> 判定依据是 `deletionTimestamp` + `finalizers` 同时存在，而非 kubectl 显示状态。\n\n**RCA症状**：\n1. `kubectl get pod` 显示 Pod 状态为 Terminating 或 Error/Failed，但 Pod 对象持续存在\n2. `kubectl get pod -o jsonpath='{.metadata.deletionTimestamp}'` 返回非空时间戳\n3. `kubectl get pod -o jsonpath='{.metadata.finalizers}'` 返回非空列表\n（以上为kubectl直接可观测的现象，不包含诊断结论）\n\n**资源准备**：\n1. 确认目标应用已正常运行\n2. 确认目标 Pod 当前没有 finalizers（`kubectl get pod <name> -o jsonpath='{.metadata.finalizers}'` 返回空）\n\n**演练步骤**：\n1. 定位目标 Pod\n2. 使用 kubectl patch 给 Pod 添加自定义 finalizer：\n   `kubectl patch pod <pod-name> -n <namespace> -p '{\"metadata\":{\"finalizers\":[\"example.com/block-deletion\"]}}'`\n3. 使用 `--wait=false` 删除 Pod，触发终止流程：\n   `kubectl delete pod <pod-name> -n <namespace> --wait=false`\n   > 不加 `--wait=false` 会导致 kubectl 等待删除完成，因 finalizer 阻塞而超时。\n4. 观察 Pod 状态变化\n\n**注入验证**：\n1. 执行 `kubectl get pod <pod-name>`，确认 Pod 对象仍存在（显示 Terminating 或 Error）\n2. 执行 `kubectl get pod <pod-name> -o jsonpath='{.metadata.deletionTimestamp}'`，确认已设置\n3. 执行 `kubectl get pod <pod-name> -o jsonpath='{.metadata.finalizers}'`，确认包含注入的 finalizer\n4. 确认没有控制器在处理该 finalizer（`example.com/block-deletion` 是注入的假标识）\n\n**注入恢复**：\n1. 移除 Pod 上的 finalizer：\n   `kubectl patch pod <pod-name> -n <namespace> --type=json -p '[{\"op\":\"remove\",\"path\":\"/metadata/finalizers\"}]'`\n2. Pod 将被 Kubernetes GC 自动清除\n\n**恢复验证**：\n1. 执行 `kubectl get pod <pod-name>`，确认 Pod 已从集群中删除（返回 NotFound）\n2. 确认 ReplicaSet 已创建替代 Pod 且状态为 Running\n\n**基准事实**：\n- **根因**：Pod 的 metadata 中存在 finalizers，Kubernetes 在删除资源时会设置 deletionTimestamp 但不会从 etcd 中移除资源对象，直到所有 finalizer 被外部控制器清除\n- **必现现象**：Pod 对象持续存在于 API 中；deletionTimestamp 已设置；metadata.finalizers 非空\n\n<!-- File: blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_Terminating/Pod_Terminating_Volume卸载失败.md (Tokens: ~725 | Category: anthropic-skill) -->\n**用例名称** Volume卸载失败 导致 Pod_Terminating\n\n**故障现象**：\n1. Pod 状态长时间停留在 Terminating\n2. Pod Events 或 Node Events 中显示 `FailedMount`、`UnmountVolume failed`、`device is busy`\n3. Volume 无法从节点上正常 unmount/detach，阻塞 Pod 终止流程\n\n**资源准备**：\n1. 确认应用 A 已正常运行，且挂载了 PVC（云盘类型）\n2. 确认监控系统可观测 Pod 和 Volume 状态\n\n**演练步骤**：\n1. 定位应用 A 的 Pod 及其挂载的 Volume 路径\n2. 进入目标节点，在 Volume 的挂载目录下创建一个持续占用文件句柄的进程，模拟 device busy：\n   ```bash\n   # 在节点上执行（通过 nsenter 或 debug pod）\n   # 找到 volume 挂载路径\n   mount | grep <pv-name>\n   # 创建持续占用的进程\n   tail -f <挂载路径>/some-file &\n   ```\n   或使用 chaosblade 对节点注入 IO 负载，锁住磁盘操作：\n   ```bash\n   blade create k8s node-disk burn \\\n     --names <节点名> \\\n     --path <volume挂载路径> \\\n     --read --write \\\n     --timeout 180 \\\n     --kubeconfig <路径>\n   ```\n3. 删除应用 A 的 Pod，触发 Terminating 流程\n4. 观察 Pod Terminating 状态持续时间\n\n**注入验证**：\n1. 执行 `kubectl get pods`，确认 Pod 状态为 Terminating 且长时间未消失\n2. 查看 Node Events 或 `kubectl describe pod`，确认有 UnmountVolume 失败或 device busy 相关错误\n3. 在节点上确认 volume 挂载路径仍被占用\n\n**注入恢复**：\n1. 终止节点上占用 volume 的进程（kill tail 进程）\n2. 若使用 chaosblade：销毁 IO 实验 `blade destroy <UID>`\n3. 等待 kubelet 自动重试 unmount 操作\n\n**恢复验证**：\n1. 执行 `kubectl get pods`，确认 Terminating 的 Pod 已完成删除\n2. 确认 volume 已成功 unmount 和 detach\n3. 确认 PV 状态恢复为 Available 或被新 Pod 重新绑定\n\n**基准事实**：\n- **根因**：Volume unmount 时设备仍被占用（device busy）或 CSI 异常，导致 kubelet 无法完成卷卸载，Pod 终止流程被阻塞\n- **必现现象**：Pod Terminating 持续；Events 显示 UnmountVolume failed/device busy；Volume 挂载路径未释放\n\n<!-- File: blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_Terminating/Pod_Terminating_网卡卸载失败.md (Tokens: ~688 | Category: anthropic-skill) -->\n**用例名称** 网卡卸载失败 导致 Pod_Terminating\n\n**故障现象**：\n1. Pod 状态长时间停留在 Terminating\n2. 容器已停止，但 Pod sandbox 清理失败\n3. Events 或 kubelet 日志中显示 CNI DEL 调用失败或网络资源释放异常\n\n**资源准备**：\n1. 确认应用 A 已正常运行\n2. 确认集群使用 ENI/Terway 等需要显式清理网络资源的 CNI 插件\n3. 确认监控系统可观测 Pod 状态和 CNI 插件日志\n\n**演练步骤**：\n1. 定位应用 A 的 Pod 所在节点\n2. 使用 chaosblade 挂起节点上的 CNI 插件进程（如 terway-daemon），模拟 CNI 响应异常：\n   ```bash\n   blade create k8s node-process stop \\\n     --names <节点名> \\\n     --process terway \\\n     --timeout 120 \\\n     --kubeconfig <路径>\n   ```\n   或删除 CNI 插件 DaemonSet 中该节点的 Pod（先 cordon 节点防止重建）\n3. 删除应用 A 的 Pod，触发 Terminating 流程\n4. 观察 Pod Terminating 状态\n\n**注入验证**：\n1. 执行 `kubectl get pods`，确认 Pod 状态为 Terminating 且长时间未消失\n2. 查看 kubelet 日志（`journalctl -u kubelet`），确认有 CNI DEL 调用超时或失败的记录\n3. 确认 CNI 插件进程处于 stopped 状态或不可用\n\n**注入恢复**：\n1. 恢复 CNI 插件进程：等待 chaosblade 超时或执行 `blade destroy <UID>`\n2. 若删除了 CNI Pod：uncordon 节点，等待 CNI DaemonSet Pod 重建\n3. kubelet 将自动重试 sandbox 清理\n\n**恢复验证**：\n1. 确认 CNI 插件进程恢复正常\n2. 执行 `kubectl get pods`，确认 Terminating 的 Pod 已被完全清理\n3. 确认节点网络资源（ENI/IP）已释放\n4. 确认新 Pod 可以正常创建和分配网络\n\n**基准事实**：\n- **根因**：CNI 插件异常或不可用，导致 Pod 删除时网卡/ENI 资源无法正常释放，sandbox 清理失败，Pod 卡在 Terminating\n- **必现现象**：Pod Terminating 持续；kubelet 日志显示 CNI DEL 失败；网络资源未释放\n\n<!-- File: blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_Terminating/Pod_Terminating_节点宕机kubelet失联.md (Tokens: ~611 | Category: anthropic-skill) -->\n**用例名称** 节点宕机kubelet失联 导致 Pod_Terminating\n\n**故障现象**：\n1. Pod 状态长时间停留在 Terminating，无法完成删除\n2. 节点状态变为 NotReady，kubelet 停止上报\n3. API Server 已下发删除指令，但 kubelet 无法执行实际清理操作\n\n**资源准备**：\n1. 确认应用 A 已正常运行，至少有一个副本运行在目标节点上\n2. 确认监控系统可观测节点状态和 Pod 状态\n\n**演练步骤**：\n1. 定位运行应用 A 的目标节点\n2. 先通过 kubectl 删除应用 A 在目标节点上的 Pod（触发 Terminating）\n3. 立即使用 chaosblade 对目标节点注入网络完全丢包（node-network drop 即全量丢包，不需要 --percent），并设置 `--timeout 300`，模拟节点宕机导致 kubelet 失联\n4. 观察 Pod Terminating 状态持续时间\n\n**注入验证**：\n1. 执行 `kubectl get pods`，确认目标 Pod 状态为 Terminating 且长时间未消失\n2. 执行 `kubectl get nodes`，确认目标节点状态为 NotReady\n3. 查看 Pod 详情，确认 deletionTimestamp 已设置但 Pod 未被实际清理\n\n**注入恢复**：\n1. 等待 chaosblade 实验自动超时恢复（300 秒内）\n2. 如超时后仍未恢复，通过 `blade destroy <UID>` 或重启节点强制恢复\n3. kubelet 恢复后会自动清理 Terminating 状态的 Pod\n\n**恢复验证**：\n1. 执行 `kubectl get nodes`，确认目标节点恢复 Ready\n2. 执行 `kubectl get pods`，确认 Terminating 的 Pod 已被清理\n3. 确认应用 A 的新 Pod 在其他节点正常运行\n\n**基准事实**：\n- **根因**：节点宕机或 kubelet 失联，导致 API Server 下发的删除指令无法被执行，Pod 停留在 Terminating 状态\n- **必现现象**：Pod 状态为 Terminating 且长时间不消失；节点 NotReady；deletionTimestamp 已设置\n\n<!-- File: blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_云盘空间打满/Pod_云盘空间打满_日志未清理.md (Tokens: ~701 | Category: anthropic-skill) -->\n**用例名称** 日志未清理 导致 Pod_云盘空间打满\n\n**故障现象**：\n1. Pod 挂载的云盘空间使用率达到 100%\n2. 应用写入操作失败，日志报 `No space left on device`\n3. 应用功能异常，数据无法持久化\n\n**资源准备**：\n1. 确认应用 A 已正常运行，且挂载了 PVC 用于数据存储\n2. 确认 PVC 对应的云盘容量已知\n3. 确认监控系统可观测 PVC 磁盘使用率\n\n**演练步骤**：\n1. 定位应用 A 的 Pod 及其 PVC 挂载路径\n2. 使用 chaosblade 对应用 A 的 Pod 注入磁盘填充，模拟日志堆积打满云盘：\n   ```bash\n   blade create k8s pod-disk fill \\\n     --namespace <namespace> \\\n     --labels \"app=<app>\" \\\n     --path <PVC挂载路径> \\\n     --percent 99 \\\n     --timeout 300 \\\n     --kubeconfig <路径>\n   ```\n3. 观察应用 A 的写入行为和错误日志\n\n**注入验证**：\n1. 进入 Pod 查看挂载路径磁盘使用率：`df -h <挂载路径>`，确认使用率接近 100%\n2. 在 Pod 内尝试写入文件，确认报 `No space left on device` 错误\n3. 查看应用 A 日志，确认有写入失败相关错误\n4. 确认应用 A 的业务功能受影响（如数据写入失败）\n\n**注入恢复**：\n1. 销毁 chaosblade 磁盘填充实验：`blade destroy <UID>`\n2. 确认填充的临时文件被清理\n3. 若空间未释放，手动清理注入的文件\n\n**恢复验证**：\n1. 进入 Pod 查看挂载路径磁盘使用率，确认恢复到正常水平\n2. 在 Pod 内尝试写入文件，确认成功\n3. 确认应用 A 的写入操作恢复正常\n4. 确认应用 A 业务功能恢复\n\n**基准事实**：\n- **根因**：云盘上的日志或数据文件持续增长且未配置清理策略，最终占满整个磁盘空间，导致新的写入操作失败\n- **必现现象**：磁盘使用率 100%；写入报 No space left on device；应用功能异常\n\n<!-- File: blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_磁盘空间使用率过高/Pod_磁盘空间使用率过高_应用日志数据积累.md (Tokens: ~569 | Category: anthropic-skill) -->\n**用例名称** 应用日志数据积累 导致 Pod_磁盘空间使用率过高\n\n**故障现象**：\n1. Pod 使用的存储空间接近上限，磁盘使用率告警\n2. 应用可能出现写入失败、响应变慢等问题\n3. 容器内日志目录（如 /var/log）文件过大\n\n**资源准备**：\n1. 确认应用 A/B 已正常运行\n2. 确认应用配置了日志输出（如输出到 /tmp 或挂载目录）\n\n**演练步骤**：\n1. 定位应用 A 的 Pod\n2. 使用 chaosblade 向应用 A 的 Pod 注入磁盘填充故障，模拟大量日志写入\n3. 持续向 Pod 写入大文件，填充磁盘空间至接近容量上限\n4. 观察 Pod 磁盘使用率变化及应用响应情况\n\n**注入验证**：\n1. 进入应用 A 的 Pod，使用 df -h 查看磁盘使用率，确认超过设定阈值\n2. 查看 Pod 状态，确认是否有磁盘相关异常事件\n3. 观察应用是否出现写入失败等异常表现\n\n**注入恢复**：\n1. 销毁 chaosblade 磁盘填充实验\n2. 删除 Pod 中产生的大文件，释放磁盘空间\n3. 或删除异常 Pod，触发重新调度创建新 Pod\n\n**恢复验证**：\n1. 查看 Pod 磁盘使用率，确认恢复到正常水平\n2. 查看应用是否恢复正常写入操作\n3. 确认 Pod 状态为 Running，无磁盘相关异常事件\n\n**基准事实**：\n- **根因**：应用日志未清理或数据写入过多，导致 Pod 存储空间被占满\n- **必现现象**：Pod 磁盘使用率超过设定阈值，应用出现写入失败\n\n---\n\n<!-- File: blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_网络丢包/Pod_网络丢包_服务依赖中断.md (Tokens: ~828 | Category: anthropic-skill) -->\n**用例名称** 服务依赖中断 导致 Pod_网络丢包\n\n**故障现象**：\n1. Pod 对外部服务或上下游依赖的网络请求超时或无响应\n2. 应用健康检查可能失败（如依赖外部探活）\n3. 服务间调用链路出现断裂，影响业务可用性\n\n**资源准备**：\n1. 确认目标应用已正常运行，且有对外网络调用（数据库、缓存、上下游服务等）\n2. 确认监控系统可观测网络请求成功率和延迟指标\n3. 确认目标 Pod 的标签选择器和命名空间\n\n**演练步骤**：\n1. 确认目标 Pod 的标签选择器和命名空间：\n   ```bash\n   kubectl get pods -n <namespace> -l <label-selector> -o wide\n   ```\n2. 使用 ChaosBlade 对目标 Pod 注入网络丢包故障：\n   ```bash\n   blade create k8s pod-network drop \\\n     --namespace <namespace> \\\n     --labels \"<label-key>=<label-value>\" \\\n     --source-port <port> \\\n     --kubeconfig <kubeconfig-path>\n   ```\n   - `--source-port`：限定丢包端口（如 3306 丢弃 MySQL 流量、53 丢弃 DNS 流量）\n   - 不指定端口时为全量丢包（慎用，影响所有流量包括监控和健康检查）\n3. 记录返回的 blade_uid，用于后续恢复\n\n**注入验证**：\n1. 在目标 Pod 内验证网络连通性丧失：\n   ```bash\n   kubectl exec <pod-name> -n <namespace> -- wget -qO- --timeout=5 <依赖服务地址>\n   ```\n   确认请求超时或无响应\n2. 查看应用日志确认出现连接超时错误：\n   ```bash\n   kubectl logs <pod-name> -n <namespace> --tail=20\n   ```\n3. 检查服务调用链路指标，确认目标端口流量中断\n\n**注入恢复**：\n1. 销毁 ChaosBlade 实验：\n   ```bash\n   blade destroy <blade_uid>\n   ```\n2. 如 Pod 因丢包导致健康检查失败被重启，等待新 Pod Ready\n\n**恢复验证**：\n1. 在目标 Pod 内重新验证网络连通性恢复：\n   ```bash\n   kubectl exec <pod-name> -n <namespace> -- wget -qO- --timeout=5 <依赖服务地址>\n   ```\n2. 确认应用日志不再出现连接超时错误\n3. 确认服务调用链路指标恢复正常\n\n**基准事实**：\n- **根因**：Pod 出方向网络流量被 iptables DROP 规则丢弃，导致对指定端口/地址的所有请求无响应\n- **必现现象**：目标端口的 TCP/UDP 请求超时；应用日志出现 connection timed out；依赖该连接的业务功能不可用\n\n<!-- File: blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_被驱逐重建/Pod_被驱逐重建_DiskPressure.md (Tokens: ~756 | Category: anthropic-skill) -->\n**用例名称** DiskPressure 导致 Pod_被驱逐重建\n\n**故障现象**：\n1. Pod 被 kubelet 驱逐（Evicted），状态为 Failed，reason 为 Evicted\n2. 节点 Conditions 中 DiskPressure 为 True\n3. 容器运行时目录（如 /var/lib/docker 或 /var/lib/containerd）磁盘使用超过 kubelet 驱逐阈值\n\n**资源准备**：\n1. 确认应用 A 已正常运行，有多个副本分布在不同节点\n2. 确认目标节点的容器运行时磁盘当前使用率距离驱逐阈值有一定空间\n3. 确认监控系统可观测节点磁盘使用率和 Pod 驱逐事件\n\n**演练步骤**：\n1. 查看目标节点 kubelet 配置的驱逐阈值（默认 `imagefs.available < 15%`）\n2. 使用 chaosblade 对目标节点的容器运行时目录注入磁盘填充，使其超过驱逐阈值：\n   ```bash\n   blade create k8s node-disk fill \\\n     --names <节点名> \\\n     --path /var/lib/containerd \\\n     --percent 90 \\\n     --timeout 300 \\\n     --kubeconfig <路径>\n   ```\n3. 等待 kubelet 检测到 DiskPressure 并触发 Pod 驱逐\n4. 观察应用 A 的 Pod 驱逐和重建行为\n\n**注入验证**：\n1. 执行 `kubectl describe node <节点名>`，确认 Conditions 中 DiskPressure 为 True\n2. 执行 `kubectl get pods --field-selector=status.phase=Failed`，确认有 Pod 被 Evicted\n3. 查看被驱逐 Pod 的详情，确认 reason 为 `The node was low on resource: ephemeral-storage`\n4. 确认应用 A 在其他节点重建 Pod\n\n**注入恢复**：\n1. 等待 chaosblade 实验自动超时恢复（300 秒内），或执行 `blade destroy <UID>`\n2. 等待节点磁盘空间释放\n3. 清理 Evicted Pod：`kubectl delete pods --field-selector=status.phase=Failed`\n\n**恢复验证**：\n1. 执行 `kubectl describe node <节点名>`，确认 DiskPressure 恢复为 False\n2. 确认应用 A 的 Pod 在正常节点上运行\n3. 确认节点磁盘使用率恢复到安全水位\n\n**基准事实**：\n- **根因**：容器运行时目录磁盘使用超过 kubelet 驱逐阈值（DiskPressure），kubelet 按优先级驱逐 Pod 以释放磁盘空间\n- **必现现象**：节点 DiskPressure=True；Pod 被 Evicted；reason 为 ephemeral-storage 不足\n\n<!-- File: blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_镜像拉取失败/Pod_镜像拉取失败_凭证缺失或过期.md (Tokens: ~991 | Category: anthropic-skill) -->\n**用例名称** 凭证缺失或过期 导致 Pod_镜像拉取失败\n\n**故障现象**：\n1. Pod 状态为 ImagePullBackOff 或 ErrImagePull\n2. Pod Events 中显示 `unauthorized` 或 `authentication required`\n3. 镜像仓库返回 401/403 认证错误\n\n**资源准备**：\n1. 确认应用 A 已正常运行，且使用私有镜像仓库\n2. 确认应用 A 的 Pod 配置了 imagePullSecrets\n\n**演练步骤**：\n1. 记录应用 A 当前的 imagePullSecrets 名称和 imagePullPolicy 值\n2. 记录 Deployment 当前 maxUnavailable 值，并临时设为 100%（确保滚动更新能完成，故障注入的新 Pod 不会 Ready，默认策略下 K8s 不会终止旧 Pod，导致滚动更新死锁）：\n   ```bash\n   kubectl get deployment <deployment-name> -n <namespace> \\\n     -o jsonpath='{.spec.strategy.rollingUpdate.maxUnavailable}'\n   kubectl patch deployment <deployment-name> -n <namespace> --type='json' \\\n     -p='[{\"op\":\"replace\",\"path\":\"/spec/strategy/rollingUpdate/maxUnavailable\",\"value\":\"100%\"}]'\n   ```\n3. 创建一个包含无效凭证的 Secret 来替换原有的有效凭证：\n   ```bash\n   kubectl create secret docker-registry chaos-invalid-secret \\\n     --docker-server=<registry-server> \\\n     --docker-username=invalid-user \\\n     --docker-password=invalid-password \\\n     --namespace <namespace>\n   ```\n4. 修改应用 A 的 Deployment，将 imagePullSecrets 指向无效 Secret（或直接移除 imagePullSecrets）。\n   同时检查 imagePullPolicy：如果当前为 `IfNotPresent`，需同时改为 `Always`，否则 K8s 直接使用本地缓存镜像启动 Pod，不会触发凭证校验，故障无法注入\n5. 等待 Pod 滚动更新完成，确认所有旧 Pod 已被替换\n6. 滚动更新完成后，立即还原 maxUnavailable 为原始值（maxUnavailable 只是使滚动更新完成的手段，不是故障本身，不应泄漏到恢复阶段）\n7. 观察 Pod 状态变化\n\n**注入验证**：\n1. 执行 `kubectl rollout status deployment <deployment-name>`，确认滚动更新已完成（所有旧 Pod 已被替换）。如果滚动更新未完成（卡死），则故障未完全生效，不可判定为 verified\n2. 执行 `kubectl get pods`，确认**所有**目标 Pod 状态为 ImagePullBackOff 或 ErrImagePull（不是仅一个新 Pod，而是全部副本）\n3. 执行 `kubectl describe pod <pod-name>`，确认 Events 中显示认证失败相关错误\n4. 确认错误信息包含 `unauthorized` 或 `authentication required`\n\n**注入恢复**：\n1. 恢复应用 A 的 Deployment，将 imagePullSecrets 指回原有的有效 Secret。如果注入时修改了 imagePullPolicy，需同时还原为原始值\n2. 删除测试用的无效 Secret：`kubectl delete secret chaos-invalid-secret`\n3. 等待 Pod 滚动更新完成\n\n**恢复验证**：\n1. 执行 `kubectl get pods`，确认 Pod 状态恢复为 Running\n2. 确认镜像拉取成功，无认证错误\n\n**基准事实**：\n- **根因**：imagePullSecrets 缺失或 Secret 中的凭证已过期/无效，导致向私有镜像仓库拉取镜像时认证失败\n- **必现现象**：Pod ImagePullBackOff；Events 显示 unauthorized/authentication required；镜像仓库返回 401/403\n\n<!-- File: blade-ai/skills/k8s-chaos-skills/references/catalogue/Pod_镜像拉取失败/Pod_镜像拉取失败_镜像不存在或标签错误.md (Tokens: ~736 | Category: anthropic-skill) -->\n**用例名称** 镜像不存在或标签错误 导致 Pod_镜像拉取失败\n\n**故障现象**：\n1. Pod 状态停留在 ImagePullBackOff 或 ErrImagePull\n2. Pod Event 显示镜像拉取失败，错误信息包含 `manifest for xxx not found`\n\n**资源准备**：\n1. 确认应用 A/B 所在节点正常运行\n2. 确认节点可正常访问镜像仓库\n\n**演练步骤**：\n1. 定位应用 A 的 Deployment\n2. 记录 Deployment 当前 maxUnavailable 值，并临时设为 100%（确保滚动更新能完成，故障注入的新 Pod 不会 Ready，默认策略下 K8s 不会终止旧 Pod，导致滚动更新死锁）：\n   ```bash\n   kubectl get deployment <deployment-name> -n <namespace> \\\n     -o jsonpath='{.spec.strategy.rollingUpdate.maxUnavailable}'\n   kubectl patch deployment <deployment-name> -n <namespace> --type='json' \\\n     -p='[{\"op\":\"replace\",\"path\":\"/spec/strategy/rollingUpdate/maxUnavailable\",\"value\":\"100%\"}]'\n   ```\n3. 修改应用 A 的镜像地址为不存在的镜像名称或标签\n4. 等待 Pod 滚动更新完成，确认所有旧 Pod 已被替换\n5. 滚动更新完成后，立即还原 maxUnavailable 为原始值（maxUnavailable 只是使滚动更新完成的手段，不是故障本身，不应泄漏到恢复阶段）\n6. 观察 Pod 的镜像拉取状态\n\n**注入验证**：\n1. 执行 `kubectl rollout status deployment <deployment-name>`，确认滚动更新已完成（所有旧 Pod 已被替换）。如果滚动更新未完成（卡死），则故障未完全生效，不可判定为 verified\n2. 执行 `kubectl get pods`，确认**所有**目标 Pod 状态停留在 ImagePullBackOff 或 ErrImagePull（不是仅一个新 Pod，而是全部副本）\n3. 执行 `kubectl describe pod <pod-name>`，确认 Events 包含镜像不存在相关信息，如 `manifest for xxx not found`\n\n**注入恢复**：\n1. 恢复应用 A 的镜像地址为正确的镜像名称和标签\n2. 等待 Pod 滚动更新完成\n\n**恢复验证**：\n1. 查看 Pod 状态，确认恢复为 Running\n2. 查看 Pod Event，确认镜像拉取成功\n\n**基准事实**：\n- **根因**：Pod 配置的镜像名称拼写错误或标签在镜像仓库中不存在\n- **必现现象**：Pod 状态为 ImagePullBackOff 或 ErrImagePull，日志显示 `manifest for xxx not found`\n\n<!-- ... +8 more modular skills available via /api/skills/chaosblade-io/chaosblade?path={path} -->\n</yakaai_skills>"}