基于大模型的诊断自动化——从告警触发到根因分析的端到端排障 Agent 设计一、凌晨 3 点的告警需要 5 分钟定位还是 50 分钟一条典型的 P1 告警VLLMHighTTFT: P99 TTFT 850ms (阈值 500ms, 节点 gpu-node-03)。守夜的工程师收到告警后的排查路径打开 Grafana查看 node-03 的 GPU 利用率、显存、QPS 趋势3 分钟。对比同集群其他节点的指标确认是否单点问题2 分钟。查看 node-03 的 vLLM 日志搜索ERROR和WARN关键字5 分钟。发现preemption triggered: no available blocks日志确认是 KV Cache 饱和3 分钟。查看该节点的 KV Cache 使用率趋势确认触发时间2 分钟。检查是否有异常的长 prompt 请求3 分钟。在 Grafana 上找到触发时刻的请求日志确认是一个 12000 token 的超长 prompt5 分钟。定位到具体请求来源业务方 A通知处理5 分钟。总耗时约 28 分钟。其中真正需要人类决策的只有第 8 步谁的问题通知谁前 7 步都是查这个 → 看那个 → 对比这个的机械操作。如果有一个排障 Agent 自动执行前 7 步工程师在第 1 分钟就能拿到结论node-03 的 KV Cache 被一个 12000 token 的超长 prompt 填满来源是业务 A 的批量处理任务。建议通知业务 A 拆分批处理或为该节点增加 reserved blocks 配置。二、排障 Agent 的架构设计flowchart TD A[告警触发br/Prometheus Alert] -- B[Agent 接收告警] B -- C[任务规划 LLMbr/将告警转化为排查步骤] C -- D{第 1 步: 多维指标查询} D -- E[Grafana APIbr/GPU利用率/显存/QPS] E -- F{指标对比分析} F --|单点异常| G1[第 2 步: 日志检索] F --|全集群异常| G2[第 2 步: 关联变更记录] G1 -- H[Loki/ES 日志查询br/error 关键字 时间范围] H -- I{日志语义分析} I -- J[第 3 步: 根因推断 LLMbr/综合分析 → 根因假设] J -- K{验证假设} K --|需要验证| L[第 4 步: 补充查询br/如: KV Cache 趋势/请求日志] L -- J K --|确认根因| M[第 5 步: 生成诊断报告] M -- N{是否需要人工介入} N --|是| O[推送到值班群br/含诊断摘要 建议方案] N --|否| P[自动执行修复br/如: 扩容/限流/重启]2.1 Agent 的核心能力能力工具示例指标查询Prometheus APIquery_range(vllm:gpu_cache_usage_perc, 30m)日志检索Loki / ElasticSearch{jobvllm}代码/配置变更Git API查看最近合并的 PR系统命令执行SSH / kubectl execnvidia-smi,dmesg,free -h对比分析同集群多节点指标差异node-03 KV Cache node-01 × 2.3三、排障 Agent 的工程实现3.1 告警触发与任务拆解# diagnosis_agent.py —— 排障 Agent 核心 import asyncio import json import logging from datetime import datetime, timedelta from typing import List, Dict, Optional, Any from dataclasses import dataclass from openai import AsyncOpenAI logger logging.getLogger(__name__) dataclass class DiagnosisStep: 排查步骤 step_id: int action: str # 工具调用名称 args: Dict[str, Any] # 工具参数 reasoning: str # LLM 给出的执行理由 status: str # pending | running | done | failed dataclass class DiagnosisReport: 诊断报告 alert_name: str alert_time: datetime affected_node: str root_cause: str # 根因摘要 confidence: float # 置信度 01 evidence: List[str] # 支撑证据 recommendation: str # 修复建议 steps_executed: List[DiagnosisStep] total_time_seconds: float class DiagnosisAgent: 排障 Agent 收到告警后通过 LLM 规划排查步骤 依次调用工具执行最后生成诊断报告。 # 可用工具定义供 LLM 选择 TOOLS [ { name: query_prometheus, description: 查询 Prometheus 指标PromQL, parameters: { query: PromQL 查询语句, range_minutes: 查询时间范围分钟, }, }, { name: query_loki_logs, description: 查询 Loki 日志, parameters: { query: LogQL 查询语句, start_time: 起始时间ISO 8601, end_time: 结束时间ISO 8601, limit: 返回条数上限, }, }, { name: compare_nodes, description: 对比集群中不同节点的指标差异, parameters: { metric: 指标名如 gpu_utilization, target_node: 目标节点名, time_range_minutes: 对比时间范围, }, }, { name: check_recent_deployments, description: 检查最近的代码/配置变更, parameters: { service: 服务名, hours_back: 回溯时间小时, }, }, { name: exec_kubectl, description: 在指定 Pod 内执行命令, parameters: { pod_name: Pod 名称, command: 要执行的命令, }, }, ] def __init__(self, openai_client: AsyncOpenAI): self.client openai_client self.tool_handlers { query_prometheus: self._handle_prometheus, query_loki_logs: self._handle_loki, compare_nodes: self._handle_compare_nodes, check_recent_deployments: self._handle_deployments, exec_kubectl: self._handle_kubectl, } async def diagnose( self, alert: Dict ) - DiagnosisReport: 对一条告警执行自动化诊断 Args: alert: { name: VLLMHighTTFT, labels: {instance: gpu-node-03:8000, model: qwen2-72b}, annotations: {summary: ..., description: ...}, startsAt: 2024-07-15T03:00:00Z, } Returns: DiagnosisReport 诊断报告 start_time datetime.utcnow() steps [] # # 阶段 1: 任务规划 # LLM 将告警转化为具体的排查步骤序列 # plan await self._plan_steps(alert) logger.info(f排障计划: {len(plan)} 步) for s in plan: logger.info(f Step {s.step_id}: {s.action} - {s.reasoning}) # # 阶段 2: 逐步执行 # findings [] # 收集每步的发现 for step in plan: step.status running try: handler self.tool_handlers.get(step.action) if handler is None: step.status failed findings.append( fStep {step.step_id}: 未知工具 {step.action}) continue result await handler(step.args) step.status done findings.append( fStep {step.step_id} ({step.action}): {result}) except Exception as e: step.status failed findings.append( fStep {step.step_id} 失败: {str(e)}) steps.append(step) # # 阶段 3: 根因推断 # LLM 综合分析所有发现推断根因 # root_cause, confidence, recommendation \ await self._infer_root_cause( alert, findings) elapsed (datetime.utcnow() - start_time).total_seconds() return DiagnosisReport( alert_namealert[name], alert_timedatetime.fromisoformat( alert[startsAt].replace(Z, 00:00)), affected_nodealert[labels][instance], root_causeroot_cause, confidenceconfidence, evidencefindings, recommendationrecommendation, steps_executedsteps, total_time_secondselapsed, ) async def _plan_steps( self, alert: Dict ) - List[DiagnosisStep]: 让 LLM 根据告警信息规划排查步骤 输入告警名称、描述、影响范围、时间 输出58 个具体的排查步骤 prompt f你是一位 SRE 排障专家。收到以下告警 告警名称: {alert[name]} 告警节点: {alert[labels][instance]} 告警描述: {alert[annotations][description]} 告警时间: {alert[startsAt]} 请规划排查步骤使用以下工具 {json.dumps(self.TOOLS, indent2, ensure_asciiFalse)} 规则 1. 优先查询目标节点的关键指标GPU 利用率、显存、QPS 2. 对比同集群其他节点判断是否单点问题 3. 检索相关时间段的错误日志 4. 检查最近的部署/配置变更 5. 每步需要清晰的执行理由 返回 JSON 格式 [{{ step_id: 1, action: query_prometheus, args: {{query: PROMQL, range_minutes: 30}}, reasoning: 检查 GPU 利用率和显存使用趋势 }}] response await self.client.chat.completions.create( modelgpt-4, messages[{role: user, content: prompt}], response_format{type: json_object}, temperature0.1, # 低温度确保规划稳定 ) plan_data json.loads( response.choices[0].message.content) return [ DiagnosisStep( step_iditem[step_id], actionitem[action], argsitem[args], reasoningitem[reasoning], statuspending, ) for item in plan_data.get(steps, []) ] async def _infer_root_cause( self, alert: Dict, findings: List[str], ) - tuple: 综合分析推断根因 prompt f根据以下告警信息和排查发现推断根因 告警: {alert[name]} on {alert[labels][instance]} 排查发现: {chr(10).join(f- {f} for f in findings)} 请返回 JSON {{ root_cause: 根因描述一句话, confidence: 0.85, recommendation: 修复建议 }} 规则 - root_cause 必须具体不能是可能是 XX给出最可能的原因 - confidence 根据证据的充分程度给出01 - 如果证据不足以确定根因标明还需要哪些信息 response await self.client.chat.completions.create( modelgpt-4, messages[{role: user, content: prompt}], response_format{type: json_object}, temperature0.1, ) result json.loads( response.choices[0].message.content) return ( result.get(root_cause, 无法确定), result.get(confidence, 0.0), result.get(recommendation, 请人工介入), ) # # 工具处理器简化实现 # async def _handle_prometheus(self, args): 查询 Prometheus # 实际调用 Prometheus HTTP API return fPromQL: {args[query]} → 结果: [模拟数据] async def _handle_loki(self, args): 查询 Loki 日志 return fLogQL: {args[query]} → 找到 15 条日志 async def _handle_compare_nodes(self, args): 对比节点指标 return fnode-03 {args[metric]} 比其他节点高 2.3 倍 async def _handle_deployments(self, args): 检查部署变更 return 最近 24h 无部署变更 async def _handle_kubectl(self, args): 在 Pod 中执行命令 return fkubectl exec {args[pod_name]} -- {args[command]} → OK3.2 告警严重度分级与自动修复边界排障 Agent 生成诊断报告后根据严重度和置信度决定后续动作# auto_remediation.py —— 自动修复决策 class RemediationPolicy: 根据诊断结果决定是自动修复还是人工介入 规则 - P0 告警 高置信度(0.9) → 自动执行修复 通知 - P0 告警 低置信度 → 通知 oncall附带诊断报告 - P1 告警 高置信度 → 提出修复建议等待确认 - P1 告警 低置信度 → 仅通知 - P2 告警 → 记录不通知 staticmethod def decide( severity: str, # P0/P1/P2 confidence: float, ) - str: if severity P0 and confidence 0.9: return auto_fix_and_notify elif severity P0: return notify_oncall elif severity P1 and confidence 0.9: return suggest_fix else: return log_only四、排障 Agent 的边界与风险4.1 幻觉风险——LLM 自信地给出错误结论排障 Agent 最大的风险是 LLM 的幻觉——在证据不足时编造根因。例如看到GPU 显存用量 95%就断言显存泄漏但实际是正常的 KV Cache 使用。缓解方式置信度低于 0.7 的结论自动升级为人工介入。所有诊断报告的结论必须附带支撑证据列表方便人工复核。Agent 不直接执行危险操作如重启 Pod、释放显存必须人工确认。4.2 Token 成本每次排障的 LLM 调用规划 推断约消耗 30005000 tokens。按 GPT-4 的 API 价格每次诊断约 0.050.10 美元。按每天 20 次 P1/P2 告警计算月成本约 60 美元——远低于一名 SRE 工程师的时薪。4.3 工具集的可扩展性排障 Agent 的能力上限取决于提供的工具数量和质量。如果某个排查需要的工具不在 TOOLS 列表中Agent 就无法完成诊断——LLM 的规划能力再强也受限于工具边界。定期 Review 未解决的告警补充新的诊断工具。五、总结排障 Agent 的目标不是替代 SRE而是将机械性的查指标 → 查日志 → 对比分析自动化任务规划 LLM将告警转化为 58 个具体的排查步骤每步选择最合适的工具。工具执行链依次调用 Prometheus、Loki、kubectl 等工具接口串行收集证据。根因推断 LLM综合分析所有排查发现给出具体根因和修复建议附带置信度。分级的自动修复高置信度 低风险操作如扩容可自动执行其他情况保持人工介入。