首页
运维部署
苹果MAC系统
Kubernetes(K8S)
nginx 使用geo模块识别ip归属地做跳转
Docker
Docker部署Uptime Kuma
多媒体类
NGINX + OBS = 网页直播服务搭建
CentOS 7部署DNS服务器BIND
监控告警
prometheus(一、基础使用)
Prometheus(二、用snmp监控)
Grafana(1、部署+使用)
Grafana(2、snmp交换机仪表盘自定义)
prometheus_Alertmanager(三、报警配置_邮件)
prometheus_Alertmanager(四、企微 钉钉 告警)
prometheus_blackbox(五、黑盒监测 )
Pushgateway-客户端主动推送告警
snmp_exporter快速监控交换机
多个Prometheus实例互联
exporter自定义监控项
PC
服务器
Dell 服务器R540做raid
服务器电源供电
更换raid阵列卡
企业微信
企业微信api使用
centos7中yum安装dnsmasq内网dns
centos7部署ntopng
Syslog 日志存储
IT-数据恢复
OpenVPN
JumpServer分布式部署
Gitlab
ansible常用命令
将pem证书转换为crt和key
CentOS 7 中搭建ocserv
ocserv相关收藏
ocserv服务器配置实例
ocserv客户端无法将网络共享给其它终端
本文档由 内网文摘 发布,转载请注明出处
-
+
首页
prometheus_Alertmanager(四、企微 钉钉 告警)
**告警的流程:** prometheus-server采集到的各种exporter的指标,然后根据规则去判断是不是达到规则的阈值,如果达到就判断要告警,将告警的内容发送给altermanager, altermanager是用来处理告警的,比如接收prometheus-server发来的告警信息,然后做一些整合,然后发送给消息发送组件,整合具体做了什么呢,就是告警信息的聚合、告警信息的沉默、告警分组等,altermanager将告警消息的发出,可以通过altermanager的smtp发出,也可以通过消息发送组件webhook集成,这些组件一般是自己开发或者借鉴别人开发的。 接下来要介绍一下webhook与钉钉或企业微信机器人结合实现告警消息的推送。 ## 企业微信版webhook组件 altermanager将告警消息,通过webhook协议发送到 企业微信版webhook组件。企业微信版webhook组件 再把告警转发到企微官方api。 这里使用的企业微信版webhook,使用了flask开发的,并定制消息的样式。 发送企业微信版告警消息,是调用的群机器人,所以需要将接受告警消息的人拉到一个群里,然后添加一个告警机器人,就能看到群机器人webhook地址:https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=XXXXXX-YYYYYYYY-666666-88888888, 此地址可以分成两部分, 一部分key=(包含key=)之前的部分,是api接口地址。 一部分是key=之后的部分。相当于机器人身份证号,唯一的。暂时赋予一个名称叫 ROBOT_TOKEN 吧,后面要用到。 示例环境:centos7 ``` #安装python3,centos7系统自带的是python2。 yum install -y python3 #安装需要的python的包 pip3 install requests pip3 install arrow pip3 install flask ``` [CentOS设置环境变量](/project-3/doc-319/ "CentOS设置环境变量") , ``` #在Centos中设置系统变量,app.py中需要使用 export ROBOT_TOKEN=XXXXXX-YYYYYYYY-666666-88888888 # vim /etc/profile 设置系统环境变量,修改文件后,刷新生效命令 source /etc/profile ``` ``` #新建flask框架的app程序 [root@localhost]# mkdir /opt/monitor/webhook && cd /opt/monitor/webhook [root@localhost webhook]# vim app.py 内容如下: ``` [root@localhost webhook]# cat app.py ```python # -*- coding: utf-8 -*- import os import json import requests import arrow from flask import Flask from flask import request app = Flask(__name__) def bytes2json(data_bytes): data = data_bytes.decode('utf8').replace("'", '"') return json.loads(data) def makealertdata(data): for output in data['alerts'][:]: try: pod_name = output['labels']['pod'] except KeyError: try: pod_name = output['labels']['pod_name'] except KeyError: pod_name = 'null' try: namespace = output['labels']['namespace'] except KeyError: namespace = 'null' try: message = output['annotations']['message'] except KeyError: try: message = output['annotations']['description'] except KeyError: message = 'null' if output['status'] == 'firing': status_zh = '报警' title = '【%s】xxxx环境 %s 有新的报警' % (status_zh, output['labels']['alertname']) send_data = { "msgtype": "markdown", "markdown": { "content": "## %s \n\n" %title + ">**告警级别**: %s \n\n" % output['labels']['severity'] + ">**告警类型**: %s \n\n" % output['labels']['alertname'] + ">**告警主机**: %s \n\n" % output['labels']['node_name'] + ">**告警详情**: %s \n\n" % message + ">**告警状态**: %s \n\n" % output['status'] + ">**触发时间**: %s \n\n" % arrow.get(output['startsAt']).to('Asia/Shanghai').format( 'YYYY-MM-DD HH:mm:ss ZZ') } } elif output['status'] == 'resolved': status_zh = '恢复' title = '【%s】xxxx环境 %s 有报警恢复' % (status_zh, output['labels']['alertname']) send_data = { "msgtype": "markdown", "markdown": { "content": "## %s \n\n" %title + ">**告警级别**: %s \n\n" % output['labels']['severity'] + ">**告警类型**: %s \n\n" % output['labels']['alertname'] + ">**告警主机**: %s \n\n" % output['labels']['node_name'] + ">**告警详情**: %s \n\n" % message + ">**告警状态**: %s \n\n" % output['status'] + ">**触发时间**: %s \n\n" % arrow.get(output['startsAt']).to('Asia/Shanghai').format( 'YYYY-MM-DD HH:mm:ss ZZ') + ">**触发结束时间**: %s \n" % arrow.get(output['endsAt']).to('Asia/Shanghai').format( 'YYYY-MM-DD HH:mm:ss ZZ') } } return send_data def send_alert(data): #此处获取环境变量“ROBOT_TOKEN”,会在docker-compose的配置文件中配置,docker-compose启动docker时向docker容器注入环境变量 #print(data) token = os.getenv('ROBOT_TOKEN') if not token: print('you must set ROBOT_TOKEN env') return url = 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=%s' % token send_data = makealertdata(data) print(send_data) req = requests.post(url, json=send_data) print(req) result = req.json() if result['errcode'] != 0: print('notify dingtalk error: %s' % result['errcode']) @app.route('/', methods=['POST', 'GET']) def send(): if request.method == 'POST': post_data = request.get_data() #print(post_data) send_alert(bytes2json(post_data)) return 'success' else: return 'weclome to use prometheus alertmanager dingtalk webhook server!' if __name__ == '__main__': app.run(host='0.0.0.0', port=5000) ``` 启动企业微信版webhook组件 ``` [root@localhost webhook]# python3 app.py ``` [Centos后台运行程序命令nohup](/project-3/doc-43/ "Centos后台运行程序命令nohup") nohup python3 -u app.py > app.log 2>&1 & ### 配置重启altermanager ``` [root@localhost alertmanager]# cat alertmanager.yml global: resolve_timeout: 5m route: group_by: ['instance'] group_wait: 10s group_interval: 10s repeat_interval: 1h receiver: 'ops_notify' routes: - receiver: ops_notify group_wait: 10s match_re: alertname: 'NodeStatsAlert' receivers: - name: 'ops_notify' webhook_configs: - url: 'http://localhost:5000' send_resolved: true inhibit_rules: - source_match: severity: 'critical' target_match: severity: 'warning' equal: ['alertname', 'dev', 'instance'] ``` 上面配置中的 “http://localhost:5000” ,就是新建的flask框架的app程序:企业微信版webhook组件 **重启** systemctl restart alertmanager ### prometheus中配置要监控的设备项 编辑prometheus.ym,增加如下 job_name 作用是告诉prometheus要监控的项目在snmp_device_rj.yml文件中。 vim prometheus.yml ``` - job_name: "SNMP_rj" scrape_interval: 1m scrape_timeout: 30s file_sd_configs: - files: - "snmp_device_rj.yml" refresh_interval: 5s metrics_path: /snmp params: module: - rj # 如果是其他设备,请更换其他模块。 community: - public # 指定 community,当 snmp_exporter snmp.yml 配置文件没有指定 community,此处定义的 community 生效。 relabel_configs: - source_labels: [__address__] target_label: __param_target - source_labels: [__param_target] target_label: instance - target_label: __address__ replacement: "localhost:9116" # SNMP Exporter 的地址和端口 ``` 新建snmp_device_rj.yml文件,这里面写要监控的设备。位置和prometheus.ym是同一个文件夹。 如下所示: ``` [root@localhost prometheus]# cat snmp_device_rj.yml - labels: mib: if_mib brand: RuiJie node_name: 115 model: S2910-24GT4XS-E place: 2层 targets: - 192.168.99.115 - labels: mib: if_mib brand: RuiJie node_name: 116 model: S2910-24GT4XS-E place: 3层 targets: - 192.168.99.116 ``` 上面中的 node_name 字段,在告警时会传入app.py,必不可少的。 ### 编辑prometheus.yml的告警功能 进入prometheus安装目录,编辑prometheus.yml,设置如下配置 告警配置连接 ```shell # Alertmanager configuration alerting: alertmanagers: - static_configs: - targets: - 127.0.0.1:9093 ``` 开启告警配置 ```shell rule_files: # 告警规则配置文件位置 - "rules/*.yml" ``` 增加名为Alertmanager的监控项 ```shell scrape_configs:中增加下面的job_name项 # - job_name: 'alertmanager' static_configs: - targets: ['172.20.32.218:9093'] ``` #### 检查并重新加载配置文件 ./promtool check config prometheus.yml ```shell [root@localhost prometheus]# ./promtool check config prometheus.yml Checking prometheus.yml SUCCESS: prometheus.yml is valid prometheus config file syntax ``` #### 添加报警规则 rules/node_alerts.yml 在prometheus.yml的同级目录下,在该rules目录下创建node_alerts.yml文件: ``` #创建告警目录 mkdir rules && cd rules/ vim node_alerts.yml #添加报警规则 [root@localhost rules]# cat node_alerts.yml groups: - name: general.rules rules: - alert: NodeExporterDown expr: up{job="node-exporter"} != 1 for: 5m labels: severity: warning level: 2 annotations: summary: "端口9100探测失败" description: "服务器{{ $labels.node_name }}端口9100探测失败,请尽快检查node_exporter是否出现异常!" - alert: 温度升高 expr: rjTemperature{instance="192.168.99.116"} >= 55 for: 1m labels: severity: warning level: 2 annotations: summary: "116温度升高" description: "交换机:{{ $labels.node_name }} 温度升高,所在位置:{{ $labels.place }},温度: {{ $value }} 请尽快检查是否出现异常!" ``` 注意:可以配置多个监控告警项,如上文件中配置多个 -alert {{ $value }} 表示 当前expr字段中表达式对应的值 ``` # alert:告警规则的名称。 # expr:基于 PromQL 表达式告警触发条件,用于计算是否有时间序列满足该条件。 # for:评估等待时间,可选参数。用于表示只有当触发条件持续一段时间后才发送告警。在 等待期间新产生告警的状态为 pending。 # labels:自定义标签,允许用户指定要附加到告警上的一组附加标签。 # annotations:用于指定一组附加信息,比如用于描述告警详细信息的文字等,annotations 的内容在告警产生时会一同作为参数发送到 Alertmanager。 # summary 描述告警的概要信息,description 用于描述告警的详细信息。 # 同时 Alertmanager 的 UI 也会根据这两个标签值,显示告警信息。 ``` 状态说明 Prometheus Alert 告警状态有三种状态:Inactive、Pending、Firing。 Inactive:非活动状态,表示正在监控,但是还未有任何警报触发。 Pending:表示这个警报必须被触发。由于警报可以被分组、压抑/抑制或静默/静音,所 以等待验证,一旦所有的验证都通过,则将转到 Firing 状态。 Firing:将警报发送到 AlertManager,它将按照配置将警报的发送给所有接收者。一旦警 报解除,则将状态转到 Inactive,如此循环。 当从Pending状态,转变为Firing状态,即触达到ALertManager,推送邮件信息。 **重启Prometheus** systemctl restart prometheus **企微群机器人 发送的内容示例:** ``` 【报警】xxxx环境 NodeExporterDown 有新的报警 告警级别: warning 告警类型: NodeExporterDown 告警主机: 115 告警详情: 服务器115端口9100探测失败,请尽快检查node_exporter是否出现异常! 告警状态: firing 触发时间: 2023-03-02 14:43:28 +08:00 ``` ## 钉钉版webhook组件 ```python # -*- coding: utf-8 -*- import os import json import requests import arrow from flask import Flask from flask import request app = Flask(__name__) def bytes2json(data_bytes): data = data_bytes.decode('utf8').replace("'", '"') return json.loads(data) def makealertdata(data): for output in data['alerts'][:]: try: pod_name = output['labels']['pod'] except KeyError: try: pod_name = output['labels']['pod_name'] except KeyError: pod_name = 'null' try: namespace = output['labels']['namespace'] except KeyError: namespace = 'null' try: message = output['annotations']['message'] except KeyError: try: message = output['annotations']['description'] except KeyError: message = 'null' if output['status'] == 'firing': status_zh = '报警' title = '【%s】 %s 有新的报警' % (status_zh, output['labels']['alertname']) send_data = { "msgtype": "markdown", "markdown": { "title": title, "text": "## %s \n\n" %title + ">**告警级别**: %s \n\n" % output['labels']['severity'] + ">**告警类型**: %s \n\n" % output['labels']['alertname'] + ">**告警主机**: %s \n\n" % output['labels']['node_name'] + ">**告警详情**: %s \n\n" % message + ">**告警状态**: %s \n\n" % output['status'] + ">**触发时间**: %s \n\n" % arrow.get(output['startsAt']).to('Asia/Shanghai').format( 'YYYY-MM-DD HH:mm:ss ZZ') } } elif output['status'] == 'resolved': status_zh = '恢复' title = '【%s】 %s 有新的报警' % (status_zh, output['labels']['alertname']) send_data = { "msgtype": "markdown", "markdown": { "title": title, "text": "## %s \n\n" %title + ">**告警级别**: %s \n\n" % output['labels']['severity'] + ">**告警类型**: %s \n\n" % output['labels']['alertname'] + ">**告警主机**: %s \n\n" % output['labels']['node_name'] + ">**告警详情**: %s \n\n" % message + ">**告警状态**: %s \n\n" % output['status'] + ">**触发时间**: %s \n\n" % arrow.get(output['startsAt']).to('Asia/Shanghai').format( 'YYYY-MM-DD HH:mm:ss ZZ') + " **触发结束时间**: %s \n" % arrow.get(output['endsAt']).to('Asia/Shanghai').format( 'YYYY-MM-DD HH:mm:ss ZZ') } } return send_data def send_alert(data): token = os.getenv('ROBOT_TOKEN') if not token: print('you must set ROBOT_TOKEN env') return url = 'https://oapi.dingtalk.com/robot/send?access_token=%s' % token send_data = makealertdata(data) req = requests.post(url, json=send_data) result = req.json() if result['errcode'] != 0: print('notify dingtalk error: %s' % result['errcode']) @app.route('/', methods=['POST', 'GET']) def send(): if request.method == 'POST': post_data = request.get_data() print(post_data) send_alert(bytes2json(post_data)) return 'success' else: return 'weclome to use prometheus alertmanager dingtalk webhook server!' if __name__ == '__main__': app.run(host='0.0.0.0', port=5000) ``` (其它步骤与企业微信版一样) 参考文章: [Prometheus系列--altermanager结合webhook定制钉钉和微信告警](https://bbs.huaweicloud.com/blogs/268824 "Prometheus系列--altermanager结合webhook定制钉钉和微信告警") [Prometheus系列——告警规则与告警-altermanager](https://bbs.huaweicloud.com/blogs/268833 "Prometheus系列——告警规则与告警-altermanager")
local
2023年3月3日 14:32
分享文档
收藏文档
上一篇
下一篇
微信扫一扫
复制链接
手机扫一扫进行分享
复制链接
关于 LocalNetwork
LocalNetwork
是由mrdoc开源
LocalNetwork.cn
修改的在线文档系统,作为个人和小型团队的云笔记、文档和知识库管理工具。
如果此文档给你或你的团队带来了帮助,欢迎支持作者持续投入精力更新和维护!内网文摘 & LocalNetwork
>>>主页
logo
logo
下载Markdown文件
分享
链接
类型
密码
更新密码