智能运维新实践:Prometheus 与 DeepSeek 联动实现告警自动分析 原创

发布于 2025-8-29 08:55
浏览
0收藏

前阵子,一位运维学员向我倾诉了他的困扰:日常工作中,Prometheus 虽能精准捕捉系统参数异常并告警,但生成的报警信息往往只是冰冷的指标数据。每次遇到异常,他都得手动把这些信息复制粘贴到 DeepSeek 里去询问分析建议,不仅操作繁琐,后续也难形成规整的存档用于技术沉淀。要是能让报警后自动生成带分析的智能报表,那该多方便高效啊!

在充分了解他的这一需求后,我给出了一套解决方案 —— 借助 Prometheus Server 与 Alertmanager 的告警机制,再结合 DeepSeek 的 API,让 AI 自动对告警信息深度分析并生成智能报表。实际验证下来,这套方案效果很不错,所以我打算把完整的思路和实验过程写成文章,分享给更多同行。

整体思路

在开始实践之前,我想先整理一下整体思路,这里我将其分为如下四个步骤,同时也用一张大图对其进行描述如下:

首先是 “生成指标数据”,它是一切的起点,为后续的监控与分析提供最基础的 “素材”,这些数据可以是系统的各项运行参数,也可以是业务运行的参数等。

接着进入 “采集数据、异常定义、异常检测、转发报警” 环节。系统会采集前期生成的指标数据,同时提前明确什么样的数据属于异常情况,之后对数据进行检测,一旦发现符合异常定义的数据,就会将其转化为告警并转发出去。

然后是 “处理报警” 环节,会对接收到的转发告警进行处理,确保告警信息能被有效承接,为后续的智能分析做好准备。

最后是 “生成智能报告” 环节,借助像 DeepSeek 这样的 AI 能力,对告警等信息进行深度分析,最终产出更具价值、能够辅助决策的智能报告。

智能运维新实践:Prometheus 与 DeepSeek 联动实现告警自动分析-AI.x社区

上面的文字描述了上图中靠上方的四个实心框体的内容,并且按照箭头从左到右的顺序介绍了整个实践的执行顺序。接着,我们解释靠下方的四个虚线框,他们会完成具体操作,涉及到服务、代码、系统以及他们之间的交互。

在整个实践中,我们需要监控一个应用系统中用户登陆的情况,当发现登陆异常以后会通过 DeepSeek 分析异常信息,生成异常分析报表,方便我们分析异常以及采取下一步行动。

整个实践流程环环相扣,按照顺序执行。首先,用custom_exporter.py利用 Prometheus Client 的 SDK生成登录相关指标数据,为后续监控提供基础。接着,Prometheus 采集这些登录数据,并提前定义好登录异常的规则,一旦检测到异常,就会将告警转发给Alertmanager。随后,Alertmanager 接收来自 Prometheus 的告警并进行处理。最后,利用alert_handler.py调用 DeepSeek 大模型,基于告警信息生成智能的异常分析报表,把冰冷的监控数据转化为更易理解、能辅助决策的智能报告,让监控从单纯的告警通知,升级为具备分析和解读能力的智能运维工具。

Docker 安装 Prometheus

在实践的开始,需要安装 Prometheus 保证基本的数据采集功能。这里我们采用 Docker 安装,它能快速且一致地搭建起实验所需的运行环境。它可将 Prometheus 及其依赖打包成镜像,让我们在不同环境下都能便捷部署,无需操心复杂的依赖配置与环境差异问题,同时也便于后续对容器进行管理、版本切换以及迁移等操作。

确保系统安装 Docker ,在命令行执行如下指令

docker run --name prometheus -d -p 127.0.0.1:9090:9090 prom/prometheus

这里对指令稍加解释如下:

  1. docker run:创建并启动容器;​
  2. --name prometheus:指定容器名为prometheus;​
  3. -d:后台运行容器,不阻塞终端;​
  4. -p 127.0.0.1:9090:9090:将容器内 9090 端口(Prometheus 默认端口)映射到宿主机 127.0.0.1 的 9090 端口,仅允许本地访问;​
  5. prom/prometheus:使用官方 Prometheus 镜像,本地无镜像时会自动从 Docker Hub 拉取。

这里建议大家通过 Docker Desktop 的日志检查容器是否启动成功。

智能运维新实践:Prometheus 与 DeepSeek 联动实现告警自动分析-AI.x社区

当然,此时也可以通过 Web UI 访问 Prometheus,不过此时还没有任何数据采集上来。

智能运维新实践:Prometheus 与 DeepSeek 联动实现告警自动分析-AI.x社区

采集数据

安装好 Prometheus 之后,我们需要利用它采集指标数据。Prometheus 的设计理念是 “拉取”(Pull)数据,而非 “推送”(Push)。最常用的方式是通过各种 Exporter 将数据以 Prometheus 支持的格式(OpenMetrics)暴露出来,再配置 Prometheus 去拉取。

指标数据(Metrics)

