prometheus中使用python手写webhook完成告警

本文介绍了如何使用Python编写webhook接口,配合Prometheus Alertmanager完成告警通知。通过webhook,告警信息会被转换并以邮件形式发送给指定人员。文章详细阐述了配置alertmanager、编写接口、处理告警信息、时区转换以及发送邮件的步骤,并给出了完整代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

prometheus 的几种告警方式

prometheus 我们都知道它是最近几年特别火的一个开源的监控工具,原生支持 kubernetes,如果你使用的是 kubernetes 集群,那么使用 prometheus 将会是非常方便的,而且 prometheus 也提供了报警工具alertmanager,实际上在 prometheus 的架构中,告警能力是单独的一部分,主要是通过自定义一堆的rule即告警规则,来周期性的对告警规则进行计算,并且会根据设置的报警触发条件,如果满足,就会进行告警,也就是会向alertmanager发送告警信息,进而由alertmanager进行告警。
那么,alertmanager告警又是通过何种途径呢?其实有很多种方式,例如:

  • 邮件告警
  • 企业微信告警
  • 钉钉告警
  • slack 告警
  • webhook 接口方式告警

其实还有一些,但这些都不重要,这些只是工具,重要的是如何运用,下面就介绍下使用 webhook 的方式来让 alertmanager 调用接口,发送POST请求完成告警消息的推送,而这个推送可以是邮件,也可以是微信,钉钉等。

调用接口以邮件形式告警

大体流程是这样的,首先在我们定义好一堆告警规则之后,如果触发条件,alertmanager 会将报警信息推送给接口,然后我们的这个接口会做一些类似与聚合、汇总、优化的一些操作,然后将处理过的报警信息再以邮件的形式发送给指定的人或者组。也就是下面这个图:

我们这里的重点主要是如何写这个 webhook,以及写 webhook 的时候需要注意什么?下面将一一讲解

假设你有一个 prometheus 监控系统,并且告警规则都已配置完成

配置 alertmanager

首先得先配置 alertmanager,让其可以调用接口,配置方式很简单,只需要指定一下接口地址即可,如下:

receivers:
- webhook_configs:
  url: http://10.127.34.107:5000/webhook
  send_resolved: true

这就完了!当然可以指定多种告警方式
这样配置完成后,alertmanger 就会把告警信息以 POST 请求方式调用接口

编写一个最简单的接口

既然是用 python 来编写一个接口,那么肯定是用 flask 的,代码也非常简单,如下:

import json
from flask import Flask, request
from gevent.pywsgi import WSGIServer

app = Flask(__name__)

@app.route('/webhook', methods=['POST'])
def webhook():
    prometheus_data = json.loads(request.data)
    print(prometheus_data)
    return "test"

if __name__ == '__main__':
    WSGIServer(('0.0.0.0', 5000), app).serve_forever()

上面导入的一些模块,记得要去下载哦

pip install flask
pip install gevent

这样的话,我们直接运行此段代码,此时机器上会监听 5000 端口,如果此时 prometheus 有告警,那么我们就会看到 prometheus 传过来的数据格式是什么样的了,这里我贴一个示例:

