使用EFK(Elasticsearch、Fluentd、Kibana)对日志进行收集分析可视化后,希望通过分析日志能从中发现异常并报警。Elasticsearch有提供此功能的产品Watcher,但需要收费。开源的方案中有ElastAlert,于是花了点时间实验。经过一段时间使用后,感觉效果并不太好(或许是自己还没有玩透吧),功能挺全面但配置较麻烦而且误报不少(可能我配置参数没调好吧),关键是具参考价值高的资料不多(官方文档、开发团队博客)。不过既然试用了,还是简单记录一下备忘。
安装
详细的最新文档参考Elastalert官方文档
环境依赖
- pip
- Elasticsearch 1.*
- ISO8601 timestamped data
- Python 2.6
安装Elastalert
CentOS 6默认安装的setuptools
版本为0.16
,但mock需要0.17
以上版本,所以需要升级setuptools
1
2
3
4
5
6yum install libyaml-devel python-devel python-setuptools python-pip
pip install --upgrade setuptools==17.1.1
git clone https://github.com/Yelp/elastalert.git
cd elastalert
pip install -r requirements.txt
python setup.py install
配置
配置Elasticsearch
ElastAlert可将自身信息及数据等存入Elasticsearch方便审计和debug,此为可选项但作者强烈推荐使用。使用elastalert-create-index
创建相关内容。
默认index的名称为elastalert_status
,若自定义后在ElastAlert的配置文件需要做相关修改,config.yaml
——writeback_index
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!
ElastAlert主配置文件
拷贝模板配置文件后按照自己情况修改cp config.yaml.example config.yaml
常用配置详解1
2
3
4
5
6
7
8
9
10
11rules_folder: you_rules_folder_name
run_every:
minutes: 5
buffer_time:
minutes: 6
es_host: localhost
es_port: 9200
writeback_index: elastalert_status
alert_time_limit:
days: 1
max_query_size: 20000
- rules_folder:存放规则的目录,默认为
example_rules
。ElastAlert会自动加载该目录下所有的yaml
规则文件。 - run_every:每隔多少时间查询Elasticsearch。默认5分钟。
ElastAlert的时间可选项- weeks
- days
- hours
- minutes
- seconds
- buffer_time:设置查询的时间范围。默认45分钟。
- es_host/es_port: Elasticsearch
- writeback_index:ElastAlert将查询相关信息存到Elasticsearch的index名称。通过
elastalert-create-index
命令创建 - alert_time_limit:ElastAlert查询的有效范围时间。默认查询2天。
- max_query_size:ElastAlert最大查询数据量。默认
10000
。此选项需要稍微注意一下,若项目访问量很大,在buffer_time内数据量超过10000
则需调整buffer_time或max_query_size,否则会因为查询量超过10000
导致某些时间段无数据而频繁发生误报。
ElastAlert监控规则
ElastAlert的规则都是以yaml
文件格式存储在rules_folder
目录下。ElastAlert会加载rules_folder
目录下所有的规则文件,并监控文件变化。当规则文件发生变动时会自动加载规则。
ElastAlert默认有多种规则,每种规则都有其各自的配置项。详细内容查看ElastAlert官方规则文档
默认规则类型有:
- any:一旦匹配就触发报警
- blacklist:
compare_key
里的内容在blacklist
上则触发报警 - whitelist:
compare_key
里的内容不在blacklist
上则触发报警 - change:相同
query_key
,compare_key
里的内容,在timeframe
范围内有变化则触发报警 - frequency:在满足
filter
的条件下,timeframe
时间内有num_events
个记录则触发报警 - spike:在
filter
条件下,两个timeframe
范围内数据量相差比超过spike_height
则触发报警。spike_type
设置具体涨跌方向是up
/down
/both
。threshold_ref
、threshold_cur
可设置上下限。 - flatline:
timeframe
时间范围内,数据量小于threshold
则触发报警 - new term:
terms_window_size
时间范围内最多出现terms_size
个新的fields
,多于则触发报警 - cardinality:在
filter
条件下,timeframe
时间范围内不重复的cardinality_field
值超过max_cardinality
或者低于min_cardinality
则触发报警
ElastAlert的规则中的name
必须唯一,ElastAlert启动时会检查所有规则中的name
字段,若发现不唯一则报错无法启动。
ElastAlert报警
ElastAlert提供多种报警方式,详见ElastAlert报警方式官方文档。此处主要介绍Email
Email
方式使用SMTP协议,只要在规则文件中添加SMTP
相关内容即可1
2
3
4
5smtp_host: SMTP_HOST
smtp_port: SMTP_PORT
smtp_auth_file: /path/to/smtp_auth.txt
from_addr: email_from_address
email_reply_to: ElastAlert
smtp_auth_file
是以yaml
格式记录用户和密码(注意:
后有空格)1
2user: username
password: password
Email报警例子
邮件内容可自定义,详见ElastAlert自定义邮件内容1
2
3
4
5
6
7
8
9
10
11
12
13alert:
- "email"
#收件人列表
email:
- "mogl@yourdomain.com"
- "test@yourdomain.com"
#Email邮件内容自定义
alert_text: "At {0}. http状态码200在1分钟内多于2000个"
alert_text_args:
- "@timestamp"
alert_text_type: alert_text_only
ElastAlert规则测试 & 启动
ElastAlert提供elastalert-test-rule
命令用于测试规则
执行elastalert-test-rule
命令时仅测试规则是否正确,若想真实触发报警则需加上--alert
参数1
elastalert-test-rule /path/to/your_elastalert_rules.yaml --alert
ElastAlert在终端中启动
自动加载所有规则。--verbose
观察详细过程,若使用--debug
参数不会触发alert1
python -m elastalert.elastalert --verbose --config /path/to/config.yaml
仅测试具体规则
1 | python -m elastalert.elastalert --verbose --config /path/to/config.yaml --rule /path/to/your_elastalert_rule.yaml |
ElastAlert启动时默认的起始检查时间为present
,ElastAlert允许修改起始检测时间1
python -m elastalert.elastalert --verbose --config /path/to/config.yaml --start `date +%Y-%m-%dT%H:%M:%S%z`
Supervisor管理ElastAlert
ElastAlert自身并没有提供守护进程运行方式,官方建议使用Supervisor来管理ElastAlert。
Supervisor配置文件supervisord.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28[unix_http_server]
file=/var/run/elastalert_supervisor.sock
[supervisord]
logfile=/var/wwwlog/elastalert/supervisord.log
logfile_maxbytes=100MB
logfile_backups=5
loglevel=debug
nodaemon=false
directory=%(here)s
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
[supervisorctl]
serverurl=unix:///var/run/elastalert_supervisor.sock
[program:elastalert]
command=/usr/local/elastalert/elastalert.sh
process_name=elastalert
autorestart=true
startsecs=15
stopsignal=INT
stopasgroup=true
killasgroup=true
stderr_logfile=/var/wwwlog/elastalert/elastalert.log
stderr_logfile_maxbytes=100MB
stderr_logfile_backups=5
/usr/local/elastalert/elastalert.sh
启动脚本1
2#!/bin/bash
/usr/bin/python /usr/local/elastalert/elastalert/elastalert.py --verbose --config /usr/local/elastalert/config.yaml --start $(date +%Y-%m-%dT%H:%M:%S%z)
1 | $> chmod a+x /usr/local/elastalert/elastalert.sh |
启动Supervisor1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17# 运行supervisord
supervisord -c /usr/local/elastalert/supervisord.conf
# 重新加载配置文件
supervisorctl -c /usr/local/elastalert/supervisord.conf update
# 控制所有进程
cd /usr/local/elastalert
supervisorctl start all
supervisorctl stop all
supervisorctl restart all
# 控制目标进程
cd /usr/local/elastalert
supervisorctl stop elastalert
supervisorctl start elastalert
supervisorctl restart elastalert
ElastAlert规则配置实例
####frequency
code
是field
,根据存入Elasticsearch的字段而定,此处的日志中http code定义code
(日志由fluentd收集)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26es_host: localhost
es_port: 9200
smtp_host: YOUR_SMTP_HOST
smtp_auth_file: /path/to/smtp_auth.txt
from_addr: ElastAlert@yourdomain.com
email_reply_to: ElastAlert
name: project_code_frequency
type: frequency
index: project*
num_events: 180
timeframe:
minutes: 1
filter:
- range:
code:
from: 400
to: 599
alert:
- "email"
email:
- "mogl@yourdomain.com"
alert_text: "At {0}. http异常状态码4XX-5XX在1分钟内多于180"
alert_text_args:
- "@timestamp"
alert_text_type: alert_text_only
use_local_time: true
####cardinality1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25es_host: localhost
es_port: 9200
index: project*
smtp_host: YOUR_SMTP_HOST
smtp_auth_file: /path/to/smtp_auth.txt
from_addr: ElastAlert@yourdomain.com
email_reply_to: ElastAlert
name: project_ip_cardinality
type: cardinality
cardinality_field: "ip"
max_cardinality: 2000
timeframe:
minutes: 1
filter:
- term:
code: 200
alert:
- "email"
email:
- "mogl@yourdomain.com"
alert_text: "At {0}. 独立IP在1分钟内多于2000个"
alert_text_args:
- "@timestamp"
alert_text_type: alert_text_only
use_local_time: true
####flatline1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21es_host: localhost
es_port: 9200
smtp_host: YOUR_SMTP_HOST
smtp_auth_file: /path/to/smtp_auth.txt
from_addr: ElastAlert@yourdomain.com
email_reply_to: ElastAlert
name: project_pv_flatline
type: flatline
index: project*
threshold: 500
timeframe:
minutes: 1
alert:
- "email"
email:
- "mogl@yourdomain.com"
alert_text: "At {0}. PV在1分钟内少于500"
alert_text_args:
- "@timestamp"
alert_text_type: alert_text_only
use_local_time: true