这里需要采集的指标数据,需要做一个简要说明,在IT监控领域,指标数据(Metrics) 是系统运行状态和业务活动最核心的量化反映。指标数据的本质包含如下几个方面:

  1. 数值化测量:指标是数值(例如:CPU 使用率 75%、每秒处理请求数 1200、过去5分钟登录失败次数 15、当前内存占用 4.2GB)。​
  2. 时间序列:指标数据是按时间顺序采集并存储的一系列数据点。每个点包含一个时间戳(何时采集)和一个指标值(当时的状态)。​
  3. 核心目的:
  • 监控健康状况:实时了解系统资源(CPU、内存、磁盘、网络)是否充足,服务是否可用。​
  • 追踪性能表现:衡量系统处理能力(吞吐量、请求速率)和响应速度(延迟)。​
  • 洞察业务行为:记录用户活动(如登录次数、订单量)、业务流程状态等。​
  • 诊断问题根源:当系统异常或性能下降时,指标的变化趋势和关联性是定位问题的关键线索。​
  • 支持决策与规划:基于历史趋势预测容量需求,评估优化效果。

简单来说:指标数据就是将复杂的系统运行情况和业务活动,转化为可存储、可计算、可比较、可告警的数字信号,是我们观察、理解和优化系统的“数据基石”。

关键要素预览:

  1. 指标名称 (Metric Name):告诉你测量的是什么(例如:cpu_usage,http_requests_total)。​
  2. 指标值 (Value):具体的测量数值。​
  3. 时间戳 (Timestamp):测量发生的时间点。​
  4. 维度/标签 (Dimensions/Labels/Tags):(这是理解复杂系统的关键!)一组键值对,用于细分和丰富指标的含义。例如,一个总的“登录次数”指标,可以通过标签细分为“管理员登录成功次数”、“普通用户登录失败次数”等。标签让一个指标能描述无数种具体场景。

本例中,我们让指标数据 LOGIN_COUNT,用来描述“用户登录”的业务行为。定义内容如下:

LOGIN_COUNT = Counter(
 'user_login_total', # 指标名称 (Metric Name)
 '用户登录总次数及状态统计', # 指标描述 (Help Text)
 ['user_type', 'login_status', 'ip_region'] # 标签/维度 (Labels/Dimensions)
 )

这里我们对定义的指标进行简单讲解:

1. 指标名称 (user_login_total):

这是指标的唯一标识符,代表了被测量的是什么。表明这个指标记录的是“用户登录事件”发生的总次数。它是一个 Counter(计数器)。这意味着:

  • 它的值只能单调增加(或者重置为0后重新增加)。每次发生一次登录事件,这个值就会+1。​
  • 你通常不会直接关注它的绝对值(比如当前值是 12543),而是关注它在一段时间内的变化速率(如:rate(user_login_total[5m])表示过去5分钟内每秒的平均登录次数)或一段时间内的增量(如:increase(user_login_total[1h])表示过去1小时内的总登录次数)。

2. 指标描述 (用户登录总次数及状态统计):

为指标提供人类可读的解释,说明这个指标具体测量什么内容。这段描述明确指出,这个计数器统计的是用户登录行为发生的总次数,并且会按不同状态进行统计。

3. 标签/维度 (['user_type', 'login_status', 'ip_region']):

标签/维度为指标提供了上下文和细分维度。它们允许你将一个总的登录次数指标,切割成无数个更细粒度的、具有特定含义的时间序列。

  • user_type: 标识登录用户的类型。可能的取值示例:"admin","guest"。这个标签让你能区分不同类别用户的登录行为(例如,管理员登录次数 vs 普通用户登录次数)。​
  • login_status: 标识登录尝试的结果状态。可能的取值示例:"success","failure"。这是你例子中特别强调的规则用到的标签。这个标签让你能清晰地看到成功登录、失败登录等不同状态的发生次数(例如,监控登录失败率)。​
  • ip_region: 标识登录请求来源的地理区域。

安装 Prometheus Client

在理解了 Prometheus 的数据采集模式(拉取 Pull)和采集的数据内容(指标数据)之后,我们需要在应用或者系统中安装 prometheus-client 用以数据的生成或者采集。

通过如下命令安装prometheus-client:

pip install prometheus-client

创建 Prometheus Client 应用

完成安装之后,需要利用prometheus-client 提供的 SDK 生成数据,用来模拟我们要采集的指标数据。在实际操作中可以在用户目录(选择你觉得合适的目录)下创建一个 Docker 目录,并在 Docker 目录下创建 promethues 目录,接着创建custom_exporter.py 文件。

大致的目录结构如下图所示,后面我们会在promethues 目录下面放入实践需要的脚本、服务、日志文件等信息。

智能运维新实践:Prometheus 与 DeepSeek 联动实现告警自动分析-AI.x社区

创建的 custom_exporter.py 文件内容如下:

