Chaos Agent 工作流程报告
📋 目录
1. 概述
1.1 Agent 是什么?
Chaos Redis Analyzer Agent 是一个基于 LangGraph 框架构建的智能故障分析系统。它的主要职责是:
┌─────────────────────────────────────────────────────────────┐
│ Chaos Redis Analyzer │
│ │
│ 1. 在 Kubernetes 环境中注入混沌故障(如 Pod 杀死、网络延迟等) │
│ 2. 监控故障注入后的系统状态变化 │
│ 3. 收集日志、事件、追踪数据 │
│ 4. 智能分析故障表现是否合理 │
│ 5. 生成详细的分析报告 │
└─────────────────────────────────────────────────────────────┘
1.2 为什么需要这个 Agent?
在生产环境中,我们需要验证系统的容错能力。比如:
- 当一个 Redis Pod 被意外杀死后,系统能否自动恢复?
- 网络延迟发生时,应用是否能正确处理超时?
这个 Agent 就是自动化执行这类混沌工程测试的智能助手。
2. 整体架构
2.1 技术栈
| 组件 | 用途 |
|---|---|
| LangGraph | 工作流编排框架,定义节点和边 |
| Pydantic | 数据模型验证 |
| AsyncIO | 异步执行,提高效率 |
| MCP Tools | Kubernetes 资源操作 |
| Chaos Mesh | 故障注入平台 |
2.2 工作流图
┌──────────────────────────────────────┐
│ 工作流总览 │
└──────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────────┐
│ 1. init_context │
│ 【状态初始化和信息收集】 │
│ 验证命名空间、获取所有运行中的 Pod │
└─────────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────────┐
│ 2. pre_injection_data_plane_validation │
│ 【故障注入前数据面验证】 │
│ 部署验证 Pod、执行基准测试、建立故障前基线 │
└─────────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────────┐
│ 3. inject_fault │
│ 【故障注入执行】 │
│ 调用 Chaos Mesh 执行故障注入操作 │
└─────────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────────┐
│ 4. verify_injection │
│ 【故障注入验证】 │
│ 检查故障注入是否成功完成 │
└─────────────────────────────────────────────────────────────────────────────────┘
│
┌───────────────────────┼───────────────────────┐
│ │ │
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ success │ │ running │ │ failed │
│ 成功 │ │ 运行中 │ │ 失败 │
└──────────┘ └──────────┘ └──────────┘
│ │ │
│ ▼ │
│ ┌──────────────┐ │
│ │ wait_retry │ │
│ │ 等待重试 │ │
│ └──────────────┘ │
│ │ │
│ └──────► verify_injection │
│ (重试)
▼ │
┌─────────────────────────────────────────────────────────────────────────────────┐
│ 5. monitor_data_plane │
│ 【数据面监控】 │
│ 收集 Pod 状态变化、资源趋势、数据面日志、K8s 事件 │
└─────────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────────┐
│ 6. collect_trace │
│ 【分布式追踪收集】 │
│ 收集目标 Pod 和辅助 Pod 的追踪数据 │
└─────────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────────┐
│ 7. analyze │
│ 【智能分析】 │
│ 基于规则引擎和 LLM 分析故障表现是否合理 │
└─────────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────────┐
│ 8. report │
│ 【最终报告生成】 │
│ 汇总所有分析结果,生成 JSON 格式报告文件 │
└─────────────────────────────────────────────────────────────────────────────────┘
│
▼
【END】
3. 核心组件详解
3.1 状态模型 (ChaosAnalysisState)
状态模型是整个工作流的"大脑",存储所有节点的输入输出数据:
class ChaosAnalysisState(BaseModel):
"""Agent 的状态容器 - 所有节点共享这个状态"""
# ========== 输入参数 ==========
target_namespace: str # 目标命名空间(必需)
target_pod_label: Optional[str] # Pod 标签选择器,如 "app=redis"
target_pod_name: Optional[str] # 指定的 Pod 名称
fault_type: str # 故障类型,如 "pod-kill"
fault_params: Dict[str, Any] # 故障参数,如 {"duration": "60s"}
# ========== 数据面验证配置 ==========
data_plane_cluster_host: Optional[str] # Redis 服务主机地址
data_plane_redis_type: Optional[str] # Redis 类型 (proxy/unproxy)
data_plane_test_type: Optional[str] # 测试类型 (consistency/performance)
data_plane_timeout: Optional[int] # 超时时间(秒)
# ========== 处理过程中的数据 ==========
cluster_info: Optional[Dict[str, Any]] # 集群信息
target_pods: Optional[List[Dict[str, Any]]] # 目标 Pod 列表
primary_target_pods: Optional[List[Dict]] # 主要故障目标 Pod
auxiliary_pods: Optional[List[Dict[str, Any]]] # 辅助 Pod(拓扑上下文)
all_pods: Optional[List[Dict[str, Any]]] # 所有 Pod
injection_id: Optional[str] # 故障注入 ID
injection_status: Optional[str] # 注入状态
retry_count: int = 0 # 重试计数
# ========== 收集的数据 ==========
data_plane_validation_results: Optional[Dict] # 数据面验证结果
k8s_events: Optional[List[Dict[str, Any]]] # K8s 事件
pod_state_changes: Optional[Dict[str, Any]] # Pod 状态变化
traces: Optional[Dict[str, Any]] # 追踪数据
pre_injection_validation: Optional[Dict] # 预注入验证结果
pre_injection_baseline: Optional[Dict] # 预注入基线数据
# ========== 分析结果 ==========
analysis_result: Optional[Dict[str, Any]] # 分析结果
final_report: Optional[str] # 最终报告
error: Optional[str] # 错误信息
小贴士:可以把状态模型想象成一个"共享笔记本",每个节点(函数)都可以读取和写入这个笔记本。
3.2 代理组件 (Agents)
Agent 依赖三个核心代理组件来执行具体操作:
┌─────────────────────────────────────────────────────────────────┐
│ Agent 依赖关系 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ K8sAgent │ │ ChaosAgent │ │ DataPlaneAgent │ │
│ │ │ │ │ │ │ │
│ │ • list_pods │ │ • inject_ │ │ • deploy_validation │ │
│ │ • list_ns │ │ fault │ │ _pod │ │
│ │ • get_pod │ │ • check_ │ │ • execute_data_ │ │
│ │ _details │ │ injection │ │ plane_test │ │
│ │ • collect │ │ _status │ │ • query_logs │ │
│ │ _traces │ │ │ │ │ │
│ │ • list_ │ │ │ │ │ │
│ │ events │ │ │ │ │ │
│ └─────────────┘ └─────────────┘ └─────────────────────┘ │
│ │
│ 用于 K8s 资源 用于 Chaos Mesh 用于数据面验证 │
│ 查询和操作 故障注入 和日志收集 │
└─────────────────────────────────────────────────────────────────┘
3.3 智能分析器 (IntelligentFaultAnalyzer)
智能分析器是 Agent 的"大脑",负责:
- 规则引擎分析:基于预设规则判断故障表现
- LLM 增强分析:调用大语言模型进行深度推理
- 综合评估:给出置信度和建议
# 使用工厂模式获取分析器实例(解决竞态条件问题)
class AnalyzerFactory:
_instance: Optional[IntelligentFaultAnalyzer] = None
_lock = asyncio.Lock()
@classmethod
async def get_analyzer(cls) -> IntelligentFaultAnalyzer:
"""获取线程安全的分析器实例"""
if cls._instance is None:
async with cls._lock:
if cls._instance is None: # 双重检查锁定
cls._instance = IntelligentFaultAnalyzer()
return cls._instance
4. 工作节点详解
4.1 节点 1:init_context(状态初始化)
职责:验证环境、收集所有 Pod 信息
┌──────────────────────────────────────────────────────────────┐
│ init_context 工作流程 │
├──────────────────────────────────────────────────────────────┤
│ │
│ Step 1: 验证命名空间是否存在 │
│ └── 调用 k8s_agent.list_namespaces() │
│ │
│ Step 2: 获取所有运行中的 Pod │
│ └── 调用 k8s_agent.list_pods(ns, "status.phase=Running") │
│ │
│ Step 3: 区分主要目标 Pod 和辅助 Pod │
│ ├── 主要目标:符合 label 或 name 指定的 Pod │
│ └── 辅助 Pod:命名空间中的其他 Pod(用于拓扑分析) │
│ │
│ Step 4: 丰富 Pod 数据 │
│ └── 调用 _enrich_pod_data() 获取详细信息: │
│ ├── 状态(phase、ready、restarts) │
│ ├── 资源使用(CPU、内存) │
│ ├── Top 指标 │
│ └── 环境变量 │
│ │
│ 输出:cluster_info, target_pods, primary_target_pods, │
│ auxiliary_pods, all_pods │
└──────────────────────────────────────────────────────────────┘
关键代码解析:
@ErrorHandler.safe_node_execution("init_context", required_state_fields=["target_namespace"])
async def init_context(state: ChaosAnalysisState) -> Dict[str, Any]:
# 1. 验证命名空间
namespaces = await k8s_agent.list_namespaces()
if ns not in namespaces:
return ErrorHandler.create_error(...) # 命名空间不存在
# 2. 获取所有运行中的 Pod
all_pods = await k8s_agent.list_pods(ns, field_selector="status.phase=Running")
# 3. 区分主要目标和辅助 Pod
primary_target_pods = []
if state.target_pod_name:
primary_target_pods = [p for p in all_pods if get_pod_name(p) == state.target_pod_name]
elif state.target_pod_label and "=" in state.target_pod_label:
k, v = state.target_pod_label.split("=", 1)
primary_target_pods = [p for p in all_pods
if p.get('metadata', {}).get('labels', {}).get(k) == v]
# 4. 丰富 Pod 数据(获取详细状态、资源使用等)
for pod in primary_target_pods:
enriched_pod = await _enrich_pod_data(pod, ns, k8s_agent)
enriched_pod["analysis_role"] = "primary_target"
enriched_target_pods.append(enriched_pod)
return {
"cluster_info": {...},
"target_pods": enriched_target_pods,
"primary_target_pods": enriched_target_pods,
"auxiliary_pods": enriched_auxiliary_pods,
"all_pods": ...
}
4.2 节点 2:pre_injection_data_plane_validation(预注入验证)
职责:在故障注入前验证数据面正常,建立基线
┌──────────────────────────────────────────────────────────────┐
│ pre_injection_data_plane_validation 工作流程 │
├──────────────────────────────────────────────────────────────┤
│ │
│ 检查:是否配置了 data_plane_cluster_host? │
│ │ │
│ ├── 否 → 跳过验证,返回 {"status": "skipped"} │
│ │ │
│ └── 是 → 继续执行验证 │
│ │
│ Step 1: 检查命名空间是否存在 │
│ │
│ Step 2: 自动发现数据面验证 Pod 名称 │
│ └── 调用 _discover_data_plane_pod_name() │
│ 尝试常见名称模式: │
│ • data-plane-redis-0 (StatefulSet) │
│ • data-plane-redis (普通 Pod) │
│ • redis-data-plane-0 │
│ │
│ Step 3: 检查 Pod 是否存在且镜像一致 │
│ └── 调用 data_plane_agent.check_pod_exists_validation() │
│ │
│ Step 4: 如需要则部署/重新部署 Pod │
│ └── 调用 data_plane_agent.deploy_validation_pod_if_needed() │
│ │
│ Step 5: 执行数据面测试 │
│ └── 调用 data_plane_agent.execute_data_plane_test_validation() │
│ 测试类型:consistency(一致性)或 performance(性能)│
│ │
│ 输出:pre_injection_validation, pre_injection_baseline │
└──────────────────────────────────────────────────────────────┘
4.3 节点 3:inject_fault(故障注入)
职责:调用 Chaos Mesh 执行故障注入
┌──────────────────────────────────────────────────────────────┐
│ inject_fault 工作流程 │
├──────────────────────────────────────────────────────────────┤
│ │
│ Step 1: 准备故障注入目标 │
│ target = { │
│ "namespace": state.target_namespace, │
│ "pods": [state.target_pod_name], # 如果指定 │
│ "label_selector": state.target_pod_label # 如果指定 │
│ } │
│ │
│ Step 2: 调用 Chaos Agent 执行注入 │
│ result = await chaos_agent.inject_fault( │
│ state.fault_type, # 如 "pod-kill" │
│ target, # 目标配置 │
│ state.fault_params # 如 {"duration": "60s"} │
│ ) │
│ │
│ 输出:injection_id, injection_status="initiated" │
└──────────────────────────────────────────────────────────────┘
支持的故障类型:
| 故障类型 | 说明 |
|---|---|
pod-kill | 杀死 Pod |
pod-failure | Pod 故障模拟 |
container-kill | 杀死容器 |
network-delay | 网络延迟 |
network-loss | 网络丢包 |
network-partition | 网络分区 |
cpu-stress | CPU 压力 |
memory-stress | 内存压力 |
io-stress | IO 压力 |
4.4 节点 4:verify_injection(注入验证)
职责:验证故障注入是否成功
┌──────────────────────────────────────────────────────────────┐
│ verify_injection 工作流程 │
├──────────────────────────────────────────────────────────────┤
│ │
│ Step 1: 检查 injection_id 是否存在 │
│ └── 不存在则返回错误 │
│ │
│ Step 2: 查询注入状态 │
│ status_result = await chaos_agent.check_injection_status( │
│ state.injection_id │
│ ) │
│ │
│ Step 3: 标准化状态值 │
│ ├── "success", "completed", "finished" → "success" │
│ ├── "failed", "error", "failure" → "failed" │
│ └── "running", "in_progress", "pending" → "running" │
│ │
│ 输出:injection_status (success/failed/running) │
└──────────────────────────────────────────────────────────────┘
4.5 节点 5:wait_retry(等待重试)
职责:当注入状态为 running 时智能等待
┌──────────────────────────────────────────────────────────────┐
│ wait_retry 工作流程 │
├──────────────────────────────────────────────────────────────┤
│ │
│ 智能等待策略: │
│ │
│ 前 3 次重试:固定 5 秒间隔(快速确认) │
│ │
│ 后续重试:基于故障持续时间按比例等待 │
│ └── 等待时间 = min(30s, max(5s, 剩余时间 × 30%)) │
│ │
│ 最大重试次数 = max(3, 故障持续时间/5 + 3) │
│ │
│ 例如:故障持续 60 秒 │
│ ├── 最大重试:15 次 │
│ ├── 前 3 次:每次等 5 秒 │
│ └── 后续:动态计算等待时间 │
│ │
│ 输出:retry_count = retry_count + 1 │
│ → 返回 verify_injection 继续检查 │
└──────────────────────────────────────────────────────────────┘
4.6 节点 6:monitor_data_plane(数据面监控)
职责:收集故障后的系统状态数据
┌──────────────────────────────────────────────────────────────┐
│ monitor_data_plane 工作流程 │
├──────────────────────────────────────────────────────────────┤
│ │
│ Step 1: 重新获取所有 Pod 的当前状态(故障后) │
│ └── 调用 _get_current_pod_states() │
│ │
│ Step 2: 对比故障前后的状态变化 │
│ └── 调用 _compare_pod_states() 分析: │
│ ├── 状态变化(phase、ready) │
│ ├── 重启次数变化 │
│ ├── IP 地址变化(Pod 重启后 IP 会变) │
│ ├── 资源使用变化(CPU、内存) │
│ └── 节点变化(重新调度) │
│ │
│ Step 3: 分析资源变化趋势 │
│ └── 调用 _analyze_resource_trends() 分析: │
│ ├── CPU 趋势(增加/减少/稳定) │
│ ├── 内存趋势 │
│ └── 重启趋势 │
│ │
│ Step 4: 查询数据面执行脚本日志(带时间过滤) │
│ └── 调用 data_plane_agent.query_data_plane_execution_logs() │
│ 时间窗口: │
│ ├── 故障前 30 秒开始 │
│ └── 故障持续 + 30 秒结束 │
│ 过滤:只保留 ERROR 级别日志 │
│ │
│ Step 5: 收集并过滤 K8s 事件 │
│ └── 调用 filter_k8s_events() 去除噪声: │
│ 保留重要事件:Pod 调度、重启、健康检查失败等 │
│ 过滤噪声:常规心跳、拉取镜像成功等 │
│ │
│ 输出:pod_state_changes, data_plane_validation_results, │
│ k8s_events, monitoring_summary │
└──────────────────────────────────────────────────────────────┘
4.7 节点 7:collect_trace(追踪收集)
职责:收集分布式追踪数据
┌──────────────────────────────────────────────────────────────┐
│ collect_trace 工作流程 │
├──────────────────────────────────────────────────────────────┤
│ │
│ Step 1: 优先收集主要目标 Pod 的追踪数据 │
│ for pod in target_pods: │
│ trace_data = await k8s_agent.collect_traces( │
│ namespace, pod_name │
│ ) │
│ target_traces.append({ │
│ "pod_name": pod_name, │
│ "trace_data": trace_data, │
│ "analysis_role": "primary_target" │
│ }) │
│ │
│ Step 2: 收集辅助 Pod 的追踪数据(拓扑上下文) │
│ for pod in auxiliary_pods: │
│ ...(同样流程,但标记为 auxiliary) │
│ │
│ 输出:traces = { │
│ "all_traces": [...], │
│ "target_traces": [...], # 主要目标追踪 │
│ "auxiliary_traces": [...], # 辅助追踪 │
│ "summary": {...} │
│ } │
└──────────────────────────────────────────────────────────────┘
4.8 节点 8:analyze(智能分析)
职责:基于规则引擎和 LLM 分析故障表现
┌──────────────────────────────────────────────────────────────┐
│ analyze 工作流程 │
├──────────────────────────────────────────────────────────────┤
│ │
│ Step 1: 数据验证 │
│ ├── 检查 target_pods 是否存在 │
│ ├── 检查 data_plane_validation_results 是否有效 │
│ └── 检查 k8s_events 和 pod_state_changes │
│ │
│ Step 2: 获取分析器实例 │
│ analyzer = await AnalyzerFactory.get_analyzer() │
│ │
│ Step 3: 设置故障上下文 │
│ analyzer.decision_engine.set_fault_context( │
│ fault_type, fault_params │
│ ) │
│ │
│ Step 4: 准备分析数据 │
│ chaos_event = { │
│ "fault_type": "pod-kill", │
│ "parameters": {"duration": "60s"}, │
│ "primary_target_pod": ..., │
│ "auxiliary_topology": ... │
│ } │
│ │
│ data_plane_validation = { │
│ "data_plane_validation_results": ..., │
│ "k8s_events": ..., │
│ "pod_state_changes": ... │
│ } │
│ │
│ Step 5: 执行分析 │
│ result = await analyzer.analyze( │
│ chaos_event, │
│ data_plane_validation, │
│ enhanced_context │
│ ) │
│ 分析方法: │
│ ├── 规则引擎:基于预设规则判断 │
│ └── LLM 分析:调用大语言模型深度推理 │
│ │
│ Step 6: 保存原始分析数据(供人工核实) │
│ 保存到 reports/raw_analysis_data_xxx.json │
│ │
│ 输出:analysis_result = { │
│ "is_reasonable": True/False, # 故障表现是否合理 │
│ "confidence": 0.85, # 置信度 │
│ "explanation": "...", # 解释 │
│ "recommendations": [...], # 建议 │
│ "llm_reasoning": "..." # LLM 推理过程 │
│ } │
└──────────────────────────────────────────────────────────────┘
4.9 节点 9:report(报告生成)
职责:汇总所有结果,生成最终报告
┌──────────────────────────────────────────────────────────────┐
│ report 工作流程 │
├──────────────────────────────────────────────────────────────┤
│ │
│ Step 1: 构建最终报告结构 │
│ final_report = { │
│ "status": "completed", │
│ "timestamp": "2024-01-01T12:00:00", │
│ "summary": { │
│ "target_namespace": "default", │
│ "fault_type": "pod-kill", │
│ "injection_status": "success", │
│ "analysis_status": "reasonable", │
│ "confidence": 0.85 │
│ }, │
│ "analysis": analysis_result, │
│ "topology_data": { │
│ "cluster_info": ..., │
│ "complete_pod_topology": ..., │
│ "primary_target_pods": ..., │
│ "k8s_events": ..., │
│ "distributed_traces": ... │
│ } │
│ } │
│ │
│ Step 2: 清理控制字符(确保 JSON 序列化正常) │
│ cleaned_report = clean_control_chars(final_report) │
│ │
│ Step 3: 保存报告文件 │
│ 文件名:chaos_report_{namespace}_{fault_type}_{timestamp}.json │
│ 位置:reports/ 目录 │
│ │
│ 输出:final_report, report_file │
└──────────────────────────────────────────────────────────────┘
5. 数据流转
5.1 状态更新机制
LangGraph 使用累加更新机制,每个节点返回的字典会合并到状态中:
初始状态 (initial_state)
│
▼
┌───────────────────────────────────────────────────────┐
│ init_context 返回 │
│ { │
│ "cluster_info": {...}, │
│ "target_pods": [...], │
│ "primary_target_pods": [...], │
│ "auxiliary_pods": [...], │
│ "all_pods": [...] │
│ } │
└───────────────────────────────────────────────────────┘
│
▼ 状态合并
┌───────────────────────────────────────────────────────┐
│ 当前状态 │
│ { │
│ "target_namespace": "default", # 原始 │
│ "fault_type": "pod-kill", # 原始 │
│ "cluster_info": {...}, # 新增 │
│ "target_pods": [...], # 新增 │
│ ... │
│ } │
└───────────────────────────────────────────────────────┘
│
▼
┌───────────────────────────────────────────────────────┐
│ pre_injection_data_plane_validation 返回 │
│ { │
│ "pre_injection_validation": {...}, │
│ "pre_injection_baseline": {...} │
│ } │
└───────────────────────────────────────────────────────┘
│
▼ 状态合并
...
5.2 完整数据流转图
┌─────────────────────────────────────────────────────────────────────────────┐
│ 完整数据流转 │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ 输入参数 │
│ ├── target_namespace │
│ ├── fault_type │
│ ├── fault_params │
│ └── data_plane_cluster_host (可选) │
│ │
│ init_context │
│ │ └── 输出: cluster_info, target_pods, primary_target_pods, │
│ │ auxiliary_pods, all_pods │
│ │ │
│ pre_injection_data_plane_validation │
│ │ └── 输出: pre_injection_validation, pre_injection_baseline │
│ │ │
│ inject_fault │
│ │ └── 输出: injection_id, injection_status │
│ │ │
│ verify_injection │
│ │ └── 输出: injection_status (success/failed/running) │
│ │ │
│ [wait_retry 循环] │
│ │ └── 输出: retry_count++ │
│ │ │
│ monitor_data_plane │
│ │ └── 输出: pod_state_changes, data_plane_validation_results, │
│ │ k8s_events, monitoring_summary │
│ │ │
│ collect_trace │
│ │ └── 输出: traces (target_traces, auxiliary_traces, all_traces) │
│ │ │
│ analyze │
│ │ └── 输出: analysis_result (is_reasonable, confidence, explanation) │
│ │ │
│ report │
│ └── 输出: final_report, report_file │
│ │
│ 最终输出:reports/chaos_report_xxx.json │
└─────────────────────────────────────────────────────────────────────────────┘
6. 错误处理机制
6.1 统一错误处理框架
# 错误严重程度
class ErrorSeverity(Enum):
LOW = "low" # 低严重性
MEDIUM = "medium" # 中等严重性
HIGH = "high" # 高严重性
CRITICAL = "critical" # 致命错误
# 错误分类
class ErrorCategory(Enum):
VALIDATION = "validation" # 验证错误
NETWORK = "network" # 网络错误
RESOURCE = "resource" # 资源错误
INJECTION = "injection" # 注入错误
MONITORING = "monitoring" # 监控错误
ANALYSIS = "analysis" # 分析错误
SYSTEM = "system" # 系统错误
6.2 节点安全执行装饰器
每个节点函数都被 @ErrorHandler.safe_node_execution 装饰器包装:
@ErrorHandler.safe_node_execution("init_context", required_state_fields=["target_namespace"])
async def init_context(state: ChaosAnalysisState) -> Dict[str, Any]:
# 节点实现...
装饰器功能:
- 前置状态检查:检查是否有前置错误
- 必需字段验证:验证必需的状态字段是否存在
- 异常捕获:捕获并标准化异常
- 错误日志记录:记录详细的错误信息
6.3 错误处理流程
┌──────────────────────────────────────────────────────────────┐
│ 错误处理流程 │
├──────────────────────────────────────────────────────────────┤
│ │
│ 节点执行开始 │
│ │ │
│ ▼ │
│ 检查前置错误? │
│ │ │
│ ├── 有错误 → 跳过执行,返回错误 │
│ │ │
│ └── 无错误 → 验证必需字段 │
│ │ │
│ ▼ │
│ 必需字段完整? │
│ │ │
│ ├── 缺失 → 返回 VALIDATION 错误 │
│ │ │
│ └── 完整 → 执行节点函数 │
│ │ │
│ ▼ │
│ 执行成功? │
│ │ │
│ ├── 成功 → 返回结果 │
│ │ │
│ └── 异常 → 捕获并分类 │
│ │ │
│ ▼ │
│ 返回标准化错误响应 │
└──────────────────────────────────────────────────────────────┘
7. 辅助函数
7.1 Pod 名称提取
def _get_pod_name(pod: Dict[str, Any]) -> str:
"""从各种数据格式中提取 Pod 名称"""
if 'name' in pod:
return pod['name']
elif 'metadata' in pod and isinstance(pod['metadata'], dict):
return pod['metadata'].get('name', 'unknown')
return 'unknown'
7.2 持续时间解析
def _parse_duration(duration_str: str) -> int:
"""解析持续时间字符串为秒数
支持格式:
- 纯数字: "60" → 60
- 秒: "60s" → 60
- 分钟: "5m" → 300
- 小时: "1h" → 3600
- 组合: "1h30m" → 5400
"""
7.3 Pod 状态对比
def _compare_pod_states(initial_pod: Dict, current_pod: Dict) -> Dict[str, Any]:
"""对比故障前后的 Pod 状态变化
检测项:
1. 状态变化(phase 变化)
2. 重启次数变化
3. Ready 状态变化
4. IP 地址变化
5. 资源使用变化(CPU、内存)
6. 节点变化(重新调度)
"""
7.4 资源趋势分析
def _analyze_resource_trends(pod_changes_list: List[Dict]) -> Dict[str, Any]:
"""分析资源使用趋势
输出:
{
"cpu_trends": {"increasing": 2, "decreasing": 1, "stable": 5, "unknown": 0},
"memory_trends": {"increasing": 1, "decreasing": 2, "stable": 5, "unknown": 0},
"restart_trends": {"increased": 1, "decreased": 0, "stable": 7},
"overall_impact": {"affected_pods": 3, "total_pods": 8}
}
"""
7.5 数据面 Pod 发现
async def _discover_data_plane_pod_name(namespace: str) -> Optional[str]:
"""自动发现数据面验证 Pod 名称
尝试常见名称模式:
- data-plane-redis-0 (StatefulSet)
- data-plane-redis (普通 Pod)
- redis-data-plane-0
"""
8. 快速上手示例
8.1 基本用法
from core.graph import create_chaos_graph
async def run_chaos_analysis():
# 1. 创建工作流图
graph = create_chaos_graph()
# 2. 准备初始状态
initial_state = {
"target_namespace": "default",
"target_pod_label": "app=redis",
"fault_type": "pod-kill",
"fault_params": {
"duration": "60s"
},
"data_plane_cluster_host": "redis-cluster.default.svc.cluster.local",
"data_plane_redis_type": "proxy",
"data_plane_test_type": "consistency"
}
# 3. 执行工作流
result = await graph.ainvoke(initial_state)
# 4. 查看结果
print(f"分析结果: {result['analysis_result']}")
print(f"报告文件: {result['report_file']}")
8.2 查看报告
报告会保存在 reports/ 目录下:
reports/
├── chaos_report_default_pod-kill_20240101_120000.json # 最终报告
└── raw_analysis_data_default_pod-kill_20240101_120000.json # 原始分析数据
8.3 报告结构示例
{
"status": "completed",
"timestamp": "2024-01-01T12:00:00",
"summary": {
"target_namespace": "default",
"fault_type": "pod-kill",
"injection_status": "success",
"analysis_status": "reasonable",
"confidence": 0.85
},
"analysis": {
"is_reasonable": true,
"confidence": 0.85,
"explanation": "Pod 被杀死后正常重启,服务恢复正常...",
"recommendations": [
"建议增加 Pod 健康检查超时时间",
"考虑添加 Pod 反亲和性配置"
]
},
"topology_data": {
"complete_pod_topology": [...],
"k8s_events": [...],
"distributed_traces": [...]
}
}
附录:常见问题
Q1: 如果命名空间不存在会怎样?
A: init_context 节点会检测并返回错误,工作流直接跳转到 report 节点生成错误报告。
Q2: 如果故障注入失败会怎样?
A: verify_injection 节点会检测到 failed 状态,工作流跳转到 report 节点。
Q3: 如果没有配置数据面验证会怎样?
A: pre_injection_data_plane_validation 节点会跳过验证,继续执行后续节点。
Q4: 最大重试次数是多少?
A: 动态计算:max(3, 故障持续时间/5 + 3)。例如 60 秒故障最大重试 15 次。
Q5: 分析结果如何判断?
A: 分析器会综合规则引擎和 LLM 的分析结果,给出:
is_reasonable: 故障表现是否合理confidence: 置信度 (0-1)explanation: 解释说明recommendations: 改进建议
文档版本: 1.0
最后更新: 2024年
作者: Chaos Redis Analyzer Team