我的运维开发生涯-网络设备指标告警实现

目录

网络监控工具所应具备的特性

网络指标告警系统

系统设计

系统详细设计

执行流程

本章小结

新网络指标告警系统

系统设计

系统详细设计

执行流程

本章小结

总结


 

 

作为一个在在网络监控工具开发摸爬滚打三年的小码农,每天接触最多的就是网络监控工具的开发维护,其中属交换机、防火墙指标监控项最多。每天这些监控项产生的数据高达几十亿条,当数据出现异常时,又需要即使产生告警,让网络组的同学能快速响应,依据告警内容处理网络异常。

 

 

网络监控工具所应具备的特性


有了这些需求,我们就需要一个高效、稳定、准确的网络指标监控系统。

首先,监控系统需要的是准确。这里的准确不仅指代监控数据准确,而且告警配置的阈值也要准确。若数据不准,那监控呈现的趋势图、告警阈值判断肯定都是有问题的,没办法反应网络设备当前运行情况。若告警配置的阈值不准,有可能网络设备已经出现了问题,但是没有触发阈值告警;或是网络设备运行正常,运维同学却被短信与邮件轰炸,从而降低了对告警的敏感程度,当出现真正告警时运维同学会出现响应不及时的情况。

其次,监控系统需要的是稳定。每时每刻,监控系统都需要稳定运行,实时监控网络设备的运行情况。若经常出现宕机情况,系统不但会丢失一部分运行数据,导致无法查看这段时间网络设备指标数据;而且还会导致告警无法有效产生,可能在网络设备出现严重故障时运维同学没有收到相应告警,从而对上层业务造成不可挽回的损失。除了上面的原因,还有一个对系统稳定性提出要求的是我们自己,因为想偷懒,作为运维开发,我们不想因为担心监控系统出问题而随时随地都背着电脑,所以在制作系统时,让系统尽量稳定运行。实际得出的效果是我们制作的指标监控系统可以在无人监管的情况下运行一年以上不出问题。

最后,监控系统需要的才是高效。在数据准确与系统稳定的基础上,监控系统最后的要求才是高效,因为即使监控数据延迟5-10分钟展示,也不是很让人抓狂。同样告警延迟5-10分钟产生,也不是一件无法接受的事情。毕竟网络作为底层支持,大型的上层应用肯定是做了一定的容灾处理,底层出现一部分问题,上层会依据方案做应急处理,除非底层全挂,那就只能等死了。所以在无可奈何的时候,监控数据延迟5-10分钟,运维同学慢5-10分钟处理问题,也不是不能接受。

但作为精益求精的我,这就是不能接受,既然做到了数据准确、系统稳定,为何不再配上系统高效这一道主菜让整个系统使用得更舒服呢。所以在接手了公司监控系统,并完全理清楚其中的逻辑后,就要对原有的监控系统进行大刀阔斧的重构了。

 

 

网络指标告警系统


在真正介绍监控系统重构之前,先说明一下使用到的数据库:

mysql - 存储告警配置、告警数据

clickhouse - 列存储数据库,用于存储海量设备指标数据

 

系统设计

在我接手原有监控系统时,系统结构是这样的:

我的运维开发生涯-网络设备指标告警实现

1. 探针采集设备指标数据->存入clickhouse表

2. 定时拉起监控系统后台执行程序->读取mysql告警规则->依据告警规则查询clickhouse表获取指标数据->判断指标数据是否异常->生成告警→存入mysql

3. 拉起推送系统推送后台执行程序->读取mysql中的告警->判断是否屏蔽→推送给推送系统。

这一套设计强调的就是系统稳定性,每一个模块各司其职。

 

1. 探针负责采集数据,采集好的数据存入clickhouse数据库。

a. 探针是分布式部署在每一个数据中心的,一般只探测各自数据中心的设备,尽量降低了中间链路对采集造成的影响。

b. 同时采集到的数据几乎未做运算就存入clickhouse,尽量降低计算bug对数据的影响

c. 由于数据及时罗盘,后续任何操作都由数据库提供数据,做到了数据持续化,尽量降低了数据丢失风险

