基于 DeepSeek+Prometheus 搭建运维巡检 Agent,自动生成企微巡检日报
前言:
日常需要维护 Linux 服务器集群。之前每天都要人工登录主机或者查看 Prometheus 指标,逐个核对 CPU、内存、磁盘,手动汇总巡检报告发到企业微信。
人工巡检重复枯燥,节点多的时候很容易漏看告警,汇总耗时很长。于是基于 Python 开发了一套轻量运维 Agent,实现Prometheus 指标采集 → LLM 结构化汇总 → 企微机器人推送的全链路自动化巡检日报系统。
本项目特点:
- 基于 OpenAI 兼容接口,无重型 AIOps 平台依赖,单脚本即可部署;
- 面向服务器巡检场景,强约束 Prompt,严格限制 LLM 幻觉,只基于采集到的数据输出;
- 模块解耦,采集、LLM 调用、推送相互独立,方便替换监控源、大模型服务商;
- 自带降级逻辑,LLM 超时 / 接口异常时不会直接崩溃,推送降级提示通知运维。
一、整体方案架构
整个Agent采用三段解耦流水线设计,各模块可独立替换
1、采集层: 调用Prometheus API 来取监控指标、包含内存使用率、全分区磁盘使用率、CPU15分钟负载;自动过滤tmpfs、overlay等虚拟文件系统,识别磁盘挂载点/,/data,/log等(这个可以在根据实际情况可修改)
2、LLM分析层: 将结构化监控文本送入DeepSeek接口,通过Prompt约束,自动区分异常告警项,正常指标分组汇总,禁止编造数据;
3、推送层: LLM生成完成巡检日报后,通过企业微信Webhook机器人推送;
4、调度层: Linux crontab定时调度脚本,实现每日定点自动巡检。
这样架构的优势:
- 轻量:单Python脚本,兼容Python3.6,适配老旧服务器环境;
- 可扩展:后续可对接Zabbix,SkyWalking等其他监控源;
- 高可控:任何场景服务器巡检场景优先保证准确性,杜绝AI幻觉编造告警;
- 容错:LLM调用失败自动降级,推送异常通知,保障运维感知;
二、项目踩坑实录
坑 1:OpenAI 兼容协议 ≠ 模型名称通用
最开始开发时直接沿用 OpenAI 写法,模型参数写gpt-3.5-turbo,接口直接返回 400
排查:
- 先使用 curl 最小用例验证 API 密钥、网络连通正常;
- 在用脚本打印完整请求 header、payload,对比报文;
- 查看返回报错:DeepSeek 不识别
gpt-3.5-turbo,仅支持deepseek-flash、deepseek-v4-pro等自有模型标识。
✅ 得出的结论:兼容只是 HTTP 协议、请求体格式对齐,模型名称是各大厂商独立管控,不能直接复用 OpenAI 模型标识。
坑 2:Prompt 模板占位符忘记替换,LLM 拿不到监控数据
写好 Prompt 模板后,直接把模板字符串发给 LLM,{metrics}占位符没有替换成采集到的监控文本,大模型返回提示监控数据为空,无法生成日报。
✅ 解决:使用字符串format方法,采集完成拿到结构化指标文本之后,填充进 Prompt 模板,再发起 LLM 请求。
坑 3:原始指标无字段说明,LLM 产生幻觉,报告可读性差
早期版本采集输出只有IP + 数值,没有标注指标类型,大模型不知道数字代表 CPU、内存还是磁盘,容易自行猜测指标含义,输出报告其他人看不懂。
✅ 优化:采集层统一结构化输出格式:
节点IP | 指标名称 | 挂载点(磁盘专属) | 数值
- CPU、内存无挂载点的指标,挂载点填充
-; - 磁盘指标携带
mountpoint挂载点,区分多个业务分区; - Prompt 增加强约束:禁止猜测指标含义,仅基于输入数据输出。
坑 4:磁盘只采集根分区,巡检覆盖不全
一开始 PromQL 只采集根分区/使用率,忽略/data、/log等业务分区,日志盘、数据盘打满风险无法感知。
✅ 优化 PromQL,过滤虚拟文件系统,抓取全部真实挂载分区:
100 - (node_filesystem_avail_bytes{mountpoint!~"/sys|/proc|/dev|/run",fstype!~"tmpfs|devtmpfs|overlay"} / node_filesystem_size_b
坑 5:新增指标后输入文本变长,出现 Read timed out
扩容指标(增加全分区磁盘、CPU 负载)之后,送入 LLM 的文本 token 上涨,大模型生成耗时变长,requests 默认超时时间短,抛出读取超时。
✅ 解决:给 post 请求显式设置读写超时 timeout=(10,30),10s 连接超时,30s 读取超时;
预留优化方向:节点数量过多时,做指标裁剪,只保留高风险指标,减少输入 token,避免频繁超时。
三、核心代码(Python3.6 兼容)
import requests
import logging
# ========== 配置区,请自行修改 ==========
PROM_URL = "http://127.0.0.1:9090/api/v1/query"
DEEPSEEK_KEY = "sk-xxxx"
DEEPSEEK_URL = "https://api.deepseek.com/v1/chat/completions"
WECOM_WEBHOOK = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxxx"
# =======================================
# 日志开关,方便调试排错
logging.basicConfig(level=logging.INFO)
def collect_all_metrics():
"""采集Prometheus指标:内存、全分区磁盘、15分钟负载、CPU核数"""
query_map = {
"mem": '100 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes * 100)',
"disk": '100 - (node_filesystem_avail_bytes{mountpoint!~"/sys|/proc|/dev|/run",fstype!~"tmpfs|devtmpfs|overlay"} / node_filesystem_size_bytes{mountpoint!~"/sys|/proc|/dev|/run",fstype!~"tmpfs|devtmpfs|overlay"} * 100)',
"load15": "node_load15",
"cpu_core": "count by (instance) (node_cpu_seconds_total{mode='idle'})"
}
ip_core_map = {}
line_list = []
# 第一步:先获取所有节点CPU核数,构建映射关系
resp_core = requests.get(PROM_URL, params={"query": query_map["cpu_core"]}, timeout=5)
for item in resp_core.json()["data"]["result"]:
ip = item["metric"]["instance"]
core = float(item["value"][1])
ip_core_map[ip] = core
# 采集内存使用率
resp_mem = requests.get(PROM_URL, params={"query": query_map["mem"]}, timeout=5)
for item in resp_mem.json()["data"]["result"]:
ip = item["metric"]["instance"]
val = round(float(item["value"][1]), 2)
line_list.append(f"节点IP:{ip} | 指标:内存使用率 | 挂载点:- | 数值:{val}")
if val > 85:
line_list.append(f"⚠️ 告警:节点IP:{ip} | 指标:内存使用率 | 阈值85%")
# 采集全分区磁盘使用率
resp_disk = requests.get(PROM_URL, params={"query": query_map["disk"]}, timeout=5)
for item in resp_disk.json()["data"]["result"]:
ip = item["metric"]["instance"]
mp = item["metric"]["mountpoint"]
val = round(float(item["value"][1]), 2)
line_list.append(f"节点IP:{ip} | 指标:磁盘使用率 | 挂载点:{mp} | 数值:{val}")
if val > 85:
line_list.append(f"⚠️ 告警:节点IP:{ip} | 指标:磁盘使用率 | 挂载点:{mp} | 阈值85%")
# 采集CPU 15分钟负载
resp_load = requests.get(PROM_URL, params={"query": query_map["load15"]}, timeout=5)
for item in resp_load.json()["data"]["result"]:
ip = item["metric"]["instance"]
val = round(float(item["value"][1]), 2)
core = ip_core_map.get(ip, 4)
line_list.append(f"节点IP:{ip} | 指标:CPU15分钟负载 | 挂载点:- | 数值:{val}")
if val > core:
line_list.append(f"⚠️ 告警:节点IP:{ip} | 指标:CPU15分钟负载 | 阈值本机CPU核数{core}")
return "\n".join(line_list)
def call_llm(metrics_text):
prompt_template = """
你是金融运维工程师,负责服务器巡检日报整理。
数据格式:节点IP | 指标类型 | 挂载点(磁盘专属) | 数值(%)
⚠️ 告警标记 = 指标超出预设阈值
阈值规则:
- 内存使用率:>85%告警
- 单分区磁盘使用率:>85%告警
- CPU 15分钟负载:高于节点CPU核数告警
要求:
1. 严禁编造数据、禁止猜测指标含义,只基于输入内容生成;
2. 输出结构固定:标题 → 统计概览 →【异常告警项】→【正常指标汇总】
3. 异常告警项优先,每条写明:IP、指标、挂载点(磁盘)、当前值、阈值;
4. 正常指标汇总:按【CPU负载、内存使用率、各磁盘分区】分组展示,同IP的指标合并,不要无意义逐条刷屏;
5. 输出适配企业微信,只用换行、序号,不要markdown加粗;
6. 正常指标只展示关键范围,列出高值节点,方便运维快速感知整体状态。
监控数据:
{metrics}
"""
final_prompt = prompt_template.format(metrics=metrics_text)
headers = {
"Authorization": f"Bearer {DEEPSEEK_KEY}",
"Content-Type": "application/json"
}
payload = {
"model": "deepseek-flash",
"messages": [{"role": "user", "content": final_prompt}],
"temperature": 0.2
}
try:
resp = requests.post(DEEPSEEK_URL, headers=headers, json=payload, timeout=(10, 30))
resp.raise_for_status()
return resp.json()["choices"][0]["message"]["content"]
except Exception as e:
logging.error(f"LLM调用失败,触发降级。err:{e}")
return "【巡检降级通知】LLM接口调用异常,请人工查看Prometheus监控"
def send_wecom(content):
"""企业微信机器人推送"""
data = {
"msgtype": "text",
"text": {"content": content}
}
requests.post(WECOM_WEBHOOK, json=data, timeout=10)
if __name__ == "__main__":
metrics = collect_all_metrics()
report = call_llm(metrics)
send_wecom(report)
四、定时调度配置
使用 Linux crontab 实现每日自动巡检,同时输出日志方便排查:
# 每天早上8点执行巡检脚本
0 8 * * * /usr/bin/python3.6 /opt/aihmt/agent_demo.py >> /opt/aihmt/agent.log 2>&1
五、推送效果样例(企微机器人)
【巡检告警日报】
金融运维巡检日报
数据合计56条,告警2条。
【异常告警项】
1. IP:10.13.51.21;指标:内存使用率;当前值:88.39%;阈值85%
2. IP:10.13.51.69;指标:内存使用率;当前值:97.73%;阈值85%
【正常指标汇总】
CPU15分钟负载:
10.13.51.21:2.7;10.13.51.69:1.8;其余节点负载均低于本机CPU核数,无负载异常
内存使用率(正常节点):
范围:0.84% ~ 84.64%,全部低于85%阈值
磁盘分区使用率:
10.13.51.21:/ 72.1%、/data 61.5%、/log 44.2%
10.13.51.69:/ 53.2%、/data 78.6%
其余节点各分区使用率均低于85%阈值
六、后续优化方向
- 增加 token 长度判断,节点过多时自动采样聚合,避免超长上下文、超时;
- 增加 LLM 重试机制,失败重试 1-2 次后再执行降级;
- 告警分级,区分 P1/P2 级告警;
- 巡检记录落库,支持历史趋势查看;
- 支持多环境分组巡检,区分生产、测试环境;
- 密钥加密,增加权限控制,适配金融环境安全规范。
七、总结
这个运维 Agent 不是简单的 Demo,是在金融交付运维场景落地可用的自动化工具。
核心思路不是让大模型做复杂推理,而是把 LLM 当成结构化文本汇总工具,依靠强约束 Prompt 规避幻觉,贴合金融行业对准确性、稳定性的硬性要求。
整个项目从 0 到 1 踩了协议兼容、Prompt 拼接、指标采集不全、接口超时等一系列坑,最终实现每日自动巡检,解放运维人员重复的汇总工作。
更多推荐


所有评论(0)