vlambda博客
学习文章列表

基于kibana8的告警功能配置及解析

elk收集业务日志日志后,可以基于业务日志做告警.

我们以目前最新的kibana8.1.2为例,展示告警功能,并简要分析原理

功能场景分析

告警功能是xpack提供的高级功能.kibana提供了接入界面.

在kibana中告警配置分为四部分:

步骤 作用
输入

定义数据源. 一般是es.

elastic提供的一些插件,支持把其他中间件作为数据源.这些插件的主要作用是把数据采集到ES里.

触发器 异常检测的触发规则.
异常诊断 判断检测结果是否正常.需要结合触发器使用.比如1min内error大于5次(配置时 需要查最近一分钟内的error日志,总数>=5)
告警执行 将告警信息发送到钉钉,邮箱,保存到索引等

基于此,我们可以将下面的监控告警需求进行分解:

如果一分钟出现5次取消订单,就发送业务告警到邮箱.

步骤拆解 场景对应
输入 (采集到的)业务日志
触发器 至少1min一次.也可以20s一次
异常诊断 最近1min内的数据告警日志条数>=5
告警执行 发送告警信息到邮箱


告警配置说明

阈值告警

kibana提供了简单的阈值告警功能. 效果是"当某个指标触发过大或过小的阈值时,能够记录并触发告警".

阈值告警的数据源是某个或某些ES索引. 作为数据源的索引 需要有一个date类型的字段,用来支持时间范围查询.

选择数据源

异常诊断

基于kibana8的告警功能配置及解析


之所以称其为简单阈值报警,是因为这个功能只支持一个阈值条件.

所以其适用一般是系统指标异常检测. 如 当cpu>70%的时候告警.

事实上,kibana内置的es监控告警,大多数是这种简单告警.

kibana内置的ES状态告警

基于kibana8的告警功能配置及解析

触发规则

阈值告警的触发规则也比较简单,包含 count/avg/sum/max/min.  不支持基于复杂条件做匹配/聚合查询

基于kibana8的告警功能配置及解析

告警推送

触发告警后,可以将告警信息通过多种渠道输出或持久化.

默认支持写到kibana日志,或者写到指定索引中.

基于kibana8的告警功能配置及解析


多种告警渠道配置

kibana可以同时向多个渠道推送告警信息. 比如将异常信息写入索引,供面板展示,同时通过webhook推送到钉钉,发送告警邮件到邮箱

但除日志和索引外的功能,需要升级es许可证来开启功能

基于kibana8的告警功能配置及解析

高级告警

了解了阈值告警,我们发现它并不适用于我们的业务场景. 查询条件太简单, 阈值设置不灵活,导致难以对业务数据实施监控.

如果要基于索引的某些业务字段做聚合统计,可以使用"高级告警"功能.(该功能在新版本中改为 [安全-告警])

基于kibana8的告警功能配置及解析


在高级告警中,同样分为 输入-触发器-异常诊断-告警执行 四步..与阈值告警的区别在于: 查询条件更灵活;支持多条校验规则;可以只记录索引,不触发IM,邮件等告警

基于kibana8的告警功能配置及解析


告警推送

相较于简单的阈值告警,高级告警可以灵活定义推送的周期,

提供以下几种策略:

不触发告警;

每次运行规则检查时触发;

每小时触发;

每天触发;

每周触发;

基于kibana8的告警功能配置及解析



异常识别


触发器


不想升级许可?

可以给kibana安装sentinl插件.

帮助文档:https://sentinl.readthedocs.io/en/latest/

sentinl插件近两年没有维护,最新的release版本时6.8.4, pre-release版本时7.6.1


相关源码

kibana中告警触发器和告警规则接口:

https://github.com/elastic/kibana/tree/v8.1.2/x-pack/plugins/triggers_actions_ui/server/data

可以使用下面的接口主动拉取实时的检测结果.(实时计算时间可能较长,建议使用时改为异步调用)

curl -k  "https://elastic:changeme@localhost:5601/api/triggers_actions_ui/data/_time_series_query" \
-H "kbn-xsrf: foo" -H "content-type: application/json" -d "{
\"index\": \"es-hb-sim\",
\"timeField\": \"@timestamp\",
\"aggType\": \"avg\",
\"aggField\": \"summary.up\",
\"groupBy\": \"top\",
\"termSize\": 100,
\"termField\": \"monitor.name.keyword\",
\"interval\": \"1s\",
\"dateStart\": \"`now-iso -10s`\",
\"dateEnd\": \"`now-iso`\",
\"timeWindowSize\": 5,
\"timeWindowUnit\": \"s\"
}"

响应结果

{
"results": [
{
"group": "host-A",
"metrics": [
[ "2020-02-26T15:10:40.000Z", 0 ],
[ "2020-02-26T15:10:41.000Z", 0 ],
[ "2020-02-26T15:10:42.000Z", 0 ],
[ "2020-02-26T15:10:43.000Z", 0 ],
[ "2020-02-26T15:10:44.000Z", 0 ],
[ "2020-02-26T15:10:45.000Z", 0 ],
[ "2020-02-26T15:10:46.000Z", 0 ],
[ "2020-02-26T15:10:47.000Z", 0 ],
[ "2020-02-26T15:10:48.000Z", 0 ],
[ "2020-02-26T15:10:49.000Z", 0 ],
[ "2020-02-26T15:10:50.000Z", 0 ]
]
}
]
}


阈值告警和自定义查询拼接查询条件

https://github.com/elastic/kibana/blob/v8.1.2/x-pack/plugins/triggers_actions_ui/server/data/lib/time_series_query.ts

  const esQuery: any = {
index,
body: {
size: 0,
query: {
bool: {
filter: {
range: {
[timeField]: {
gte: dateRangeInfo.dateStart,
lt: dateRangeInfo.dateEnd,
format: 'strict_date_time',
},
},
},
},
},
// aggs: {...}, filled in below 后续拼接agg聚合条件
},
ignore_unavailable: true,
allow_no_indices: true,
};
 
...
let esResult: estypes.SearchResponse<unknown>;
...
esResult = (await abortableEsClient.search(esQuery, { ignore: [404] })).body;
...
return getResultFromEs(isCountAgg, isGroupAgg, esResult);
 
//getResultFromEs做的是结果集解析,返回基于<date,number>的metrics数组.


查询参数校验

https://github.com/elastic/kibana/blob/v8.1.2/x-pack/plugins/triggers_actions_ui/server/data/lib/time_series_types.ts