当AI学会“修服务器”:我告警风暴中重生,把修复时间从泡面凉透缩短到一首歌
我是如何用 AI Agent + RAG 把告警平均修复时间(MTTR)从 30 分钟降到 3 分钟的
一个运维开发者的 AIOps 实战之路:从"告警风暴中疲于奔命"到"AI 自动诊断+修复+通知全闭环"
摘要
本文复盘了一套从零搭建的 AIOps 平台:通过 AI Agent + RAG 知识库,将告警平均修复时间(MTTR)从约 30 分钟降至约 3 分钟,实现 10 倍提升。系统以 FastAPI + AsyncSSH 为核心,设计了 Auto-Remediation Pipeline(自动修复管道),由 LLM 生成修复命令并经三层安全防护(Prompt 约束、13 条危险命令正则拦截、完整审计日志)后方可执行;同时引入 RAG 语义检索,将团队特有的运维经验向量化后注入 LLM Prompt,让 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 来填补"告警触发"到"问题修复"之间的鸿沟。
三、架构总览
技术选型原则:每一步都选最"轻"的方案。
| 需求 | 为什么不用 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 完整流程
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 实现方案
模型选型: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 并行执行
同层节点并行执行(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 类型、新的知识库条目。
一个人走得快,一群人走得远。
附GitHub 源码:https://github.com/okudhdheheuus
在线演示链接:http://8.137.178.63:3000
作者注:本文所有代码均为生产环境实际运行代码,非 Demo 演示。欢迎转载,请注明出处。
更多推荐


所有评论(0)