@gaoxiaoyunwei2017
2020-01-03T15:17:42.000000Z
字数 7621
阅读 596
彭小阳
作者简介:龚诚,58集团智能运维团队负责人,高级技术经理。负责运维及自动化团队的技术和管理工作。
智能运维其实比较好的落地点是在监控领域,因为监控领域首先有很多的数据,我们有数据作为基础,可以做更多的智能分析。
我们在监控领域也有很多需求,对于大量的指标需要做异常检测,指标检测方式是不一样的。
另外我们收到大量的告警需要进行一定的合并,并且从中摘取出重要的内容,有这么负责的调用链,负责的系统,不同的监控系统之间是有关系的,怎么样从系统自动化的从各个关联关系当中分析出哪个是关联原因,哪些是衍生引起的,这也是比较重要的问题。
提到多维异常检测,大家肯定非常熟悉,在监控领域其实最重要的一点是要能够通过一些监控指标发现问题,当我们的系统越来越大越来越复杂的时候,想从繁杂的指标当中,几百个监控策略当中发现异常的时候其实是非常困难的,尤其是最初开始使用静态阈值的方式相对来说比较简单。
静态阈值这种方式,初期对主机性能进行监控,对你的CPU和内存使用率进行监控,这种方式还是比较好的,我们可以通过人工方式确定资源使用率达到60%,基本上达到了安全水平线,再高就有风险,就需要告警了,这个指标也有一定的特点,取值是在0到100%之间,可以根据人工的方式,根据我们的经验确定一个值,然后把它设立为一个告警阈值。
除此之外,当我们进行更多业务监控的时候,面临的挑战就更大了。
举个例子,比如说第二幅图里面,某些集训由于处理的逻辑比较简单,所以响应时间会比较低,正常来说,响应时间比较低,是不是设置阈值的时候,阈值也要设置的比较低,一旦发现异常可以马上发现。
如果基于传统的方式我们来解决这个问题,其实需要人工有很多分析,但是监控指标数量实在太多了,已经达到了人类不太好人工处理的地步了。怎么办?我们采用一些基于统计的方法,我们后面再详细来说一下,比较好解决了这个问题。
第三种监控指标是随着每天用户访问量,发生变化的,当用户访问量比较小,自然数值就下降,达到用户访问高峰期的时候,数值就比较高,呈现波动性变化,很难用一个阈值来解决这个问题,我们利用机器学习的方法,学习历史数据规律,采用分类模型的方式判断是否有异常。
第一个比较简单,固定阈值这种方式,好处是比较简单直观,坏处是难以适应日益复杂的需求。
第二个方面,某一个机群显示时间,类似这种指标我们用统计判别的方式来设定是比较好的,其中比较好的方法也能够比较好的识别出历史数据大部分时间是分布在哪个区域,从而设定一个合适阈值的。
另外这种方式也有一定好处,当你集群行为发生变化的时候会自适应进行一些调整,比如说如果这个集群最开始响应时间比较低,自动生成阈值,自然也是比较低的,当前几天突然出现响应时间增高,出现一个变化的时候,那自然是要出现一些告警的,这也是符合需求的,前几天出现了一些显示时间增大,我们肯定要进行一些告警,但是如果后续持续每天都出现这些问题的话,就说明这是没有问题的,可能由于处理逻辑更加复杂了,所以响应时间就增常了。
我们通过统计最近几天显示时间历史数据变化,从而重新生成和调整阈值,逐渐把阈值调高,这样后续几天就不会有异常发出了。
周期性指标异常检测,由于这些数据的变化是随着用户的访问量进行变化的,一般来说都是一些关键指标,用户访问的成交量、订单量这些指标,对于运维比较关注的,像网络出口流量和业务流量,以及集群和域名的访问量,还有一些宏观业务数据,相对来说,这种类型的指标如果能够发现异常,并且有问题发出告警,产生的意义会更大一些。
这个事情具体怎么做,我们采用机器学习的方式,用最近一段时间的历史数据通过对模型进行训练,然后把实时数据抛到模型里面,从而得出当前数据是正常还是异常,从而发现这些异常。
如果用机器学习的方式,是一种有监督学习的方式,运维过程当中指标的数量这么多,怎么样标记这些数据,得到一个有标记的样本库,采用统计判别,首先得到一个基础样本库,一个训练集,然后经过一定处理,训练模型,从而得到了通过分裂模型做异常检测的任务,同时训练一个回归模型来得到曲线预测,实现这样一种功能。
这里面体现了我们用到的对比样本库,以及我们选取的一些特征。
选取这些特征采取的算法是Lightgbm。
智能异常检测的效果,普遍异常我们标记为黄色的点,如果出现一些严重的异常我们标志成红色的点,这三个图当中,异常等级不一样,第一个图是普通异常,偶尔有一个毛刺飙上去了,对于整个数据的影响是比较小的。
第二种是严重异常,说明一些应户的推广活动或者运营活动,也有可能是系统出现了某些方面的问题,导致流量下降。
第三种是陡变异常,这种陡变异常变化,一般来说比较致命,有可能是流量大幅度上升,突然大量攻击流量,或者说流量突然下降,整个机房网络这方面有问题了。针对不同类型的异常我们做不同的告警分级,普通的异常我们甚至不用太关注,对于严重异常我们可以用告警短信和微信的方式解决。对于特别严重的异常可以通过语音告警的方式来进行。
分类模型的方式进行异常检测效果也是比较好的,尤其具有比较好的普世性。我们对于,尤其做业务指标监控,收入监控和产品线PV、UV监控,以及小的业务集群的监控,这种方式都可以实现,适用于不同级别的数据,包括网络带宽比较大,甚至几十亿级别的数据,对于某些业务集群,可能每天的QPS低峰的时候只有几十,不到一百,所以可以很好解决这个问题。
作为技术人员都有一个痛,系统出现异常的时候会出现很多告警,平常有一些关键告警,当某一个核心系统真正出现异常的时候,大家肯定有这个体会,同时会有大量的告警发出。
举个例子,现在比较流行微服务的方式,如果某个集群里面有一百个节点,当由于访问量变化,导致资源使用率上,或者说因为某次上线,导致程序出现了Bug,我们如果设置一个短信的接受方式,是不是手机一直在响,一方面要检查出现什么事故,排除问题。
CPU如果有什么问题,导致集群的可惜会上将,也会导致时间上升甚至其他的问题,刚才说的告警数量去翻了,我们需要有一个能够比较智能的对大量的告警做理解和信息合并,并且提取出一些信息,告诉我们究竟发生了什么。而不是给我们原始数据,我们要的是信息。
因为之前和很多大型中型和小型公司的负责人都沟通过,其实做智能告警处理之前,最好先把告警数量降下来做好告警分类,我们现推荐语音的方式,除此之外大部分的告警还是推荐员工订阅微信告警,只要员工订阅了微信公众号告警,里面可以展示的信息非常多样化,我们可以展示告警详情和相关的应对,包括一些合并的信息列表和做一些根根因分析,避免误告。
我们对内部监控系统也做了分析,有些可能做的不太好的监控系统,有一些设置连续一次异常就告警,这种无效告警非常多,甚至说无效告警内容达到50%或者更多,正常来说,两次告警间隔时间间隔五分钟,设置最高的告警次数是多少,如果超三十分钟,还可以提到更高的优先级进行椎理。
在告警时间窗口选择上,如果把窗口拉的比较长,相关的告警就可以合并效果更好,但是反而时效性会下降,为了兼顾时效性,在合并维度上我们发现一个集群之内,同时会出现多个告警,我们合并起来效果就会比较好,对于单个节点和IP里面,上面可能会出现异常,上面不同监控指标也会出现异常。
比如说某个机器宕机或者僵死,有一些进程和端口也是不及时的,也有业务指标也是不及时的。另我们服务器也是使用网络连接起来的,如果某一个网络设备出现问题,同网段的一些机器也会出现丢包率过高的问题。
另外我们可以按照异常种类进行合并。以上只是常见的维度,真正的维度更加复杂,而且出现的异常不仅仅是单个合并了,往往是几个维度互相组合了,这样实践起来大家很自然最先想到的可以用规则和模板的方法,但是维护代价非常高,而且扩展性比较低。我们用了一个新的方式,我们提出了告警合并数的方式,对告警进行划分,实时计算出来应该按照哪些维度进行合并。
这个算法简单理解起来我们按照一分钟的告警信息进行合并的,我们那一分钟的告警进行集合,需要到每个人的告警进行合并,对于每个人相关告警的类型,以及不同的告警方式,按照这几个维度,如果一致的情况下会对这个人的告警进行合并。
具体合并过程是什么样的,其实可以理解为树型结构,一分钟的所有告警,根据刚才的维度划分,生成一个集合,可以理解为一个树的根节点,尝试用不同的几个备选维度进行集合划分,按照集群的维度,IP的维度或者网段的维度进行划分。
这样我们有一个备选集合,再针对备选集合,计算基尼值,看是不是把同类消息划分到同一个下级节点,如果是的话会带来这棵树的信息纯度上升,我们就是为了让同样的告警划分到同一个地方去,这样的话我们除了根节点之外,我们就得到了第二层节点,以此类推,如果当前告警数量还是比较多,可以看其他维度。
如果尝试合并的话是否也可以再进一步拆分出节点,基于这些规则,告警里面信息条数和程度提升到了什么程度,从这棵树的根节点,最终到达叶子节点,其实经过了多个维度的告警合并,我们就可以确定我们应该按照哪些维度把这些告警进行划分,推送给我们的用户了。
这是告警合并的效果,刚才已经提到了,我们比较推荐微信告警,因为里面展示的信息可以把我们想展示的表格和一些数据,甚至一些图形化的信息都展示进去。
我们收到第一个告警,告诉我有一个集群里面有22条宕机告警,传统的方式是22条告警,现在只告诉我一条,而且告诉我合并的告警异常机器占总体机器数的比例,如果我想看这22个宕机告警分别是哪些,点进去看可以看到一个列表,再往下可以看到每台机器的具体情况和监控指标的变化曲线图。
这里面也是我们智能告警合并,按照多个不同维度合并之后的效果展示,首先我们看一下第一个方面,某一个集群有22个宕机告警,可以提示当前服务器异常比例84%,整个集群里面26台机器,现在有22个有问题,不仅仅是说把告警机器人简单合并,而是说从22个告警里面能够提取出一些有用的信息,并且展示给运维人员,这样就很方便让我们判断,什么地方出现了什么问题。
对于服务器和指标级别进行合并,某一个服务器现在有内存过高的告警,我们知道这个服务器内存有问题,影响面就是服务器。
对于集群和指标维度进行合并,能够看到某个集群现在已经有六表磁盘空间不足的告警,当前集群服务器的日常比例,百分比是多少。
其实难点就在于合并的时候是按照多个维度进行合并的,而且是实时对数据进行分析的,看哪个维度进行合并会带来信息纯度提升最大。某一个机房有四条虚拟机宕机告警,由于宿主机都是同一台,从而判断出虚拟机由于物理机宕机导致的。再往后某一个机房,这些机器归属于同一个网段,很有可能是某一个网络设备出现了问题,非常方便运维人员判断究竟哪个点出现了异常。
服务器维度和指标维度相结合,服务器在五个集群有五条GAM过高的报警,最后一条是服务器维度,某个集群的服务器有三条GAM内存过高的告警。
展示这个,我们可以通过实时分析数据,按照报警合并的这种做法,按照不同的维度进行最恰当的方式进行合作,并且在合并国境里面提取出一些更加更加有用的实习。告警合并最重要的目的是减少告警数量,这里面可以看到告警数量的变化趋势,红线之前可以看到不同的方式,包括、锻炼、语音,每天变化比较剧烈,数值比较大。
同时和大家分析一些知识图谱构建,如果我们想打造一个更聪明的运维智慧大脑的话,想做更深入的分析,比如说根因分析,现在人为什么有智能化的处理能力,或者说这种分析能力,其实一方面是有知识,另外一个方面是相关经验,对于同学来说,知识和经验这两方面都是空白。
所以说可能要进行更加智能化的判断,先要建设好知识图谱,知识图谱很重要的两点,一个是知识一个是经验,首先对于知识来说,需要把运维相关的各个系统的知识进行整合打通,现在有很多系统CMDB,监控、管理、云平台,如果出现故障,可能和各个系统之间都有关联,尤其是一些变更上的事件,导致引起一些问题。把所有系统联动,把信息整合起来。
我们关注的这些运维相关的数据对象也比较多,包括机群、服务器、端口、进程。我们通过挖掘得到了主题之间的关系,包括关联、因果、部署这些。
获取到运营主体的各个特性和变化规律,从而得到和集群和服务的画像。
运维知识图谱当中这些点是最实用的,比如说整个网站结构是一定要清楚的,整个用户的流量,通过VIP进入网站,也一个流量分组,在Nginx上有流量变化,有一些外部服务,还有一些数据服务、屯出服务,每层的关联关系是什么样的,病人有什么特性。
调用链毋庸置疑也是非常重要的方面,是服务之间的调用关系,现在在微服务部署的背景下,现在有很多业务非常复杂,相关的服务也是非常多,而且关联关系也非常复杂,如果有了这个调用链信息,就可以很容易判断故障之间的关联。
对于监控指标也要进行分层,服务器层、系统层、业务层,这些都是相互之间一定的因果关系。服务故障关系方面,缓存挂掉,数据库压力比较大,也是比较常用的一些知识,包括对于基础设施的依赖,内网对于DNS的依赖。
这些知识和经验需要怎么挖掘出来,刚才提到数据也是智能化的基础,我们首先要收集到各方面的数据,然后从这里面挖掘出一些信息。首先第一步有各方面的基础数据,将平台打通,使数据之间建立起一定的关联。第三步要进行关系挖掘,比如说故障之间有什么关联,服务部署调用的状态是什么样的,每个集群每个服务的变化规律和特性是什么的,能够达到运维画像。
这里面有一个例子,不同的平台不同的实体是有一定的关联关系的,但是由于不同的系统是在不同的时期开发完成的,所以当时设计的时候没有考虑到进行一定的关联,后期为了更好的打造运维大脑,必须把相关的中心关联起来。
CMDB里面有一个集群名的概念,更早有服务名的概念,要在多层服务之间,A和B之间有很多机器和节点,时间实现自动化调度,实现了服务器管理平台,调动都是通过服务管理平台连在一起,所以很自然我们要把集群和集群名进行。
我们抽取了很多的一些特征,比如说归属于哪个部门,负责人有哪些,集群做什么用途,以及一些流量变化的趋势和集群当中有哪些服务器,最终抽象成为有哪些是一致的特征,有哪些是重合的特征,哪些是归属的特征,最后用孤立森林的决策方式,完全了主体影射,从而把各个系统之间进行打通。
关联挖掘方面我们使用一些其他的改进算法,发掘出哪些是常常会一块出现的异常。同样使用这些算法过程当中,也可以根据我们的业务,调用链或者常见的根因经验,从而减少算法的复杂性。
通过关联挖掘方式可以拿到哪些是相关的,可以对因果关系进行验证。根据实际监控指标曲线,监控曲线的变化看是不是真的相关,相关度如何,就可以用皮尔逊相关指数方式进行验证。
最终我们得出的一些指标关联图比较复杂,我们也是为了方便大家理解选了一些比较简单的。比如说CPU.idle,或者说ping.down,通过这样一个比较大的图,所有的监控指标之间的因果关系就比较清楚了。
调用链也是非常重要的知识,服务之间有非常复杂的调用关系,出现一些异常我们必然会根据调用链判断它们之间谁是因谁是果。我们公司有一个公共框架,大家在写代码的时候会把这个框架包含进去,我们也会自动采集服务的调用链。
这些是更高级一些的东西,我们可以搞一些集群和服务的画像,从而应用在低负载管理、容量管理、容量预测、预算各个方面的系统里,建立起一个类似于大家比较熟悉的用户画像,我们对于集群和服务的一些特征和一些日常运行的规范规则进行服务画像,其中也包含一些基础信息,比如说集群名,是不是全容器,全上云的集群,部署方式是什么样的,服务类型,以及访问量,访问量的变化和规律,流量是属于比较低中等还是比较高,以及访问时间段,我们做一些流量预测或者说容量评估的时候其实都会用到类似于这些相关的系统。
讲到根因分析,只要我们收集到大量的数据知道当前时刻所有的监控指标的变化的数据,并且能够标记当前出现了什么故障,收集了足够多的数据训练模型,只要把数据扔给模型就知道这个根因分析了,这是一个比较理想化的想法,实践起来比较难。
因为首先整个系统非常复杂,相对来说需要非常庞大的训练集。但是我们的训练集基本上都是一些故障或者事故的数据,这些事故数据是不可能非常多的,如果非常多的话说明稳定性做的非常差,基本上这种方式不太好实现。
所以我们采用动态决策的方式,输入一些实时异常和变更实践,通过根因分析组件,每个系统动态决策哪个地方出现了问题。
实现根据人的经验,根本这些知识判断哪个地方出现问题,其实又有两种可选择的方案,一种是状态机的方式,一种是行为树的方式,这两种方式在之前游戏开发的时候比较类似,应用比较广泛,因为游戏里面有很多角色,会有一些动作。
比如说一些简单的游戏,有卫兵在守卫城堡进行巡逻,这些逻辑都是用状态机或者行为树的方式呈现,这种方式不是特别好的方式,整体来说系统耦合度较高,因为每个状态都是有一个节点来表示的。之间的关联比较复杂,可扩展性会比较差,所以我们使用了行为树的这种方式。
行为树这种方式比较好的一点是有几种节点,有逻辑节点和执行节点,逻辑节点可以理解为控制节点,根据经验去追查这个问题,我应该按照哪个逻辑,按照哪个顺序查什么信息,得出判断。
这是我们和根因分析相关的行为树,在逻辑节点上可以分为选择节点,底层的这些节点如果执行的成功就结束了,数需节点是数需执行一直到失败或者结束,主要目标也是为了控制我们根据人的经验。
如果我们要判断在哪些领域哪些方面排查这些问题。很关键是行为节点,主要执行的是数据的处理分析任务,人的经验用来判断我从哪些方面排查问题,定位到问题的时候要用到监控不同指标之间的因果关系,两者结合起来就可以比较好的完成这个任务。
这里面有一些行为节点可以发现的一些问题,能够关联起来的一些根因,指标关联分析,如果你的访问量上涨了,CPU负载会比较高,如果一个底层的服务出现问题,会影响上层服务。
这是一个根因分析框架,左侧主要是数据提取方面,中间这部分其实也涉及到很多监控指标的关联或者服务调用的关联,以及变更操作的关联,以及底层网关硬件相关的状态关联。最终我们如果说去验证关联是不是真的有比较高的相关性,可以用曲线相似度再判别一下。
这是几个例子,这是根因分析,某一个宿主机出现宕机了,会导致两台虚拟机出现问题,导致这个集群出现了504比较高的问题,通过这种比较图形化的方式,能够比较好的展示异常,红色节点经过点击可以收缩起来再展开。
这是另两个例子,当集群左侧的访问量升高的时候会导致丢弃率比较高,从而影响响应时间和可能性。右侧是由于一次上线事件,导致了可能性下降,这样可以把多个集群和多个监控指标之间的异常串起来,而且很好的展示给我们的用户。