2. 通过系统的crontab,定时拉起监控系统的告警模块;监控系统告警模块读取mysql的告警配置,然后依据告警配置查询clickhouse数据库获得设备指标数据;监控系统再对告警配置与指标数据进行对比,生成告警并存入mysql数据库。

a. 由于指标数据已经存入clickhouse,剩下就是上层应用如何使用指标数据了。为了在告警时效性与易于维护性中找一个平衡,我们使用了crontab来进行告警调用。这样即使某一次运行出了bug导致进程中断,后续的调用任然会补上前面的数据。这样设计还是以系统稳定性为主。

b. 告警配置是通过页面形式,让运维同学来做的,所以作为开发人员,我不关心告警配置的准确性。如果告警过多,他们会被其他部门的同学怼,所以配置就由他们去吧。

c. 这套设计最消耗时间的地方来了,那就是从clickhouse中读取数据。由于同一时间点,clickhouse都有几百万上千万条数据,需要从这些数据中查询出监控对象的数据,这里的耗时非常严重。我亲身体会是耗时以分钟计算,简直爆炸。

d. 指标值与阈值进行比较,这都是脚本来完成的,耗时不大,作为监控工具开发的同学对这一部分应该不会陌生。

e. 最终把告警数据存入mysql,落盘心才安。这个过程都突出了稳,问了系统的极致稳定性,可以丢弃时效性。

3. 继续使用另外一个crontab,定时拉起推送模块。推送模块从mysql读取告警数据,通过屏蔽等判断,生成可推送告警,调用外部系送系统的api,推送给相应的运维同学。

a. 还是那一套设计,为了系统的稳定,任然使用了crontab,定时拉起推送进程,从磁盘中读取数据,推送。一气呵成。

 

从系统的粗略设计可以看出,任何模块间的数据流通都是经过了数据库,在系统稳定性上确实可以做的不错,只要保证探针不出问题,上层应用无论出什么bug,对原始数据都没有影响。但是这样的设计也严重制约了告警的时效性,毕竟都经过数据库,面对海量数据,指望数据库高效是不现实的。

 

系统详细设计

依据上面的系统设计,对每一个模块进行详细解剖可以得到如下图:

我的运维开发生涯-网络设备指标告警实现

由于上面已经说明了整个系统设计,这里就不再详细说明了。只是说明一下为何要两分钟执行一次。因为实际情况就是每一次运行都要执行一分半,而且我们告警配置有一个连续性要求,必须以前面的告警作为参考。这就需要上一次告警执行完后才能执行本次告警,所以就需要两分钟才执行一次告警判断。

 

执行流程

我的运维开发生涯-网络设备指标告警实现

这里需要详细说明一下监控系统中整个指标采集-存盘-告警流程。如上图,整个指标数据经过如下流程:任务-探测采集-数据聚合-存盘-指标提取-生成告警-告警推送

1. 探针部分:完成 任务-探测采集-数据聚合-存盘 这四个流程。

a. 探针向监控系统的api获取采集任务,监控系统的api依据探针页面中配置的探针探测站点与采集策略,组装成采集任务列表发送给探针

b. 依据采集任务的间隔时间,探针定时向设备发送snmp协议进行数据采集

c. 获取到采集数据后,需要进行一定的聚合。如接口速率指标拿到的是当前时间点设备的总发送包大小,需要与前一个时间点的总包大小做一个减法运算获取间隔时间内的发包大小。

d. 将聚合好的数据转化为写入clickhouse格式数据,并写入clickhouse。

2. sknyet_cron定时任务部分(告警生产、告警推送这两个红色框):完成 指标提取-生成告警-告警推送 这三个流程。这部分是定时执行的,上面已经提到当前指标告警没执行一次大约需要70s左右,因此这部分设定为120s执行一次,也就是2分钟定时拉起一次。

a. 监控系统定时任务查询mysql数据,获取每一个告警对象对应的告警匹配规则。

