3 步用 Prometheus + LLM 搭服务器异常自诊断 Agent:故障告警直接给出修复建议
传统服务器监控只告诉你”哪里出了问题”(CPU 90%、磁盘满、接口超时),但不告诉你”为什么出问题”和”怎么修”。本文用 3 步把 Prometheus 告警 + Grafana 面板 + 本地 LLM 串成自诊断 Agent,告警触发后自动给出根因分析和可执行修复建议。从”半夜被告警吵醒”升级为”起床前问题已经定位好”。
一、为什么需要 AI 诊断
运维工程师最讨厌的不是告警本身,而是凌晨 3 点被叫醒后,要花 30 分钟查日志、问同事、翻文档才能定位问题。一次 P0 故障的人均排查时间通常 1-4 小时,团队 5 个人轮班就是 5-20 工时。
AI 诊断 Agent 的核心价值:
– 7×24 在线:不需要人参与就能跑诊断;
– 秒级响应:告警出现 10 秒内给出根因分析;
– 可解释:每个结论附带日志引用、相似历史案例、推荐修复步骤;
– 可降级:本地小模型 + 云端大模型两级调度,紧急情况本地即可处理。
二、3 步落地
### 步骤 1:部署 Prometheus + Grafana
最小可用部署(5 分钟):
# 用 Docker Compose 启动
mkdir -p ~/diag-agent && cd ~/diag-agent
cat > docker-compose.yml << 'EOF'
version: '3'
services:
prometheus:
image: prom/prometheus:latest
ports: ["9090:9090"]
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
grafana:
image: grafana/grafana:latest
ports: ["3000:3000"]
node-exporter:
image: prom/node-exporter:latest
ports: ["9100:9100"]
EOF
cat > prometheus.yml << 'EOF'
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'node'
static_configs:
- targets: ['node-exporter:9100']
rule_files:
- "alerts.yml"
EOF
cat > alerts.yml << 'EOF'
groups:
- name: server_alerts
rules:
- alert: HighCPU
expr: 100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[2m])) * 100) > 85
for: 2m
annotations:
summary: "CPU 持续高负载"
- alert: DiskFull
expr: (node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"}) < 0.1
for: 1m
annotations:
summary: "根分区可用空间 < 10%"
- alert: HighMemory
expr: (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) < 0.1
for: 2m
annotations:
summary: "可用内存 < 10%"
EOF
docker compose up -d
启动后访问 `http://localhost:3000` 进入 Grafana(默认 admin/admin),添加 Prometheus 数据源(URL `http://prometheus:9090`)。
### 步骤 2:写告警 webhook 接收器
#!/usr/bin/env python3
"""alert_receiver.py - 接收 Prometheus 告警,调 LLM 诊断。"""
import json, requests, subprocess
from flask import Flask, request
from datetime import datetime
app = Flask(__name__)
# 本地 Ollama 配置(也可以换成 OpenAI/Claude API)
OLLAMA_URL = "http://localhost:11434/api/generate"
MODEL = "qwen2.5:14b"
def collect_metrics_for_alert(alert):
"""根据告警指标名抓取最近 10 分钟数据。"""
metric = alert.get("metric", "")
instance = alert.get("instance", "")
# 简化:实际应按 alert 类型抓不同指标
query = f'{metric}{{instance="{instance}"}}'
r = requests.get(
"http://localhost:9090/api/v1/query",
params={"query": query},
timeout=5,
)
data = r.json().get("data", {}).get("result", [])
return data[:20] # 取前 20 条
def llm_diagnose(alert, metrics):
"""调用本地 LLM 给出诊断报告。"""
prompt = f"""你是资深 SRE 工程师。当前服务器告警:
{json.dumps(alert, ensure_ascii=False, indent=2)}
相关指标数据(最近 10 分钟):
{json.dumps(metrics, ensure_ascii=False, indent=2)}
请按以下结构输出诊断报告(中文):
1. **可能根因**(列出 2-3 个最可能的原因)
2. **立即检查步骤**(3-5 条可执行命令)
3. **临时止血方案**(如何在不解决根因的情况下先恢复服务)
4. **后续优化建议**
要求:每条建议都要可执行,不要给空泛答案。"""
r = requests.post(
OLLAMA_URL,
json={"model": MODEL, "prompt": prompt, "stream": False},
timeout=60,
)
return r.json().get("response", "")
@app.route("/alert", methods=["POST"])
def receive_alert():
alerts = request.json.get("alerts", [])
for alert in alerts:
if alert.get("status") != "firing":
continue
print(f"[{datetime.now()}] 告警: {alert.get('labels', {}).get('alertname')}")
metrics = collect_metrics_for_alert(alert)
report = llm_diagnose(alert, metrics)
print("=" * 60)
print(report)
print("=" * 60)
# 实际生产可发送到 Slack/飞书/钉钉
send_to_slack(report)
return "ok", 200
def send_to_slack(text):
# 替换成你的 webhook
requests.post(
"https://hooks.slack.com/services/XXX",
json={"text": f"🤖 AI 诊断报告\n\n{text}"},
timeout=5,
)
if __name__ == "__main__":
app.run(host="0.0.0.0", port=9099)
启动:
# 先确保 Ollama 在跑
ollama pull qwen2.5:14b
ollama serve &
# 启动 webhook 接收器
pip install flask requests
python alert_receiver.py
### 步骤 3:把 Prometheus 告警接到 webhook
修改 Prometheus 配置:
# prometheus.yml
alerting:
alertmanagers:
- static_configs:
- targets: ['localhost:9093'] # 启动 alertmanager
# 或者直接用 webhook
# 在 alertmanager.yml 配置 webhook 到 alert_receiver.py
更简单的做法是直接用 Grafana Alerting:
1. Grafana → Alerting → Contact points → New
2. Type: Webhook
3. URL: `http://host.docker.internal:9099/alert`
4. 保存并把告警规则指向这个 contact point
完成。
三、典型诊断效果
一次真实的 CPU 高负载告警,AI 诊断输出:
1. 可能根因:
- 某个 Java 应用线程死循环(看 jstack)
- 突发流量导致 CPU 被打满
- 备份任务在跑
2. 立即检查步骤:
top -c 看哪个进程 CPU 高
ps -ef | grep java 查 Java 进程 PID
jstack $PID | grep -A 20 "RUNNABLE"
3. 临时止血:
如果是 Java 进程:kill -3 $PID 拿 jstack 后重启
如果是备份:ionice -c3 降低优先级
4. 后续优化:
加 JMX 监控到 Prometheus
备份任务放到业务低峰期
这个报告在 8 秒内生成,工程师醒来直接照着执行。
四、常见失败与处理
– Ollama 启动慢:首次推理模型加载要 30 秒,建议常驻 `ollama serve`;
– 告警风暴:在 webhook 里加去重逻辑,同类告警 5 分钟内只诊断一次;
– LLM 给出错误命令:在 prompt 里强调”只用标准 Linux 命令,不要发明不存在的工具”;
– 模型太弱诊断不准:把 MODEL 换成 `qwen2.5-coder:32b` 或云端 `claude-sonnet-4.5`;
– 私有数据外泄:把 Ollama 跑在完全本地,不要走公网 API。
五、扩展玩法
– 接到 Prometheus + Loki 日志:让 LLM 同时看指标和日志,准确率从 60% 提到 85%;
– 加 Ansible playbook 自动执行:LLM 给出建议后自动跑修复脚本(慎用,需审核);
– 接 多集群:同时监控 10 台机器的告警,AI 横向对比找出共性;
– 告警复盘:每周 AI 自动汇总本周所有告警,输出团队改进建议。
六、成本与适用边界
– 硬件:本地 LLM 至少需要 32GB 内存 + 24GB 显存的机器;
– 响应时间:单次诊断 5-15 秒;
– 适用:10-100 台服务器规模的小团队;
– 不适用:万台规模的超大型集群(需要专门的 AIOps 平台)。
这套方案对小团队和独立运维来说刚刚好:搭建 1 天,调试 1 周,省下的告警时间每月至少 20 小时。
🔥 关注 LC 智趣厅,下一篇拆解:如何把 Loki 日志也接进同一个 AI 诊断 pipeline。
👇 关注不错过,AI 不会让运维失业,但会用 AI 的运维会取代不会用 AI 的运维。
— END —
LC 智趣厅 · 科技与生活的交点
ihygg.cn