本教程基于CentOS7.9的环境下,安装Python3.10版本部署ElastAlerts2
要成功部署ElastAlert2需要以下先决条件,本文按以下顺序部署:
1. 升级OpenSSL到openssl1.1.1版本
2.CentOS7.9安装Python3.10,并校验openssl1.1.1版本成功
3.部署ElastAlerts并测试告警
升级OpenSSL
版本务必使用1.1.1版本
https://www.openssl.org/source/openssl-1.1.1o.tar.gz
1、先安装组件
yum -y install perl perl-devel gcc gcc-c++
2、下载openssl 1.1.1o
wget https://www.openssl.org/source/openssl-1.1.1o.tar.gz
3、解压进入openssl-1.1.1o目录并编译
tar -zxvf openssl-1.1.1o.tar.gz
cd openssl-1.1.1o
./config --prefix=/usr/local/openssl
make && make install
4、备份文件
mv /usr/bin/openssl /usr/bin/openssl.old
mv /usr/include/openssl /usr/include/openssl.old
mv /usr/lib64/openssl /usr/lib64/openssl.old
mv /usr/lib64/libssl.so /usr/lib64/libssl.so.old
ln -s /usr/local/openssl/bin/openssl /usr/bin/openssl
ln -s /usr/local/openssl/include/openssl /usr/include/openssl
ln -s /usr/local/openssl/lib/libssl.so /usr/lib64/libssl.so
echo "/usr/local/openssl/lib" >> /etc/ld.so.conf
ldconfig -v
5、 检查版本
openssl version
OpenSSL 1.1.1q 5 Jul 2022
CentOS7.9下安装Python3.10
本环境:
[root@elastalert ~]# uname -a
Linux elastalert 3.10.0-1160.el7.x86_64 #1 SMP Mon Oct 19 16:18:59 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
[root@elastalert ~]# cat /etc/redhat-release
CentOS Linux release 7.9.2009 (Core)
本环境下所有依赖都需要安装,即使已经安装了openssl1.1.1
1、依赖安装
yum -y groupinstall "Development tools"
yum install -y ncurses-devel gdbm-devel xz-devel sqlite-devel tk-devel uuid-devel readline-devel bzip2-devel libffi-devel
yum install -y openssl-devel openssl11 openssl11-devel
wget https://www.python.org/ftp/python/3.10.4/Python-3.10.4.tgz
下载源码包,实践我试过3.10.4和3.10.5都可以
tar xvzf Python-3.10.4.tgz
cd Python-3.10.4
2、编译安装
编译安装分两种情况,
第一种安装方式需要修改Module目录下Setup文件,指定openssl的安装路径,以便Python能够调用ssl模块;
第二种安装方式是不需要修改Setup,在编译前config指定openssl的路径;
如果第一种安装方式编译失败或者import ssl失败,可以尝试第二种安装方式
第一种安装方式:
进入Modules目录,修改Setup文件中的ssl目录
添加一行实际路径即可:(升级安装openssl1.1.1时候的编译安装路径)
然后
./configure --with-openssl=/usr/local/openssl
然后再
指定编译依赖库为新版本openssl相关依赖,这里的路径需要根据安装目录灵活配置,例如:
export LD_LIBRARY_PATH=/usr/local/openssl/lib64:$LD_LIBRARY_PATH
这种安装方式编译可能会失败(编译过程就会报错),但是没有关系,我们还有第二种安装方式,更加直接简单,屡试不爽:
第二种安装方式
哈哈,其实就是直接编译前指定configure的openssl路径,什么都不需要改,不需要输出依赖变量
./configure --with-openssl=/usr/local/openssl
make && make install
最后同样成功了:不需要export上述变量环境
验证安装:
/usr/local/bin/python3.10 --version
/usr/local/bin/pip3.10 --version
通过设置软链接简化命令输入:
ln -sf /usr/local/bin/python3.10 /usr/bin/python3
ln -sf /usr/local/bin/pip3.10 /usr/bin/pip3
配置pip源
这一步很关键,安装ElastAlert2需要使用pip安装大量的依赖,我们使用非ssl的国内py源进行安装,这样可以提升速度和成功率:
新建pip配置文件
mkdir -p ~/.pip
touch ~/.pip/pip.conf
编辑配置文件
vim ~/.pip/pip.conf
[global]
index-url=http://mirrors.aliyun.com/pypi/simple/
#proxy = [user:passwd@]proxy.server:port
[install]
trusted-host=
mirrors.aliyun.com
ssl_verify: false
验证
pip3 install --upgrade pip
至此ElastAlert2的安装环境准备完成
ElastAlert2部署
配置文件介绍:
安装完成后,会在examples/config下找到配置文件config.yaml
其中rules_folder配置:指定规则rule的存放路径,可以提供绝对路径
rules_folder是ElastALerts2将从加载规则配置文件的地方。它将尝试加载文件夹中的每个 .yaml 文件。没有任何有效的规则,Elastalert2 将不会启动。ElastAlert2 还将加载新规则,停止运行缺少的规则,并在此文件夹中的文件更改时重新启动已修改的规则。
1、下载安装
pip3 install elastalert2
git clone https://github.com/jertel/elastalert2.git
$ pip3 install "setuptools>=11.3"
$ python3 setup.py install
2、证书文件准备
elasticsearch 8.x版本以上均开启了安全认证和证书认证,ElastAlert2访问es需要提供证书,
本文使用以准备好的ELK8.x的环境进行部署(具体部署将会在另外的文章介绍)
ELK8.x在安装后会准备好默认的证书系统,我们测试环境使用其提供的默认证书即可
官网文档的配置文件提示需要使用pem格式的证书,使用crt格式是同样可以的。
elasticsearch 8.3.2版本
8.X 版本自带证书,但自带的证书做转换和导出需要密码,需要查询密码。
我使用了自带的默认http.p12证书,通过openssl转换成crt证书,并提取了key
以下为elasticsearch 8x上的自带证书,把http_ca.crt拷贝过去elastalert2,并把http.p12通过openssl转换提取客户端证书和key
查询http证书密码的命令:
elasticsearch-keystore show xpack.security.http.ssl.keystore.secure_password
rlpWCQsySZuPanG0vG5dRA
转换命令:转换过程要输入上述密码
// Private Key 私钥
openssl pkcs12 -in http.p12 -nocerts -nodes > http.key
// Public Certificate 公共证书
openssl pkcs12 -in http.p12 -clcerts -nokeys > http.crt
Elastalert2配置文件config.yaml
配置文件目录位于elastalert2/examples/目录下,把config.yaml.sample复制一份成config.yaml
elasticsearch7.x版本
7.x版本的,参考8.x的实践,使用的需要是http的证书。可以通过elasticsearch-certutil http命令生成
3、创建索引
直接创建索引测试安装情况
创建成功
也可以使用配置文件创建,进入到config.yaml所在目录
elastalert-create-index --config config.yaml
如果没有启用ssl verify,会有如下报错
在配置文件config.yaml中启用ssl verify为Ture后成功创建了索引
然后在elasticsearch上tail -f /etc/elasticsearch/elasticsearch.log看到创建日志
4、创建告警规则
ElastAlert2支持的告警渠道非常多,本文以qq邮箱告警为例,详细展开如何配置邮件告警
其他告警渠道:ElastAlert2官网告警渠道
Rule配置
所有的告警规则,通过在rule目下创建配置文件进行定义,这里简单创建一个来作为演示。
首先我的elk集群中又action服务的索引,其索引名称也是action。然后如果想查询该服务日志中是否又error字段出现,则配置如下:
# Alert when the rate of events exceeds a threshold
cp example_frequency.yaml my_rule.yaml
es_host: 172.10.10.13
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
#查询message中出现ERROR
filter:
- query:
query_string:
query: "message: ERROR"
#告警渠道:邮件
alert:
- "email"
#在邮件正文会显示你定义的alert_text
alert_text: "you have a error message" #主题的名称
#报警邮箱的
smtp server
#要加双引号
smtp_host: "smtp.qq.com"
#报警邮箱的smtp 端口
smtp_port: 465
smtp_ssl: True
#需要把认证信息写到额外配置文件里,需要user和password两个属性
smtp_auth_file: /usr/local/elastalert/example_rules/smtp_auth_file.yaml
#要加双引号
email_reply_to: "150313xxxxx@163.com"
from_addr: "150313xxxxx@163.com"
#发送给哪个邮箱通知告警
email:
- "xxxxxxx@163.com"
smtp_auth_file字段是需要额外建立一个文件,作为发邮件的用户名 和密码的文件。
接下来需要配置smtp认证文件了,touch 一个配置文件,路径一定要和上边配置的对应好。
vi smtp_auth_file.yaml
#文件配置内容如下:
user: "test"
password: "test@12345"
邮箱ssl
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
配置好rule文件之后,也可以先语法检查一下:
elastalert-test-rule example_rules/example_frequency.yaml
如果要指定要使用的配置文件,则可以使用config标志运行它:
elastalert-test-rule --config <path-to-config-file> example_rules/example_frequency.yaml
如果没有报错,则说明可用。
[root@elastalert elastalert2]# elastalert-test-rule /root/elastalert2/rule/test.yaml --config /root/elastalert2/examples/config.yaml --alert
#如果要确认是告警是否能触发的话,需要加 --alert
elastalert-test-rule ./examples/rules/exemple_discord_any.yaml --config=./examples/config.yaml
5、启动
在elastalert下启动:注意要指定配置文件的路径
后台记录日志的启动方式
nohup python3 -m elastalert.elastalert --verbose --config config.yaml --rule example_rules/my_rule.yaml &
通过查询nohup.out的日志能够很清晰看到整个过程
造一些error状态的日志,过一会儿应该可以看到日志中的说明,有告警发出,邮箱应该也能收到了。
前台输出日志的启动方式:
python3 -m elastalert.elastalert --config /usr/local/elastalert/config.yaml --rule /usr/local/elastalert/example_rules/frequency.yaml --verbose
启动测试
规则截图:这个截图是我做any规则的时候测试的截图,查询字段geoip.geo.country_name中出现Chian的时候触发告警邮件通知
插入一条查询日志(具体触发方式是通过logstash插入一条日志到elasticsearch,或者可以通过dev tool PUT 一个文档进去,这里不详细论述,留在其他文章展开)
有查询命中和匹配,并发送邮件告警
邮件内容:
告警文本优化-推荐增加的配置:
alert_subject: "test告警"
alert_text_args:
- "@timestamp" #选取日志中的field或者字段做参数0,以下类推
- "geoip.ip"
- "http.version"
alert_text: "you have a error message of weblog:\n
告警时间:{0}\n地理地址:{1}\n协议版本:{2}"
以为摘了常用的告警参数:
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
更多规则可以查看官网
Rule Types and Configuration Options — ElastAlert 0.0.1 documentation
subject也可以配参数
alert_subject: "app 正式环境 告警 {}" # 这里使用python 的format 进行格式化 alert_subject_args: - category
html格式
# 下面这些不配置,会发送一个默认的告警模板,纯文字太丑了,因此咱们进行了格式化,发送一个html格式的 email_format: html
<span style="color:red">kama</span>
# 若是这个去掉,那么发送alert_text的同时,也会发送默认模板内容 alert_text_type: alert_text_only # 下面这个是本身配置的 alert_text: "<div style='display:block;background-color: red;padding: 10px;border-radius: 5px;color: white;font-weight: bold;' > <p>{}</p></div><br><a href='这里填写本身的kibana地址href' target='_blank' style='padding: 8px 16px;background-color: #46bc99;text-decoration:none;color: white;border-radius: 5px;'>Click to Kibana</a><br><h3>告警详情</h3><table><tr><td style='padding:5px;text-align: right;font-weight: bold;border-radius: 5px;background-color: #eef;'>@timestamp:</td><td style='padding:5px;border-radius: 5px;background-color: #eef;'>{}</td></tr><tr><td style='padding:5px;text-align: right;font-weight: bold;border-radius: 5px;background-color: #eef;'>@version:</td><td style='padding:5px;border-radius: 5px;background-color: #eef;'>{}</td></tr><tr><td style='padding:5px;text-align: right;font-weight: bold;border-radius: 5px;background-color: #eef;'>_id:</td><td style='padding:5px;border-radius: 5px;background-color: #eef;'>{}</td></tr><tr><td style='padding:5px;text-align: right;font-weight: bold;border-radius: 5px;background-color: #eef;'>_index:</td><td style='padding:5px;border-radius: 5px;background-color: #eef;'>{}</td></tr><tr><td style='padding:5px;text-align: right;font-weight: bold;border-radius: 5px;background-color: #eef;'>_type:</td><td style='padding:5px;border-radius: 5px;background-color: #eef;'>{}</td></tr><tr><td style='padding:5px;text-align: right;font-weight: bold;border-radius: 5px;background-color: #eef;'>appType:</td><td style='padding:5px;border-radius: 5px;background-color: #eef;'>{}</td></tr><tr><td style='padding:5px;text-align: right;font-weight: bold;border-radius: 5px;background-color: #eef;'>appVersion:</td><td style='padding:5px;border-radius: 5px;background-color: #eef;'>{}</td></tr><tr><td style='padding:5px;text-align: right;font-weight: bold;border-radius: 5px;background-color: #eef;'>business:</td><td style='padding:5px;border-radius: 5px;background-color: #eef;'>{}</td></tr><tr><td style='padding:5px;text-align: right;font-weight: bold;border-radius: 5px;background-color: #eef;'>category:</td><td style='padding:5px;border-radius: 5px;background-color: #eef;'>{}</td></tr><tr><td style='padding:5px;text-align: right;font-weight: bold;border-radius: 5px;background-color: #eef;'>geoip:</td><td style='padding:5px;border-radius: 5px;background-color: #eef;'>{}</td></tr><tr><td style='padding:5px;text-align: right;font-weight: bold;border-radius: 5px;background-color: #eef;'>guid:</td><td style='padding:5px;border-radius: 5px;background-color: #eef;'>{}</td></tr><tr><td style='padding:5px;text-align: right;font-weight: bold;border-radius: 5px;background-color: #eef;'>host:</td><td style='padding:5px;border-radius: 5px;background-color: #eef;'>{}</td></tr><tr><td style='padding:5px;text-align: right;font-weight: bold;border-radius: 5px;background-color: #eef;'>message:</td><td style='padding:10px 5px;border-radius: 5px;background-color: red;color: white;'>{}</td></tr><tr><td style='padding:5px;text-align: right;font-weight: bold;border-radius: 5px;background-color: #eef;'>num_hits:</td><td style='padding:5px;border-radius: 5px;background-color: #eef;'>{}</td></tr><tr><td style='padding:5px;text-align: right;font-weight: bold;border-radius: 5px;background-color: #eef;'>num_matches:</td><td style='padding:5px;border-radius: 5px;background-color: #eef;'>{}</td></tr><tr><td style='padding:5px;text-align: right;font-weight: bold;border-radius: 5px;background-color: #eef;'>path:</td><td style='padding:5px;border-radius: 5px;background-color: #eef;'>{}</td></tr><tr><td style='padding:5px;text-align: right;font-weight: bold;border-radius: 5px;background-color: #eef;'>server:</td><td style='padding:5px;border-radius: 5px;background-color: #eef;'>{}</td></tr><tr><td style='padding:5px;text-align: right;font-weight: bold;border-radius: 5px;background-color: #eef;'>uid:</td><td style='padding:5px;border-radius: 5px;background-color: #eef;'>{}</td></tr><tr><td style='padding:5px;text-align: right;font-weight: bold;border-radius: 5px;background-color: #eef;'>uri:</td><td style='padding:5px;border-radius: 5px;background-color: #eef;'>{}</td></tr><tr><td style='padding:5px;text-align: right;font-weight: bold;border-radius: 5px;background-color: #eef;'>userAgent:</td><td style='padding:5px;border-radius: 5px;background-color: #eef;'>{}</td></tr></table>" #效果如下:
# 这里须要配置area_text中出现的各个字段,其实跟sprintf同样按照顺序格式化的 #从上到下的顺序填入{}
alert_text_args: - message - "@timestamp" - "@version" - _id - _index - _type - appType - appVersion - business - category - geoip - guid - host - message - num_hits - num_matches - path - server - uid - uri - userAgent
可以按需简化一下html:
<div style='display:block;background-color:#46bc99 ;padding: 10px;border-radius: 5px;color: white;font-weight: bold;' > <p>{}</p></div><h3>告警详情</h3><table><tr><td style='padding:5px;text-align: right;font-weight: bold;border-radius: 5px;background-color: #eef;'>@timestamp:</td><td style='padding:5px;border-radius: 5px;background-color: #eef;'>{}</td></tr><tr><td style='padding:5px;text-align: right;font-weight: bold;border-radius: 5px;background-color: #eef;'>_index:</td><td style='padding:5px;border-radius: 5px;background-color: #eef;'>{}</td>
按需要自行新增html标签
至此,ElastAlert2的部署完成,大家可以自行探索更多玩法。