项目仓库:andersthorvald/sre-lab-doctor,tag v0.1.0(2026-07-02),已开源。
一句话定位:
把学员的实验问题贴进来,AI 按主机拆分给出排障步骤、修复建议、验证命令和复盘笔记。
严格只诊断不执行命令,所有命令由学员手动复制粘贴。
故事开头:为什么做这个
我做 iptables、DNS、SSH、Nginx 实验的时候,反复踩同一批坑:
- 防火墙没放行 → 配了半天服务最后发现 80 端口被拦
- BIND9 配
listen-on { 127.0.0.1; };→ slave 当然连不上 master - Docker 容器里
curl 127.0.0.1→ 这是容器自己,不是宿主机 - 自定义 NAT 网段宿主机没路由 → ping 都 ping 不通
每次都当场查、查完忘、下次再踩。
想法很朴素——把这些坑整理成知识库,让 AI 帮我按「踩过的坑」针对性诊断。同时选了一个开源 AIOps 平台 NightMend(Apache 2.0)做底座,它已经有账号、权限、审计、夜莺原生告警这套基础设施,省得我从零造。
不做什么,先讲清:
- 不是通用 ChatGPT 替代品
- 不会自动 SSH 到学员机器执行命令
- 不会自动改学员配置文件
走 Diagnosis-only Mode。
整体架构 + 关键代码
诊断流程一张图:
[学员填 7 字段表单]
│
▼
基础清洗(lab_type / goal 非空)
│
▼
知识库匹配(按 lab_type + tag 关键词打分,取 top-2)
│
▼
Prompt 构造(系统提示 + 知识库参考 + 用户问题)
│
▼
LLM 调用(MiniMax-M2.7 reasoning,约 30–50 秒)
│
▼
思考块剥离(剥掉 <!-- … --> 中的推理痕迹)
│
▼
高危命令检测(17 条正则,命中追加「🚨 高危命令警告」块)
│
▼
Markdown 输出给前端
知识库匹配这段最关键,简化版:
def match_knowledge(lab_type: str, error_text: str) -> list[Case]:
"""按 lab_type + 关键词给 10 个内置案例打分,取 top-2"""
candidates = [c for c in ALL_CASES if c.lab_type == lab_type]
if error_text:
keywords = extract_keywords(error_text) # connection refused / 502 / …
for c in candidates:
c.score = sum(1 for kw in keywords if kw in c.tags)
return sorted(candidates, key=lambda x: x.score, reverse=True)[:2]
Prompt 构造也是关键一环。它根据「是否包含故障关键词」决定走故障模板还是概念模板:
def build_prompt(lab_type: str, goal: str, error_text: str, cases: list[Case]) -> str:
is_incident = any(kw in (error_text + goal)
for kw in INCIDENT_KW) # refused / timeout / denied / …
if is_incident:
template = INCIDENT_TEMPLATE # 7 节排障模板
else:
template = CONCEPT_TEMPLATE # 7 节知识模板
refs = "\n\n".join(f"### {c.title}\n{c.body}" for c in cases)
return template.format(lab_type=lab_type, goal=goal, refs=refs)
技术栈:
| 层 | 选型 |
|---|---|
| 底座 | NightMend(fork 自上游,Apache 2.0) |
| 后端 | FastAPI + Python 3.11 |
| 前端 | React + Ant Design |
| 数据 | PostgreSQL + Redis |
| LLM | MiniMax Coding Plan MiniMax-M2.7 |
| 部署 | Docker Compose(5 容器:postgres / redis / backend / frontend / mcp) |
三个踩过的坑
坑 1:双场景 Prompt 的形式错位
最早的 prompt 我写得很死——一句话「按 7 节排障模板输出」。
学员输入了「DNS 服务器是什么」这种概念性问题。LLM 干了什么?强行套模板输出「## 1. 当前现象总结」,内容完全是维基百科腔的科普文。
形式错位。故障场景要「现状→原因→步骤→验证」那种 runbook 范儿;概念场景要「是什么→原理→实验里怎么用」那种知识范儿。同一个模板两不靠。
改成「先判断场景再选模板」:
- 故障场景(含「报错 / 失败 / refused / timeout / denied」等关键词)→ 7 节排障模板
- 概念场景(其他)→ 7 节知识模板
回头看,这个坑的本质:prompt 是给模型的合同,合同对不上场景就会乱套。
坑 2:Reasoning 思考块 + 三层超时
MiniMax-M2.7 是 reasoning 模型,会输出一段 <!-- … --> 思考块,占最终输出长度的 40% 左右。用户不需要看这些推理过程,所以加了一个 _strip_thinking() 正则剥掉。
M2.7 在复杂 prompt 下要 30–50 秒生成。链路里默认有三个超时,任一个不调就会被切断:
| 层 | 默认值 | 调到 |
|---|---|---|
| httpx 客户端 | 45s | 180s |
nginx 反代 proxy_read_timeout | 60s | 180s |
| 前端 axios | 15s | 用项目自带的 aiApi(60s) |
体感从「卡死了」变成「在跑」。三个都要动。
坑 3:17 条高危命令 —「帮倒忙」设计
最初想的方案是「检测到危险命令直接替换成 [已过滤]」。
跑了两轮 review,发现反而帮倒忙:
- 学员照着报告敲命令,跑出来发现字段没了
- 学员不知道哪一步被吃了,排查二次故障更麻烦
- LLM 会反复尝试把危险命令换个写法重新塞进去
最终的妥协:只警告不阻挡。命中之后在报告末尾追加一个「🚨 高危命令警告」块,列出命中的命令类型和风险,命令原文保留。学员自己知情决策。
17 条覆盖:rm -rf / / mkfs / dd if=... of=/dev/sdX / iptables -F / nft flush ruleset / ufw disable / systemctl stop sshd|network|firewalld / chmod -R 777 / / chown -R / curl ... | sh / wget ... | bash / kill -9 1 / shutdown / reboot / setenforce 0 等。
数据说话:v0.1 现状
| 维度 | 数据 |
|---|---|
| v0.1 主功能 | 8 / 8 完成 |
| 回归测试场景 | 5 / 5(100% 通过) |
| 内置知识库案例 | 10 个(Nginx ×2 / DNS ×2 / iptables ×2 / SSH ×2 / rsync ×1 / Docker ×1) |
| 高危命令正则 | 17 条 |
| LLM 平均响应 | 30–50 秒 |
| LLM 偶发超时 | 2–5%(MiniMax Coding Plan 限流时段) |
- 不 SSH 到任何目标机器
- 不调用 systemd、不触碰任何配置
- 不保存任何 SSH 密码、私钥、API Key
这不是技术限制,是设计选择。一个实验排障 Agent 如果能帮我执行命令,对一个 SRE 学员来说是「省事」,但对一个攻击面来说是「定时炸弹」。
下一步路线图
v0.2(2–3 周后开搞)
- LLM 兜底:MiniMax 超时自动切 DeepSeek 备用 Key
- 流式响应(SSE):用户边看边等,体感从 30 秒变成「几乎是即时」
- 多轮对话:追问「我执行步骤 3 还是失败」
- 知识库扩展:补 Kubernetes / Prometheus / Zabbix / Linux 基础 / Python 自动化 5 个 lab_type
- 用户反馈:报告下方 👍 / 👎 按钮
v0.3(中期)
- 知识库后台管理 UI(增删改案例不需要改 JSON 文件)
- Prompt 模板版本管理 + A/B 测试
- 导出 PDF
v1.0(长期)
- 多租户 SaaS
- 与 NightMend 告警联动(告警触发时自动诊断)
- 主动学习(从学员操作日志自动归纳案例)
写在最后
做这个项目最大的收获不是「我会做 AI Agent 了」,是真切体会到 LLM 产品跟传统软件不一样:
- 一个 prompt 改了,整条链路可能全变
- 一个超时没调够,体感就像挂了
- 一个安全设计偷懒,整个产品都不可信
下一篇会讲选型对比——为什么没从零写、为什么选 NightMend、对比过哪几个开源 AIOps 项目、各自适合什么场景。下一篇会有架构对比图。
如果你的 SRE 课也有一堆「反复踩的坑」,欢迎评论告诉我——我会挑进 v0.2 的知识库里。
系列导航
- 当前:第 1 篇 — 我基于开源 AIOps 项目做了一个 SRE 实验排障 AI Agent
- 下一篇:第 2 篇 — 选型对比:4 个候选 AIOps 开源项目
- ← 回到系列主页