用ELK stack来做日志收集分析,Kibana
强大而方便,跟踪分析统计样样俱全,然而,但是,却有一个问题。ELK自能通过手动查询日志,而不能发出邮件通知。而ElastAlert可以实现此功能。elastalert依照一定频率查询es,将查询结果对比告警阈值,超过阈值即进行告警。告警方式包括但不局限于邮箱、jira等。虽然官方没有提供微信等告警方式,但是也有第三方版本可以使用。
Elastalert是通过python实现的,所以需要python的环境。官方提供的python版本是2.7.6,但经过测试目前2.7.6的版本根本不适合了,需要Python 3.6.9,同时需要安装pip 20.0.2。
安装依赖包:
yum -y install wget openssl openssl-devel gcc gcc-c++
下载包:
wget https://www.python.org/ftp/python/3.6.9/Python-3.6.9.tgz
安装:
tar xf Python-3.6.9.tgz
cd Python-3.6.9./configure --prefix=/usr/local/python --with-openssl
make && make install
配置
mv /usr/bin/python /usr/bin/python_old
ln -s /usr/local/python/bin/python3 /usr/bin/python
ln -s /usr/local/python/bin/pip3 /usr/bin/pip
pip install --upgrade pip
注意所有依赖python2的脚本,都需要更改为python2.7,因为现在默认的python为3.6,例如
sed -i '1s/python/python2.7/g' /usr/bin/yum
sed -i '1s/python/python2.7/g' /usr/libexec/urlgrabber-ext-down
验证
$ python -V
Python 3.6.9
$ pip -V
pip 19.3 from /usr/local/python/lib/python3.6/site-packages/pip (python 3.6)
下载包
git clone https://github.com/Yelp/elastalert.git
cd elastalert
pip install "elasticsearch<7,>6"
#因为我们的es是7.2.0,所以这里选用的版本是这个
pip install -r requirements.txt
python setup.py install
安装成功后可以看到四个命令
ll /usr/local/python/bin/elastalert*
/usr/local/python/bin/elastalert
/usr/local/python/bin/elastalert-create-index
/usr/local/python/bin/elastalert-rule-from-kibana
/usr/local/python/bin/elastalert-test-rule
ln -s /usr/local/python/bin/elastalert* /usr/bin
官方文档:https://elastalert.readthedocs.io
规则文档:https://elastalert.readthedocs.io/en/latest/ruletypes.html
一.首先是主配置文件的模板为config.yaml.example,生成全局配置
复制一份修改名字为config.yaml
大体配置如下:
#存放elastalert 规则的文件夹,你的elastalert 放到哪里就放到哪里就行了
rules_folder: example_rules
#Elastalert 多久去查询一下根据定义的规则去elasticsearch 查询是否有符合规则的字段,如果有就会触发报警,如果没有就等待下一次时间再检查,时间定义的单位从周到秒都可以,具体定义方法如下。
run_every:
minutes: 1
#hours:1
#days:1
#weeks:1
#当查询开始一直到结束,最大的缓存时间
buffer_time:
minutes: 15
es_host: x.x.x.x
es_port: 9200
#这个是elastalert 在es里边写的index
writeback_index: elastalert_status
writeback_alias: elastalert_alerts
#如果alert当时没有发出去重试多久之后放弃发送;
alert_time_limit:
days: 2
执行elastalert-create-index命令在ES创建索引,这不是必须的步骤。因为我们其他系统对接的时候 已经创建了需要的索引。不过可以验证是否正确:
执行 elastalert-create-index 一定要加引号,除了端口号不加,否则会报错。
如果执行成功,结果如下:
Elastic Version: 7.2.0
Reading Elastic 6 index mappings:
Reading index mapping 'es_mappings/6/silence.json'
Reading index mapping 'es_mappings/6/elastalert_status.json'
Reading index mapping 'es_mappings/6/elastalert.json'
Reading index mapping 'es_mappings/6/past_elastalert.json'
Reading index mapping 'es_mappings/6/elastalert_error.json'
New index elastalert_status created
Done!
也可以请求一下看看:
curl x.x.x.x:9200/_cat/indices?v
所有的告警规则,通过在rule目下创建配置文件进行定义,这里简单创建一个来作为演示。
首先我的elk集群中又action服务的索引,其索引名称也是action。然后如果想查询该服务日志中是否又error字段出现,则配置如下:
# Alert when the rate of events exceeds a threshold
cp example_frequency.yaml my_rule.yaml
es_host: x.x.x.x
es_port: 9200
#rule name 必须是独一的,不然会报错,这个定义完成之后,会成为报警邮件的标题
name: es_rule
type: frequency #选择某一种数据验证方式,支持很多种数据验证方式
#这个index 是指再kibana 里边的index,支持正则匹配,支持多个index,同时如果嫌麻烦直接* 也可以。
#index: es-nginx*,winlogbeat*
index: action
#时间出发的次数
num_events: 2
#和上边的参数关联,也就是说在4分钟内出发5次会报警
timeframe:
#hours: 4
minutes: 1
filter:
- query:
query_string:
query: "message: ERROR"
alert:
- "email"
#在邮件正文会显示你定义的alert_text
alert_text: "you have a error message" #主题的名称
#报警邮箱的smtp server
smtp_host: "smtp.163.com"
#报警邮箱的smtp 端口
smtp_port: 25
#需要把认证信息写到额外配置文件里,需要user和password两个属性
smtp_auth_file: /usr/local/elastalert/example_rules/smtp_auth_file.yaml
email_reply_to: "[email protected]"
from_addr: "[email protected]"
email:
smtp_auth_file字段是需要额外建立一个文件,作为发邮件的用户名 和密码的文件。
接下来需要配置smtp认证文件了,touch 一个配置文件,路径一定要和上边配置的对应好。
vi smtp_auth_file.yaml
#文件配置内容如下:
user: "test"
password: "test@12345"
elastalert默认支持的规则有以下几种:
any:只要有匹配就报警;
blacklist:compare_key字段的内容匹配上 blacklist数组里任意内容;
whitelist:compare_key字段的内容一个都没能匹配上whitelist数组里内容;
change:在相同query_key条件下,compare_key字段的内容,在 timeframe范围内 发送变化;
frequency:在相同 query_key条件下,timeframe 范围内有num_events个被过滤出 来的异常;我的实验就是参考了这个规则配置的
spike:在相同query_key条件下,前后两个timeframe范围内数据量相差比例超过spike_height。其中可以通过spike_type设置具体涨跌方向是- up,down,both 。还可以通过threshold_ref设置要求上一个周期数据量的下限,threshold_cur设置要求当前周期数据量的下限,如果数据量不到下限,也不触发;
flatline:timeframe 范围内,数据量小于threshold 阈值;
new_term:fields字段新出现之前terms_window_size(默认30天)范围内最多的terms_size (默认50)个结果以外的数据;
cardinality:在相同 query_key条件下,timeframe范围内cardinality_field的值超过 max_cardinality 或者低于min_cardinality
关于这些不同的规则,官方有一些模板案例可以参考,路径在example_rules下面
配置好rule文件之后,也可以先语法检查一下:
elastalert-test-rule example_rules/example_frequency.yaml
如果要指定要使用的配置文件,则可以使用config标志运行它:
elastalert-test-rule --config
如果没有报错,则说明可用。
在elastalert下启动:
nohup python -m elastalert.elastalert --verbose --config config.yaml --rule example_rules/my_rule.yaml &
通过查询nohup.out的日志能够很清晰看到整个过程
造一些error状态的日志,过一会儿应该可以看到日志中的说明,有告警发出,邮箱应该也能收到了。
推荐增加的配置:
1、报警频率
#限定时间内,发生事件次数
num_events: 3
#与上面参数结合使用,表示在2分钟内发生3次就报警
timeframe:
minutes: 2
2、避免重复告警
避免一定时间段中重复告警,可以配置realert和exponential_realert这两个选项:
# 5分钟内相同的报警不会重复发送
realert:
minutes: 5
# 指数级扩大 realert 时间,中间如果有报警,
# 则按照5->10->20->40->60不断增大报警时间到制定的最大时间,
# 如果之后报警减少,则会慢慢恢复原始realert时间
exponential_realert:
hours: 1
3、聚合相同告警
# 根据报警的内容将相同的报警按照 name 来聚合
aggregation_key: name
# 聚合报警的内容,只展示 name 与 message
summary_table_fields:
- name
- message
4、告警内容格式化
可以自定义告警内容,内部是使用Python的format来实现的。
alert_subject: "Error {1} @{2}"
alert_subject_args:
- name
- "@timestamp"
alert_text_type: alert_text_only
alert_text: |
> Name: {1}
> Message: {2}
> Host: {3} ({4})
alert_text_args:
- name
- message
- hostname
- host
更多规则可以查看官网
https://elastalert.readthedocs.io/en/latest/ruletypes.html