from prometheus_client import start_http_server, Counter
 import random
 import time

 # 定义一个计数器类型的指标(累计值,适合记录次数)
 # 标签说明:
 # - user_type: 用户类型(普通用户/管理员)
 # - login_status: 登录状态(成功/失败)
 # - ip_region: IP所属地区(模拟分布式用户场景)
 LOGIN_COUNT = Counter(
 'user_login_total', # 指标名(遵循Prometheus命名规范:小写+下划线)
 '用户登录总次数及状态统计', # 指标描述
 ['user_type', 'login_status', 'ip_region'] # 标签(用于多维度筛选)
 )

 def simulate_login():
 """模拟用户登录行为(每3秒产生一次登录事件)"""
 # 模拟用户类型(70%普通用户,30%管理员)
 user_type = random.choices(['normal', 'admin'], weights=[0.7, 0.3])[0]
 
 # 模拟登录状态(90%成功,10%失败)
 login_status = random.choices(['success', 'failed'], weights=[0.9, 0.1])[0]
 
 # 模拟IP地区(国内主要城市)
 ip_region = random.choice(['beijing', 'shanghai', 'guangzhou', 'shenzhen', 'hangzhou'])
 
 # 记录一次登录事件(计数器+1)
 LOGIN_COUNT.labels(
 user_type=user_type,
 login_status=login_status,
 ip_reginotallow=ip_region
 ).inc() # 每次调用+1

 if __name__ == '__main__':
 # 启动HTTP服务,暴露指标在9091端口
 start_http_server(9091)
 print("用户登录监控Exporter运行在 http://localhost:9091/metrics")
 
 # 持续模拟登录事件
 while True:
 simulate_login()
 time.sleep(3) # 每3秒模拟一次登录

这里我们对上面代码进行简单解读,有这个代码在后面会因为测试进行修改,所以还会出现,届时再对修改部分进行进一步解释。

这段 Python 代码创建了一个模拟用户登录行为的监控数据采集器,它会持续生成登录事件数据并通过 Prometheus 格式暴露出来。以下是关键组件解析:

1. 核心功能:模拟用户登录行为

def simulate_login():
 # 随机生成用户类型(70%普通用户,30%管理员)
 user_type = random.choices(['normal', 'admin'], weights=[0.7, 0.3])[0]
 
 # 随机生成登录结果(90%成功,10%失败)
 login_status = random.choices(['success', 'failed'], weights=[0.9, 0.1])[0]
 
 # 随机选择IP地区(国内主要城市)
 ip_region = random.choice(['beijing', 'shanghai', 'guangzhou', 'shenzhen', 'hangzhou'])
 
 # 记录登录事件
 LOGIN_COUNT.labels(
 user_type=user_type,
 login_status=login_status,
 ip_reginotallow=ip_region
 ).inc() # 计数器+1
  • 每3秒模拟一次用户登录事件(通过time.sleep(3)控制)​
  • 使用随机数生成器创建真实场景中的用户行为分布​
  • 模拟了业务系统中的关键维度:用户身份、操作结果、地理位置

2. 指标定义:多维度登录计数器

LOGIN_COUNT = Counter(
 'user_login_total', # 指标名称
 '用户登录总次数及状态统计', # 指标描述
 ['user_type', 'login_status', 'ip_region'] # 三维度标签
 )
  • 类型Counter(计数器),只增不减​
  • 名称user_login_total(符合Prometheus命名规范)​
  • 三维度标签

A.user_type:区分用户身份(普通用户/管理员)

B.login_status:记录登录结果(成功/失败)

C.ip_region:标记用户地理位置

3. 数据暴露:Prometheus 采集接口

if __name__ == '__main__':
 start_http_server(9091) # 启动指标暴露服务
 print("服务运行在 http://localhost:9091/metrics")
 
 while True:
 simulate_login()
 time.sleep(3)
  • 启动 HTTP 服务(端口 9091)​
  • 通过/metrics端点提供标准 Prometheus 格式数据​
  • 持续运行,每3秒产生一个新数据点

完成代码编写之后,执行custom_exporter.py 文件如下:

python ~/docker/prometheus/custom_exporter.py

看到如下结果:

Exporter运行在 http://localhost:9091/metrics

说明 customer exporter 开始运行,访问对应的地址得到如下结果:

# HELP python_gc_objects_collected_total Objects collected during gc
 # TYPE python_gc_objects_collected_total counter
 python_gc_objects_collected_total{generatinotallow="0"} 255.0
 python_gc_objects_collected_total{generatinotallow="1"} 118.0
 python_gc_objects_collected_total{generatinotallow="2"} 0.0
 # HELP python_gc_objects_uncollectable_total Uncollectable object found during GC
 # TYPE python_gc_objects_uncollectable_total counter
 python_gc_objects_uncollectable_total{generatinotallow="0"} 0.0
 python_gc_objects_uncollectable_total{generatinotallow="1"} 0.0
 python_gc_objects_uncollectable_total{generatinotallow="2"} 0.0
 # HELP python_gc_collections_total Number of times this generation was collected
 # TYPE python_gc_collections_total counter
 python_gc_collections_total{generatinotallow="0"} 40.0
 python_gc_collections_total{generatinotallow="1"} 3.0
 python_gc_collections_total{generatinotallow="2"} 0.0
 # HELP python_info Python platform information
 # TYPE python_info gauge
 python_info{implementatinotallow="CPython",major="3",minor="9",patchlevel="18",versinotallow="3.9.18"} 1.0
 # HELP my_custom_metric 自定义测试指标
 # TYPE my_custom_metric gauge
 my_custom_metric{label1="test",label2="normal"} 1.3487897665970805