b. 通过告警对象,查询clickhouse获取这些告警对象对应的指标值。这一部分非常耗时,因为告警对象很多(10万级),所以需要查询这几十万告警对象配置的指标,python的clickhouse的sql语句一次只能查询50个告警对象,因此需要查询将近1万次。这一部分大约需要60s才能完成。

c. 获取到对象的clickhouse数据后,监控系统定时任务依据告警匹配规则对对象的指标值进行遍历,进行阈值判断、连续性判断,生成告警数据。

d. 将生成的告警写入mysql的指标告警表。

e. 写入数据后,监控系统定时任务的告警模块调用推送系统的推送模块,让推送系统的推送模块开始工作。

f. 推送系统的推送模块查询mysql,获取本次生成的告警数据、告警屏蔽规则。

g. 推送系统的推送模块依据屏蔽规则数据,计算告警是否需要屏蔽。

h. 推送系统的推送模块将不被屏蔽的告警生产推送系统接收的数据块,并推送给推送系统。

 

经过初步计算,从设备出现异常到告警最终通过推送系统进行推送,整体耗时大约是(定时采集10s + 写入clickhouse5s) + (定时拉起任务120s + 告警配置读取10s + 读取指标数据60s + 告警计算5s) = 210s,也就是三分半钟。

这只是计算结果,实际从数据采集到到最后的告警通知到运维同学,中间经历8分钟。/(ㄒoㄒ)/~~

 

本章小结

详细解释了这三个模块后,我们会发现这一套流水线有一个很大的问题,clickhouse仓库存入了大量的数据,但是这些数据中只有很少一部分为告警所需,而且这些数据分散在仓库不同位置,仓库管理员需要拿着监控系统给的物料表(告警对象表)一件一件地去查,这效率非常低,对于几十万个对象,在查询数据上就消耗了60s,而且对象增加时查询耗时增加得更为恐怖。同时mysql仓库存入告警后,推送任务还需要从mysql仓库中把告警取出来,这也是没必要的,因为监控系统可以直接把物品交给推送系统,没必要在中间再来一次存入取出操作。原先这样做的目的只是避免出错,但是现在看来会很没有必要。

 

 

新网络指标告警系统


上面的系统中,数据准确性有探针采集时已经得以保障,告警准确性有运维同学在进行告警配置时保障,所以可以不考虑数据准确性问题了。可以看出上述系统最大的特点就是极度强调稳定性,毕竟是第一版告警系统,是从无到有的一个过程,系统设计时难免会进入一个死胡同。

为了在系统稳定的基础上增加高效,那就必须挖一点稳定性的墙角,分配给高效。因此在新版系统设计时,我优化了告警集中计算这个巨大的坑,交给了每一个探针来进行。告警计算前移,分散计算,解决时效性问题。

 

系统设计

废话不多说,直接上图

我的运维开发生涯-网络设备指标告警实现

图与旧版相比,只加入的一个kafka,但是事情不会这么简单。

为了解决上述旧结构的缺点(过于强调稳定性,忽略了时效性),新版结构对 数据聚合-存盘-指标提取-生成告警 四个流程进行优化,目的是竟可能降低这部分所消耗的时间,同时在增加告警对象的基础上也不增加这四个流程的时间消耗。出于这个目的,系统的指标数据流被设计为:

1. 指针采集数据→告警判断→告警预处理写入clickhouse与kafka、指标数据存入clickhouse表

2. 定时拉起监控系统定时任务后台执行程序->读取mysql告警规则->获取告警预处理数据(通过clickhouse或者kafka)->判断指标数据是否异常→生成告警→存入mysql

3. 告警数据推入推送系统后台程序→读取mysql中的屏蔽规则→判断是否屏蔽→推送给推送系统。

这里的clickhouse不只是存储原有的指标数据,还存储了告警预处理数据,由于告警预处理数据是达到指标数值超过阈值才会记录,所以相比指标数据,预处理数据要少很多。实际情况是指标数据大约每分钟条数是千万级,预处理数据是十级或者百级,直接降低了百万倍。

这样即使是通过读取clickhouse数据,也可以从过去的两分钟降低了200ms。

 

