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