配置 Exproter

虽然此时采集数据的服务已经启动,但是还需要在prometheus server 端对采集数据的服务进行定义,才能够拉取对应的指标数据,于是在prometheus目录下面创建 prometheus.yml 文件,如下:

global:
 scrape_interval: 5s # 每15秒拉取一次数据

 scrape_configs:
 # 监控Prometheus自身
 - job_name: 'prometheus'
 static_configs:
 - targets: ['localhost:9090']

 # 监控本地的自定义Exporter(关键配置)
 - job_name: 'custom_exporter'
 static_configs:
 # 这里的IP不是localhost,而是你本地机器的实际IP(容器内访问宿主机的地址)
 # 如何获取:在本地终端执行 `ifconfig` 或 `ip addr` 查看(例如192.168.x.x)
 - targets: ['192.168.0.8:9091'] # 你的本地IP + Exporter端口

需要注意的是这里设置的 targets 标签定义的就是 prometheus-client 的 ip 地址和端口,也就是刚才我们编写的custom_exporter.py 所运行的ip 地址和端口。

接着,让我们重启prometheus 服务器,命令如下:

docker stop prometheus
 docker rm prometheus

然后执行如下命令:

docker run --name prometheus -d -p 127.0.0.1:9090:9090 -v /Users/cuihao/docker/prometheus:/etc/prometheus prom/prometheus --config.file=/etc/prometheus/prometheus.yml

该命令需要注意的是,通过参数 -v /Users/cuihao/docker/prometheus:/etc/prometheus 的配置,将主机目录作为配置文件存储,当修改主机上的 prometheus.yml 会直接影响容器内的配置。

查看指标结果

完成上述操作之后,通过访问http://localhost:9090/query返回到 prometheus server 的 web 界面。

在查询输入框中输入如下命令:

user_login_total

此时会得到对应的指标数据:

智能运维新实践:Prometheus 与 DeepSeek 联动实现告警自动分析-AI.x社区

可以看到从 192.168.0.8:9091 发送的指标数据,包含了用户的登录信息。

我们在输入框中输入的 user_login_total 实际上是,查询语言是 PromQL(Prometheus Query Language),它是用来对 Prometheus 采集到的指标数据进行查询的语言。下面通过它的几个组成部分的表格给大家展开描述:

概念

说明

示例

指标名

要查询的基础指标

user_login_total

标签过滤

{}

筛选特定维度

{user_type="admin"}

时间范围

[时间]

指定范围

[5m]

最近5分钟

函数

数据处理和计算

rate()

, sum()

运算符

数学和逻辑运算

>

, +

, /

聚合

按维度分组统计

by (ip_region)

因此,我们可以通过编写 ProQL 按照条件查询指标数据,后面在设置告警规则的时候会用到。

到这里,我们已经能够通过 promeheus-client 采集到数据,并且通过 prometheus-server 端的 ProQL 查询数据结果了。

定义 Prometheus 告警规则

接着,我们就需要针对采集的数据进行报警,这里需要先设置报警规则,当触发报警规则时通知 alertmanager 进行后续处理。

1. 创建告警规则文件

在你的本地 Prometheus 配置目录(/Users/cuihao/docker/prometheus)中,新建一个告警规则文件 alert_rules.yml,内容如下(以 “用户登录异常” 为例):

groups:
 - name: login_anomaly_rules # 规则组名称
 rules:
 # 规则1:5分钟内登录失败率超过20%(可能是攻击或系统故障)
 - alert: HighLoginFailureRate
 expr: |
 sum(rate(user_login_total{login_status="failed"}[5m])) 
 / 
 sum(rate(user_login_total[5m])) 
 > 0.2 # 失败率>20%
 for: 1m # 持续1分钟触发告警
 labels:
 severity: critical # 告警级别(紧急)
 annotations:
 summary: "登录失败率过高"
 description: "过去5分钟登录失败率{{ $value | humanizePercentage }},可能存在异常登录行为"

 # 规则2:管理员账号1分钟内登录失败次数>5次(可能被暴力破解)
 - alert: AdminLoginFailureSpike
 expr: |
 sum(rate(user_login_total{user_type="admin", login_status="failed"}[1m])) 
 > 5 # 1分钟内失败>5次
 for: 30s # 持续30秒触发
 labels:
 severity: warning
 annotations:
 summary: "管理员登录失败次数突增"
 description: "管理员账号1分钟内登录失败{{ $value }}次,可能存在暴力破解风险"

2. 让 Prometheus 加载告警规则

修改你的 prometheus.yml 配置文件,添加告警规则文件的路径(确保和已有配置合并):

global:
 scrape_interval: 15s

 rule_files:
 - "alert_rules.yml" # 加载刚才创建的告警规则文件

 scrape_configs:
 - job_name: 'custom_exporter'
 static_configs:
 - targets: ['192.168.0.16:9091'] # 你的Exporter地址

