一 背景
基于ELK日志的报警时互联网公司标配,大一点公司都会自研组件,报警信息更加准确、规则多样化。(之前的五八到家就是自研的)我们采用了Elastalert报警。
官网的地址:https://github.com/Yelp/elastalert
Elastalert自带的报警方式虽然多种多样,如下所示,但是不能实现根据报警信息分组发送。而且,不太符合国情:
我们需要的是:邮件+短信+钉钉+微信+电话这种常见的组合。
Currently, we have built-in support for the following alert types:
- JIRA
- OpsGenie
- Commands
- HipChat
- MS Teams
- Slack
- Telegram
- GoogleChat
- AWS SNS
- VictorOps
- PagerDuty
- PagerTree
- Exotel
- Twilio
- Gitter
- Line Notify
- Zabbix
Additional rule types and alerts can be easily imported or written.
不能分组这就很蛋疼,要么就是全体收,要么就是制定几个人收。报警太多我自身的感受就是跟“狼来了”差不多,一天几百个报警,时间一长没几天你就忽略了,真的报警也报淹没了。所以分组报警必要性性就体现出来了。主要目的是为了响应项目的报警发给对应的组内。
网上关于Elastalert 文章很多,但是实际上实用有分量的较少,我自己分析下:
方案 1: 报警方式实用post,
优点:便于拓展,
缺点:新开发一套报警相关的工程,工作量不是一两天的事
方案2: 基于Commands自定义报警组件:
优缺点:对于我来说,主要是Python语法上的挑战。不懂啊,只是硬着头皮看点介绍。
这里我要重点介绍下一位大神:https://blog.csdn.net/sdmei/article/details/89928964
要没有他的文章,我就采用方案1了,因为对于不懂Python外行来说,还是有一定的技术门槛的。
关于elastalert的安装:mac:ElastAlert 安装
二 拓展改造
注意:Recent changes: As of Elastalert 0.2.0, you must use Python 3.6. Python 2 will not longer be supported.
这里首选说明下,要是使用对应的Python版本,
python
Python 3.6.0 (v3.6.0:41df79263a11, Dec 22 2016, 17:23:13)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
我为了测试,就把mac自带的python2.7的升级到3.6.0版本,mac如何升级Python不展开,网上有很多文章。
2.1 告警数据怎么来获取?
这里关注下如何针对大神的文章去改造参数适配:
es_host: 10.10.10.1
es_port: 9200
name: freq-status-500
type: frequency
index: nginx-*
num_events: 30
timeframe:
minutes: 1
filter:
- bool:
must:
- terms:
status: ["500","501","502","503","504"]
use_terms_query: true
doc_type: doc
terms_size: 10
query_key:
- domain
- status
realert:
minutes: 60
alert:
- command
new_style_string_format: true
command: ["/root/elastalert-0.1.38/myalert/elastalert-alarm/alarm.py","--level=warning","--domain={domain,status}","--rulename=freq-status-500","--type=frequency","--num_events=30","--timeframe=1min"]
上面原作者的监控nginx 500的错误配置。我们业务就是简单的监控ES错误日志:filter 哪里:query error
对应实际来说:监控规则是不用变的,原来发邮件前怎么监控还是继续。主要是方式:就是alert:从 email 变成command。
而且业务所需要的参数:command要输出很多自定义参数,脚本通过这些参数决定发送的组合发送的内容如IP,es对应的index,tradeid,message,appname等具体报警参数需要传入到command。对应的py脚本:alarm.py。
2.2 报警人员如何获取?
这里要先看下配置:我改动较少,沿用原来的yaml配置。
project1:
member:
zhouwu:
mail: [email protected]
wangliu:
mail: [email protected]
主要还是以项目XXpeoject为主,获取对应的报警人信息。有一点麻烦就是工程比较多的情况下需要收集下不同部门不同项目的报警人邮件,逐一配置。毕竟是Python啊,如果换成Java,还是会好处理很多。但是维护组织结构与对应的负责项目这种 映射关系是不可缺少的。
2.3 报警内容组装
原始版本的内容:
def make_msg(self):
"""
get msg by rulename
freq-status-*, warning: sina_www status of 500 exceed 30 per 2min
freq-reqtime-*, warning: sina_www request time greater than 5sec exceed 30 per 2min
"""
if re.match("freq-status-", self.rulename):
self.msg = "%s: %s status of %s exceed %s per %s" % \
(self.level, self.domain, self.status, self.num_events, self.timeframe)
elif re.match("freq-reqtime-", self.rulename):
self.msg = "%s: %s request time greater than %s exceed %s per %s" % \
(self.level, self.domain, self.reqtime_gt, self.num_events, self.timeframe)
else:
self.msg = ''
这里可以自定义报警内容去替换,我不需要钉钉跟短信,只保留邮件,所以做了调整。
相关代码说明:
alarm.py --程序入口,参数解析
alert_channel.py --报警发送通道(短信、语音、邮件、钉钉群)
alert.py --构造发送对象和消息内容
aliyunsdk_SingleCallByTtsRequest.py --阿里电话语音第三方库
config-contact.yaml --报警对象配置文件
config.py --加载配置文件
requirements.txt --依赖
util.py --工具方法
效果展示:
再测试环境确定对应的ES起来了。然后模拟使用postman给es推送error触发报警。
本地起来了elastalert项目:
python -m elastalert.elastalert --config ./config.yaml --verbose --rule example_rules/my_rule.yaml
以邮件为例:
1 rules loaded
INFO:elastalert:Starting up
INFO:elastalert:Disabled rules are: []
INFO:elastalert:Sleeping for 59.99993 seconds
INFO:elastalert:Queried rule Example frequency rule from 2020-01-05 16:49 CST to 2020-01-05 16:59 CST: 1 / 1 hits
INFO:elastalert:New aggregation for Example frequency rule, aggregation_key: None. next alert at 2020-01-05 09:00:00+00:00.
INFO:elastalert:Ran Example frequency rule from 2020-01-05 16:49 CST to 2020-01-05 16:59 CST: 1 query hits (0 already seen), 1 matches, 0 alerts sent
INFO:elastalert:Disabled rules are: []
INFO:elastalert:Sleeping for 59.999657 seconds
INFO:elastalert:Background configuration change check run at 2020-01-05 17:00 CST
INFO:elastalert:Background alerts thread 1 pending alerts sent at 2020-01-05 17:00 CST
2020-01-05 17:00:12,556:alarm:INFO:mail -> [email protected],msg ->
elastalert索引中,hits
表示规则命中条数;matches
表示规则命中条数,并且匹配规则触发告警数量。
邮件效果:
数据都是造的,只是为了验证下效果。
没有加html 格式化。初步达到目的。
前后大概花了1天半的时间,开始半天被mac安装python折磨,后面1天主要是改动Python的时候语法错误。
另外,调试的时候遇到的一个坑是es的时间,一开始忽略了.
举个例子: "@timestamp": "2020-01-05T08:58:11.092Z",
这个时间实际上是1月5日16:58产生的,有个8小时时差。
剩下就是调整报警参数及邮件格式了。不得不承认,不懂Python语法调起来很费劲,全靠请教大师+百度。
期间我还咨询了小米的一个大神,大神说也没用过这个报警组件啊,不知道怎么改。其实看看核心代码不是很长大概200多行吧,熟悉的人半天就搞定了吧,但是对于不熟悉的改造加调试的确需要花时间。你得找机器去安装es.我自测试使用的就是线上版本6.7. elastalert是0.2 ,Python是3.6.0. 一步一个坑。最大收获就是磨练了自己的耐心。
最后再次感谢大神:他的地址:https://me.csdn.net/sdmei ,没有他的文章我不会尝试修改Python。也不会有本文。