【导语】告警面临的一大问题,是警报太多,相当于狼来了的形式。收件人很容易麻木,不再继续理会。关键的告警常常被淹没。在运维监控系统中,告警收敛是指对告警信息进行分析、合并和丢弃,以此来降低告警信息的规模。因此,针对每天上万条的告警事件比如ping事件告警,如何进行收敛并帮助用户更优针对性地发现批次性告警问题,具有重要意义。
目录
- 1. 背景和意义
- 1.1. 背景
- 1.2. 现有技术方案
- 1.3. 改进技术方案
- 2. 告警收敛服务框架
- 3. AI告警收敛流程框图
- 3.1. 告警事件输入
- 3.2. 告警聚类收敛
- 3.3. 告警事件输出
- 3.4. 通用化解决方案
- 3.5. 方案收益
- 4. 产品形态
- 4.1. 单条告警的产品形态
- 4.1.1. 单条实时告警
- 4.1.2. 告警收敛后的产品形态
- 4.1.3. 描述
- 4.1.4. 示例效果图一
- 4.1.5. 示例效果图二
- 4.2. 所有告警的复盘分析
- 4.3. 效果展示
- 4.1. 单条告警的产品形态
- 5. 参考资料
1. 背景和意义
1.1. 背景
当监控系统爆发大规模告警信息时,不仅会给短信网关造成巨大压力,还会增大SRE的故障监管压力,致使其忽略核心根因告警信息。在运维监控系统中, 告警收敛是指对告警信息进行分析、合并和丢弃,以此来降低告警信息的规模。因此,通过告警收敛来降低告警信息的规模对网络运维监控系统而言显得尤为重要。
右下图是每天的告警事件分布情况,可以看出平均每分钟有1.5k - 4k左右的告警量,形成告警风暴,用户难以直接从所有告警事件中发现有效的信息。
1.2. 现有技术方案
现有技术方案的技术问题主要是收敛方式单一:比如对于告警时间维度,当告警时间都在约定的范围内才能进一步考虑是否收敛;告警收敛依据固定化,当且仅当两个告警维度信息完全相同才能收敛,方式单一。对于一些存在差异的告警维度无法收敛,比如包含时间的名称,用户自定义的名称等等,举例如下:
如果想以图中告警的红色框内的告警维度进行收敛,目前的收敛手段只能支持完全相同的告警收敛,然而不同机器的相关维度可能会有编号、自定义、随机生成等形式,导致告警维度相似但是不完全相同。
1.3. 改进技术方案
本文提出一种智能告警收敛的方法,解决人工定位异常根因耗费时间长等技术问题。主要的关键技术和创新点是通过统计方法来实现异常定位或根因分析。创新点主要如下:
- 结构简单:通用化的智能告警收敛方案结构清晰,通用化程度高
- 多层收敛策略:告警收敛策略包含多层,支持用户自定义,支持文本相似性匹配自动收敛等多种方式。
- 通用化:可以选定告警收敛前提,选定告警维度信息进行收敛;对于不同类型的告警事件均可采用。
- 展示方式:用户可以选定维度作为收敛后的信息展示,可以发送多条原始告警,但放在一块儿展示发送
2. 告警收敛服务框架
下图为AMP、收敛服务、小程序等三方面的整体服务框架设计。原始数据源上报数据,在告警发送通道中缓存一定时间粒度的告警时间(比如1分钟,5分钟),然后调用AI告警收敛服务,得到收敛后的告警事件,再发送到小程序或者短信、邮件等发送端,推送给客户。如下图所示,以ping不可达告警事件为例。备注:通用告警收敛方案以此为例说明,但不局限于Ping不可达告警事件。
3. AI告警收敛流程框图
主要包括三个步骤:
- 原始告警事件输入:读取原始的固定时间粒度的告警时间,并根据告警收敛前提分组
- AI告警收敛服务:对告警收敛依据进行格式解析预处理,并通过多层收敛决策判定是否可归为一类告警
- 收敛告警事件输出:对可以收敛为一类的告警,将相关维度信息分别处理展示
3.1. 告警事件输入
不同的运维监控系统会采用不同的形式发送告警事件,事件中包含的维度字段等信息也不尽相同。因此,在告警事件输入过程中,需要对告警事件的格式进行解析,统一转换为维度key-value的形式。
告警收敛前提:在进行告警收敛之前,用户可以指定满足收敛前提的告警才可以进一步收敛。比如,设定为:事件名称、产品名称、appId用户,表示当事件名称、产品名称和appId用户相同的情况下,告警才能进一步考虑收敛,否则应该分开发送。
告警时间粒度:根据告警的重要和紧急程度等属性,用户可以设定多长内的告警事件才可以收敛并发送。若时间太长,则收敛事件量大但告警发送的延时较大;若时间太短,则告警延时较小但收敛效果不明显。通常可设置为1分钟。
3.2. 告警聚类收敛
告警收敛依据:用户可以指定根据哪个字段将告警事件进行收敛。比如“服务器名”,[未命名63,未命名78,未命名61]等在形式上是“固定部分 可变部分”的维度信息,很明显这类告警属于同一类型的告警,因而可以进一步收敛。
告警聚类收敛注意包括以下三个步骤:
1、预处理:告警收敛依据中的字符可能存在一些特殊字符,因而需要进行格式解析和剔除特殊符号;同时,参照“固定部分 可变部分”的形式,将数字和ip地址、url等可变部分转换成统一的*通配符形式,最后生成的字符称为通配字符。
2、分层收敛:收敛层可分为如下三层:
- 收敛第一层:若两次告警的通配字符完全相同,告警可收敛为同一类
- 收敛第二层:若告警收敛依据中包含有”-”或”_”这类的分隔符,如右图,则根据分隔符将字符分割;对于两次告警,统计其中分割后的字符中相同的字符数量,以此计算相似度,若相似度大于相似度阈值,则可收敛为同一类
- 收敛第三层:采用文本匹配和相似度计算的方式比如wordToVec, wordToWord等等,对于两次告警,计算告警通配字符的相似度,若相似度大于相似度阈值,则可收敛为同一类。
3、模板归类:对于可收敛为同一类的告警,取其中最早出现的告警通配字符作为当前告警收敛列表的模板;对于新输入的告警,若其符合已有的告警模板,则收敛为同一类事件;若不能收敛到已有的告警模板中,则自称一类新的告警模板。
重复以上三个收敛步骤,直至告警事件列表里所有的告警事件均被遍历。
3.3. 告警事件输出
- 告警收敛维度:对于收敛后的同类告警事件,对于所有告警维度进行不同的处理,以生成最新的收敛告警事件:
- 告警统一标识:所有告警完全相同,可保留原始字段
- 告警收敛依据:若收敛事件列表的所有告警事件完全相同,则可展示其中一个原始字段;若不完全相同,则可展示预处理后的通配字符;比如对于[未命名,未命名,未命名]展示“未命名”;对于[未命名63,未命名78,未命名61]展示“未命名*”
- 告警收敛维度:其他可以收敛在一起统一展示的维度信息,比如内网IP,外网IP等,将所有的告警时间的收敛维度统一在一起,以列表的形式展示。而对于剩下的维度若不收敛,则可直接舍弃,比如告警触发时间、告警恢复时间等
- 新增维度:用户往往想知道有多少告警被收敛为一次告警发送,因此对于收敛后的告警,增加计 数字段,表明当前告警收敛了多少次告警。
3.4. 通用化解决方案
通用化告警收敛方案,其通用性和定制化体现在几个方面:
- 告警收敛前提/唯一标识、告警收敛依据、告警收敛维度,三者均可自定义为告警事件的任一维度,也可设置为None,满足各种场景需求;全都设置为None表明不做任何处理直接返回原始告警事件列表
- 告警收敛依据 可以是告警事件中任一维度的信息,可由用户自主选择,比如服务器名、instanceId、uuid等
- 收敛策略共有三层,第一层可以完全通用化开放;第二层和第三层可以部分通用化开放,根据维度信息调整后效果可以更定制化
3.5. 方案收益
- 减少告警:告警收敛数据挖掘装置可以将多个告警事件收敛成较少的告警事件,解决告警冗余的问题
- 提高效率:提高SRE获取告警信息的效率,
- 辅助根因定位:并助其从大规模告警信息中寻找故障根因
- 减少成本:减少告警信息的存储成本、短信或邮件通知等成本
4. 产品形态
4.1. 单条告警的产品形态
4.1.1. 单条实时告警
单条实时Ping不可达告警事件
4.1.2. 告警收敛后的产品形态
4.1.3. 描述
- 告警收敛前提:保持现状展示,展示在最前面
- 告警收敛依据:
- 若收敛的所有事件的维度信息完全相同,则展示原始维度信息;
- 若不完全相同,则展示通配符处理后的通配形式
3. 告警收敛维度: 如果维度信息完全相同,则只展示一次;如果有不同,则以列表的形式依次展示。 用户可指定哪些维度需要收敛展示;若不指定,则默认为所有维度中除去告警收敛前提和告警收敛依据的剩余所有维度。
4. 附加信息:
- 事件量计数:收敛后的告警事件包含了多少次告警,是统计数字
- 通配字符串(可选):所有告警事件的告警收敛依据通过通配符处理后的形式汇总列表,前期便于查看聚类效果和调整最小相似度阈值
- 收敛事件最早时间(可选):收敛后的告警事件中包含的最早告警事件的时间,如 min{occurTime}
- 收敛事件最晚时间(可选):收敛后的告警事件中包含的最晚告警事件的时间,可结合查看告警事件时间
4.1.4. 示例效果图一
图1. 收敛事件包含的原始告警事件的 alias告警收敛依据不同,则以通配符的形式展示,原始的在 aliasList中以列表形式展示 其中,region 维度相同均为 sh, 则只展示一次;其他告警收敛维度以列表形式展示; eventCount 表示收敛了5次告警事件。
图2. 收敛事件包含的原始告警事件的 alias告警收敛依据相同,则展示最原始形式, aliasList也只展示一次。
4.1.5. 示例效果图二
图2. 收敛事件包含的原始告警事件的alias告警收敛依据相同,则展示最原始形式, aliasList也只展示一次。在不该表原来事件结构的前提下,可以收敛的多条事件,统一放到收敛的列表内。
代码语言:javascript复制[[{'additionalMsg': [{'key': 'ip', 'value': 'something unnormal'}, {'key': 'alias', 'value': 'scf_function_tcbm'}, {'key': 'deviceLanIp', 'value': '9.1.32.124'}, {'key': 'deviceWanIp', 'value': ''}, {'key': 'uniqVpcId', 'value': 'vpc-99nlipgq'}], 'appId': '1253665819', 'dimensions': [{'key': 'uuid', 'value': 'c006d2b4-3e51-4c2e-9d61-0a3d4ed3e99a'}], 'displayFlag': 1, 'eventId': 42, 'eventName': 'ping_unreachable', 'instanceId': 'ins-otm8jy9t', 'occurTime': 1590116683, 'productName': 'cvm', 'projectId': '0', 'region': 'sh', 'seqId': 'a463080f-dec3-4204-9b46-0d70bb39b767', 'status': 0, 'type': 2},
{'additionalMsg': [{'key': 'ip', 'value': 'something unnormal'}, {'key': 'alias', 'value': 'scf_function_tcbm'}, {'key': 'deviceLanIp', 'value': '9.1.74.9'}, {'key': 'deviceWanIp', 'value': ''}, {'key': 'uniqVpcId', 'value': 'vpc-99nlipgq'}], 'appId': '1253665819', 'dimensions': [{'key': 'uuid', 'value': 'b82b738d-bc0e-4950-8ab2-346b24bd7208'}], 'displayFlag': 1, 'eventId': 42, 'eventName': 'ping_unreachable', 'instanceId': 'ins-9kdyahtv', 'occurTime': 1590116682, 'productName': 'cvm', 'projectId': '0', 'region': 'sh', 'seqId': 'eb176177-b832-4cc4-a085-60da4c4c9571', 'status': 0, 'type': 2}],
{'additionalMsg': [{'key': 'ip', 'value': 'something unnormal'}, {'key': 'alias', 'value': 'scf_function_tcbm'}, {'key': 'deviceLanIp', 'value': '9.1.79.40'}, {'key': 'deviceWanIp', 'value': ''}, {'key': 'uniqVpcId', 'value': 'vpc-99nlipgq'}], 'appId': '1253665819', 'dimensions': [{'key': 'uuid', 'value': '5ebe690e-7c88-4b1e-8940-824b7053f200'}], 'displayFlag': 1, 'eventId': 42, 'eventName': 'ping_unreachable', 'instanceId': 'ins-3n1zcw6j', 'occurTime': 1590116682, 'productName': 'cvm', 'projectId': '0', 'region': 'sh', 'seqId': 'd9c04f26-74ff-4228-b774-cefc51502746', 'status': 0, 'type': 2},
{'additionalMsg': [{'key': 'ip', 'value': 'something unnormal'}, {'key': 'alias', 'value': 'test_tcbm'}, {'key': 'deviceLanIp', 'value': '9.1.60.164'}, {'key': 'deviceWanIp', 'value': ''}, {'key': 'uniqVpcId', 'value': 'vpc-99nlipgq'}], 'appId': '1253665819', 'dimensions': [{'key': 'uuid', 'value': 'e593dbc8-8d38-4036-94e9-1518c9cd1f0e'}], 'displayFlag': 1, 'eventId': 42, 'eventName': 'ping_unreachable', 'instanceId': 'ins-fxjj63lt', 'occurTime': 1590116683, 'productName': 'cvm', 'projectId': '0', 'region': 'sh', 'seqId': '13ec8c62-d3e7-4aab-a278-397bb15a3e78', 'status': 0, 'type': 2}]
4.2. 所有告警的复盘分析
基于此功能可以设计丰富的相关功能,比如:
- 左上角可选择不同时间,包括但不限于ping不可达、带宽超限、磁盘只读、无限重启等事件。
- 事件量统计:选择当前时间和对比时间,查看事件量的时间变化曲线。
- 提供选择告警收敛前提、告警收敛依据、告警展示维度;以上三个维度的选择均依赖于上报的事件包含的所有维度字段信息。所有信息均体现在表格中。
- 相似度阈值调整:通过滑块设置不同的相似度阈值,变化体现在表格中的告警收敛依据,不同相似度下体现不同的服务器名称模式。同时还可以和选择的对比时间对比所有告警模式的数量变化。
4.3. 效果展示
说明:以下template为收敛后的模板/模式,alias_list为收敛所包含的单条告警事件的alias列表。
1、部分日期可变型
代码语言:javascript复制template: activity-cvm-*-*-*
====================
alias_list: ['activity-cvm-2020-02-27', 'activity-cvm-2020-03-25', 'activity-cvm-2020-05-12', 'activity-cvm-2020-05-22', 'activity-cvm-2020-01-11', 'activity-cvm-2020-03-25', 'activity-cvm-2020-05-27', 'activity-cvm-2020-05-27', 'activity-cvm-2019-12-12', 'activity-cvm-2019-12-12', 'activity-cvm-2020-05-27', 'activity-cvm-2020-05-27', 'activity-cvm-2020-01-11', 'activity-cvm-2020-05-26', 'activity-cvm-2020-01-11']
2、多次重复出现的
代码语言:javascript复制template: u672au547du540d
====================
alias_list: ['u672au547du540d', 'u672au547du540d', 'u672au547du540d', 'u672au547du540d', 'u672au547du540d', 'u672au547du540d', 'u672au547du540d', 'u672au547du540d', 'u672au547du540d', 'u672au547du540d', 'u672au547du540d', 'u672au547du540d']
template: 星海资源网
====================
alias_list: ['星海资源网', '星海资源网', '星海资源网', '星海资源网', '星海资源网']
template: centos-2GB-sh-2073
====================
alias_list: ['centos-2GB-sh-2073', 'centos-2GB-sh-2073', 'centos-2GB-sh-2073', 'centos-2GB-sh-2073'
3、纯数字型
代码语言:javascript复制template: *
====================
alias_list: ['789', '25', '19', '33', '1', '9', '15', '18', '17', '21', '34', '26']
4、末尾数字可变型
代码语言:javascript复制template: TRANSGROUP_*
====================
alias_list: ['TRANSGROUP_039', 'TRANSGROUP_035', 'TRANSGROUP_006', 'TRANSGROUP_029', 'TRANSGROUP_035', 'TRANSGROUP_015', 'TRANSGROUP_015', 'TRANSGROUP_009', 'TRANSGROUP_031', 'TRANSGROUP_025', 'TRANSGROUP_025', 'TRANSGROUP_009', 'TRANSGROUP_041', 'TRANSGROUP_024', 'TRANSGROUP_006', 'TRANSGROUP_009', 'TRANSGROUP_022', 'TRANSGROUP_017', 'TRANSGROUP_017', 'TRANSGROUP_019', 'TRANSGROUP_028']
template: T*-斗鱼-*
====================
alias_list: ['T4-斗鱼-0203', 'T4-斗鱼-0203', 'T4-斗鱼-0316', 'T4-斗鱼-0316', 'T4-斗鱼-0203', 'T4-斗鱼-0203', 'T4-斗鱼-0203', 'T4-斗鱼-0203']
template: 默认项目*
====================
alias_list: ['默认项目96', '默认项目69', '默认项目33', '默认项目40', '默认项目96', '默认项目82', '默认项目69', '默认项目14', '默认项目30', '默认项目33', '默认项目56', '默认项目40', '默认项目64', '默认项目75', '默认项目53', '默认项目64']
template: CD*
====================
alias_list: ['CD2', 'CD2', 'CD2', 'CD2',`CD001', 'CD2']
template: 账号*
====================
alias_list: ['账号1', '账号5', '账号1', '账号5']
template: wshm-logic*
====================
alias_list: ['wshm-logic01', 'wshm-logic01', 'wshm-logic03', 'wshm-logic022', 'wshm-logic01']
5、中间数字可变型
代码语言:javascript复制template: psd-练习环境*-长期* 张宇
====================
alias_list: ['psd-练习环境1-长期2 张宇', 'psd-练习环境1-长期4 张宇', 'psd-练习环境2-长期4 张宇', 'psd-练习环境2-长期3 张宇']
6、参数配置型
代码语言:javascript复制template: as-cpu-*x-*
====================
alias_list: ['as-cpu-4x-232', 'as-cpu-4x-233', 'as-cpu-4x-218', 'as-cpu-4x-238', 'as-cpu-4x-212', 'as-cpu-4x-236', 'as-cpu-4x-26', 'as-cpu-4x-28', 'as-cpu-4x-246', 'as-cpu-4x-217', 'as-cpu-4x-225', 'as-cpu-4x-222', 'as-cpu-4x-218']
template: windows-*GB-bj-*
====================
alias_list: ['windows-1GB-bj-2148', 'windows-1GB-bj-2148', 'windows-4GB-gz-3235', 'windows-4GB-gz-3235', 'windows-2GB--6988', 'windows-1GB-bj-2148', 'windows-1GB-bj-2148', 'windows-1GB-cd-5807', 'windows-4GB-bj-6096', 'windows-1GB-bj-2148', 'windows-1GB-bj-2148', 'windows-1GB-bj-2148', 'windows-1GB-bj-2148', 'windows-1GB--5298']
7、‘-’ 和 ‘_’ 两种符号共存型
代码语言:javascript复制template: *_*
====================
alias_list: ['emr-task1_emr-c0r0wdr6', 'emr-task2_emr-c0r0wdr6', 'emr-task1_emr-c0r0wdr6', 'emr-task2_emr-c0r0wdr6', 'T4-DY-0509_4', 'T4-DY-0509_4']
8、长-短相似型
代码语言:javascript复制template: scf_func_d
====================
alias_list: ['scf_func_d', 'scf_func_d', 'scf_func_d', 'scf_func_d']
template: scf_function_tcbm
====================
alias_list: ['scf_function_tcbm', 'scf_function_tcbm', 'scf_function_tcbm']
template: scf_func_ziyan
====================
alias_list: ['scf_func_ziyan', 'scf_func_ziyan', 'scf_func_ziyan', 'scf_func_ziyan']
5. 参考资料
1、《大规模集群之告警系统实践》
https://zhuanlan.zhihu.com/p/42190073
2、《文本相似度算法总结》
https://blog.csdn.net/qq_33373858/article/details/90812282?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.nonecase
3、《浅析文本相似度》
https://blog.csdn.net/qq_28031525/article/details/79596376