这个告警规则文件定义了一个名为login_anomaly_rules的规则组,包含两个针对用户登录异常行为的监控规则:第一个规则HighLoginFailureRate会检测系统整体登录失败率,当5分钟内平均失败率超过20%并持续1分钟时触发严重级别(critical)告警,提示可能存在系统故障或恶意攻击;第二个规则AdminLoginFailureSpike专门监控管理员账号的安全状态,当检测到1分钟内管理员登录失败次数超过5次且持续30秒时触发警告级别(warning)告警,提示可能存在暴力破解尝试。两个规则都通过PromQL表达式实时计算指标数据,并在触发时提供包含具体数值的描述信息。

3. 重启 Prometheus 使配置生效

docker restart prometheus

访问 Prometheus UI 的 “Alerts” 页面(​http://localhost:9090/alerts​),可以看到定义的规则,当异常发生时,规则会从 “Inactive” 变为 “Pending” 再到 “Firing”(触发状态)。

智能运维新实践:Prometheus 与 DeepSeek 联动实现告警自动分析-AI.x社区

部署 Alertmanager 转发告警

到此, Prometheus 的告警规则已经配置完毕,并且可以通过 Web UI 查看到规则。由于 Prometheus 本身不处理告警转发,需要用Alertmanager接收 Prometheus 的告警,然后转发到你的处理服务(后续调用 DeepSeek)。因此,接下来我们需要部署和配置 Alertmanager,并且编写 处理服务 。

1. 安装启动 Alertmanager 容器

执行如下指令,在prometheus 目录下面创建alertmanager 目录,该目录下会存放报警处理的文件。并且通过 docker run 命令启动alertmanager 的容器服务。

# 先创建Alertmanager配置目录
 mkdir -p /Users/cuihao/docker/prometheus/alertmanager

 # 启动容器(映射9093端口,挂载配置目录)
 docker run --name alertmanager -d -p 127.0.0.1:9093:9093 -v /Users/cuihao/docker/prometheus/alertmanager:/etc/alertmanager prom/alertmanager

2. 配置 Alertmanager

在 alertmanager 目录下创建配置文件 alertmanager.yml,通过对该文件的配置,转发告警到处理服务。

route:
 group_by: ['alertname'] # 按告警名称分组
 group_wait: 10s # 组内等待10秒再发送
 group_interval: 10s # 组内间隔10秒发送
 repeat_interval: 1h # 重复告警间隔1小时
 receiver: 'webhook_handler' # 转发到名为webhook_handler的接收者

 receivers:
 - name: 'webhook_handler'
 webhook_configs:
 - url: 'http://192.168.0.8:5008/alert' # 你的处理服务地址(本地5000端口)
 send_resolved: true # 告警解决后也发送通知

请注意这里我们定义的服务地址是 http://192.168.0.8:5008/alert​​, 也就是后续需要创建的处理服务需要工作的地址。也就是需要从 docker 容器alertmanager 去访问本机的 ​http://192.168.0.8:5008/alert 服务。

3. 重启 Alertmanager 生效

更新完配置文件需要重启alertmanager 的容器实例。

docker restart alertmanager

4. 将 Prometheus 和 Alertmanager 加入同一网络

alertmanager 配置完毕之后,还有一个重要步骤,就是要保证 Prometheus 服务和Alertmanager 服务在同一个网络中。由于我们的实验一直使用的 docker 容器进行部署,所以需要通过如下操作进行 docker 的网络设置。

(1)停止运行中的容器

docker stop prometheus alertmanager
(2)创建一个共享网络(若不存在)

docker network create prometheus-network

(网络名称可自定义,如monitoring-network,保持统一即可)。

(3)将两个容器加入同一网络

# 将Prometheus加入网络
 docker network connect prometheus-network prometheus

 # 将Alertmanager加入网络
 docker network connect prometheus-network alertmanager
(4)重启容器,使网络配置生效

docker start prometheus alertmanager
(5)验证网络是否生效

进入 Prometheus 容器,测试能否解析alertmanager容器名:

# 进入Prometheus容器
 docker exec -it prometheus /bin/sh

 # 测试DNS解析(若容器内有nslookup)
 nslookup alertmanager

 # 若没有nslookup,用ping测试(能ping通说明解析正常)
 ping alertmanager

5. 让 Prometheus 连接 Alertmanager

完成网络设置之后,我们再回头到Prometheus 配置告警通知,修改 prometheus.yml,添加 Alertmanager 地址如下:

alerting:
 alertmanagers:
 - static_configs:
 - targets:
 - 'alertmanager:9093'

这里的alertmanager:9093 就是Alertmanager 服务所在的地址和端口号。

最后,重启 Prometheus:

docker restart prometheus

编写 DeepSeek 分析代码

到这里,我们完成了文章开头所说的前三步操作,如下图所示。我们将整体思路做一个回顾,已经完成生成中指标数据,采集数据,处理报警的工作,最后需要“生成智能报告”。

智能运维新实践:Prometheus 与 DeepSeek 联动实现告警自动分析-AI.x社区

编写alert_handler.py代码如下:

from flask import Flask, request, jsonify
 import os
 import sys
 import datetime
 import json
 from openai import OpenAI
 from dotenv import load_dotenv # 用于加载环境变量

 # 初始化Flask应用
 app = Flask(__name__)

 # 加载环境变量(从.env文件读取DEEPSEEK_API_KEY)
 try:
 # 尝试加载环境变量,并添加日志
 load_result = load_dotenv() # 默认读取当前目录的.env文件
 script_dir = os.path.dirname(os.path.abspath(__file__))
 env_path = os.path.join(script_dir, ".env")
 
 # 配置日志和报告路径(使用脚本所在目录)
 error_log = os.path.join(script_dir, "error.log") # 错误日志路径
 report_dir = os.path.join(script_dir, "alert_reports") # 分析报告保存目录
 
 # 记录环境变量加载情况
 with open(error_log, "a", encoding="utf-8") as f:
 if load_result:
 f.write(f"[{datetime.datetime.now()}] 成功加载环境变量文件: {env_path}\n")
 else:
 f.write(f"[{datetime.datetime.now()}] 未找到环境变量文件,使用系统环境变量: {env_path}\n")
 
 # 确保报告目录存在
 os.makedirs(report_dir, exist_ok=True)
 with open(error_log, "a", encoding="utf-8") as f:
 f.write(f"[{datetime.datetime.now()}] 报告目录准备就绪: {report_dir}\n")
 except Exception as e:
 # 记录初始化错误
 error_msg = f"初始化文件系统时出错: {str(e)}"
 print(f"[{datetime.datetime.now()}] {error_msg}") # 控制台也输出,方便调试
 # 尝试写入错误日志
 try:
 with open("error.log", "a", encoding="utf-8") as f:
 f.write(f"[{datetime.datetime.now()}] {error_msg}\n")
 except:
 pass
 raise # 抛出错误,终止启动

 def init_deepseek_client():
 """初始化DeepSeek客户端(兼容OpenAI SDK)"""
 try:
 # 验证环境变量
 api_key = os.environ.get("DEEPSEEK_API_KEY")
 with open(error_log, "a", encoding="utf-8") as f:
 if api_key:
 f.write(f"[{datetime.datetime.now()}] 成功获取DEEPSEEK_API_KEY (部分隐藏): {api_key[:4]}****\n")
 else:
 f.write(f"[{datetime.datetime.now()}] 未在环境变量中找到DEEPSEEK_API_KEY\n")
 
 if not api_key:
 raise ValueError("未在环境变量中找到DEEPSEEK_API_KEY,请检查.env文件")
 
 # 初始化客户端(DeepSeek兼容OpenAI SDK格式)
 client = OpenAI(
 api_key=api_key,
 base_url="https://api.deepseek.com/v1" # DeepSeek API基础地址
 )
 
 # 验证客户端连接
 try:
 # 发送一个简单的测试请求验证连接
 response = client.chat.completions.create(
 model="deepseek-chat",
 messages=[{"role": "user", "content": "test"}],
 max_tokens=1
 )
 with open(error_log, "a", encoding="utf-8") as f:
 f.write(f"[{datetime.datetime.now()}] DeepSeek客户端初始化成功,API连接正常\n")
 except Exception as e:
 with open(error_log, "a", encoding="utf-8") as f:
 f.write(f"[{datetime.datetime.now()}] DeepSeek API连接测试失败: {str(e)}\n")
 raise
 
 return client
 except Exception as e:
 # 记录初始化错误
 error_msg = f"DeepSeek客户端初始化失败:{str(e)}"
 with open(error_log, "a", encoding="utf-8") as f:
 f.write(f"[{datetime.datetime.now()}] {error_msg}\n")
 raise # 抛出错误,避免服务启动后无法调用API

 # 初始化DeepSeek客户端(服务启动时执行)
 try:
 with open(error_log, "a", encoding="utf-8") as f:
 f.write(f"[{datetime.datetime.now()}] 开始初始化DeepSeek客户端...\n")
 client = init_deepseek_client()
 except Exception as e:
 with open(error_log, "a", encoding="utf-8") as f:
 f.write(f"[{datetime.datetime.now()}] 初始化DeepSeek客户端失败,服务无法启动:{str(e)}\n")
 raise


 def call_deepseek_analysis(alert_info):
 """调用DeepSeek分析告警信息,返回分析结果和报告路径"""
 try:
 with open(error_log, "a", encoding="utf-8") as f:
 f.write(f"[{datetime.datetime.now()}] 开始处理告警分析...\n")
 
 # 1. 验证并提取告警关键信息
 if not isinstance(alert_info, dict):
 raise ValueError(f"告警信息格式错误,预期字典类型,实际为: {type(alert_info)}")
 
 # 验证必要字段
 required_fields = ["labels", "annotations"]
 for field in required_fields:
 if field not in alert_info:
 raise ValueError(f"告警信息缺少必要字段: {field}")
 
 alert_name = alert_info["labels"].get("alertname", "未知告警")
 severity = alert_info["labels"].get("severity", "未知级别")
 description = alert_info["annotations"].get("description", "无描述")
 start_time = alert_info.get("startsAt", datetime.datetime.now().isoformat())
 labels = alert_info["labels"]
 
 with open(error_log, "a", encoding="utf-8") as f:
 f.write(f"[{datetime.datetime.now()}] 提取到告警信息 - 名称: {alert_name}, 级别: {severity}\n")

 # 2. 构造提示词(系统角色+用户输入)
 system_prompt = """

你是一名资深运维与安全分析师,擅长分析业务系统异常告警。
请根据提供的登录监控告警信息,生成结构化分析报告,包含:
1. 告警基本信息(名称、级别、时间、关键标签)
2. 可能的原因分析(结合业务场景,如攻击、系统故障、用户行为异常等)
3. 具体处理建议(分步骤说明,可操作)
4. 预防措施(如何避免类似问题再次发生)
报告风格需专业、简洁,重点突出。

""" user_prompt = f"""

告警详细信息如下:

- 告警名称:{alert_name}
 - 严重级别:{severity}
 - 告警描述:{description}
 - 发生时间:{start_time}
 - 关联标签:{json.dumps(labels, ensure_ascii=False)} # 包含用户类型、地区等维度
 
 请基于以上信息分析并生成报告。
 """

 # 3. 调用DeepSeek模型
 with open(error_log, "a", encoding="utf-8") as f:
 f.write(f"[{datetime.datetime.now()}] 开始调用DeepSeek API进行分析...\n")
 
 response = client.chat.completions.create(
 model="deepseek-chat", # 使用的模型名称
 messages=[
 {"role": "system", "content": system_prompt},
 {"role": "user", "content": user_prompt}
 ],
 stream=False,
 max_tokens=1000 # 限制最大返回长度
 )

 # 4. 提取分析结果
 if not response.choices or len(response.choices) == 0:
 raise ValueError("DeepSeek API返回结果为空")
 
 analysis_content = response.choices[0].message.content
 
 with open(error_log, "a", encoding="utf-8") as f:
 f.write(f"[{datetime.datetime.now()}] 成功获取DeepSeek分析结果,长度: {len(analysis_content)}\n")

 # 5. 生成分析报告文件
 timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
 report_filename = f"analysis_{alert_name}_{timestamp}.txt".replace(" ", "_")
 report_path = os.path.join(report_dir, report_filename)
 
 with open(report_path, "w", encoding="utf-8") as f:
 f.write(f"=== 告警分析报告 ===\n")
 f.write(f"生成时间:{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
 f.write(f"告警名称:{alert_name}\n")
 f.write(f"严重级别:{severity}\n")
 f.write(f"发生时间:{start_time}\n\n")
 f.write("=== 分析内容 ===\n")
 f.write(analysis_content)
 
 with open(error_log, "a", encoding="utf-8") as f:
 f.write(f"[{datetime.datetime.now()}] 分析报告已保存至: {report_path}\n")

 return analysis_content, report_path

 except Exception as e:
 # 记录调用错误
 error_msg = f"DeepSeek分析调用失败:{str(e)}"
 with open(error_log, "a", encoding="utf-8") as f:
 f.write(f"[{datetime.datetime.now()}] {error_msg}\n")
 return f"分析失败:{str(e)}", None


 @app.route('/alert', methods=['POST'])
 def handle_alert():
 """接收Alertmanager的Webhook告警,调用分析并返回结果"""
 try:
 with open(error_log, "a", encoding="utf-8") as f:
 f.write(f"[{datetime.datetime.now()}] 收到新的告警请求\n")
 
 # 1. 解析Alertmanager发送的JSON数据
 try:
 alert_data = request.json
 except Exception as e:
 raise ValueError(f"解析JSON数据失败: {str(e)}")
 
 if not alert_data:
 return jsonify({"status": "failed", "reason": "未收到有效数据"}), 400
 
 with open(error_log, "a", encoding="utf-8") as f:
 f.write(f"[{datetime.datetime.now()}] 成功解析告警数据,包含字段: {', '.join(alert_data.keys())}\n")

 # 2. 提取第一个触发的告警
 if not alert_data.get("alerts"):
 return jsonify({"status": "failed", "reason": "告警数据中无alerts字段"}), 400
 
 if not isinstance(alert_data["alerts"], list) or len(alert_data["alerts"]) == 0:
 return jsonify({"status": "failed", "reason": "alerts字段不是有效的列表或为空"}), 400
 
 first_alert = alert_data["alerts"][0]
 alert_name = first_alert['labels'].get('alertname', '未知告警')
 print(f"[{datetime.datetime.now()}] 收到告警:{alert_name}") # 控制台输出
 with open(error_log, "a", encoding="utf-8") as f:
 f.write(f"[{datetime.datetime.now()}] 处理第一个告警: {alert_name}\n")

 # 3. 调用DeepSeek分析
 analysis_content, report_path = call_deepseek_analysis(first_alert)

 # 4. 返回结果
 return jsonify({
 "status": "success",
 "analysis": analysis_content,
 "report_path": report_path
 })

 except Exception as e:
 # 记录请求处理错误
 error_msg = f"告警处理失败:{str(e)}"
 with open(error_log, "a", encoding="utf-8") as f:
 f.write(f"[{datetime.datetime.now()}] {error_msg}\n")
 return jsonify({"status": "failed", "reason": str(e)}), 500

 # 添加一个健康检查接口,方便测试服务是否正常运行
 @app.route('/health', methods=['GET'])
 def health_check():
 try:
 return jsonify({
 "status": "healthy",
 "timestamp": datetime.datetime.now().isoformat(),
 "services": {
 "deepseek": "initialized" if 'client' in globals() else "not initialized",
 "report_dir": report_dir,
 "report_dir_writable": os.access(report_dir, os.W_OK)
 }
 })
 except Exception as e:
 return jsonify({
 "status": "unhealthy",
 "reason": str(e)
 }), 500


 if __name__ == '__main__':
 try:
 with open(error_log, "a", encoding="utf-8") as f:
 f.write(f"[{datetime.datetime.now()}] 开始启动alert_handler服务...\n")
 f.write(f"[{datetime.datetime.now()}] 服务将监听端口: 5008\n")
 
 # 启动服务(监听所有IP的5008端口)
 app.run(host='0.0.0.0', port=5008, debug=True)
 except Exception as e:
 error_msg = f"服务启动失败:{str(e)}"
 print(f"[{datetime.datetime.now()}] {error_msg}")
 with open(error_log, "a", encoding="utf-8") as f:
 f.write(f"[{datetime.datetime.now()}] {error_msg}\n")
 sys.exit(1)

上面这段 Python 代码构建了一个智能告警分析服务,它通过 Flask 框架接收 Prometheus Alertmanager 发送的告警通知,利用 DeepSeek 大模型进行智能分析并生成专业报告。服务启动时会从 .env 文件加载 API 密钥并初始化 DeepSeek 客户端,在接收到告警后自动提取关键信息(如告警名称、严重级别和描述),构造专业提示词调用 AI 接口进行深度分析,最终生成包含原因诊断、处理建议和预防措施的结构化报告保存到本地目录。整个流程配备完善的错误处理和日志记录,通过 /health 端点提供实时服务状态监控,将传统告警升级为智能诊断系统,帮助运维人员快速定位复杂问题根源。

由于 alertmanager 发送报警信息需要基于 Prometheus 官方报警格式,所以我们需要对写好的代码进行测试,如下命令执行代码:

python alert_handler.py

通过命令行测试服务。

curl -X POST "http://localhost:5008/alert" \
 -H "Content-Type: application/json" \
 -d '{
 "version": "4",
 "groupKey": "{}:{alertname=\"HighLoginFailureRate\"}",
 "status": "firing",
 "receiver": "webhook_handler",
 "groupLabels": {
 "alertname": "HighLoginFailureRate"
 },
 "commonLabels": {
 "alertname": "HighLoginFailureRate",
 "severity": "critical"
 },
 "commonAnnotations": {
 "description": "登录失败率过高,当前失败率为30%,超过阈值20%",
 "summary": "登录失败率异常升高"
 },
 "externalURL": "http://localhost:9093",
 "alerts": [
 {
 "status": "firing",
 "labels": {
 "alertname": "HighLoginFailureRate",
 "severity": "critical"
 },
 "annotations": {
 "description": "登录失败率过高,当前失败率为30%,超过阈值20%",
 "summary": "登录失败率异常升高"
 },
 "startsAt": "2025-08-14T08:30:00.000Z",
 "endsAt": "0001-01-01T00:00:00Z",
 "generatorURL": "http://localhost:9090/graph?g0.expr=sum(rate(user_login_total%7Blogin_status%3D%22failed%22%7D%5B5m%5D))+%2F+sum(rate(user_login_total%5B5m%5D))+%3E+0.2&g0.tab=1"
 }
 ]
 }'

测试功能

按以下步骤逐步验证,每一步确认无误后再进行下一步:

终端窗口

命令(操作)

作用

窗口 1

启动 Exporter(带控制接口)cd /存放/custom_exporter.py的目录python custom_exporter.py

生成模拟登录数据,

暴露 9091 端口指标,

9092 端口控制接口

窗口 2

启动处理服务(alert_handler)cd /存放/alert_handler.py的目录python alert_handler.py

监听 5000 端口,

接收告警并调用 DeepSeek

窗口 3

启动 Prometheus 容器docker start prometheus

采集数据、检测异常

窗口 4

启动 Alertmanager 容器docker start alertmanager

转发告警到处理服务

安装上述操作之后,观察如下图的 alert_reports 目录,这个目录下面保存了生成分析报告信息。如下图所示:

智能运维新实践:Prometheus 与 DeepSeek 联动实现告警自动分析-AI.x社区

作者介绍

崔皓,51CTO社区编辑,资深架构师,拥有18年的软件开发和架构经验,10年分布式架构经验。

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
已于2025-8-29 08:59:02修改
收藏
回复
举报
回复
相关推荐