{
   
   
	'receiver': 'webhook',
	'status': 'firing',
	'alerts': [{
   
   
		'status': 'firing',
		'labels': {
   
   
			'alertname': '内存使用率',
			'instance': '10.127.92.100',
			'job': 'sentry',
			'severity': 'warning',
			'team': 'ops'
		},
		'annotations': {
   
   
			'description': '内存使用率已超过55%,内存使用率:58%',
			'summary': '内存使用率'
		},
		'startsAt': '2020-12-30T07:20:08.775177336Z',
		'endsAt': '0001-01-01T00:00:00Z',
		'generatorURL': 'http://prometheus-server:9090/graph?g0.expr=round%28%281+-+%28node_memory_MemAvailable_bytes%7Bjob%3D%22sentry%22%7D+%2F+%28node_memory_MemTotal_bytes%7Bjob%3D%22sentry%22%7D%29%29%29+%2A+100%29+%3E+55&g0.tab=1',
		'fingerprint': '09f94bd1aa7da54f'
	}, {
   
   
		'status': 'firing',
		'labels': {
   
   
			'alertname': '内存使用率',
			'instance': '10.127.92.101',
			'job': 'sentry',
			'severity': 'warning',
			'team': 'ops'
		},
		'annotations': {
   
   
			'description': '内存使用率已超过55%,内存使用率:58%',
			'summary': '内存使用率'
		},
		'startsAt': '2020-12-30T07:20:08.775177336Z',
		'endsAt': '0001-01-01T00:00:00Z',
		'generatorURL': 'http://prometheus-server:9090/graph?g0.expr=round%28%281+-+%28node_memory_MemAvailable_bytes%7Bjob%3D%22sentry%22%7D+%2F+%28node_memory_MemTotal_bytes%7Bjob%3D%22sentry%22%7D%29%29%29+%2A+100%29+%3E+55&g0.tab=1',
		'fingerprint': '8a972e4907cf2c60'
	}],
	'groupLabels': {
   
   
		'alertname': '内存使用率'
	},
	'commonLabels': {
   
   
		'alertname': '内存使用率',
		'job': 'sentry',
		'severity': 'warning',
		'team': 'ops'
	},
	'commonAnnotations': {
   
   
		'summary': '内存使用率'
	},
	'externalURL': 'http://alertmanager-server:9093',
	'version': '4',
	'groupKey': '{}:{alertname="内存使用率"}',
	'truncatedAlerts': 0
}

通过 prometheus 传过来的告警信息,可以看到是一个标准的json,我们在使用python在做处理时,需要先将json字符串转换成python的字典,可以用json这个模块来实现,通过这个json我们可以得到以下信息(非常重要):

  • 每次发出的json数据流中的报警信息是同一个类型的报警,比如这里都是关于内存的
  • status:表示告警的状态,两种:firingresolved
  • alerts:是一个列表,里面的元素是由字典组成,每一个元素都是一条具体的告警信息
  • commonLabels:这里面就是一些公共的信息

剩下的几个 key 都比较好理解,就不一一说了,下面结合 prometheus 的一些 rule 来看下这个告警是凭什么这样发的。

# cat system-rule.yaml  #文件名随意设置,因为prometheus的配置里配置的是: *.yaml
groups:
    - name: sentry
      rules:
      - alert: "Memory Usage"
        expr: round((1-(node_memory_MemAvailable_bytes{
   
   job='sentry'} / (node_memory_MemTotal_bytes{
   
   job='sentry'})))* 100) > 85
        for: 5m
        labels:
          team: ops
          severity: warning
          cloud: yizhuang
        annotations:
          summary: "Memory usage is too high and over 85% for 5min"
          description: "The current host {
   
   {$labels.instance}}' memory usage is {
   
   { $value }}%"

这里就是配置的告警规则,告诉 prometheus 应该按照什么方式进行告警,配置完成后,要在 prometheus 的配置里引用下,如下所示:

# cat prometheus.yml
global:
  scrape_interval:     15s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
  evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.
  # scrape_timeout is set to the global default (10s).

# Alertmanager configuration
alerting:
  alertmanagers:
  - static_configs:
    - targets: ['10.10.10.111:9093']

# 就是这里,看这里
rule_files:
  - "/alertmanager/rule/*.yaml"  #文件目录随意设置
...
...
...
此处省略一堆配置

到这里应该就知道告警规则是什么发出来的了吧,然后也应该知道告警内容为什么是这样的了吧,嗯,下面看下最关键的地方

处理原始告警信息并进行邮件告警

原始的告警信息看起来还挺规则的,只需要拼接下就可以了,但是有一个问题就是alerts里面的startsAtendsAt这俩时间格式有些问题,是 UTC 时区的时间,需要转换下。还有一个地方需要注意的,最外层的status如果是firing状态,就不代表alerts中的status就一定都是firing,还有可能是resolved,如下json所示:

{
   
   
	'receiver'
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值