如何让Zabbix告警推送出来的消息内容具有可读性、易识别?比如故障时是红色标题,恢复时是绿色标题,监控项目之间要有换行,清晰可辨。在这里我分享一下我的思路,在这个小项目中我们统一使用Python3来发送消息,并且实现了推送到Exchange、钉钉、企业微信、自研IM多种消息平台。
首先,我们先来看一下Zabbix 消息内容加了样式后的效果
Exchange样式
告警 如图1
如图 1
恢复 如图2
如图 2
企业微信样式
告警 如图3
如图 3
恢复 如图4
如图 4
钉钉样式
告警 如图5
如图 5
恢复 如图6
如图 6
源码逻辑
以上效果基本实现了我们的预期,接下来,讲讲实现逻辑吧,比较简单,先把动作里传过来的字符串转为字典,再进行数据重组,添加html或markdown样式,发送给各个消息平台。
如图 7
在这里讲讲实现过程中的3个问题吧。问题1.为什么要把消息内容转成dict而不是json对象?因为在python中对json做处理,value外层必须用双引号,但是实际测试,发现zabbix的原消息内容里带有双引号,会和json的外层双引号冲突,于是动作的消息内容字符串外层改用单引号。dict支持单引号,所以处理成dict更合适。
问题2. 样式为什么写在了脚本里,而不是动作的消息内容里?样式确实可以直接在动作的消息内容里添加,比如配置xml,html,纯文本很容易,但是markdown 很容易搞成一团,发送出来的内容没有换行,所以建议把样式写到了脚本里。
问题3. token 或key收件人还是脚本里好?如果要复用脚本,写到收件人里更好,比如群机器人比较多时这种情况下,多个token可以复用/usr/lib/zabbix/alertscripts/下的同一个脚本。当然,如果只有一个群机器人的话,写到哪都比较方便,看个人习惯而言。
在这里我们以企业微信为例,说说具体流程,当zabbix的字符串消息通过位置参数传给脚本send-wework-problems.py后,ast.literal_eval()函数接受参数并转为字典类型,以便进行数据重组,使用join()函数进行字符串拼接,加入markdown样式,加入换行,完成数据重组。企业微信字体支持3种内置颜色,markdown语法如下:
<fontcolor="info">绿色</font> <fontcolor="comment">灰色</font> <fontcolor="warning">橙红色</font>
我们使用橙红色作为 告警消息标题颜色样式,使用绿色作为恢复消息标题颜色样式,发送请求代码如下:
#!/usr/bin/env python3 import requests import os import sys import logging import json import urllib3 import ast urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) logging.basicConfig(filename = os.path.join(os.getcwd(), 'push.log'), level = logging.INFO,format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s') subject = sys.argv[1] data = sys.argv[2] # 把字符串转为字典 message = ast.literal_eval(data) # 测试用 #filename = '/usr/lib/zabbix/alertscripts/1.txt' #with open(filename, 'w') as file_object: # file_object.write(data) HOSTNAME = ': '.join(('> 告警主机',message["HOSTNAME"])) HOSTIP = ': '.join(('告警地址',message["HOSTIP"])) ITEMNAME = ': '.join(('监控项目',message["ITEMNAME"])) ITEMLASTVALUE = ': '.join(('监控取值',message["ITEMLASTVALUE"])) TRIGGERSEVERITY = ': '.join(('告警等级',message["TRIGGERSEVERITY"])) TRIGGERSTATUS = ': '.join(('当前状态',message["TRIGGERSTATUS"])) TRIGGERNAME = ': '.join(('告警信息',message["TRIGGERNAME"])) EVENTTIME = ': '.join(('告警时间',message["EVENTTIME"])) EVENTAGE = ': '.join(('持续时间',message["EVENTAGE"])) EVENTID = ': '.join(('事件ID',message["EVENTID"])) sendtext = '\n >'.join((HOSTNAME,HOSTIP,ITEMNAME,ITEMLASTVALUE,TRIGGERSEVERITY,TRIGGERSTATUS,TRIGGERNAME,EVENTTIME,EVENTAGE,EVENTID)) # 请修改key, zabbix server url def send_wework_message(sendtext): logger = logging.getLogger(__name__) WEWORK_API_URL="https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=x" data = { 'msgtype': 'markdown', "markdown": { "content": ''.join(('## <font color="warning">',subject,'</font> \n',sendtext,'\n','#### [点击转到ZABBIX](https://www.zabbix.com/) \n')) } } resp = requests.post( WEWORK_API_URL, data=json.dumps(data), headers={'Content-Type': 'application/json'} ) print(resp.text) if resp.status_code != 200: logger.info('[REQUESTS WEWORK API ERROR]%s'% resp.text) send_wework_message(sendtext)
企业微信消息发送可以参考https://work.weixin.qq.com/help?doc_id=13376#如何使用群机器人
其他类型的我都放到了github上,见https://github.com/ZuoGuocai/zabbix_push
开始配置
需要先把send-problems-wework.py,send-recovery- wework.py两个脚本放在zabbix server 的/usr/lib/zabbix/alertscripts 目录下,这两个脚本功能分别对应告警推送,恢复推送。
管理--报警媒介类型--创建媒体类型
如图 8
在这里我把key放到了脚本里,收件人里配置了一个无用的字符串,所以没有添加{ALERT.SENDTO},只有如下两项
{ALERT.SUBJECT} {ALERT.MESSAGE}
如果要复用脚本,建议配置以下三项
ALERT.SENDTO} {ALERT.SUBJECT} {ALERT.MESSAGE}
管理--用户--Admin--报警媒介--添加--收件人
配置--主机--监控项和触发器,再配置动作
为了方便演示,我配置了一台主机,添加了Zabbix 原生的ICMP Ping模板,自带了监控项和触发器 。
开始配置动作
如图10
消息内容如下
{ "HOSTNAME":"{HOST.NAME}", "HOSTIP":"{HOST.IP}", "ITEMNAME":'{ITEM.NAME}', "ITEMLASTVALUE":"{ITEM.LASTVALUE}", "TRIGGERSEVERITY":"{TRIGGER.SEVERITY}", "TRIGGERSTATUS":"{TRIGGER.STATUS}", "TRIGGERNAME":"{TRIGGER.NAME}", "EVENTTIME":"{EVENT.DATE} {EVENT.TIME}", "EVENTAGE":"{EVENT.AGE}", "EVENTID":"{EVENT.ID}" }
有没有发现第三项的value外层是单引号,value里经常有双引号出现,所有外层改用了单引号。这儿很好解释了 问题1.为什么要把消息内容转成dict而不是json对象
开始测试
在监测主机上操作
禁止ping
echo 1>/proc/sys/net/ipv4/icmp_echo_ignore_all
查看告警消息
允许ping
1. echo 0>/proc/sys/net/ipv4/icmp_echo_ignore_all
查看恢复消息
排错
告警消息为什么没有发出,脚本执行报错,为了更好的排错,建议添加动作日志,在web控制台的路径如下
监测--仪表盘--编辑仪表盘--添加构件--类型--动作日志
如图11
爱美之心,人皆有之,用Python3改写样式后,Zabbix发送的告警消息简洁优雅,并且能很好地跟多种IM集成,不禁感慨,这才是我要的告警效果呀。
本文作者:左国才,VIPKID运维工程师,笔名icai,主要研究开源Linux操作系统,数据库,云计算领域相关技术,平时喜欢阅读脚本之家公众号。
声明:本文为 脚本之家专栏作者 投稿,未经允许请勿转载。