云计算百科
云计算领域专业知识百科平台

当AI学会“修服务器”:我告警风暴中重生,把修复时间从泡面凉透缩短到一首歌

我是如何用 AI Agent + RAG 把告警平均修复时间(MTTR)从 30 分钟降到 3 分钟的

一个运维开发者的 AIOps 实战之路:从"告警风暴中疲于奔命"到"AI 自动诊断+修复+通知全闭环"


摘要

本文完整复盘了一套从零搭建的 AIOps 平台,通过 AI Agent + RAG 知识库实现 MTTR 从约 30 分钟降至约 3 分钟(10 倍提升)。系统以 FastAPI + AsyncSSH 构建 Auto-Remediation Pipeline,LLM 生成的修复命令经 三层安全防护 后执行;同时引入 RAG 将团队特有运维经验向量化,让 AI 诊断不再泛泛而谈。平台还内置定时巡检 + 8 类日志事件检测、12 个专业 Agent、可视化工作流 DAG 并行调度及 5 通道通知。文中附完整核心代码、5 个踩坑记录和一周可上线的最小可行方案,项目已开源、Docker Compose 一键部署。

一、先说结论

指标改造前改造后提升
MTTR(平均修复时间) ~30 分钟 ~3 分钟 10 倍
告警响应方式 人工 SSH 逐台排查 AI 自动诊断+修复 全自动化
危险操作拦截 靠人工审查 13 条规则自动拦截 0 误操作
运维知识复用 依赖个人经验 RAG 语义检索知识库 知识沉淀
通知覆盖率 单一渠道 5 通道(钉钉/企微/飞书/邮件/Webhook) 全覆盖

这篇文章会完整复盘我是怎么从零搭建这套 AIOps 平台的——包括架构设计、关键代码、踩坑经验,以及你可以直接复用的技术方案。


二、背景:我被告警"淹没"了

我负责维护公司 20+ 台阿里云 ECS 服务器,Prometheus + Node Exporter 采集指标,AlertManager 配置了 CPU > 80%、内存 > 85%、磁盘 > 90% 等规则。

