
半夜两点半手机连续震了五下。群里没人说话但我知道所有人都在等——等那个“倒霉蛋”先爬起来处理告警。我以前就是那个倒霉蛋。Prometheus一响第一件事是摸黑打开电脑第二件事是同时切好几个面板Grafana看负载曲线、Kibana翻应用日志、systemctl查服务状态……运气好十分钟定位运气不好折腾到天亮最后发现是某个Pod被OOMKilled了。后来我花了几周时间基于一堆开源组件攒了一个AI运维Agent。现在告警进来它自己先跑一遍“扒面板”的动作拉监控数据、查日志、看服务状态、结合历史故障记录给出判断——能自动修的低风险问题顺手就修了需要动刀子的操作推到IM上等我点确认。我只需要在它拿不准的时候回一句“同意”或者“拒绝”。这篇文章就把这套方案的完整思路、架构选型、核心代码和踩坑记录整理出来。内容偏实战适合正在被告警折腾的运维、SRE、DevOps也适合想了解AI Agent怎么落地到基础设施的同学。1. 告警处理这件事到底难在哪1.1 传统告警处理流程的三个真实痛点先说第一个痛点信息割裂。现在稍微有点规模的公司监控数据、日志、服务状态分散在完全不同的系统里。告警在Alertmanager监控曲线在Grafana应用日志在Loki或者ES服务状态得SSH到机器上手动敲命令。遇到一个告警至少要开四五个页面来回切换。光是“把信息凑齐”这一步就够折腾半小时。第二个痛点是重复劳动。我统计过自己处理过的告警大概80%都是同一批类型反复出现磁盘空间告警、Nginx 5xx比例高、Pod频繁重启、接口响应时间飙涨。每一次的处理流程几乎一模一样但每次都得重新走一遍排查步骤。这种活干多了人会变得很麻木反而容易漏掉关键线索。第三个痛点也是我最想解决的半夜状态差决策质量低。凌晨被叫起来脑子是糊的眼睛是花的。这时候看监控面板经常盯着一行日志发呆半天。更危险的是人在困倦状态下容易做出错误操作——我见过有人半夜把主库当从库重启就是因为没看清节点角色。1.2 为什么规则引擎和自动化脚本不够用可能有人会说这些问题写自动化脚本不就行了磁盘告警就自动清理日志Nginx告警就自动重启网关。理论上行得通但实际上规则引擎能覆盖的场景非常有限。规则引擎擅长处理“完全确定”的场景比如“磁盘使用率超过90%就删除/tmp下的旧文件”。但真实运维里大量告警属于“半确定”场景——你知道Nginx 5xx高了但不知道是上游超时、后端进程挂了、还是流量突增导致连接数耗尽。这需要根据现场情况做判断而判断恰恰是规则引擎最不擅长的。还有个更现实的问题规则多了以后维护成本会爆炸。每条规则之间可能有隐含的优先级和依赖关系今天加一条规则明天可能要连带改三条。规则之间互相打架的情况我遇到过不止一次。AI Agent的价值就在于它能理解告警背后的上下文像人一样做推理判断而不是机械地匹配规则。1.3 AI Agent能改变什么AI Agent做的事情本质上就是把人工排查的“感知→分析→决策→执行→验证”这个回路自动化。告警进来先做感知——拉取相关监控数据和日志再做分析——让大模型理解这些信息判断可能的根因然后做决策——生成处理方案区分能自动执行还是需要人工确认接着执行——调用工具去修复最后验证——再次拉取指标确认问题是否恢复。需要强调一点AI Agent不是要取代运维工程师。它处理的是那些重复、机械、需要跨系统查信息的脏活累活把人从半夜爬起来扒面板的循环里解放出来。当Agent遇到拿不准的情况或者要执行高风险操作时依然会停下来等人工决策。这是整套方案设计的核心原则。2. 整体方案设计与选型思考2.1 架构分层感知、决策、执行、通知这套方案在架构上分了四层每一层都有明确的职责边界。感知层负责统一接收监控系统的告警事件。我这边用的是Prometheus加Alertmanager把所有服务的监控告警汇总到Alertmanager再通过Webhook统一推送给Agent服务。这一步的好处是告警源单一Agent不用对接每一套监控系统。决策层由大模型承担。它接收告警事件后结合工具层返回的现场数据、知识库里的历史处理经验给出故障分析结论和处理建议。这里不是简单的“一问一答”而是走一个多步骤的Agent工作流先收集信息再判断根因最后决策执行方式。执行层是Agent的“手”。它通过一系列工具去实际操作系统SSH到服务器执行命令、调用Kubernetes API查Pod状态、查询Loki日志。每个工具都返回结构化结果供大模型分析。通知层负责把处理过程和结果推送给值班人员。我用的是飞书机器人Webhook故障处理完成后推送一份包含时间线、根因分析、处理动作的报告。2.2 Agent框架怎么选LangGraph还是自研Agent框架的选型我纠结了一段时间。主流选择有LangChain、LangGraph也可以完全自研。先说结论我最终选了LangGraph。原因是告警处理天然是一个有状态、多步骤、带分支判断的工作流——Agent先要收集信息信息不完整要继续查查到根因要决定是直接修复还是申请人工审批执行完还要验证结果。这种流程用LangGraph的StateGraph来编排非常顺滑每个节点是明确的处理逻辑节点之间通过状态传递数据。如果只是处理几种非常固定的告警用FastAPI加函数调用也能实现不一定需要引入重框架。我就见过有同事用纯Python写了个几十行的Webhook服务配合OpenAI的函数调用能力效果也不错。方案适用场景优点缺点LangGraph多步骤、有分支的工作流状态管理好支持循环和条件分支概念多学习曲线稍陡LangChain简单的工具调用链API丰富集成方便复杂流程编排能力一般自研FastAPI告警类型少、流程固定轻量完全可控要自己处理状态和流程逻辑2.3 大模型选型云端API还是本地部署大模型的选择上有两种路线。一种是调用云端大模型API效果稳定部署省事不用管GPU另一种是本地私有化部署开源模型数据不出内网延迟可控。我建议先把流程跑通用云端API最省事。我当时就是用OpenAI兼容接口先验证了整体流程确认了Agent的核心链路没问题再考虑要不要切成本地部署。如果要切本地部署现在开源模型里Qwen系列对工具调用Function Calling的支持比较成熟配合Ollama部署很方便几行命令就能把模型跑起来。模型大小方面7B到14B的参数量在工具调用场景下表现已经够用更大的模型推理速度会拖慢告警处理时效不太划算。2.4 安全边界设计Agent不能乱动这是整套方案里最核心、最不能妥协的部分。AI Agent有“手”了但它不能什么都碰。我的安全策略是三层第一层是权限收敛。Agent使用的SSH账号是一个独立的专用账号只授予执行必要运维命令的权限绝不给root。这样即使Agent判断失误破坏范围也可控。第二层是命令白名单。Agent生成的每一个Shell命令在执行前都要经过服务端的白名单校验。我维护了一个正则列表只放行那些安全的诊断和修复命令比如df -h、tail -n、systemctl status等。不在白名单里的命令一律拒绝执行。第三层是分级处置。低风险操作收集信息、查询状态Agent可以自动执行中风险操作清理临时文件、重启普通服务需要标记后异步通知高风险操作重启数据库、删除数据、变更网络配置必须在IM里等人工确认人不点“同意”Agent绝不动手。注意AI可以做诊断但高风险操作必须有人确认。这条原则我在设计阶段就写进了系统约束宁可少修复一些问题也不能让Agent在没人盯着的时候做危险操作。3. 核心模块拆解与实操配置3.1 告警接入Alertmanager Webhook配置详解告警接入是整个链路的第一环。Alertmanager的配置分两部分告警路由规则和接收器。我在这里贴一份关键的配置参考。route: group_by: [alertname, instance] group_wait: 10s group_interval: 2m repeat_interval: 4h receiver: ai-agent receivers: - name: ai-agent webhook_configs: - url: http://agent-server:8000/webhook/alert send_resolved: true这段配置里有几个关键参数需要理解。group_by定义了告警分组的维度相同alertname和instance的告警会合并成一组这能有效减少告警风暴带来的推送数量。group_wait是组内第一条告警等待的时间目的是收集同一批告警一起发送。repeat_interval控制告警未恢复时的重复提醒频率我设了4小时避免同一个故障反复轰炸。send_resolved设置为true很关键恢复告警也要推给Agent方便做状态清理。Alertmanager推送的Webhook请求体是标准JSON结构核心字段包括statusfiring或resolved、alerts数组、groupLabels等。Agent端主要解析alerts数组里的labels和annotationslabels里通常有alertname、severity、instance等关键信息annotations里则是人类可读的告警描述和修复建议。3.2 Agent服务接收告警并创建处理任务Agent服务的骨架是一个FastAPI应用接收Alertmanager的Webhook校验后用队列做任务串行化处理。这里有个设计细节告警处理必须串行化原因很简单——如果同时处理多个告警多个SSH会话并发执行命令输出会互相污染大模型也容易串上下文。from fastapi import FastAPI, Request, HTTPException import asyncio app FastAPI() task_queue asyncio.Queue() app.post(/webhook/alert) async def receive_alert(request: Request): # 校验 Webhook 请求头中的 Token token request.headers.get(X-Webhook-Token) if token ! config.WEBHOOK_TOKEN: raise HTTPException(status_code403, detailInvalid token) payload await request.json() for alert in payload.get(alerts, []): await task_queue.put(alert) return {status: accepted} async def worker(): while True: alert await task_queue.get() try: await process_alert(alert) except Exception as e: logger.error(f处理告警失败: {e}) finally: task_queue.task_done()这里除了Token校验还需要做幂等去重。Alertmanager可能在网络抖动时重复推送同一个告警我用告警的fingerprint字段做唯一性判断处理过的告警直接丢弃。去重表用的是内存字典加过期时间告警恢复后五分钟清掉记录避免占用太多内存。3.3 工具层让Agent拥有“动手能力”工具层是Agent能否真正落地的关键。我封装了几个核心工具每个工具都会校验输入参数执行完返回结构化结果。第一个是SSH执行器基于Paramiko实现。这个工具接收目标主机和命令在命令执行前做白名单校验。import paramiko import re ALLOWED_COMMANDS [ r^df -h$, r^top -b -n 1$, r^tail -n \d /var/log/[a-zA-Z0-9_./-]$, r^systemctl status [a-zA-Z0-9_-]$, r^free -h$, r^ps aux \| grep [a-zA-Z0-9_-]$, r^uptime$, ] def validate_command(cmd: str) - bool: for pattern in ALLOWED_COMMANDS: if re.match(pattern, cmd.strip()): return True return False def run_ssh_command(host: str, cmd: str, key_path: str) - dict: if not validate_command(cmd): return {status: error, message: Command not allowed} client paramiko.SSHClient() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) client.connect(host, usernameagent-bot, key_filenamekey_path) stdin, stdout, stderr client.exec_command(cmd, timeout15) output stdout.read().decode() client.close() return {status: success, output: output}除了SSH工具我还封装了Kubernetes查询工具用来查Pod状态和容器日志。实现方式是调用kubectl get pods -n namespace -o wide以及kubectl logs pod --tail50。这些命令同样走白名单校验。工具层还有一个原则每个工具返回的结果必须结构清晰不能是一大堆无格式的文本。大模型解析结构化JSON的成功率远高于解析自由文本处理速度和准确率都会提升。3.4 通知与反馈闭环飞书机器人推送告警处理完成后要把结果推给值班人员。我用飞书自定义机器人Webhook封装了一个简单的推送函数。import requests import json def send_feishu_message(webhook_url: str, title: str, content: str) - None: payload { msg_type: interactive, card: { header: { title: {tag: plain_text, content: title}, template: red }, elements: [ {tag: markdown, content: content} ] } } requests.post(webhook_url, jsonpayload, timeout10)推送的内容分两部分。处理过程中Agent每完成一个关键步骤比如确认了根因、准备执行修复会推送一条进度消息全部处理完成后推送一份完整报告包含告警基本信息、排查时间线、根因分析结论、执行的处理动作和验证结果。这个闭环很重要值班人员即使不在电脑前也能通过手机掌握全部情况。3.5 知识库与RAG增强把知识库做进Agent是整个方案效果提升最大的一步。没有知识库的Agent就像一个刚入职的实习生知道通用运维知识但不了解你们公司的具体环境。我在知识库里放了三类内容公司主机和服务清单、历史故障处理记录、运维SOP文档。查询的时候用Embedding模型加向量检索把告警内容转成向量后召回最相关的历史处理经验作为上下文注入到大模型的提示词里。实现方式不复杂。Embedding用开源的bge-small-zh模型向量数据库用FAISS几百条文档毫秒级就能返回结果。关键是知识库的内容质量——历史故障记录必须包含根因结论和处理步骤不能是流水账。我花了一周时间整理过去一年的告警处理记录这段投入的回报非常明显Agent对新故障的准确率提高了不少。4. 落地部署与联调实录4.1 部署步骤总览整套系统的部署分成六步跟着顺序来基本不会踩坑准备Agent服务运行环境一台Linux服务器安装Python 3.10部署FastAPI服务。配置大模型接入如果是云端API配置好API Key和Base URL如果是本地部署先安装Ollama再拉取模型。修改Alertmanager配置添加webhook接收器指向Agent服务。配置知识库准备历史故障记录构建向量索引。配置飞书机器人创建自定义机器人拿到Webhook地址。联调测试手动触发一条测试告警验证全链路。时间上不熟悉这套技术栈的人从零开始大概需要两到三个工作日。熟悉的话一天能跑通。4.2 关键配置文件展示Agent服务的环境变量配置长这样# LLM API 配置 LLM_API_KEYsk-xxxx LLM_BASE_URLhttps://api.example.com/v1 LLM_MODELqwen-plus # Agent 服务配置 WEBHOOK_TOKENyour-webhook-secret AGENT_HOST0.0.0.0 AGENT_PORT8000 # SSH 执行器配置 SSH_USERagent-bot SSH_KEY_PATH/etc/agent/id_rsa # 飞书通知配置 FEISHU_WEBHOOK_URLhttps://open.feishu.cn/open-apis/bot/v2/hook/xxxx飞书机器人的创建方法很简单群聊里打开设置找到群机器人添加自定义机器人拿到Webhook地址再把上面配置里的FEISHU_WEBHOOK_URL替换掉即可。这里提醒一个坑飞书自定义机器人的安全问题。默认情况下任何知道Webhook地址的人都能往群里发消息所以创建机器人时一定要开启签名校验把密钥配置到Agent服务里。4.3 一次完整告警处理演练Nginx 5xx告警用一次真实故障演练来展示Agent的完整处理过程。凌晨2点15分Prometheus产生告警HighNginx5xxRate触发条件是Nginx 5xx比例超过5%持续5分钟。Alertmanager把这条告警推送给Agent服务。Agent服务的处理流程是这样的第一步Agent解析告警内容提取出关键信息告警类型是Nginx 5xx比例高受影响实例是web-server-01。第二步Agent调用知识库检索找到了历史处理经验一周前同主机也触发过类似告警当时的根因是后端Java服务线程池耗尽。第三步Agent通过SSH工具链收集现场信息。先执行uptime看负载再执行tail -n 100 /var/log/nginx/error.log看错误日志接着执行systemctl status backend-service看后端进程状态。第四步大模型综合这些信息做判断。错误日志里出现了大量connect() failed (111: Connection refused)的报错后端服务状态是active (exited)——进程异常退出了。Agent分析结论后端服务挂掉导致上游请求失败最终表现为Nginx 5xx比例飙升。第五步Agent生成处置方案。重启后端服务属于中高风险操作系统把“执行systemctl restart backend-service”这条动作推到飞书群等人确认。凌晨2点18分值班人员在手机上点了同意。Agent立刻执行重启命令两秒后服务恢复正常。Agent再次调用工具验证确认Nginx 5xx比例已经降到0推送最终报告。整个过程从告警产生到处理完成不到四分钟人工只做了一次点击确认。以前这种情况至少折腾半小时。5. 常见问题与避坑实录5.1 告警风暴把Token烧光了上线第一周我就遇到了事故。某个底层服务故障一下子触发了两百多条关联告警。Agent对每条告警都执行了一遍完整分析流程把云上API的Token额度烧掉了一大半而且群消息被刷屏了。解法分三层。第一层在Alertmanager做告警分组把相同alertname的告警聚合成一条第二层在Agent端做去重根据fingerprint判断是否已处理第三层加冷却时间同一实例的同类告警处理完后十分钟内不重复处理。5.2 模型幻觉导致错误命令大模型有时候会编造不存在的命令或者参数这是AI Agent最危险的问题之一。有一次Agent分析磁盘告警时生成了rm -rf /var/log/old/*这样的命令显然超出了应该清理的范围。幸好有白名单机制拦住了。rm -rf根本不在白名单正则里命令在SSH执行前就被拒绝了。但这也给我提了个醒白名单必须做得足够严格宁可漏掉一些合理命令也不能放任何有破坏性的操作进来。5.3 重复告警导致重复修复调试期间发现一个问题如果告警一直处于firing状态Alertmanager会按照repeat_interval周期重复推送同一条告警。Agent每收到一次推送就重新处理一遍可能导致服务被反复重启。解决方案是在Agent端维护一个告警状态表。以alertname instance为键记录首次处理时间。在告警未恢复到resolve状态之前重复的推送直接丢弃只在达到一定时间阈值后做一次状态复核。5.4 上下文太长Token超限Agent在分析问题时会不断追加工具返回的结果日志一次就是几十行几轮下来上下文很容易超过模型窗口限制。解法是控制上下文大小。日志类工具返回前做截断处理默认只保留关键的最后五十行监控数据打点采样不需要把所有数据点传给模型。另外历史对话要定期做摘要把前面已经完成的步骤压缩成一句简短总结而不是把完整的历史记录一直带着。5.5 如何防止别人伪造WebhookAgent服务暴露在内网但安全防护不能少。Alertmanager推送Webhook时在请求头里带了一个自定义TokenAgent端校验通过后才接受请求。如果环境更严格可以做HMAC签名验证Alertmanager端用密钥对请求体签名Agent端用同样的密钥验签防止请求被篡改。5.6 常见问题速查表现象可能原因解决方案Token消耗过快告警风暴没有有效去重Alertmanager分组 Agent端冷却Agent执行了错误命令模型幻觉生成危险命令严格白名单校验服务被反复重启重复告警重复处理用告警指纹做幂等请求报Token超限上下文太长日志截断 历史摘要Webhook被伪造没有鉴权机制HeadToken或HMAC签名SSH连接超时目标主机网络异常增加超时重试机制6. 从“处理告警”到“预防故障”的扩展思路Agent跑稳之后我开始琢磨怎么让它做更多事情。第一个方向是故障复盘报告自动化。每周五晚上Agent自动汇总本周所有告警的处理记录生成一份趋势分析哪类告警最多、哪个服务最不稳定、平均处理耗时多长。这份报告以前要人工花半天整理现在Agent十分钟就能出稿还有数据图表。第二个方向是变更后的自动巡检。每次发布上线后Agent自动拉取发布涉及的服务的核心指标和发布前做对比一旦发现异常指标就立刻告警并展开自动诊断。这对发现灰度发布引入的问题非常有效。第三个方向是更复杂的修复编排。现在Agent只能执行单条命令下一步可以设计更复杂的工具链比如自动执行蓝绿切换、自动扩缩容等。当然这些高风险操作必须搭配更严格的审批流程和回滚机制。这些扩展的核心思路是一样的Agent不是越多越好而是把重复的、需要跨系统查信息的场景逐个自动化让人的精力聚焦在真正需要判断力的工作上。我跑这套系统三个多月最深的感觉是真正省时间的不是那几次自动修复而是它把每次告警的上下文都串了起来。以前半夜爬起来翻面板信息是一块一块的断片现在Agent给我的是一份拼好的完整故事。如果你也想搭一套建议从一条最让你头疼的告警类型入手先跑通全流程再加场景。Agent这东西用起来比看起来简单但设计好边界比什么都重要——它替你值班但最终责任还是你的。