概览
普米
grafana
智能运维在百度日常业务监控中的探索
https://blog.51cto.com/u_15471709/4868953
三、运维中面临的监控问题
当前,面对复杂的业务监控和问题诊断,运维人员想找到指标和事件之间的关联关系,进行因果关系推导,并最终定位故障,基本依靠人的经验来进行。但随着业务和监控规模的膨胀,运维也希望能够更加自动化、智能化地达成保证服务高可用性的目标,即快速的问题发现、分析定位或止损。
下面,我们可以从发现问题—分析问题—解决问题的思路出发,逐步给出递进的解决方案。
四、发现问题篇:异常自动检测
日常运维的业务指标数据会出现一些环比昨日的明显异常、持续偏离的明显问题和随着时间周期漂移的指标数据等问题,以前这些监控的配置基本靠工程师经验或持续的迭代修正,甚至纯人工排查。随着监控系统的发展,可以通过制定监控标准和自动化监控部署实现运维的标准化和自动化,最终的目标,是希望用智能化的方法彻底解决这个问题。
一般,在系统出现指标数据波动时,需要先判定是否确实为异常情况,确定异常后再实现精准报警。那么,怎么自动检测业务的异常指标,帮助运维工程师和开发工程师处理问题呢?
这里主要有两个策略,自动恒定阈值设定与动态阈值设定:
1.恒定阈值设定法
对于普通数据,运维人员在服务器端设定服务器应用指标超过某合理数值自动报警,并对服务器异常的波动状态进行报警。这个可使用一些标准的统计学方法去自动计算这个阈值,取代人工配置成本。
参考方式:
基于历史数据统计
假设正态分布
3-sigma策略
2.动态阈值设定法
百度大多数业务数据的流量呈现很强的天周期特性,在某时刻出现数据波峰的骤降或波谷数据的骤增等变动情况时,恒定阈值法很难解决这类问题的精准异常判断。那么我们可以把上述方法衍变升级一下,采用动态时间窗口的阈值设定法来解决周期性数据的异常判断。
参考方式:
多分布形式:将数据分段 按天同期计算统计阈值 分段3-sigma策略
3.恒定阈值和动态阈值的使用
针对以上两种阈值划分方式,异常检测系统如何知道应该对每组数据进行什么样的异常检测策略呢?这就需要一种方法提前对数据进行分类,可以采用一种可判断数据是否具有周期性趋势的分类器方式来解决。如果数据具有很强的周期性特征,建议使用动态阈值设定法;如果数据分析后没有周期性特征,那么使用恒定阈值就可以了。
另外,我们还会遇到这种特殊的情况,数据会随时间出现漂移。比如某产品流量,会按照工作日、周末、传统长假等时间呈现出不同的数据特征,产生阶段性变化。这个时候要进行异常检测,就不仅要考虑数据的普通周期性,还要考虑季节性和趋势性的变化。监控系统可通过对日常数据进行分析,采用三次指数平滑等方法,对数据本身的趋势性进行学习。
当然,上述方法都是基于从历史数据进行学习分析从而进行异常检测的,如果缺少历史数据,那么对于这些指标,基于历史数据进行同环比分析的意义就不大,核心就转化为检测数据有没有突升和突降异常。可采用类似于局部平滑的方法查看真实数据与局部平滑后数据有没有大的出入,如果差距较大,可判断为有大的突升和突降,可以标识数据异常。
参考方式:
局部平滑法
速度法
经过经验的积累,对于核心产品的流量变动,即使波动不大,监控系统也可以做到灵敏且精准的指标监控,能够快速发现异常情况。当然,全自动的异常检测系统难免会出现误报、漏报等情况,这就要求异常检测系统需要支持工程师的标注与反馈,百度监控系统的自学习能力可以根据工程师的需求进行动态调整,可同时支持人为调整和系统自动参数学习调整,系统可自动根据工程师的标注或报警量的多少,进行参数训练,把异常检测参数调整到合理的范围。
工程师标注
修改参数 标记未检测到的异常 标记错误的报警
机器学习
标注报警 => 参数训练 综合上述方法,百度智能监控系统中的自动异常检测最终形成两种状态的结合:离线状态和在线状态,离线部分可根据历史数据进行分类学习、参数训练,而在线部分能够进行最终的异常检测和报警。
具体的组成如图所示:
五、发现问题篇:精准报警
监控系统仅仅发现了问题还不够,由于指标数量太过繁杂,为了起到辅助工程师快速解决问题的效果,还需要做到精准化报警。百度的精准报警主要分成两个层面,一个是单个指标的报警是否足够精准;这里需要考虑两个问题,一是是否每次异常都应该报警?需要容忍系统毛刺的存在;二是异常过滤,把离散的异常点转化为异常事件或状态,找到指标和事件的关联关系。
在单一指标的报警足够精准的基础上,另一个是把不同指标的报警结合起来做到足够精准。如何把多个指标的报警综合起来呢?简单策略是固定时间窗口来报警,时间相近的报警可进行一定的合并,只要将首先出现的指标报警送达给到运维人员即可。从整个监控策略来看,把报警综合起来,同类的报警进行合并来报给运维人员。复杂一些的策略是关联挖掘,把历史上产生的运维报警和事件关联起来报警,同时,某些报警经常频繁地一起出现,可以认为这是同一个报警,不再单独分别进行报警。
采用的具体策略有:
- 报警合并简单策略
固定时间窗口 相同监控策略 相同监控对象
- 报警合并复杂策略
关联挖掘 合并置信度较高的频繁项集
- 报警依赖
策略依赖 异常依赖
六、分析问题篇:关联分析
监控系统不仅需要帮助工程师发现问题,同时还需要通过建立关联分析,进行辅助问题定位,甚至迅速找到相关的指标或影响。那么,如何为复杂多样的运维数据建立关联呢?
产品服务层级的关联关系图:
运维工程师可以把一些基础的关联关系配置到监控系统中,可以让监控系统明白一些常态化的运维指标与其它指标是否存在关联,比如多个模块的异常是否存在关联、服务器升级或者部署产生问题是否与数据中心或交换机异常有关等。
具体的实现策略有:
1.关联挖掘
(1)事件和事件间的关联
频繁项集挖掘 所有运维事件
(2)事件和时序间的关联
指标异常经常与部署升级事件相伴发生 问题诊断&故障定位
(3)多时序间的关联
2.关联可视化
通过关联变动,帮助运维人员分析重点数据的变动情况。
(1)事件&事件关联
(2)事件&时序关联
3.服务透视定位问题
运维事件多是与时间持续紧密关联,我们可以把运维事件按照时间轴演进顺序进行展示。同时,运维工程师常常接触的服务拓扑,本身也是一种运维模块的关联关系。把这些离散的运维数据通过模块关联、时间关联、数据流关联等紧密地联系起来,构成一个完整的服务透视图,如果异常发生在关系透视图中的某个部分,就可以按照周边关系的通路来快速定位问题。
(1)模块调用关系
(2)事件和模块关联
六、分析问题篇:故障定位
仅仅找到关联还不够,真正分析业务问题解决问题才是关键。这里介绍两个常用的辅助定位问题策略。
1.多维数据分析
监控系统采集到的很多指标具备包含关系,很多情况下,一个总体指标是由许多子指标加和构成的,或者也可以说成是总体维度是由许多子维度组成的。监控系统可以计算出每个子指标或子维度占总指标总维度的百分比,并按照影响权重去进行分析,当某个子指标的变化幅度对总体指标影响权重最大,我们就倾向于认为这个指标可能是问题的原因。
举个例子,百度的总体流量指标对应每个地域的流量之和,总体流量有问题有可能是某个地域流量出现问题,找到目前对总体流量变化影响最大的地域进行问题处理就可以解决问题。同样的道理也可以推广到其它情况。
2.故障诊断树
运维人员可以通过数据可视化(热力图、多维报表)的形式,结合以前发现问题的经验沉淀模式,发现指标间的强相关,做出问题诊断。那我们是不是可以将运维人员的经验固化到监控系统中,通过不同指标的分析方向和下探方法可以形成树状结构,通过树上的某个节点进行逐级探查。最终形成故障诊断树,通过推导路径不仅可以帮助运维人员快速完成问题出现时的排查过程,节省这部分的定位时间,也很有可能达到直接定位问题或加速解决故障的目的。
故障检测:
(1)领域专家知识
(2)逻辑推导引擎
(3)迅速找到问题根因
七、解决问题篇
监控系统产生决策 部署调度系统执行
1.单边故障自动止损
单边故障指单个IDC故障、单个链路故障等。比如一个IDC或者某些IDC出现问题,解决办法是切走这部分流量,利用监控系统来做动态的部署调度。通过某个数据中心或链路的部署调整,帮助系统快速恢复,进而实现自动化决策和执行来实现单边故障止损。
具体策略有:
(1)实现自动冗余与调度
(2)智能监控系统负责动态决策
(3)部署调度系统负责调度执行
2.灰度发布自动止损
研发工程师做灰度发布时,可以先做小流量的发布,部署系统可以跟监控系统配合,如果出现问题,直接进行状态终止或回滚,把问题控制在灰度发布范围内。
八、智能运维监控总结
通过上述说明,百度的智能运维监控系统最终形成了一个监控闭环,包含问题发现、分析决策和问题的解决。具体的组成包括异常检测、报警收敛、关联分析、故障定位和自动处理五部分内容。
九、未来运维变被动为主动
1.全方位覆盖
在用户端(APP、浏览器等)、云端(机房、服务器、自身服务、第三方服务等)、管道(链路、运营商)等任何维度进行数据采集并进行异常自动检测。
- 让监控更聪明
分析运用已有数据,并把服务状态、问题影响分析等可视化 自动学习并理解故障的趋势和模式 自动发现服务或依赖环境的变更
当然,更进一步地,监控系统是不是可以先于故障发生而预测到故障,在故障发生之前就可以处理并解决故障,从而达成产品的超高可用性目标。未来的智能监控应该是这样的,运维工程师经过完善的监控部署,实现全方位的异常自动检测覆盖,同时,在系统刚出现故障征兆,有损之前就进行处理并解决,实现完整的智能化监控系统解决方案。
欢迎所有对智能化运维技术感兴趣的同学加入百度运维部,一起推动智能化运维的发展。
干货概览
监控报警是故障发现的重要一环,也是百度在AIOps的最早切入方向之一,目前百度 AIOps 在监控报警方面已经有两个场景取得突出效果:智能异常检测和智能报警合并。
如何支撑 AIOps 算法在监控报警系统的快速落地并产生业务价值,这对监控报警架构提出了很大的挑战!
本文首先介绍百度Noah监控报警的功能和业务模型,然后重点分析百度监控报警系统在落地 AIOps 过程中遇到的挑战。
百度Noah监控报警系统
首先我们介绍下百度的标准故障处理流程,如上图所示,主要分为以下7个过程:
故障发生:比如当内网机房核心交换机发生故障时,会造成内网的网络故障,从而导致产品线的流量损失。
故障发现:监控系统实时检测到产品线的流量异常。
故障通告:监控系统会通过短信或电话等渠道通知业务运维人员,产品线流量有异常。
故障止损:业务运维人员会执行故障预案,或者借助故障自愈平台智能地执行故障止损操作,以达到快速止损的目的,常见的操作是将流量从故障机房切到非故障机房。
故障定位:运维人员和研发人员一起定位故障根因。
故障恢复:当定位到问题后,运维人员开始执行修复操作,直到线上的所有服务(包括未接流量的模块)都彻底恢复正常。
故障总结:运维人员会对故障处理流程进行复盘总结,好的方面继续保持,不好的方面排期改正。
在整个故障处理流程中,监控系统主要负责故障发现到故障定位的环节;报警系统作为监控系统的子系统,主要负责故障发现和故障通告。
百度Noah报警系统最早服务于百度内部的监控平台,提供从机器、实例到上层业务等全方位、立体化的监控报警能力,已经覆盖百度的所有产品线。
同时,系统面临很大的挑战,每秒需要处理千万级个数据点,线上的监控配置已经达到百万级别,每天会产生千万个报警事件,在这么大的量级下,还需保证秒级的报警时效性。
百度Noah报警系统不仅为百度内部用户服务,我们还同时为公有云和私有云服务提供监控报警能力。
我们将内部强大的监控产品和运维理念输出到业界,打造了NoahEE产品(详见《百度云企业级运维平台——NoahEE》介绍 ),帮助客户一起提升运维效率和线上稳定性。
另外,我们还依托报警系统孵化出了百度AIOps智能运维产品,包括智能异常检测、故障定位、报警合并等高级功能,已经落地金融、交通、互联网等行业,受到客户一致好评。
业务模型
监控报警系统的核心使命是精准报警,那报警系统是如何进行故障发现和故障通告呢?我们通过一个场景来了解下。
假设上图中的曲线是某产品线的流量指标(简称PV),其中每个点代表一个PV数据点,假设希望当PV值小于100时,异常判断结果为异常,并通告给业务运维人员。
监控报警系统会周期性地对最近一个数据点(Data)进行判断,如果PV小于100则判断结果为异常,否则判断结果为正常。
当首次异常的时候(即判断结果从正常转为异常),会产生一个报警事件(Event);当异常恢复时,则将报警事件结束掉。
在报警事件持续期间,会根据报警规则产生一个或多个报警消息(Message),并将报警消息渲染成容易理解的文本,通过下游发送渠道(短信、电话等)送达给运维工程师。
通过这么一个流程,监控报警系统就达到了故障发现和故障通告的目的。
相应地,我们将监控报警系统拆分成以下三个子系统:
异常判断系统:主要功能是根据异常判断配置周期性地对数据进行判断,并将产生的判断结果(正常或异常)发送给下游。异常判断系统不仅需要提供基于传统四则运算的异常判断,还需要提供基于AIOps算法的异常判断。
事件管理系统:主要负责报警事件的管理工作,并基于报警事件提供防抖动过滤、报警认领、逐级通告、报警静默等功能。
通告发送系统:主要负责报警合并、渲染和发送等功能。另外为了防止下游发送网关的带宽被某些业务的突发报警流量淹没而导致其它业务的报警消息得不到及时发送,还需要提供配额和流控功能,从而保证每个业务公平地使用发送网关资源。
将监控报警系统拆分成三个子系统后,有以下两个好处:
系统功能边界清晰,具备可扩展的报警架构能力
每个子系统可以根据自身的功能特点采用不同的技术栈和部署架构,由不同的研发工程师负责研发和维护。比如异常判断系统更偏向计算逻辑,可以采用Golang或C++这类更加注重执行效率的技术栈;而事件管理和报警发送系统更偏向于业务逻辑,可以采用Java或PHP等更注重研发效率的技术栈。
每个子系统也可以独立进行功能和架构升级。比如异常判断系统需要大量的CPU资源,比较适合采用集群架构,这样方便横向扩展,增加系统吞吐能力;而通告发送系统的流量相对小些,初期可以采用主备架构,不仅架构简单可靠,而且研发和维护成本小。假设随着业务的发展,业务需要更大的报警发送能力,通告发送系统只需保证对外接口不变,独立将自身架构升级为集群架构,就可获取更大的报警发送能力。
报警功能组件化,具备灵活的商业化交付能力
每个子系统都是一个独立的功能组件,可以独立部署、升级,这样就具备灵活支持商业化交付能力。比如我们可以只将通告发送系统单独交付给商业化客户,客户通过直接调用通告发送的接口就可以获取报警合并、渲染、发送等能力。
我们遇到了哪些挑战?
通过上面的业务模型介绍,大家已经对监控报警系统有了全局的认识,那下面来详细分析落地AIOps遇到的问题。
落地AIOps算法周期长,迭代成本高
我们继续来看PV指标,通过对历史PV数据的观察,我们发现不同时间段的PV大小是上下波动的,比如在早上八九点是流量高峰期,在凌晨两三点是流量低峰期,另外工作日和周末的流量大小也是不同的。
这意味着,我们不可能设置统一的阈值来检测PV流量的变化情况,那么怎么办呢?
百度策略人员研发了基于鲁棒回归的无监督突升突降检测算法,这个算法不需要设置PV阈值,即可检测流量的变化。
下面展示的这个公式是其中的一步,其中变量y就是真实的PV值,f(x)代表利用某种算法预测到的PV值。
如果对算法细节感兴趣,可参考文章:《我们不一样!告诉你百度是如何做智能流量异常检测的》。
这类异常检测算法相对于传统的四则运算,有以下不同:
对不同类型指标在不同的场景下,算法f(x)是不相同的,特别是在初期探索阶段,我们需要快速迭代算法,以验证哪种算法效果最优。
算法f(x)会依赖根据历史数据训练到的模型,然而业务数据的特征复杂,不断变化,这意味着我们需要定期更新策略模型,以保证算法的效果。
算法f(x)对CPU资源的需求差异很大,有的算法计算量非常小,可能单个CPU核就可以运行数千个此类任务,而有的算法会引入RNN等深度学习算法,计算复杂度特别高,往往就需要独占某个CPU核。
最初我们落地这类AIOps算法时,整体的流程如上图所示:
策略工程师用Python或Matlab编写算法脚本,并在线下进行Case回溯,保证算法的普适性。
研发工程师将算法脚本改写成线上代码(C++或Java),以便在线上运行。
测试工程师对改写后的算法代码进行测试回归。
运维工程师对模块(包括算法代码和策略模型)进行发布上线。
上面的研发流程暴露出很多的问题。
一方面,对我们的研发工程师要求比较苛刻,既需要看得懂策略算法,又要熟知工程研发;
另一方面,算法的迭代周期比较长,经常以月为单位,可能算法刚上线,数据特征就发生了变化,导致算法失效;
最后,即使算法程序迭代稳定了,但是参数模型还需要定期更新,由于参数模型和算法程序没有分离,导致后期参数模型的更新需要不断上线,提高了维护成本。
报警管理需求繁杂多样,疲于应付
我们再来看下报警管理的挑战。
报警管理需要处理的需求比较多,我们以一个典型的运维场景来串一下这些需求:
凌晨一点,网络运维工程师对网络进行调整,导致网络产生了短时间的抖动,这类抖动的持续时间通常都在1到2分钟左右。网络抖动导致大量的业务监控指标发生相应的抖动,从而触发报警。此时业务运维工程师就希望系统能够提供防抖动过滤功能,避免指标在短时间抖动时触发报警。
凌晨三点,由于系统日志清理机制有问题,导致集群内60%机器的磁盘占用率超过安全线,触发报警。但是报警电话未能唤醒值班工程师,最终导致大规模系统故障。因此值班工程师希望系统提供报警重复提醒功能,当值班工程师没有及时响应报警时,通过多次重复呼叫来避免报警遗漏。
但是,当值班工程师被及时唤醒并开始处理故障后,系统持续的重复提醒会对值班工程师形成很大的干扰。因此工程师们就希望引入报警认领功能,告知报警系统故障已经有人在处理,重复提醒可以停止了。
凌晨4点半,由于值班工程师是新入职的,对系统不够熟悉,日志清理的操作还未完成,导致故障持续。此时,就希望系统能够提供报警升级功能,在故障长时间未解除的时候可以通知资深的二线值班工程师介入处理。
凌晨4点50,二线值班工程师完成日志清理,故障恢复。这时,二线工程师发现日志清理操作其实是一套标准的止损操作,完全可以在发生报警时自动执行。因此希望系统能够提供报警回调功能,将来类似的问题就无需人工介入处理了。
除此之外,值班工程师可能还有断流检测、报警静默等等各种需求。
可见报警管理的需求复杂多样,如果我们不能抽象出一个可扩展的报警管理模型,我们将变得越来越被动。
报警风暴淹没核心报警,束手无策
看完报警管理,我们再来看下报警风暴的挑战。
为了避免遗漏故障,运维工程师常常会在监控系统中定制大量的监控指标和报警规则,从而建立起从网络到机器、从实例到模块、再到上层业务的立体化监控。
立体化的监控虽然极大提高了故障发现的能力,但是很容易导致一个故障触发大量报警,造成报警风暴。
为了让大家认识报警风暴的真面目,我们来看三个典型的场景:
机器故障:机器发生故障时,监控机器健康度的报警规则将会产生报警;然后监控机器上实例运行状态的报警规则也会产生报警;最后这些实例的上游应用模块也会受到影响,相关的报警规则也会开始报警。这样一来,一个机器的故障就可能会产生几十条的报警消息。
应用模块故障:首先这个应用模块中的所有实例都会发出报警,紧接着上游应用模块也会产生报警。当应用模块中包含的实例比较多时,这类故障常常会产生数百条的报警消息。
机房故障:会同时造成网络、机器、域名、应用模块、业务等多层次、多方面的异常报警,产生的报警消息可以多达数万条。
我们可以看到,这三种典型故障对值班工程师都非常的不友好。他们的手机会被短信和电话轰炸,与此同时大量的报警消息却并不能帮助他们迅速寻找根因和制订止损方案。对大量报警消息先进行有效地组织,然后再发送,就成为值班工程师的一大需求。
总 结
本文首先介绍了百度Noah监控报警系统功能和业务模型,然后结合案例场景分析了我们在落地AIOps时遇到的问题,让大家对监控报警系统的现状有一个直观的认识。
我们将在下篇文章中讲解如何来解决这些挑战,敬请期待。
干货概览
随着软件系统的发展,监控目标场景越来越广泛,对监控系统的能力要求也越来越高。
对于监控系统来说,从能力上看基本可以划分为数据采集、数据计算、数据存储、异常检测、报警处理以及监控可视化六块。
为了更好应对大规模、复杂化的监控业务场景,我们不仅仅需要在具体监控能力上做深、做强,还需要建立对应机制来统筹这些能力一起良好协作。
今天的这篇文章就为大家介绍监控系统的神经中枢——配置管理与分发系统,让我们一起揭开它神秘的面纱吧!
需求
在业务系统发展的初期,由于场景简单,对监控的需求也比较简单,比如仅采集默认的机器监控数据,不需要进行进程、日志等监控能力。
同时监控的规模也相对较小,用户的配置数量一般在百或千级别,这时只需定期读取数据库中的配置就可以很好的工作。
随着业务系统的快速发展,业务体量越来越大,业务复杂度越来越高,对监控的需求也越来越高。传统的简单读取数据库配置在业务扩展性和性能上遇到了挑战。
1支持不同类型的配置管理
监控指标采集、计算、报警等方面的配置种类越来越多。如物理机的机器资源类指标、应用程序的进程和日志指标的采集配置、站点的连通性采集配置、服务器的宕机检测任务配置、多个实例间指标的计算任务配置、指标数据的异常检测配置、告警信息发送配置等。
2支持不同场景的配置分发
高并发配置下载场景:监控系统中每个物理机部署一个Agent用于对部署在该机器上的应用程序相关指标进行采集。Agent需要下载与主机关联的采集配置,在大规模的监控系统中,Agent的数量达到百万级别,采集配置的更新周期为10s,配置分发系统需要应对高并发查询的压力。
一致性配置下载场景:为了应对高可用、大规模的数据计算及报警场景,各个子系统往往使用集群化部署。以报警集群为例,同一机器的数据可能会由报警集群的不同实例进行判断,若配置在集群内不一致,那么报警系统的行为就会变得不可预期。
3支持故障快速恢复
配置分发系统作为监控的枢纽,关联的模块比较多,系统故障会影响采集、计算、报警子系统工作的正确性以及用户新加监控配置不生效,所以需要相应的方案来保障监控系统的快速恢复或重建能力,来保障监控系统的可用。
图1 配置管理&分发系统交互流程图
方案
梳理完问题、需求,接下来就要针对这些问题进行相应的改造升级。
下面我们从技术的角度介绍下如何解决这些问题吧!
一、支持配置可扩展性
复杂的监控能力意味着监控系统的配置种类灵活多样。如果直接将配置分发模型与业务模型对接,意味着业务上的每次改动都需要配置下发系统进行对应的变更。
那么如何统一配置的多样性,做到配置下发对上层业务透明呢?答案是:归类+抽象。
将不同的配置按照“目录”进行分类管理,实现统一的配置管理需求。
以文件作为载体,所有配置都以文件的形式进行管理。不同的文件内容格式代表着不同类型的配置,原有格式的升级以及新类型的添加统一抽象为文件处理,增强了系统的扩展能力。
通过代码管理系统管理文件的方式,实现变更历史追踪。通过对文件系统的定时备份与构建快速故障恢复机制提升系统的可用性与可靠性。
图2 配置归类&抽象
在归类方面,由于不同的能力需要的配置形式不同,我们以此为依据进行分类。对应到实现中则通过目录表达分类的含义,通过子目录来表达配置的层级与归属等关系。这里我们将配置目录的层级分为监控功能层级->用户层级->应用层级三层,在应用目录下将具体配置(如进程监控配置、日志监控配置)写入文件中。
二、确保一致下发
通过对配置管理方式的抽象与归类整理,配置的一致性下发可以通过构建配置文件内容的一致性机制解决。我们使用“版本”作为文件内容一致性机制的核心。当用户变更配置时,配置管理系统会生成一个全局唯一的版本描述此次配置变更操作,版本中包含此次变更操作对应的配置文件变更详情。
配置下发时,在各个子系统会定期检测配置版本差异并更新本地配置至最新版本,从而保证配置在每个更新周期内保持一致。
三、应对高并发压力
大规模的压力则主要体现在采集Agent的配置下发部分。
由于Agent只需拿到部署主机所需的监控配置,因此将配置文件按照监控的最小单元进行拆分,并按照规范进行打包。
图3 Agent配置拆分&下载流程
当前的业务部署往往采用混布方式,同一主机中会部署多个不同类型的应用程序。为了支持这种监控场景,主机上部署的采集Agent会查找主机上部署的应用并下载对应的多个应用配置。当业务规模增大时,物理机增多,配置下载请求也会成倍增长,因配置存储的Server端很容易达到性能瓶颈。通过可水平扩展的静态文件下载服务来应对高并发下载压力,通过ETag方式检测文件是否变更,只针对变更的配置文件才进行传输以减少下载流量,最终满足了百万级主机、千万级实例的配置下发需求。
四、故障快速恢复
考虑到配置在监控系统中的重要程度,为了保障业务的可用性,就需要构建监控系统的快速故障恢复机制。
同时,由于监控系统配置集中管理,随着系统的发展,配置的体积也在不断增长,配置文件体积达到数十GB级别,并且全部由小文件组成,文件个数也达到了数百万级别。为了减轻系统压力,在系统中加入“快照”机制,每隔一段时间便生成当前全量配置的快照,当出现大量更新时,先通过“快照”减少更新量,再通过对应同步机制进行少量的文件更新。
总结
经过不断的努力和多次改造,目前的配置管理及分发可以满足监控系统的需求。
由于能够灵活管理多种配置,并且快速、一致地送至各个系统。
在面对故障场景时候,也可以及时撤回配置,避免更大的损失。然而随着监控业务的发展,系统架构的变迁,起着中枢作用的配置管理与分发系统将会面临新的挑战。
路漫漫其修远兮,吾将上下而求索!
背景
如何将多条告警关联在一起进行展示和分析,以及如何将多条有联系的告警转换成一条或少量几条包含更多故障信息的告警,以此达到降低活动告警的种类和数目,减轻运维人员的工作压力,提高故障精确定位效率,是一个很值得研究的课题。
1. 背景
在实际运维过程中,为了避免异常的遗漏,业务运维人员经常针对不同的业务,设定大量不同的监控指标和告警规则。
在这些告警信息中存在着很多相关联的告警规则,或强相关的业务指标等。换句话说,一个业务模块发生了故障,可能会引起多个模块触发告警。
因此,在每天产生的大量告警信息中,存在着很大的冗余信息。真正有效的告警信息,很有可能就被隐藏在这众多冗余的信息中,从而导致业务运维人员忽略掉了有效的告警信息,导致业务故障不能够及时的去处理。
如何将多条告警关联在一起进行展示和分析,以及如何将多条有联系的告警转换成一条或少量几条包含更多故障信息的告警,以此达到降低活动告警的种类和数目,减轻运维人员的工作压力,提高故障精确定位效率,是一个很值得研究的课题。
2. 定义
2.1. 告警数据一般可以分为指标型和事件型(Metrics and Events)俩种数据类型。
Metrics
如上图所示,指标型数据又可以分为业务指标和资源指标。
指标型数据示例(某机器的内存时序数据):
Events
除了可以或多或少连续收集的指标之外,某些监视系统还可以捕获事件:
不连续的,不经常发生的事件,这些事件为理解系统行为的变化提供了关键的环境。
比如:
(1)更改:代码发布,构建和构建失败
(2)警报:主要监视系统或集成的第三方工具生成的通知
(3)扩展事件:添加或减去主机或容器
事件型数据示例(AMP的一条历史告警信息):
事件型数据往往可以包含更多的字段信息,里面的内容可能是结构化的,也可能是半结构化和非结构化的。
通过对告警事件的关联分析,往往可以发现系统故障的原因,分析出到底是什么导致了异常。
2.2. 告警关联包括告警关联展示,告警关联搜索,告警合并以及告警摘要。
2.2.1. 告警关联展示是通过把异常里的相关联/相似的告警记录(可能是相似的时间序列,或者相似的告警事件记录),通过合并或者聚类的方法,给放在一起展示。给运维人员一个多视图的关联数据,便于去找出问题的故障根因和更快的解决相类似的故障。
2.2.2. 告警关联搜索是通过一段有异常的时间序列,去搜索到与之相类似的时间序列。范围不局限在异常告警里。这样,通过关联到的结果,可以更好的挖掘与之关联的所有业务指标,从而更好的挖掘出异常根因。搜索范围不局限在异常告警的原因在于,有些与之相类似的上下游业务时间序列,检测结果并不一定是一场(不同业务设定阈值不同,接入的检测算法也不相同,等)。
2.2.3. 告警合并:告警合并的理解很简单,一般就是指在某个确定的时间窗内,把多条相似的告警,合并为一条。这样做可以大大减少告警的数量,但是对于发现问题解决问题的效率,没有本质的提升。
2.2.4. 告警摘要:告警摘要相比告警合并,则显得更加智能一些。 在合并的过程中,通过一些字段提取,相似性计算以及聚类等操作,从多条相似,或者关联的告警记录中,提取成一条精简的告警记录信息。一方面告警数量可以从多条削减为1条,另一方面,告警记录的内容经过加工,更利于运维人员进行故障查找和修复。
3.竞品公司的告警关联模块:
3.1. Data-dog:
Data-dog的关联分析模块,主要目的是想通过关联来做根因分析和定位。
从他们的博客可以看到,任何一段时间序列,选定对应的时间段后,Data-dog可以搜索与之相关联的指标数据,也可以查看与对应时间序列相关的主机信息,日志及其他信息。
通过对目标的时间序列段进行关联搜索,可以展示出与之相类似的所有指标。
通过相关的业务指标分析,可以辅助分析出出现异常指标的上下游业务,从而更好更快的去定位的问题。
更多:https://www.datadoghq.com/blog/metric-correlations/
3.2. 百度:
3.2.1. 简单的报警合并:
选择合适的字段,直接将字段进行groupby,多条合并为一条记录。
具体细节为:一个报警产生以后,我们先把这个报警插入一个发送等待队列而非立即发送。每一个报警策略都有一个在等待队列里的最长存留时间,换言之,是这条报警可以容忍的 最长延迟发送时间 。报警产生后先插入等待队列里面去,在队列里等进行延迟计时,当达到了能够容忍的延迟时间以后,我们在等待队列中找到可以和该报警一起合并发送的报警,根据实际的合并维度渲染成不同的报警短信内容,然后合并成一条报警短信发送。
在下面的例子里,A,B,C代表了3个不同的模块,A模块上配置了两条报警策略分别为rule1,rule2,B模块上配置了rule3,C模块上配置了rule4,红色的报警A:rule1即将到达最长存留时间,按照合并策略,黄色的报警可以一起合并为一条发送,这样实际的报警信息中包含了三条报警。
最简单的报警合并方法可以基于报警策略的自然属性,包含策略名或者部署维度等。
百度的生产系统使用了虚拟化技术混布各项服务,因此部署的逻辑维度包含了实例、模块、集群等层次,物理维度包含机器和机房等层次。
一个层次同时刻的报警,大多数都存在着一定联系,因而可以将这些报警合并。
举一个实际的例子,A模块在bj机房部署有100个实例,统一为每个实例配置了端口存活报警策略rule1,某个时刻这个策略在0.A.bj(A模块在bj机房的0号实例)和1.A.bj(A模块在bj机房的1号实例)上都报警了。
这两个报警属于同一个模块的同一个策略,因而可以合并在一起,便于值班工程师了解整体情况。最终发送的报警样式如下:
{A:instance:rule1}{总体异常实例比例:2%}{异常(2):0.A.bj,1.A.bj}{05-02 16:49:36 - 16:54:09} {http://noah.xxx/… }
报警合并策略
报警合并对很多做监控的同学来说并不陌生,大部分介绍报警收敛的文章都提到了这个过程,但大多数提及的报警合并都是将某个时间窗口内的报警简单的合并成为一条,此举对削减报警数量固然有效,但不利于值班工程师进行故障诊断。
我们希望把若干描述同一故障的报警合并在一起,让值班工程师可以快速捕捉到故障本质,甚至故障根因,而并非一味的削减报警量。
在本文中,我们先介绍一个合并来源于相同报警策略或者相同模块的重复报警的策略,下一篇文章中将讨论如何合并跨模块、跨策略的报警和一个消除机房网络故障期间报警风暴的方法,这一方法也可以用来检测机房的网络故障。
3.2.2. 关联策略的报警合并:
某个模块的出现问题的时候,往往会引发上游或者下游模块也一并报警。
假设模块A调用了模块B,当模块B出现问题的时候,很显然模块A和模块B都会产生报警。
为了解决这个问题,我们尝试从 历史报警数据中挖掘关联的报警策略列表:
常用的频繁项集挖掘方法有:Apriori,Fp-Growth,Eclat等。
通过对历史告警数据的挖掘,我们可以建立关联规则库,这样发生告警时,可以去关联规则库去匹配对应的关联项。
3.3. Prometheus 的告警收敛功能
Pometheus成功的把一条告警发给了Altermanager,而Altermanager并不是简简单单的直接发送出去,这样就会导致告警信息过多,重要告警被淹没。
所以需要对告警做合理的收敛
告警收敛手段:
分组(group):将类似性质的警报分类为单个通知,类似于百度的告警合并
(1)减少报警消息的数量
(2)同类告警聚合帮助运维排查问题
抑制(Inhibition):当警报发出后,停止重复发送由此警报引发的其他警报
静默(Silences):是一种简单的特定时间静音提醒的机制
4. 我们怎么做:
最后,再简单介绍下我们在告警关联这个场景下的思考。
从数据类型上分,告警信息可以分为时间序列和事件。对应的关联分析可以分为基于时间序列的告警关联,基于事件的告警关联,以及事件和时间序列的联动分析。
4.1. 基于时间序列相似性的关联展示
我们通过对monitor单视图下的所有异常时间序列做聚类,将相似的时间序列放在一起展示。目前已经实现了同一视图下的所有时间序列异常做关联展示。
对于未来的跨视图时间序列关联,一方面可以继续沿用现有的逻辑。另外,也可以通过挖掘历史告警数据,结合关联规则库的方法,以提高在线关联查找的效率。
4.2. 基于事件相似的关联展示和告警摘要:
对于相同/相似的告警记录,仅仅是简单的进行合并,可以通过groupby的方法获得。但这样只是从数量上减少了告警数量,对于内容质量的提升并没有太大。
我们的想法是通过挖掘和提取告警记录中一些非结构化的字段内容+对告警维度进行一定的扩展,从而获得更多的告警信息,整理总结成一个告警摘要的形式发送给业务运维人员,辅助他们进行故障的定位和解决。
4.3. 事件和时间序列的联动分析:
从指标的时间序列探测到异常,往往也对应着一条告警记录。可以选择合适的id,将事件记录和时间序列关联起来,这样可以给运维人员提供更多的信息。
5. 案例分享:
5.1. 异常的时间序列关联展示(腾讯-云监控)
在告警记录里面,将相似得告警记录进行聚类,放在一起展示。
以monitor时间序列关联为例,将在monitor同一视图下的异常时间序列进行聚类,一起展示的效果图:
5.2. 通过时间序列的关联搜索,进行辅助的根因分析(Datadog)
在可能包含数百个服务以及数千个主机和容器的应用程序体系结构中,可能需要花费数小时的时间才能找出问题的根本原因。
Datadog的“关联”视图通过隔离相关的指标来确定性能或可用性的任何变化,从而缩小了调查的范围,并揭示了潜在的根本原因。
例如,当完成的检出次数意外下降时,“关联”视图会自动识别哪些服务或基础结构系统可能是导致中断的原因。
然后,Datadog会显示来自每个系统的相关指标。
借助相关性,运维人员可以将问题的源头归零,而不必依靠猜测或费时的,可能的根本原因的广泛探索。
来自 datadog :https://www.datadoghq.com/solutions/machine-learning/
流程
用户侧:规则配置 + 接收处理报警 + 调整规则
处理时:需要用到抑制+升级 归因分析 自动处理 历史经验
指标采集=》规则配置
闭环:审计 FATAL===> 事件
告警风暴
在上述常见问题中,我们日常运维过程中遇到的最多、影响最大的便是【告警风暴】问题。
运维监控系统,一般都是通过配置固定阈值、条件,达到阈值或满足特定条件后自动触发告警。
运维监控人员经常会困扰于如下的告警风暴场景:
-
故障期间,告警风暴,手机/邮箱会被海量告警淹没;
-
运维人员很难从海量告警从筛选出重要告警,容易忽略重要告警;
-
固定阈值控制,频繁误报、漏报告警;
在监控场景下,一旦出现告警风暴,告警本身就失去了意义和价值。
因此需要有一套方案,帮助用户在不遗漏重要告警前提下,有效减少告警数量。
告警管理
其中告警管理模块为用户提供了降噪控制的能力,用户可以通过自定义降噪规则,完成对不同来源的告警的去重、合并、路由、抑制、静默等降噪操作。
本次发布对告警管理模块中的告警合并能力进行升级,支持智能合并,一键开启告警风暴抑制!
SLS最新发布:告警智能合并
如前述介绍,SLS告警运维系统已经为用户提供了自定义规则降噪的能力。
然而现实环境总是十分复杂的,作为运维人员,往往很难确定如何按照某种固定的规则去对告警进行降噪;即使设置了比较合理的降噪规则,现实场景下也有可能出现意想不到的告警风暴。
因此SLS最新推出了告警智能合并能力,让用户只需一些极简的配置,便可开启告警的智能降噪。
1. 什么是告警智能合并
为了解决告警风暴问题,很多监控系统、平台都推出了告警合并(降噪)功能,来有效地减少告警数量,减轻运维人员的负担。
对于监控系统的运维人员来说,告警的合并不仅可以将相关告警作为单个聚合单元进行管理来降低噪音,还可以引导他们找到告警的可能共同的根本原因。
告警合并分为自定义规则合并和智能合并,其原理是通过一些用户自定义的合并规则或者智能算法自动合并,将重复、冗余或者有关联的告警合并到一个分组中,并且每个分组的告警在一段时间内只会通知一次,从而有效减少告警通知的数量。
2. SLS告警智能合并原理
SLS告警智能合并依托于NLP算法,自动化地去学习告警之间的关联或相似关系,在不依赖于历史告警数据的前提下(冷启动),可以实时地对不同来源的告警进行智能合并,然后再通知给用户,让用户免于告警风暴的困扰。
如上图所示,SLS告警智能合并的核心步骤包括4个步骤:
多源告警数据汇集:将不同来源的告警数据汇集到一起,进行集中处理;
告警文本的预处理:基于告警专业特色词/停用词库,数据字典,人工标注信息等,对告警全文本进行预处理,剔除无用文本,提取关键词。
告警文本聚类:采用两种不同的聚类技术对告警文本进行聚类
MinJoin聚类算法:一种通过最小化局部哈希值来进行文本编辑距离计算及聚类的高效率算法
向量相似度聚类:首先对告警文本进行分词,接着利用特征工程将其向量化表示,最后基于告警向量之间的相似度(如余弦相似度等)进行聚类
聚类蔟合并:将第3步中两种聚类技术各自得到的聚类结果进行合并,得到一个最终的聚类结果,即是告警智能合并的最终结果。
合并+抑制具体例子
最近设计一个告警的产品,参考了开源的 alertmanager ,但是功能上面有一些疑问:
告警合并/分组:假设一台物理机宕机,这台物理机上面的虚拟机都有宕机告警,如果不分组的话,就会一次性发送多个宕机告警,这个确实不友好,所以可以按告警规则名称这个维度对告警进行合并,这个是合理的。但是除了按告警规则名称进行合并外,也想不到按其他维度进行合并告警的有意义案例。比如按数据中心这个维度进行合并的话,某个数据中心当了,一来概率极低,二来数据中心都宕了,我的告警系统应该也挂了。
告警抑制:比如某台机器宕机了,那么这台机器上面的服务不可用的告警就不发。但是实际情况是,机器宕机告警是发给 SRE ,服务不可用是发给服务开发的人,原则上不应该抑制,服务开发人员需要知道我的服务挂了。告警抑制功能目前我并没有想到真正合理的案例。
告警升级:比如某个服务有问题了,发出了告警,但是一直没人处理,一段时间后通知给到这个服务负责人的 leader 。这个功能虽然谈告警的时候一直有人谈,但实际上我没有遇到真正用到的场景,除非一个人想要离职了,否则一般不会不处理告警。所以这个功能有必要做吗?
我的疑问就是这三个功能,大家有实际的应用场景吗?
负责小公司的监控告警平台:
-
不是没有聚合的维度, 是维度太灵活了, 不同告警可能需要不同的维度, 由用户定义, 比如我调度中心想按照应用维度聚合, 模型平台想根据模型 code 聚合, 这块我们一直没做, 因为通知这一层做了聚合, 勉强能用.
-
我们把抑制做了细分: 处理/屏蔽/静默, 处理是指我知道了告警, 在处理, 你先别发我了; 屏蔽是我不想收到这个告警, 或者这个告警我处理不了; 静默是每天的这个时间段可能是有问题, 别告警
-
升级还是有必要的, 一种是告警没处理升级(离职了或者开会没看到通知等) 一种是处理长时间没恢复需要通知上级(特定告警等级才会升级)
AlertManager
Prometheus自身不具备告警能力,因此需要结合第三方告警程序来实现监控指标告警。
AlertManager是一款不错的告警程序,首先由prometheus配置告警规则,当告警规则触发后,会把告警信息推送给Altermanager,AlertManager收到告警之后在根据配置的路由,根据报警级别不同分别发送给不同的receive(收件人),AlertManager可以实现email、企业微信等报警
Prometheus作为客户端Alertmanager负责处理由客户端发来的告警通知。
对告警通知进行分组、去重后,根据路由规则将其路由到不同的receiver。
Prometheus监控系统的告警逻辑
首先要配置Prometheus成为Alertmanager的告警客户端;同时Alertmanager也是应用程序,它自身同样应该纳入prometheus的监控目标;
Alertmanager也通过默认端口9093和metrics路径暴露自身的指标。
部署AlertManager以及配置文件介绍
Altermanager是一个独立的go二进制程序,需要独立部署及维护;
按需下载相应的程序包,展开至特定的目录下即可运行;例如:
[root@k8s-m1 ~]# wget https://github.com/prometheus/alertmanager/releases/download/v0.22.2/alertmanager-0.22.2.linux-amd64.tar.gz
[root@k8s-m1 ~]# tar -zxv -f alertmanager-0.22.2.linux-amd64.tar.gz
配置文件介绍
global:
resolve_timeout //解析超时时间,也就是报警恢复不是立马发送的,而是在一个时间范围内不在触发报警,才能发送恢复报警,默认为5分钟
smtp_from //收件人的邮箱地址
smtp_smarthost //邮箱提供商的smtp地址
smtp_auth_username //收件人的邮箱账号
smtp_auth_password //邮箱授权码
smtp_require_tls //是否需要tls协议,默认是true
wechart_api_url //微信api地址
wbchart_api_secret //密码
wechat_api_corp_id //机器人应用的id
route:
group_by //采用哪个标签作为分组
group_wait //分组等待的时间,收到报警不是立马发送出去,而是等待一段时间,看看同一组中是否有其他报警,如果有一并发送
group_interval //告警时间间隔
repeat_interval //重复告警时间间隔,可以减少发送告警的频率
receiver //接收者是谁
routes //子路由配置
receivers:
name //接收者的名字,这里和route中的receiver对应
email_configs
- to //接收者的邮箱地址
配置AlertManager邮箱告警
global:
resolve_timeout: 5m
smtp_smarthost: 'smtp.163.com:465'
smtp_from: 'system71@163.com'
smtp_auth_username: 'system71@163.com'
smtp_auth_password: 'Ye1111111'
smtp_require_tls: false
route:
group_by: ['alertname']
group_wait: 10s
group_interval: 10s
repeat_interval: 10m
receiver: 'mail'
receivers:
- name: 'mail'
email_configs:
- to: '9146002@qq.com'
配置prometheus集成AlertManager
1.修改配置文件
[root@prometheus-server ~]# vim /data/prometheus/prometheus.yml
alerting:
AlertManagers:
- static_configs:
- targets:
- 127.0.0.1:9093 #AlertManager地址
rule_files: #告警规则路径
- "rules/alerts.yml"
2.创建rules告警规则目录
[root@prometheus-server ~]# mkdir /data/prometheus/rules
3.加载配置
[root@prometheus-server ~]# curl -XPOST 127.0.0.1:9090/-/reload
告警规则状态
告警规则分为三种
inactive:无任何报警,一切正常
pending:已触发阈值,但未满足告警持续时间,也就是在告警规则中写的for,在for规定的时间内触发都不会发送给AlertManager,当for持续时间一过会立即发送给AlertManager
firing:已触发阈值且满足告警持续时间,告警发送给接收者
AlertManager告警路由配置
路由配置介绍
alertmanager路由配置可以将不同的告警级别分别发送给不同的邮件接收人
Alertmanager的route配置段支持定义“树”状路由表,入口位置称为根节点,每个子节点可以基于匹配条件定义出一个独立的路由分支;
所有告警都将进入路由根节点,而后进行子节点遍历;
若路由上的continue字段的值为false,则遇到第一个匹配的路由分支后即终止;否则,将继续匹配后续的子节点;
route路由配置文件介绍
route:
group_by: ['alertname'] //定义分组,根据label标签进行分组
group_wait: 10s //分组等待时间,也就是说在10秒内同一个组中有没有一起报警的,如果有则同时发出报警邮件,也就是有2个报警同时发在一个邮件
group_interval: 10s //告警时间间隔
repeat_interval: 10m //重复告警间隔,也就是触发的一个告警在10分钟内没有处理则再次发一封邮件。
continue: false //若路由上的continue字段的值为false,则遇到第一个匹配的路由分支后即终止。否则,将继续匹配后续的子节点;
receiver: 'yunwei' //默认邮箱
routes: //启用一个子路由
- receiver: 'dba' //接收者为dba
group_wait: 10s //分组等待时间
match_re: //匹配一个正则
service: mysql|db //service标签包含mysql和db的统一发送给dba的邮箱
continue: false //若路由上的continue字段的值为false,则遇到第一个匹配的路由分支后即终止。否则,将继续匹配后续的子节点;
- receiver: 'yunwei' //接收者为yunwei
group_wait: 10s //分组时间
match_re:
serverity: error //将serverity标签值包含error的发送给yunwei的邮箱
continue: false //若路由上的continue字段的值为false,则遇到第一个匹配的路由分支后即终止。否则,将继续匹配后续的子节点;
receivers: //定义接收者的邮箱
- name: 'yunwei' //接收者名字,要和routes中的receiver对应
email_configs:
- to: '9146002@qq.com' //yunwei的邮箱地址
- name: 'dba' //接收者名字,要和routes中的receiver对应
email_configs:
- to: 'system51@126.com' //dba的邮箱地址
参考资料
Prometheus 告警配置以及抑制规则inhibit_rules 说明
https://github.com/grafana/tempo
https://www.alibabacloud.com/help/zh/cms/user-guide/manage-notification-policies
https://global.v2ex.com/t/1003836
https://www.alibabacloud.com/help/zh/anti-ddos/anti-ddos-origin/use-cases/configure-alert-notifications-for-ddos-attack-events
百度
https://developer.baidu.com/article/detail.html?id=290468
https://www.infoq.cn/article/depliaiig66go1xxzhxj
https://cloud.baidu.com/article/290323
https://blog.csdn.net/weixin_48493350/article/details/108008756
智能运维 | 百度网络监控实战:NetRadar横空出世(上) |
智能运维|脱始于Noah,万众期待的企业级运维平台NoahEE来了: https://zhuanlan.zhihu.com/p/52268678
走近监控系统的神经中枢: https://cloud.baidu.com/article/290323
百度云报警通告系统的下一幕: https://www.infoq.cn/article/depliaiig66go1xxzhxj
AIOps对监控报警架构的挑战: https://developer.baidu.com/article/detail.html?id=290468
相似度
-
https://www.datadoghq.com/blog/metric-correlations/
-
https://www.datadoghq.com/solutions/machine-learning/
-
https://mp.weixin.qq.com/s/9IZbmulUA18OCZ-ECSNSUQ
-
https://mp.weixin.qq.com/s/vODNelOyTwyciI-6sYBUtA
-
https://www.cnblogs.com/xiangsikai/p/11289937.html
-
https://zhuanlan.zhihu.com/p/30628883