表面上看,监控体系很完善。但实际上:

  • 告警风暴:凌晨 3 点,一个 Java 应用内存泄漏,连锁触发 12 条告警——CPU 高、内存高、GC 频繁、接口超时……我要从 12 条告警中找到根因。

  • 知识在脑子里:“上次这个服务 OOM 是因为 JVM 参数没配 -XX:MaxMetaspaceSize”——但这句经验只在我脑子里,别人值班遇到同样的问题还是抓瞎。

  • 操作风险:凌晨迷迷糊糊 SSH 上去,kill -9 打错 PID 怎么办?rm -rf /tmp/logs 多打了一个空格变成 rm -rf / tmp/logs 怎么办?

  • 重复劳动:80% 的告警都是"磁盘满了,清理日志 → 重启服务"这种固定套路,但我每次还是要手动执行一遍。

  • 核心矛盾:告警发现是自动的,但告警处理完全靠人。

    我决定做一套系统,让 AI 来填补"告警触发"到"问题修复"之间的鸿沟。


    三、架构总览

    #mermaid-svg-1y5Lu6POru2gbEIx{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-1y5Lu6POru2gbEIx .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-1y5Lu6POru2gbEIx .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-1y5Lu6POru2gbEIx .error-icon{fill:#552222;}#mermaid-svg-1y5Lu6POru2gbEIx .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-1y5Lu6POru2gbEIx .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-1y5Lu6POru2gbEIx .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-1y5Lu6POru2gbEIx .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-1y5Lu6POru2gbEIx .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-1y5Lu6POru2gbEIx .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-1y5Lu6POru2gbEIx .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-1y5Lu6POru2gbEIx .marker{fill:#333333;stroke:#333333;}#mermaid-svg-1y5Lu6POru2gbEIx .marker.cross{stroke:#333333;}#mermaid-svg-1y5Lu6POru2gbEIx svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-1y5Lu6POru2gbEIx p{margin:0;}#mermaid-svg-1y5Lu6POru2gbEIx .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-1y5Lu6POru2gbEIx .cluster-label text{fill:#333;}#mermaid-svg-1y5Lu6POru2gbEIx .cluster-label span{color:#333;}#mermaid-svg-1y5Lu6POru2gbEIx .cluster-label span p{background-color:transparent;}#mermaid-svg-1y5Lu6POru2gbEIx .label text,#mermaid-svg-1y5Lu6POru2gbEIx span{fill:#333;color:#333;}#mermaid-svg-1y5Lu6POru2gbEIx .node rect,#mermaid-svg-1y5Lu6POru2gbEIx .node circle,#mermaid-svg-1y5Lu6POru2gbEIx .node ellipse,#mermaid-svg-1y5Lu6POru2gbEIx .node polygon,#mermaid-svg-1y5Lu6POru2gbEIx .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-1y5Lu6POru2gbEIx .rough-node .label text,#mermaid-svg-1y5Lu6POru2gbEIx .node .label text,#mermaid-svg-1y5Lu6POru2gbEIx .image-shape .label,#mermaid-svg-1y5Lu6POru2gbEIx .icon-shape .label{text-anchor:middle;}#mermaid-svg-1y5Lu6POru2gbEIx .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-1y5Lu6POru2gbEIx .rough-node .label,#mermaid-svg-1y5Lu6POru2gbEIx .node .label,#mermaid-svg-1y5Lu6POru2gbEIx .image-shape .label,#mermaid-svg-1y5Lu6POru2gbEIx .icon-shape .label{text-align:center;}#mermaid-svg-1y5Lu6POru2gbEIx .node.clickable{cursor:pointer;}#mermaid-svg-1y5Lu6POru2gbEIx .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-1y5Lu6POru2gbEIx .arrowheadPath{fill:#333333;}#mermaid-svg-1y5Lu6POru2gbEIx .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-1y5Lu6POru2gbEIx .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-1y5Lu6POru2gbEIx .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-1y5Lu6POru2gbEIx .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-1y5Lu6POru2gbEIx .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-1y5Lu6POru2gbEIx .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-1y5Lu6POru2gbEIx .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-1y5Lu6POru2gbEIx .cluster text{fill:#333;}#mermaid-svg-1y5Lu6POru2gbEIx .cluster span{color:#333;}#mermaid-svg-1y5Lu6POru2gbEIx div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-1y5Lu6POru2gbEIx .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-1y5Lu6POru2gbEIx rect.text{fill:none;stroke-width:0;}#mermaid-svg-1y5Lu6POru2gbEIx .icon-shape,#mermaid-svg-1y5Lu6POru2gbEIx .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-1y5Lu6POru2gbEIx .icon-shape p,#mermaid-svg-1y5Lu6POru2gbEIx .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-1y5Lu6POru2gbEIx .icon-shape .label rect,#mermaid-svg-1y5Lu6POru2gbEIx .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-1y5Lu6POru2gbEIx .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-1y5Lu6POru2gbEIx .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-1y5Lu6POru2gbEIx :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    外部系统

    数据层

    服务层

    用户层

    运维人员

    Nginx 反向代理 :80

    FrontendNext.js 16 + React Flow

    BackendFastAPI + asyncio

    Multi-Agent AI Engine12个专业Agent

    WorkflowEngineDAG 拓扑排序 + 并行执行

    APScheduler300秒定时巡检

    SSH Connection PoolAsyncSSH · 最大30连接

    RAG 语义检索sentence-transformers

    PostgreSQL 16告警/服务器/审计

    Redis 7会话/限流/缓存

    LLM APIGLM-4 / DeepSeek / OpenAI

    目标服务器群ECS × 20+

    通知渠道钉钉/企微/飞书/邮件

    技术选型原则:每一步都选最"轻"的方案。

    需求为什么不用 X最终选择
    Web 框架 Django ORM 同步模型在 asyncio 下需要 sync_to_async 包装 FastAPI — 原生异步
    任务调度 Celery 需要 Broker + Worker,太重 APScheduler — 嵌入进程
    SSH Paramiko 同步,需要线程池包装 AsyncSSH — 原生异步
    LLM SDK LangChain 太重,抽象层太多 自研 Provider — 策略模式
    向量模型 OpenAI Embedding 要钱 all-MiniLM-L6-v2 — 免费 80MB

    四、核心设计一:Auto-Remediation Pipeline(自动修复管道)

    4.1 完整流程

    通知渠道目标服务器SSH Connection PoolRAG 知识库LLM APIPostgreSQLFastAPI /alerts/webhookPrometheus通知渠道目标服务器SSH Connection PoolRAG 知识库LLM APIPostgreSQLFastAPI /alerts/webhookPrometheus#mermaid-svg-hUvpDQCEOOXAsRkh{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-hUvpDQCEOOXAsRkh .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-hUvpDQCEOOXAsRkh .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-hUvpDQCEOOXAsRkh .error-icon{fill:#552222;}#mermaid-svg-hUvpDQCEOOXAsRkh .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-hUvpDQCEOOXAsRkh .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-hUvpDQCEOOXAsRkh .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-hUvpDQCEOOXAsRkh .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-hUvpDQCEOOXAsRkh .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-hUvpDQCEOOXAsRkh .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-hUvpDQCEOOXAsRkh .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-hUvpDQCEOOXAsRkh .marker{fill:#333333;stroke:#333333;}#mermaid-svg-hUvpDQCEOOXAsRkh .marker.cross{stroke:#333333;}#mermaid-svg-hUvpDQCEOOXAsRkh svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-hUvpDQCEOOXAsRkh p{margin:0;}#mermaid-svg-hUvpDQCEOOXAsRkh .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-hUvpDQCEOOXAsRkh text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-hUvpDQCEOOXAsRkh .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-hUvpDQCEOOXAsRkh .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-hUvpDQCEOOXAsRkh .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-hUvpDQCEOOXAsRkh .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-hUvpDQCEOOXAsRkh #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-hUvpDQCEOOXAsRkh .sequenceNumber{fill:white;}#mermaid-svg-hUvpDQCEOOXAsRkh #sequencenumber{fill:#333;}#mermaid-svg-hUvpDQCEOOXAsRkh #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-hUvpDQCEOOXAsRkh .messageText{fill:#333;stroke:none;}#mermaid-svg-hUvpDQCEOOXAsRkh .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-hUvpDQCEOOXAsRkh .labelText,#mermaid-svg-hUvpDQCEOOXAsRkh .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-hUvpDQCEOOXAsRkh .loopText,#mermaid-svg-hUvpDQCEOOXAsRkh .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-hUvpDQCEOOXAsRkh .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-hUvpDQCEOOXAsRkh .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-hUvpDQCEOOXAsRkh .noteText,#mermaid-svg-hUvpDQCEOOXAsRkh .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-hUvpDQCEOOXAsRkh .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-hUvpDQCEOOXAsRkh .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-hUvpDQCEOOXAsRkh .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-hUvpDQCEOOXAsRkh .actorPopupMenu{position:absolute;}#mermaid-svg-hUvpDQCEOOXAsRkh .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-hUvpDQCEOOXAsRkh .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-hUvpDQCEOOXAsRkh .actor-man circle,#mermaid-svg-hUvpDQCEOOXAsRkh line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-hUvpDQCEOOXAsRkh :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}Webhook POST (CPU 95%)去重查询 (alert_name+instance+firing)无重复 → 新建告警语义检索告警相关运维经验Top-3 相关知识片段告警上下文 + RAG知识 → 生成修复命令```bash\\n预检→修复→验证\\n```13项危险命令安全检查 ✓ 通过获取连接 (host:port:user)systemctl restart java-appOK (exit 0)执行结果 → 分析是否成功修复成功, 服务已恢复写入 RemediationLog更新 Alert 状态 → resolved推送修复结果 (钉钉+企微)
    #mermaid-svg-QaACDDX4cCZQ8sRj{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-QaACDDX4cCZQ8sRj .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-QaACDDX4cCZQ8sRj .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-QaACDDX4cCZQ8sRj .error-icon{fill:#552222;}#mermaid-svg-QaACDDX4cCZQ8sRj .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-QaACDDX4cCZQ8sRj .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-QaACDDX4cCZQ8sRj .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-QaACDDX4cCZQ8sRj .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-QaACDDX4cCZQ8sRj .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-QaACDDX4cCZQ8sRj .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-QaACDDX4cCZQ8sRj .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-QaACDDX4cCZQ8sRj .marker{fill:#333333;stroke:#333333;}#mermaid-svg-QaACDDX4cCZQ8sRj .marker.cross{stroke:#333333;}#mermaid-svg-QaACDDX4cCZQ8sRj svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-QaACDDX4cCZQ8sRj p{margin:0;}#mermaid-svg-QaACDDX4cCZQ8sRj .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-QaACDDX4cCZQ8sRj .cluster-label text{fill:#333;}#mermaid-svg-QaACDDX4cCZQ8sRj .cluster-label span{color:#333;}#mermaid-svg-QaACDDX4cCZQ8sRj .cluster-label span p{background-color:transparent;}#mermaid-svg-QaACDDX4cCZQ8sRj .label text,#mermaid-svg-QaACDDX4cCZQ8sRj span{fill:#333;color:#333;}#mermaid-svg-QaACDDX4cCZQ8sRj .node rect,#mermaid-svg-QaACDDX4cCZQ8sRj .node circle,#mermaid-svg-QaACDDX4cCZQ8sRj .node ellipse,#mermaid-svg-QaACDDX4cCZQ8sRj .node polygon,#mermaid-svg-QaACDDX4cCZQ8sRj .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-QaACDDX4cCZQ8sRj .rough-node .label text,#mermaid-svg-QaACDDX4cCZQ8sRj .node .label text,#mermaid-svg-QaACDDX4cCZQ8sRj .image-shape .label,#mermaid-svg-QaACDDX4cCZQ8sRj .icon-shape .label{text-anchor:middle;}#mermaid-svg-QaACDDX4cCZQ8sRj .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-QaACDDX4cCZQ8sRj .rough-node .label,#mermaid-svg-QaACDDX4cCZQ8sRj .node .label,#mermaid-svg-QaACDDX4cCZQ8sRj .image-shape .label,#mermaid-svg-QaACDDX4cCZQ8sRj .icon-shape .label{text-align:center;}#mermaid-svg-QaACDDX4cCZQ8sRj .node.clickable{cursor:pointer;}#mermaid-svg-QaACDDX4cCZQ8sRj .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-QaACDDX4cCZQ8sRj .arrowheadPath{fill:#333333;}#mermaid-svg-QaACDDX4cCZQ8sRj .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-QaACDDX4cCZQ8sRj .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-QaACDDX4cCZQ8sRj .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-QaACDDX4cCZQ8sRj .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-QaACDDX4cCZQ8sRj .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-QaACDDX4cCZQ8sRj .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-QaACDDX4cCZQ8sRj .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-QaACDDX4cCZQ8sRj .cluster text{fill:#333;}#mermaid-svg-QaACDDX4cCZQ8sRj .cluster span{color:#333;}#mermaid-svg-QaACDDX4cCZQ8sRj div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-QaACDDX4cCZQ8sRj .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-QaACDDX4cCZQ8sRj rect.text{fill:none;stroke-width:0;}#mermaid-svg-QaACDDX4cCZQ8sRj .icon-shape,#mermaid-svg-QaACDDX4cCZQ8sRj .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-QaACDDX4cCZQ8sRj .icon-shape p,#mermaid-svg-QaACDDX4cCZQ8sRj .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-QaACDDX4cCZQ8sRj .icon-shape .label rect,#mermaid-svg-QaACDDX4cCZQ8sRj .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-QaACDDX4cCZQ8sRj .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-QaACDDX4cCZQ8sRj .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-QaACDDX4cCZQ8sRj :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    新告警

    重复

    危险

    安全

    成功

    失败

    Prometheus 告警

    Webhook 接收

    去重检查

    入库 firing

    跳过, 仅更新时间

    RAG 知识检索

    LLM 生成命令

    安全检查

    Blocked记录拦截日志

    SSH 连接池执行

    LLM 分析结果

    修复成功?

    Alert → resolved

    Alert → acknowledged

    多通道通知

    4.2 为什么 AI 生成的命令可以放心执行?—— Zero-Touch Safe Execution Layer

    这是整个系统最关键的安全设计。AI 生成命令后,不会直接执行,而是经过三层防护:

    第一层:Agent Prompt 层面约束

    # remediation Agent 的 system prompt 明确禁止:
    # – 禁止 kill -9 作为首选
    # – 禁止 rm -rf
    # – 禁止 reboot / shutdown
    # – 要求每条修复命令标注 # ROLLBACK: 回滚方案

    第二层:13 条危险命令正则拦截

    DANGEROUS_PATTERNS = [
    (r'\\brm\\s+-rf\\s+/', "递归删除根目录"),
    (r'\\bdd\\s+if=', "裸磁盘写入(dd)"),
    (r'\\bmkfs\\.', "创建文件系统(mkfs)"),
    (r':\\(\\)\\s*\\{.*:\\|:&.*\\};:', "Fork炸弹"),
    (r'>\\s*/dev/sd[a-z]', "覆盖裸设备"),
    (r'\\bchmod\\s+777\\s+/', "修改根目录权限为777"),
    (r'\\bshutdown\\s+-h\\s+now', "立即关机"),
    (r'\\breboot\\s+-f', "强制重启"),
    (r'\\biptables\\s+-F\\b', "清空iptables规则"),
    (r'\\bwget\\s+.*\\|.*sh\\b', "管道执行远程脚本"),
    (r'\\bcurl\\s+.*\\|.*sh\\b', "管道执行远程脚本"),
    (r'>\\s*/etc/', "覆盖/etc/配置文件"),
    ]

    命令生成后先过正则,匹配到任何一个模式 → 直接返回 status: "blocked",不执行。

    第三层:完整审计

    每条修复操作记录到 remediation_logs 表:

    • 谁触发的(auto/manual)
    • 输入了什么(告警上下文)
    • AI 生成了什么命令
    • 实际执行了什么
    • 输出是什么、退出码是多少
    • 耗时多久

    出问题可以完整回溯。

    4.3 核心代码:AI 管道

    async def _ai_execute_on_server(self, agent_type, user_input, server, timeout):
    """统一的 AI 驱动运维管道"""
    cmd_gen_prompt = self.CMD_GEN_PROMPTS.get(agent_type)
    analysis_prompt = self.ANALYSIS_PROMPTS.get(agent_type)

    # Step 1: LLM 生成命令
    rag_context = await build_rag_context(user_input)
    full_prompt = f"{rag_context}\\n{cmd_gen_prompt}\\nUser request: {user_input}"
    llm_response = await call_llm(full_prompt, temperature=0.2)
    commands = self._extract_commands(llm_response)

    # Step 2: 安全检查
    blocked = self._check_dangerous(commands)
    if blocked:
    return {"status": "blocked", "output": f"拦截: {blocked}"}

    # Step 3: SSH 执行
    async with pool.get_connection(host, port, username, password) as conn:
    result = await conn.run(commands, check=False, timeout=timeout)

    # Step 4: LLM 分析输出
    analysis = await call_llm(f"{rag_context}\\n{analysis_prompt}\\nOutput:\\n{result.stdout}")

    return {"status": "success", "output": analysis, "commands": commands}

    4.4 修复记录卡死的教训

    实际运行中遇到了一个关键 Bug:修复记录永远卡在"执行中"。

    根因:remediate_alert() 方法中,如果 LLM API 调用失败或 SSH 连接异常,异常没有被捕获,数据库记录的状态永远是 running。

    修复:加了 try/except 包裹整个执行过程,异常时更新记录为 failed,并在应用启动时自动清理上次异常退出遗留的 running 记录。

    try:
    result = await self._ai_execute_on_server("ai_remediation", repair_prompt, server, 60)
    except Exception as exc:
    await self._update_remediation_log(log_id, status="failed",
    error_output=f"修复执行异常: {exc}", duration_ms=duration_ms)
    return {"status": "failed", "output": str(exc)}

    经验:AI 管道中的任何一步(LLM API、SSH 连接、命令执行)都可能失败,必须全部包在 try/except 里。


    五、核心设计二:RAG 知识库 —— Institutional Memory Kernel

    5.1 为什么需要 RAG?

    直接用 LLM 回答"服务器 CPU 高怎么办",它会给你通用的答案——“top 看看哪个进程、检查一下是否有死循环”。

    但你的运维环境有自己的特点:

    • “我们的 Java 应用 OOM 是因为 JVM 参数 -XX:MaxMetaspaceSize 没配”
    • “Redis 连接数超标是因为有个定时任务每次创建新连接没释放”
    • “Nginx 502 通常是因为后端服务健康检查超时设的太短”

    这些公司特有的经验,LLM 不知道。RAG 就是把这些经验"喂"给 LLM。

    5.2 实现方案

    #mermaid-svg-yifKjSzjzXVCtwIQ{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-yifKjSzjzXVCtwIQ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-yifKjSzjzXVCtwIQ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-yifKjSzjzXVCtwIQ .error-icon{fill:#552222;}#mermaid-svg-yifKjSzjzXVCtwIQ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-yifKjSzjzXVCtwIQ .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-yifKjSzjzXVCtwIQ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-yifKjSzjzXVCtwIQ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-yifKjSzjzXVCtwIQ .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-yifKjSzjzXVCtwIQ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-yifKjSzjzXVCtwIQ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-yifKjSzjzXVCtwIQ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-yifKjSzjzXVCtwIQ .marker.cross{stroke:#333333;}#mermaid-svg-yifKjSzjzXVCtwIQ svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-yifKjSzjzXVCtwIQ p{margin:0;}#mermaid-svg-yifKjSzjzXVCtwIQ .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-yifKjSzjzXVCtwIQ .cluster-label text{fill:#333;}#mermaid-svg-yifKjSzjzXVCtwIQ .cluster-label span{color:#333;}#mermaid-svg-yifKjSzjzXVCtwIQ .cluster-label span p{background-color:transparent;}#mermaid-svg-yifKjSzjzXVCtwIQ .label text,#mermaid-svg-yifKjSzjzXVCtwIQ span{fill:#333;color:#333;}#mermaid-svg-yifKjSzjzXVCtwIQ .node rect,#mermaid-svg-yifKjSzjzXVCtwIQ .node circle,#mermaid-svg-yifKjSzjzXVCtwIQ .node ellipse,#mermaid-svg-yifKjSzjzXVCtwIQ .node polygon,#mermaid-svg-yifKjSzjzXVCtwIQ .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-yifKjSzjzXVCtwIQ .rough-node .label text,#mermaid-svg-yifKjSzjzXVCtwIQ .node .label text,#mermaid-svg-yifKjSzjzXVCtwIQ .image-shape .label,#mermaid-svg-yifKjSzjzXVCtwIQ .icon-shape .label{text-anchor:middle;}#mermaid-svg-yifKjSzjzXVCtwIQ .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-yifKjSzjzXVCtwIQ .rough-node .label,#mermaid-svg-yifKjSzjzXVCtwIQ .node .label,#mermaid-svg-yifKjSzjzXVCtwIQ .image-shape .label,#mermaid-svg-yifKjSzjzXVCtwIQ .icon-shape .label{text-align:center;}#mermaid-svg-yifKjSzjzXVCtwIQ .node.clickable{cursor:pointer;}#mermaid-svg-yifKjSzjzXVCtwIQ .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-yifKjSzjzXVCtwIQ .arrowheadPath{fill:#333333;}#mermaid-svg-yifKjSzjzXVCtwIQ .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-yifKjSzjzXVCtwIQ .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-yifKjSzjzXVCtwIQ .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-yifKjSzjzXVCtwIQ .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-yifKjSzjzXVCtwIQ .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-yifKjSzjzXVCtwIQ .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-yifKjSzjzXVCtwIQ .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-yifKjSzjzXVCtwIQ .cluster text{fill:#333;}#mermaid-svg-yifKjSzjzXVCtwIQ .cluster span{color:#333;}#mermaid-svg-yifKjSzjzXVCtwIQ div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-yifKjSzjzXVCtwIQ .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-yifKjSzjzXVCtwIQ rect.text{fill:none;stroke-width:0;}#mermaid-svg-yifKjSzjzXVCtwIQ .icon-shape,#mermaid-svg-yifKjSzjzXVCtwIQ .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-yifKjSzjzXVCtwIQ .icon-shape p,#mermaid-svg-yifKjSzjzXVCtwIQ .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-yifKjSzjzXVCtwIQ .icon-shape .label rect,#mermaid-svg-yifKjSzjzXVCtwIQ .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-yifKjSzjzXVCtwIQ .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-yifKjSzjzXVCtwIQ .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-yifKjSzjzXVCtwIQ :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    结果

    在线查询

    离线阶段

    运维知识库22+ 条 Markdown 条目

    SentenceTransformerall-MiniLM-L6-v2

    384维向量缓存numpy array

    用户提问 / 告警内容

    同模型编码

    余弦相似度计算

    相似度 > 0.2?

    Top-3 知识片段拼入 LLM Prompt

    返回空上下文不阻塞主流程

    模型选型:sentence-transformers/all-MiniLM-L6-v2

    为什么不用 OpenAI Embedding?

    • 免费:不需要 API Key,本地 CPU 推理
    • 轻量:模型仅 80MB,向量维度 384,22 条知识库 ≈ 33KB
    • 够用:中文语义理解能力完全满足运维场景

    架构:

    知识库条目 → SentenceTransformer.encode() → 384维向量缓存 (numpy array)
    用户提问 → SentenceTransformer.encode() → 查询向量

    余弦相似度计算 (normalized dot product)

    相似度 > 0.2 的 Top-K 片段 → 拼入 LLM Prompt

    知识库条目示例:

    ## CPU 飙高排查
    当收到 CPU 使用率告警时:
    1. 先用 top -bn1 -o %CPU | head -5 定位高 CPU 进程
    2. 如果是 Java 进程,用 jstack <pid> 查看线程堆栈
    3. 检查 /proc/loadavg 判断是 CPU 瓶颈还是 IO 等待
    4. 常见原因:GC 频繁、死循环、正则回溯

    5.3 关键代码

    from sentence_transformers import SentenceTransformer

    class KnowledgeService:
    def __init__(self):
    self.model = SentenceTransformer('all-MiniLM-L6-v2')
    self.embeddings = None # 预计算的知识库向量
    self.entries = [] # 知识库条目文本

    def build_index(self, entries: list[str]):
    """离线构建向量索引"""
    self.entries = entries
    self.embeddings = self.model.encode(entries, normalize_embeddings=True)

    def search(self, query: str, top_k: int = 3, threshold: float = 0.2) > str:
    """语义检索,返回相关片段"""
    query_vec = self.model.encode([query], normalize_embeddings=True)
    # 余弦相似度 = 归一化向量的点积
    scores = (self.embeddings @ query_vec.T).flatten()
    # 取 Top-K
    top_indices = scores.argsort()[top_k:][::1]
    results = []
    for idx in top_indices:
    if scores[idx] >= threshold:
    results.append(f"相关知识片段 (相似度: {scores[idx]:.2f}):\\n{self.entries[idx]}")
    return "\\n\\n".join(results)

    5.4 容错设计

    模型加载可能失败(缺依赖、被墙、OOM),但不能让 RAG 的失败阻塞整个 AI 管道。

    async def build_rag_context(query: str) > str:
    try:
    return knowledge_service.search(query)
    except Exception:
    logger.warning("RAG 检索失败,降级为空上下文")
    return "" # Fail-open:不阻塞主流程


    六、核心设计三:定时巡检 + 日志事件检测

    6.1 不只是采集指标

    传统的巡检就是跑个 top、free、df,超过阈值发告警。我加了日志事件检测——八类系统异常自动识别:

    LOG_EVENT_PATTERNS = {
    "OOM Killer": r"Out of memory|oom-killer|Killed process",
    "Segfault": r"segfault|segmentation fault",
    "Hung Task": r"blocked for more than \\d+ seconds|hung_task",
    "Disk I/O Error": r"I/O error|buffer I/O error|ext4.*error",
    "Network Flood": r"SYN flood|possible SYN flooding",
    "Kernel Panic": r"Kernel panic|BUG:",
    "Hardware Error": r"Hardware Error|MCE|machine check",
    "Filesystem Error": r"filesystem.*error|read-only",
    }

    每次巡检执行 dmesg –level=err,warn | tail -20,正则匹配到事件 → 自动生成告警 → 触发通知 → 触发 AI 修复。

    6.2 告警升级机制

    CPU > 80% → warning 告警
    CPU > 96% → critical 告警(原阈值 × 120%)

    严重级别的告警会触发更激进的修复策略。


    七、核心设计四:可视化工作流引擎

    7.1 12 个专业 Agent

    Agent功能需要 SSH需要 LLM
    monitor(指标采集) CPU/内存/磁盘/负载/进程/连接数 AI 分析报告
    diagnostic(故障诊断) 根因分析,假设+证据链
    remediation(自动修复) 预检→修复→验证三步安全修复
    alert_analyzer(告警分析) 评估严重程度 P0-P4
    log_analyzer(日志分析) 日志取证,异常模式识别
    change_executor(变更执行) 变更计划+回滚方案 可选
    doc_generator(文档生成) 巡检报告 Markdown → 服务器 /tmp 可选
    compliance_checker(合规检查) 8 项安全评分
    shell_command(命令执行) 直接执行 Shell,跳过 LLM
    health_check(健康检查) HTTP GET 检查服务状态
    webhook(通知推送) POST 结果到 Webhook
    generic(通用助手) 意图识别自动路由

    7.2 四种真实运维场景模板

    场景一:服务健康监控(不需 SSH、不需 AI Key)

    health_check(HTTP GET) → webhook(推送结果)

    场景二:磁盘巡检告警(只需 SSH,不需 AI Key)

    shell_command(df -h) → webhook(钉钉/飞书告警)

    场景三:日志错误扫描(需要 SSH + AI Key)

    shell_command(grep ERROR) → log_analyzer(AI 分析) → webhook(报告)

    场景四:服务器全量巡检(需要 SSH + AI Key)

    monitor(指标采集) → log_analyzer(日志分析) → doc_generator(生成报告)

    7.3 DAG 并行执行

    #mermaid-svg-dttE64hyPSQulCHV{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-dttE64hyPSQulCHV .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-dttE64hyPSQulCHV .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-dttE64hyPSQulCHV .error-icon{fill:#552222;}#mermaid-svg-dttE64hyPSQulCHV .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-dttE64hyPSQulCHV .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-dttE64hyPSQulCHV .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-dttE64hyPSQulCHV .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-dttE64hyPSQulCHV .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-dttE64hyPSQulCHV .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-dttE64hyPSQulCHV .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-dttE64hyPSQulCHV .marker{fill:#333333;stroke:#333333;}#mermaid-svg-dttE64hyPSQulCHV .marker.cross{stroke:#333333;}#mermaid-svg-dttE64hyPSQulCHV svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-dttE64hyPSQulCHV p{margin:0;}#mermaid-svg-dttE64hyPSQulCHV .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-dttE64hyPSQulCHV .cluster-label text{fill:#333;}#mermaid-svg-dttE64hyPSQulCHV .cluster-label span{color:#333;}#mermaid-svg-dttE64hyPSQulCHV .cluster-label span p{background-color:transparent;}#mermaid-svg-dttE64hyPSQulCHV .label text,#mermaid-svg-dttE64hyPSQulCHV span{fill:#333;color:#333;}#mermaid-svg-dttE64hyPSQulCHV .node rect,#mermaid-svg-dttE64hyPSQulCHV .node circle,#mermaid-svg-dttE64hyPSQulCHV .node ellipse,#mermaid-svg-dttE64hyPSQulCHV .node polygon,#mermaid-svg-dttE64hyPSQulCHV .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-dttE64hyPSQulCHV .rough-node .label text,#mermaid-svg-dttE64hyPSQulCHV .node .label text,#mermaid-svg-dttE64hyPSQulCHV .image-shape .label,#mermaid-svg-dttE64hyPSQulCHV .icon-shape .label{text-anchor:middle;}#mermaid-svg-dttE64hyPSQulCHV .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-dttE64hyPSQulCHV .rough-node .label,#mermaid-svg-dttE64hyPSQulCHV .node .label,#mermaid-svg-dttE64hyPSQulCHV .image-shape .label,#mermaid-svg-dttE64hyPSQulCHV .icon-shape .label{text-align:center;}#mermaid-svg-dttE64hyPSQulCHV .node.clickable{cursor:pointer;}#mermaid-svg-dttE64hyPSQulCHV .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-dttE64hyPSQulCHV .arrowheadPath{fill:#333333;}#mermaid-svg-dttE64hyPSQulCHV .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-dttE64hyPSQulCHV .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-dttE64hyPSQulCHV .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-dttE64hyPSQulCHV .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-dttE64hyPSQulCHV .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-dttE64hyPSQulCHV .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-dttE64hyPSQulCHV .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-dttE64hyPSQulCHV .cluster text{fill:#333;}#mermaid-svg-dttE64hyPSQulCHV .cluster span{color:#333;}#mermaid-svg-dttE64hyPSQulCHV div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-dttE64hyPSQulCHV .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-dttE64hyPSQulCHV rect.text{fill:none;stroke-width:0;}#mermaid-svg-dttE64hyPSQulCHV .icon-shape,#mermaid-svg-dttE64hyPSQulCHV .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-dttE64hyPSQulCHV .icon-shape p,#mermaid-svg-dttE64hyPSQulCHV .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-dttE64hyPSQulCHV .icon-shape .label rect,#mermaid-svg-dttE64hyPSQulCHV .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-dttE64hyPSQulCHV .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-dttE64hyPSQulCHV .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-dttE64hyPSQulCHV :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    Level 2 — 串行

    Level 1 — 并行

    Level 0 — 串行

    输出: CPU 95%

    asyncio.gather

    asyncio.gather

    拓扑分层结果

    Level 0

    Level 1

    Level 2

    monitor指标采集

    log_analyzer日志分析

    diagnostic故障诊断

    compliance_checker合规检查

    等待全部完成

    doc_generator生成巡检报告

    同层节点并行执行(asyncio.gather),串行层的节点依次执行,上游输出自动传给下游。


    八、踩坑记录(真金白银的经验)

    坑 1:HuggingFace 在国内被墙

    现象:Docker 构建时 sentence-transformers 无法下载模型,构建失败。

    解决:

    • CI 构建(GitHub Actions 境外机器)走 HF 官方
    • Docker 镜像内预下载模型(python -c "from sentence_transformers import SentenceTransformer; SentenceTransformer('all-MiniLM-L6-v2')"),运行时不需要联网
    • 国内部署时设置环境变量 HF_ENDPOINT=https://hf-mirror.com

    坑 2:修复记录永远卡在"运行中"

    现象:AI 修复执行过程中 LLM API 超时或 SSH 断开,数据库记录永远停留在 status: "running"。

    解决:

  • remediate_alert() 整个执行路径加 try/except,异常时更新为 failed
  • 应用启动时自动扫描并清理上次异常退出遗留的 running 记录
  • 坑 3:LLM API Key 隔离问题

    现象:多个用户共用系统级 Key,手动修复也用系统 Key 计费。

    解决:UserLLMConfig 表存储每个用户自己的 API Key。Provider 工厂模式:用户有 Key → 创建独立 Provider;无 Key → 回退全局单例。

    坑 4:ECS 内存不足 OOM

    现象:1.7 GB 内存的 ECS 跑了 PostgreSQL + Redis + Backend + Frontend 四个容器,后端容器频繁 OOM。

    解决:

    • PostgreSQL 调低 shared_buffers、work_mem
    • Redis 设 maxmemory 64mb
    • 建议加 swap(fallocate -l 2G /swapfile && mkswap /swapfile && swapon /swapfile)

    坑 5:Agent 命令生成质量不稳定

    现象:LLM 有时生成带 Markdown 解释的命令,有时代码块不闭合,有时生成无意义的 echo 语句。

    解决:

    • 每个 Agent 的 CMD_GEN_PROMPT 极度具体,限制输出格式
    • 代码块未闭合时的兜底提取逻辑(正则处理 LLM token 截断场景)
    • Prompt 要求"Output ONLY a bash code block. The block MUST be closed with "

    九、量化成果

    指标数据
    Agent 类型 12 个(9 个 AI 驱动 + 3 个实用节点)
    API 端点 60+ REST + SSE 流式
    通知通道 5 种(钉钉/企微/飞书/邮件/Webhook)
    安全检查规则 13 条危险命令黑名单
    日志事件检测 8 类系统异常自动识别
    知识库条目 22+ 条预设 + 用户自定义
    工作流模板 4 个真实运维场景
    数据库表 14 张(完整审计追踪)
    容器化 Docker Compose 一键部署 + K8s Helm Chart
    CI/CD GitHub Actions 自动 lint → test → build → 推送阿里云 ACR

    十、你可以怎么复用自己的项目里?

    10.1 最小可行方案(一周可上线)

  • 搭一个 FastAPI 接收 Prometheus Webhook → 解析告警,写入数据库
  • 接一个 LLM API(GLM-4-Flash 免费) → 让 AI 分析告警内容,生成诊断命令
  • 用 AsyncSSH 执行命令 → 在目标服务器执行,返回结果
  • 加 13 条危险命令正则 → 安全拦截
  • 钉钉机器人通知 → 告警 + 修复结果推送
  • 这就已经是一个能用的 AI 自动修复管道了。

    10.2 进阶方案

  • RAG 知识库 → 用 sentence-transformers 把你团队的运维 Wiki 向量化
  • 工作流编辑器 → React Flow 拖放编排多个 Agent
  • 定时巡检 → APScheduler + dmesg 日志检测
  • 多通道通知 → 企微/飞书/邮件
  • 10.3 项目地址 & 源码

    在线演示:http://8.137.178.63 (阿里云 ECS 部署,开源完整平台,注册即用)

    源码:

    git clone https://github.com/okudhdheheuus/Python_AIops.git
    cd Python_AIops
    docker compose up -d

    技术栈:Python/FastAPI + Next.js/React + PostgreSQL + Redis + Docker + Kubernetes


    十一、写在最后

    做这个项目的初心很简单:我不想凌晨 3 点被叫起来处理磁盘满这种问题。

    传统运维的困境在于——监控系统能告诉你"出问题了",但它不能帮你"解决问题"。"发现问题"到"解决问题"之间这段路,以前全靠人走。

    AI Agent 的价值就在于填平这段路。

    它不是替代运维人员,而是让你从"告警响应者"变成"平台建设者"。你把经验沉淀到知识库,把重复操作写成工作流,把安全检查做成规则——然后 AI 替你执行。

    如果这篇文章对你有帮助,欢迎 Star、提 Issue、贡献代码。特别欢迎贡献新的通知通道、新的 Agent 类型、新的知识库条目。

    一个人走得快,一群人走得远。


    作者注:本文所有代码均为生产环境实际运行代码,非 Demo 演示。欢迎转载,请注明出处。

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » 当AI学会“修服务器”:我告警风暴中重生,把修复时间从泡面凉透缩短到一首歌
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!