基于elastalert的监控报警系统
监控报警一般都是基于日志数据来做,总结起来就是根据监控指标查询一定时间段内的该指标的变化情况,当该指标超过设定的阈值时则触发报警规则,发出报警信息包括邮件,短信,微信甚至自动拨打电话等。 要实现监控报警的功能应该几步来做:
- 指定日志规范,生成日志
- 收集日志
- 查询分析日志
- 触发报警规则
- 报警
其中第二步日志收集就是一项不小的工作。一般会有这三部分组成
-
Agent : 部署在各个应用服务器收集应用的日志
-
Collector: 日志收集中心,把分散在Agent的日志统一收集到日志中心
-
Storage: 存储层,日志收集之后的存储 当数据量大的时候,可以采用 kafaka,redis这样的中间件来缓冲日志发送量,提高系统的可靠性。 可以采用的方案有: Flume日志收集,ELK方案等
我们因为已经搭建了ELK日志收集平台,已经完成了第二步,要做监控报警自然就基于ELK来做。
方案选择
先简单分析一下我们要做的事情
- 设置报警规则
- 查询ES中的特定指标
- 分析是否达到阈值
- 发报警邮件,微信
经过调研,有这么几个选择:
- 自己开发
- ELK提供了XPack, 具有报警的作用
- 第三方开源方案
首先试用了 Xpack本身的功能还是挺吸引人的 权限控制 + ELK集群监控,但因为监控报警功能不够灵活,达不到自己的需求且是收费的(穷.jpg);
yelp开源了
Elastalert
, yelp也是先有了自己的ELK, 而后需要搭建监控报警系统的时候,开发了 Elastalert。跟我们的路线和需求非常匹配,那果断放弃重复造轮子。Elastalert非常灵活,除了通过配置进行报警规则设置,还可以自己开发独有的报警规则。 经过在测试系统的对比,决定采用Elastalert
做作为监控报警系统的核心。
下图展示了我们监控系统的组件及架构简图
服务搭建
-
安装依赖
- 新建 pyhton2.7 虚拟环境
1 2 3
& sudo apt install -y virtualenv & sudo apt install -y python-dev libffi-dev libssl-dev & virtualenv env
激活env
- 安装 pip
1 2
$ sudo apt-get install python-setuptools python-dev build-essential $ sudo easy_install pip
-
安装 elastalert 先安装这个版本,解决依赖包boto3的问题,
error: python-dateutil 2.7.0 is installed but python-dateutil<2.7.0,>=2.1 is required by set(['botocore'])
1 2 3
$ pip install "python-dateutil<2.7.0,>=2.1" & pip install elastalert & pip install elasticsearch
如果报错 permission则 denied pip install –user elastalert
-
设置 elasticsearch 把查询和报警的信息和元数据存到 elasticsearch 中。这样可以在 kibana 中查询到报警的错误,异常和执行情况。
1 2 3 4 5
$ elastalert-create-index New index name (Default elastalert_status) Name of existing index to copy (Default None) New index elastalert_status created Done!
-
配置和设置规则
- 把公共的配置写到 config.yaml
vim config.yaml
示例:
1 2 3 4 5 6
# The Elasticsearch hostname for metadata writeback # Note that every rule can have its own Elasticsearch host es_host: localhost # The Elasticsearch port es_port: 9200
- 创建报警规则
vim alert_rules/alert_frquency.yaml
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13
name: Example rule type: frequency index: access num_events: 50 timeframe: minutes: 5 filter: - term: some_field: "some_value" alert: - "email" email: - "elastalert@example.com"
- 把公共的配置写到 config.yaml
-
测试报警规则
$ elastalert-test-rule alert_rules/alert_frequency.yam
-
启动服务
$ python -m elastalert.elastalert --verbose --rule alert_frequency.yaml
-
用supervisor管理监控服务
- 安装 supervisor
sudo apt install -y supervisor
- 配置elastalert
1 2 3 4 5 6 7 8 9
[program:elastalert] command=/home/xxx/elastalert/env/bin/elastalert --config /home/xxx/elastalert/config.yaml --verbose autostart=true autorestart=true stdout_logfile=/var/log/supervisor/elastalert.log stderr_logfile=/var/log/supervisor/elastalert_error.log stopsignal=INT stderr_logfile_maxbytes=5MB stdout_logfile_maxbytes=5MB
- 启动服务
sudo supervisorctl start elastalert
- 安装 supervisor
开发报警规则和报警方式
- 报警类型
1 2 3 4 5 6 7 8 9
class AwesomeNewRule(RuleType): # ... def add_data(self, data): # ... def get_match_str(self, match): # ... def garbage_collect(self, timestamp): # ...
- 报警方式
1 2 3 4 5 6 7
class AwesomeNewAlerter(Alerter): required_options = set(['some_config_option']) def alert(self, matches): ... def get_info(self): ...
- 报警 on-the-fly
1 2 3 4 5
class MyEnhancement(BaseEnhancement): def process(self, match): # Drops a match if "field_1" == "field_2" if match['field_1'] == match['field_2']: raise DropMatchException()