@gaoxiaoyunwei2017
2019-03-08T17:57:29.000000Z
字数 9167
阅读 523
白凡
分享:龚诚
编辑:白凡
我是58集团集团智能运维团队负责人龚诚,今天想分享的主要内容一方面先讲一下我们对于智能运维的理解,第二方面讲一下我们对关键指标的一些智能监控方面的工作,接下来是监控方面的告警合并、根因分析、故障自愈等方面。
简单介绍一下我们58集团,58集团下属这么多的网站,对于我们来说,面临运维的服务器规模越来越大,业务越来越复杂,所以简单靠人力和自动化运维已经无法满足我们现在的需求,所以对于我们来说,智能运维是必须做的事情。
说到智能运维,也可以提到监控系统,监控是一个智能运维优先落地非常好的场景,因为监控是和服务稳定性相关,大家非常重视,而且有很多的数据可供我们分析和使用。
所以,今天主要是围绕监控方面来讲。
对于监控来说,它其实发展也是分这几个阶段,第一个阶段是监控的自动化,我们实现了监控系统能够可用、好用就达到了目的,第二阶段是监控的立体化,包括监控指标都能覆盖到。第三阶段是平台化,将监控系统和CMDB部署管理系统打通联动,再往后是产品化,让我们的用户,即使是内部的用户用起来也是非常容易用的。最后到了监控的智能化阶段。
传统的监控和智能的监控有什么差别?通过这里面可以看到,传统的监控指标比较侧重于单个的监控指标,而且是比较基础的指标。智能监控侧重于整个业务运行的状态,传统的监控是做固定阈值的异常判断,我们智能监控就能做周期性关键指标的检测。传统的监控只是发出基本的告警,而且很可能发出告警的数量比较多,但是我们智能的告警能够对信息进行有效的区分和整合,这样有一个更高的告警质量。
传统的监控是对故障现象的告警,需要大量的人工分析,智能告警有更多的智能能力,能够对数据进行分析,对故障的根因技术分析,最后给我们一个最可能的原因。
传统的告警是发现问题而不处理,由人来决定和处理。但是,智能的告警能够做到根据故障的根因智能地决定我应该如何处理。
最后,传统的监控是发出告警的时候,往往这个故障已经发生了,只能做一些应急的事情。对于智能监控来说,它能在故障发生之前发出预警,能提醒我们做很多系统优化方面的事情。
所以,这是我们对于智能监控方面的总体规划,从这里面可以看到下面图里的几点:
第一点,故障预警,我们希望平时做好系统的优化,在系统发生故障之前能提前做出故障的预警。
第二个,故障的告警,我们不但能对普通的监控指标进行告警,还能够对于一些周期性变化的关键指标进行一个告警。
第三个,告警的合并,我们支持按照一个合适的维度对告警进行一个合理的合并,展示出概况的信息。
第四个是概况的根因分析,我们能自动地判断出故障的根因得出最可能的原因,提示给人来做辅助决策。
最后一点,我们也可以根据故障的原因选择一个合适的故障自愈策略来自动地解决这个故障。
这个智能监控它适用于哪些场景?首先举第一个例子,网络出口流量的监控,它就是像右侧这个图一样,会呈现一个周期性的变化,凌晨的时候,流量会比较低,平时的时候我们流量会有一个高峰值。
对于这些周期性变化的曲线,我们简单用一个静态阈值肯定是做不了异常检测。
第二个场景是我们业务很复杂,有很多集群和域名,对于集群和域名的访问量变化也需要监控。
第三个就是很多宏观的业务数据,比如说整个的网站或者某项业务的PVUA,如果是电商型的网站,你的订单数变化、成交额变化,你的商业收入变化,都可以呈现出周期性变化的曲线,这其实有一些特征,规律性比较强,也就是每天基本上都有低峰高峰的流量变化。
在局部上来看,其实是有一些局部的短期小幅度波动,这些整体规律性比较强,说明我们可以做一些预测和异常检测,短期的波动比较多,说明这其实是比较有难度的。
我们对于这种指标的监控其实归纳起来是两个主要的需求,第一个是按天对流量做一个提前的预测,第二个是对于实时的流量做一个实时的异常检测。
所以,我们采用的技术方案是和机器学习的相关技术结合起来,使用回归模型方式解决数据预测问题,使用分类模型方式解决了异常检测的问题。
这是一个基本的使用机器学习方法这几个主要的步骤,明确问题、处理数据、训练模型和使用模型,这也不多介绍了。
对于我们流量的预测和异常检测的技术框槛主要分成两部分,一部分离线部分,一部分在线部分。离线部分利用原始数据得到由表及的样本库,然后通过特征工程分成回归模型来预测流量,通过分类模型来输出模型,首先拿实时的数据做一个特征工程,最后输出标记。
做机器学习很重要的一点是你有很多的数据,而且这些数据是要有标记的数据,如果采用人工来标记数据肯定需要大量的时间和精力,我们怎么在短时间内高效地解决这些问题呢?我们通过原始数据,首先通过统计判别及无监督的方法得到有标记的样本库,然后训练整个模型出来之后,后续所有的流量数据都能够进行一个实时的探别,我们人工可以去查看这些数据的方式来看待自动标记的是否准确,对于默写模型有一个反馈,这样使得模型越来越准确。
这里面最关键的部分是我们怎么样统计算法和无监督算法来做标记,其实展开的就是底下的情况。
我们首先选择了两种统计判别方法,有两种无监督的分类模型,每一个数据都经历了这四种模型进行一个判别,对于大家都认为比如说有三个或者四个模型认为是一个异常点,我们就把它标记为一个异常点。
如果这四个模型都认为是一个正常的点,我们就把这个点标记为正常的点。
所以,这样我们就得到了有标记的样本库。
当然我把这个样本库作为训练的样本库,里面肯定是异常或者正常的点,我用这些点来训练分类器,通过输入的绝对正常点和绝对异常的点,学到两者之间的特征,然后我再把全部的数据通过分类器去进行一个筛选,经过分类器输出的其实是一个异常的概率,每一个点都是有异常的概率,我选择对所有的异常概率做排序,取TOPN的是最异常的,这样就得到了原始的数据样本集里面哪些是异常的点,通过这样方法可以快速有效地完成数据的自动标记。
对于流量预测来说,它其实是有这样的特点,这些指标整体的规律性比较强,所以我们比较容易对它进行趋势的预测。
第二点是短期的小幅波动比较多,我们采用移动平均的方法去吸收一些短期的波动。
另外也是跟网站的特点相关,我们在工作日的时候,周一到周五流量高,周五周日和假期的时候流量略低,所以我们需要涉及对于历史特征的提取规则。
在模型上我们选择了回归模型方式,历史特征方面,选择了历史同期流量的统计特征以及变化的这些趋势,以及移动平均的相关特征。
这是一个流量预测的效果,这个图里面有两根线,一个是红色的线代表实际的流量,一个是蓝色的线代表绿色的流量。
通过图中来者之间的混合度比较好,说明预测的效果也比较好。
下面再介绍一下异常检测方面,一般来说,异常的流量肯定是跟正常的流量是有一定的反常的波动,而且异常相对来说发生的频率比较低,所以一方面我们通过前面统计判别接受无监督学习的方法,得到有监督的标准库来训练样本模型,然后构造一个合适的对比样本库,这样提取特征,我实时拿到一个数据提取特征之后,跟样本库进行比较就可以判断出正常和异常点。
对比样本库我们选择的是当前的时间点往前N分钟以及昨天和上周同时段的数据前后做了对比样本库,我们抽取了这样的统计特征,包括标准差最大最小值,最终选择一个新来的数据实时的数据,我采取了这样的一些样本的对比特征,比如差值、比值、同比、环比,这样得出了它是异常值的概率,就可以知道它是正常和异常的点。
对于我们解决预测和异常检测的问题其实采用的都是尝试不同的算法,看看后面效果哪个会更好一些。这是异常检测的效果,通过图中可以看到,我们其实除了能识别出来异常的数据点是一个异常点,而且能够知道它是一个什么样级别的异常,总的来说是有比较好的朴实性,它适应于不同的业务数据,对于普通异常其实比较简单,就是通过刚才的分类模型简单做一个判别就可以判断出来。图中红色的点是分类模型自动判断出来是异常的数值,已经持续地偏离了一些之前的数据,这种情况,一般来说有可能是由于一些运营推广活动造成流量增长了,也有可能是由于系统本身是存在一定的问题,所以它这个流量出现了一定的偏离。
这种方式我们怎么判断出来?首先第一点就是通过分类模型判断出来它是一个异常点,第二点是通过下面这种算法来判断它是一个持续偏离正常值的一个方式。
其实简单来理解,我当前的值减去历史上平均的值除以我历史上的标准差,如果说它在标准差的波动范围内,基本上属于正常的,如果说偏离的过多,确实就是偏离比较大的,就是严重异常的点。
对于陡变的异常,流量突然出现了断崖式的增长或者是降落,一般来说,这种是由于网络流量的攻击造成的,或者说某一个系统出现了严重的问题,流量突然下来了,或者突然涨回去了。
同样,我们首先通过类模型先判断出来它确实是一个异常点,它属于哪一个级别的异常?是采用下面的公式方法,所以怎么样能简单理解一下呢?其实就是你通过当前的时间点,你可以往前找5分钟的数据,就得到一个数据点的集合,再往前找一个数据,这样你就有两个连续5分钟的数据,你分别对这两个5分钟的数据做一个均值,看看它俩的比值如果低于1说明它们的变化不大,如果比值过大,肯定两者之间出现了巨大的变化,就说明有异常的发生。
普通的异常可以用短信的方式通知,严重的异常会用语音来通知。
其实做智能告警合并之前,我们用常规的方式也能够很好地做到告警的收敛,或者比较精准的告警,也就是你只要遵循下面几个告警的发生策略就可以做到。
第一个,首先实现告警的分级,不同重要程度的告警用不同的告警方式发送。为了避免单个点的异常会造成很多频繁的误报,我们可以连续M点的告警,或者为了解决系统不稳定时好时坏的问题,我们可以用在M时间段内有N个异常点来告警。
另外为了控制告警的数量,我们可以通过控制连续告警的两个时间间隔,让它大于5分钟,另外通过控制告警最多的次数,为了更好地提醒大家去跟进这些故障的处理,如果说我连续发送三次告警之后,再过三十分钟这个告警仍然存在,故障还在没有人解决怎么办?我会对告警做一个升级,会以更明显的方式来提醒相关的负责人。
下面是真正智能告警部分,首先我们要合并告警要选一个合适的时间窗口,我们综合考虑了合并效果和告警的实效性选择了一分钟做合并窗口。我们也得到了一些告警的合并的收益,包括避免了海量的告警,快速地根据合并后的告警信息,也可以决策故障的根因。
下面的一点是合并的策略,什么时候告警可以合并?发送给同一个人的告警可以合并,如果都是异常也可以合并,如果都是恢复正常,这个要作为另外一个进行合并。
第三点就是相同的告警方式,短信的要跟短信的一块合并,语音的跟语音一块合并,是不同的重要程度。
最后合并维度都有哪些?我们常见的一些,比如说按照集群合并,有很多时候如果由于部署上线、变更操作,更新的程序导致的告警,一个集群肯定会都出问题。
如果由于整个系统依赖的某个服务有问题,也会整个集群告警。
所以这个时候要根据集群进行一个告警合并。
第二点,如果说某一个机器出现问题,可能这个机器相关的指标多会出现异常,所以这时候会根据服务器的IP进行合并。
第三个,由于我们的网络设备下面有很多的服务器,肯定整个网段的服务器都会有一些问题,所以这时候可以进行网段进行合并。
第四个可以根据异常的种类,比如说同样都是宕机的,或者同样都是负载高的,同样都是出现错误的,根源很可能不一致,这个可以进行合并的。
最后一个比较简单,可以根据宿主机的关系进行合并。
这是我们对于智能告警合并维度选择,可以引入基尼值,你对于信息纯度的一个变化,所以我们下面举一个具体的例子,比如说左侧的截图是50条告警,其实是不同的集群都出现了问题,我们可以看到,如果按不同的集群,不同的异常信息进行合并,大概是这么多条,所以从数据上看,给人的第一感觉肯定是可以按照集群维度来合并比较合适。
所以,我们这个合并的算法其实就是一个告警合并树思路。首先你要生成这个树,要先生成这个根接点,我就根据不同的合并维度分别去算它的基尼值,算纯度的提升,选一个纯度提升最大作为根接点。
用通俗的方式就是刚才你看到很多数据如果按照不同集群技术合并的话,划分成几个集合,这个按人来说是最希望能看到这样的,比如说你把赶集的放到这个集合,把58同城放到这边,你把它分开了,每一个集合得到了提升,所以大概就是这样的思想。
我们得到根接点之后,就可以计算下面每一层的节点,最后生成这么一棵树,这棵树每一条路径其实就是一个告警合并的路径,我们就知道对于某一个人来说,一分钟内要收这么多的告警,我可以根据这么多的路径分别做一个告警的合并。
既然有这么多的告警可以合并,那也不能排个大列表直接发给他,这样对于人来说,收的信息量也不是特别够,所以说我们希望将这些告警的信息合并成一个概括的信息,把概括的信息发给他,我们就需要概括的信息第一要简单清晰,它是高度概括,符合人的沟通习惯。
第二个,要概括性比较强,能够对合并的告警进行概括,体现出其中很多的重点信息。
我们在具体的做法上也是根据不同的合并维度,使用了不同的合并模板,然后也会将一些监控指标类似于DF的这种人不太容易阅读的,其实大家更容易理解的是磁盘空间不足替换成人更容易理解的说明。
所以我们来看一下告警合并的效果,这个图首先是不同颜色的曲线代表不同的告警方式,右侧数值的红线左侧代表的是合并告警上线之前,告警的数量是非常多的,在合并之后,其实数量是比较平稳而且明显降低了不少。所以,大概告警的数量减少了76.65%左右,效果提升非常明显。
很重要的一点,它不是定死了一些规则,按照集群或者IP合并,而是我根据你这一分钟要合并的数据实时地按照告警合并数的策略去调整应该按照哪个去合并,这里面我们发出了告警的示例。
前几条可以看到它某个集群有22条宕机告警,其实是按照集群维度合并的,22条宕机就是按照监控指标进行合并,按照两个指标进行合并,这样就很容易看到某一个集群有多少条告警,基本上跟人的交互方式就比较接近了。
再往下看就像集群有两条宕机告警,一条服务器网段10.9,这是按照三个维度合并了,首先是集群,第二是告警的种类是宕机,第三个是网段。
所以从下面的几个大概也可以看出来可以灵活按不同的方式生成告警的信息,尽可能地像人和人之间沟通的方式。
这是我们微信告警的展示,提到我们告警其实提供了多种的方式,我们还是推荐大家来订阅微信告警,因为你语音和短信可能仅仅是一条比较短的信息,但是你在微信里可展示的信息非常多,可展示的数据多样性也非常好,这里面也是我们合并之后告警的概况,某一集群有22条宕机告警,点进去后看详情,这是告警合并的信息列表,上面是合并信息的概要信息,再点进去是第三条,可以看到单个告警的信息,拉到底下可以看到数据的视图,看到数据的变化,从而判断我异常的程度到底是有多严重。
其实根因分析从简单的方面做还是比较容易,比如说由于宿主机宕机,虚拟机肯定会宕机,由于服务器硬件损坏肯定会宕机,如果由于某一次服务器变更导致集群异常,所以比较容易判断。
我们也做了几个略微复杂一些的关键指标,比如说网络流量,他们会有一些变化。举两个例子,如果说我们的网站APP端流量异常了,有比较大的降低,它肯定会影响总体网站的流量变化。
另外如果某几个集群出现了故障,肯定会影响整个的网络出口流量的变化,这个都是可以分析出来的。
再往业务集群上讲,其实也有很多调用链之后,将告警信息和调用链一块进行比较分析,就能够知道某些集群的异常是由于其他的引起的。
另外对于监控指标分层也比较容易理解,我们从底向上可以分成服务器层、硬件层,然后应用层,甚至最上面的业务层。如果说宕机或者端口的异常肯定会出现一些5xx的错误。
最后一个也是基于变更事件的根因分析,变更事件跟异常数据、异常告警也有一定的关联。所以说,其实根因分析做到后来,基本上都是要依赖于运维知识图谱,但是这个说起来很炫,具体包括哪些内容呢?在我们实践方面包括第一个网站总体的结构,首先从大体上可以分为用户流量接入进来的时候,有一个流量的分组,有网站的总体流量,有三端的流量,甚至可以切分成某一个业务的流量。
再往后调用外部服务,然后再调用数据服务和存储服务,所以是总体的概况。
对于VIP流量分组,网站的总流量、三端的总流量还有VIP的流量,监控指标分层也可以看到是服务器层、系统层,还有服务层、应用层、业务层各层之间。
另外还有一些在人脑子中的一些经验,比如说缓存挂掉,肯定会压力上升。另外对于很多基础设施也是有依赖的。比如服务之间是通过内网DNS进行调度的或者是通过流量分发服务进行调度的。如果出现问题很可能是基础服务出现了问题。
除此以外还有其他的因素,一方面是异常出现的时间相关性相关联的异常往往是在相邻的时间内出现的。
异常事件和变更之间肯定有一个关联的,由于变更操作导致异常的发生,最后一个,如果说调用链真的不能采集特别完整,因为完全采集完整还是比较困难,那其实我们可以通过频繁项集方式来补充调用链不完整的情况。
如果整个网站的流量异常,或者某端流量异常他们之间的关系能不能自动地判断出来?底下用户可以看到用户流量进来,这之间有流量的关系,必然存在异常。
我们可以看到,很多我们想监控的数据其实都是持续型的数据,在这个图中都是一些曲线。其实持续型的数据都是可以用向量表现出来,如果想计算出来这些向量的控制距离、相似度,我们找到了它的改进算法,基于皮尔逊相关系数来做的。
左侧这个图可以说是网站整体的流量图,右侧的三个图是网站三端的流量图。当总体流量发生变化出现巨大的降低时候,是由于谁引起的?如果我们人去看,很明显看到的肯定和右侧的第一个图相关。
但如果在一个运维系统当中出现了故障,相关的数据特别多,你很难在海量的数据里找到相关联的数据.
我们通过皮尔逊相关系数的方式,对这些数据进行相似度计算,通过这个表里面可以看到,其实非常容易就发现我们整个网站流量异常变化是和其中的一项相关的就容易得到异常故障的原因。
再细往后追查,某一端流量的异常跟我后面具体的某些集群的异常哪些相关怎么做是类似的,我同样计算皮尔逊的相关技术,很明显,上面四个图是相关性比较高,通过皮尔逊相关技术也会计算出来它的相似度比较高,所以我们能得到根源的原因。再往后需要把调用数调用成链,简单地拆分成了A和B,A和调用C。
如果简单的没有调用链,其实用频繁项集方式可以做的,但是后续的量非常大,你计算的准确程度也不是很高比如用皮尔逊相关技术计算的有一个曲线都是对于一定值的.
有的出现5XX的错误,没有一个具体的值,那我们怎么做?我们把模型设定为如果出现了异常,我就认为它出现了1的值,如果是正常的那就是0。
对于每一个集群,每一个服务,或者每一个监控指标来说会有0和1的一个曲线,同样用相关系数的方式计算,很明显A出现了异常是与相关度更高的B引起的,这就是刚才提到的监控分层的概念,我们把很多的监控指标进行了分层,往往来说底层的告警数量可能更多一点,而且不见得那么重要。
上层的业务层监控的一些收入类的,或者整体PVUA类的业务指标会更加重要。我们寻找根因的时候,一般也是从上往下寻找,因为往往根因是在下层。如果前面通过算法已经能发现异常的告警关系,我们怎么展示出来更好的让人理解这个事?一方面采用可视化视图方式,通过这个图中可以看到红色是非常严重的告警,黄色是普通的告警,绿色以前是告警,但后来已经恢复正常了,所以就变成了绿色,这个蓝色是部署上线的。
很明显首先做了一个部署上线的操作,可能是由于这个代码有问题,导致端口流不通了,全挂,所以就立即发现由于上线操作导致了端口不通,告警发送给他收到了之后,马上执行操作,所有的端口不通的告警这种服务都恢复正常了。
另外我们现在已经可以做到调用链级别故障告警的根因分析,我们现在微信里也可以展示出这样的视图,很容易让大家知道总的流量有一些变化,是由于某一些集群有异常,这些集群有共同调用的集群4,所以就比较清楚的看到就是集群4异常,导致这一串的告警。
再来介绍故障自愈,思路是很简单的,基本上原来出现异常,我发送一个告警,现在出现异常不发送告警了,可以执行一些比较常规的,常出现的简单异常,比如像进程挂了,端口不通,或者磁盘空间满了,这些比较简单。
对于一些比较复杂的需要对应相关的系统,比如服务器宕机的单机故障自愈,我可以发现它宕机了,先尝试将它启用起来,如果真的某一个硬件发生故障了,就可以根据它所在的网段机型等信息再分配一台机器,然后再把流量切换过去就完成了流量的替换。
另外还可以自动调用云平台,自动地完成扩容的操作,对于某一个机房内的网段出问题,或者对于某一个区域的公网出现问题,或者整个IDC出问题,我们也可以通过DNS调度,或者是四层和七层的负载均衡调度来解决这些问题。
最后一个就是故障预警方面,故障预警我们首先讲一下接口和页面监控,我们为了快速地发现我们的一些重点页面和重要的接口是不是有问题,其实我们是模拟用户的方式去看这些功能是不是正常。
当然他监控的一般来说是通过VIP对于整个集群进行监控。如果说我们的监控发现问题了,肯定用户也感知到了。怎么样提前发现问题?就是我们对于集群中的每一台服务器都进行探测监控。
当有少量的机器出现问题的时候,它会有重试的机制,用户不可见故障,但是我们可以提前发现,提前把预警发送出去,相关的人员就可以提前解决这个问题。
基本上思路是通过整个集群的运行状况做告警,通过集群内的部分异常来做预警。
在智能容量预警这方面也是通过集群中的异常服务器的比例方面来做,比如说你一个集群有两台服务器,宕一台有可能就扛不住了,如果一个集群里有上千台,其实宕一两台完全不重要。
另外也会根据流量的变化以及我们对于历史流量的情况掌握和预测来判断什么时间点可能会出现流量的高峰,然后提前做评估、做扩容。
另外有了调用链,另外也可以发现流量处于瓶颈当中的系统做一些扩容的建议,比如哪些集群需要扩容,需要扩容到多少台。
另外也是基于对硬件信息的采集也能够做硬件损坏风险的预测。
另外前面也提到我们是采集了相关的调用链,并且有相关的访问量数据,也可以根据这些数据来判断某一个服务,或者某一个集群在整个网站当中的重要性,能够判断出这个服务的级别。不同级别的服务可以有不同的资源投入,比如服务器、人力等方面。
另外不同级别的服务它对于故障级别的影响也是不一样的。
最后我们也提到一点,要能够在没有事故的时候提前发现哪些服务可能是风险点,所以我们用这些数据来做可靠性的评估和优化,并且发现某些服务存在潜在的问题,所以可以做容错的策略和降级的策略。