系统详细设计

在旧结构的基础上,重构后的系统加入了kafka,而且把clickhouse的作用提升为不但存储指标数据,而且存储告警预处理数据;而告警判断不再集中在监控系统来进行,而是前移至探针中完成。这样做可以有效分担计算,而且探针是golang语言编写,在程序执行效率上是python的10倍以上。

我的运维开发生涯-网络设备指标告警实现

继续详细说明一下整个新流程。如上图,整个指标数据经过如下流程:任务-探测采集-数据聚合与告警初判-存盘-告警提取-告警生成-告警推送。与旧结构相比,系统稳定性稍有降低,主要是因为探针做了更多的运算,告警迁移导致若探针出现问题导致有一部分告警无法生成,也就会被忽略。不过考虑到告警具有一定时效性,探针除了问题后续补回告警,可能也已经过去了10分钟,此时若业务受到影响也早已经被察觉,产生的告警也就失去了作用。考虑到上述情况,

在小幅度降低系统稳定性,大幅度提升系统时效性的指导思想下,优化上面提到的最耗时的四个流程。

1. 探针部分

a. 探针向监控系统api请求采集任务、告警配置信息。监控系统api依据配置的探针采集站点与采集策略,组装成为采集任务列表;同时依据采集任务列表中的设备ip,获取到这些设备对应的告警配置信息,将这些数据传递给探针。

b. 依据采集任务的间隔时间,探针定时向设备发送snmp协议进行数据采集

c. 获取到采集数据后,经过过滤器对数据进行初筛后,进入探针输出器。输出器包括告警输出、指标输出等。告警输出进行指标值与阈值判断;指标输出器直接将指标数据存盘。未来可能还会增加需求,只需要增加输出器模块即可。

d. 探针将采集到的指标数据存入clickhouse,告警模块将告警预处理数据写入clickhouse与kafka。告警预处理数据写入clickhouse的目的是数据可追溯,写入kafka的目的是若想追求极致的告警实时性,消息队列是一个不错的选择。

2. sknyet_cron定时任务部分(告警生产、告警推送这个大红色框)

a1. 监控系统读取clickhouse中的告警预处理数据

a2. 监控系统启动kafka监听,若kafka中有生产者发布数据,则系统自动消费kafka中的告警数据

b. 依据告警数据中的告警匹配id,查询mysql获取对应的告警匹配信息、告警推送匹配信息。

c. 依据告警匹配信息,对告警的连续性进行判断,将满足连续性要求的告警预处理数据生成正式告警数据。

d. 将告警数据写入mysql告警表。

e. 依据推送匹配信息,对告警数据进行屏蔽判断,并生成推送数据。

f. 将数据推送给推送系统。

 

执行流程

我的运维开发生涯-网络设备指标告警实现

依据上面的流程,得到上面这张图。我们实际情况下,clickhouse方法的告警从数据采集到最终生成告警,约耗时10-20s;kafka方法耗时5s。

 

本章小结

系统对监控系统的功能进行了缩减,监控系统只负责告警的连续性判断,不再对指标数据进行直接阈值判断,而阈值判断这种体力活交给了探针来完成。为了让探针更具扩展性,现将探针的输出器进行结构优化与扩展,原有输出器只负责指标数据输出,现在的输出器不但进行指标数据输出,还进行告警判断与输出,未来可能还会加入数据聚合与输出等功能。

告警预处理数据生成后,告警输出器将数据同步写入clickhouse与kafka中,方便监控系统进行任意一种告警生产模式的选择。

 

 

总结


新版告警系统的设计依照了:分而治之、平衡设计为指导思想。在初始上线时是可能因为稳定性稍微降低,会有一定的心理压力。所以在上线生产环境时,我控制了灰度测试的周期,尽量做到了慢慢上线,最终效果很不错。现已全面取代了旧版指标告警,真正实现了秒级告警。

由于当前代码与公司的实际业务耦合度高,后续把业务相关的都去除后,我再把代码上传到github中,方便大家参考,也欢迎大家提出建议。