昨天一个朋友在微信群中问我数据库的指标告警的故障收敛怎么做才能真正落地。说实在的,虽然现在很多做智能化运维的企业都号称能实现很好的故障告警收敛,不过都是场景受限的。大多数情况下是在一套系统中,针对系统中多个IT组件的故障根据时间、先后顺序、以及波动曲线以及相关性要素等,通过算法进行收敛。这种收敛在有些场景下是有效的,不过也存在一定的误判和遗漏,不过总体来说还是可用的,是具有一定的实战作用的。
网友的问题并不是在一个系统中如何归并各个IT组件对于同一个问题的告警,而是针对某一个具体的运维对象,他特指的是数据库。如果把这个问题放到一个具体的运维对象上去看,比如DBA面对的数据库系统,那么这个问题就完全不是一码事了。当时那个朋友举例说系统中CPU 使用率98%,表空间使用率99%,应用响应时间异常,这个情况如何进行告警收敛呢?在我们的实际生产环境中,可能问题更为复杂,因为绝大多数IT系统都是带病工作的,我们称之为亚健康状态。系统的亚健康状态往往在实际生产环境中是常态,只是这些小毛病并不会掀起大浪,因此我们也不去关注,甚至无法感知,也不一定需要立即去做闭环解决。不过就像大量的无症状新冠感染者隐藏在人群中一样,因为自身没有发病,并没有引起社区或者社会的关注,如果我们不去做全员核酸检测,那么这些可能酿成重大传播危险的潜在威胁我们是感知不到的,只有检测或者出现了有症状的患者,周边才能感知到。
不过系统的监控与运维是一个十分复杂的东西,除了管理规程,还有成本问题。因此我们总是会把主要的成本放在急需解决的问题上,对于不是特别重要的告警信息,大多数企业已经没有能力去做闭环管理了。想象一下,如果一个人管理数十个甚至上百个数据库系统,你能不能对每天产生的数千个甚至上万个告警信息去做闭环管理?
实际上在实际生产环境,即使是已经暴露出来的一些问题,比如说CPU 使用率98%,就一定说明系统有问题吗?表空间使用率99%,也不意味着一定就有问题,如果某个表空间放置的是静态数据,或者说数据文件是自动扩展的,那么表空间使用率100%也不是什么大问题。
我们来看上面的例子,USERS表空间的使用率是97.75,容量是32GB,实际上如果从Oracle的dba_free_space来看,这个表空间已经是100%了,只是因为这个数据文件是自动扩展的,监控系统自动根据ASM磁盘组的容量给这个表空间赋予了32GB的动态容量,同时自动将表空间使用率调整为97.75。从这个动态调整来看,首先我们要关注的是指标的准确性和有效性。因为AUTOEXTEND功能的存在,以及ASM磁盘组对文件EXTEND的限制,如何计算准使用率是十分关键的。这个指标不准确,那么后面的监控报警都成为十分虚幻的事情了。
除了指标的准确性,我们还需要关注什么呢?实际上很多指标并不能很好的指示风险,比如说表空间使用率的问题。我们再来看看下面的例子。
我们可以看到,我们引入了一个“表空间容量风险”这个评估指标,并通过这个指标来给表空间使用风险报警,这个指标比表空间使用率具有更高的准确性。整个系统的表空间使用率风险是0,这是最低的等级,表明没有任何风险,刚才我们看到的97.75%使用率的USERS表空间的风险等级也是如此。为什么会这样呢?USERS表空间中存储的大多数是只读数据,增长率极低,每次增长的数量也很小,当前不扩容还可以用很长时间,那么这时候就没必要马上报警了。这种评估可以大幅度减少误报,不过也可能会带来新的问题,那就是如果有人想往USERS表空间里导入大量的数据,那么马上就会报错。因此这种表空间使用率较高的情况,也不能完全忽略。我们会在日检、周报和月报里指出这个问题,而不是在日常的告警中不断的去告警,这样也能够起到提醒运维人员的作用,而不需要半夜发个短信让人虚惊一场。
从上面的例子可以看出,准确而有效的指标体系是实现故障报警收敛的最基础的工作,实际上指标准确性也可以大大提高告警准确性,从而减少运维成本。有了这一步之后,后面该怎么走呢?我们再回到前面说的例子。应用变慢,是正常的慢还是不正常的慢?这三个指标异常之间存在关联吗?存在什么样的关联呢?
实际上,如果要针对这个场景去做告警收敛,还是脱离不了专家经验和实际运行环境中的系统运行特征。对于数据库来说,如果表空间满了无法写入数据,那么应用会报错,同时系统负载是会下降的,数据库的并发负载会下降,甚至CPU使用率可能会出现断崖式的下降。某些系统一旦出现无法写入数据,则会话会重新启动,那么数据库的新建连接数会增加,因为数据库无法写入,因此新建连接会全部失败,连接失败率会出现急剧上升,而只读应用依然会正常。如果我们能够梳理出这种场景,那么我们就肯定能够把此类场景的十几个指标异常进行很好的归类,收敛成一个告警,并直接告知故障根因。如果再加上这些指标的异常检测,能够根据这些指标的时间序列进行再分类,那么就能够更加精准的收敛故障场景,其告警准确性又可以上一个台阶。这种运行特征的梳理可以采用专家根据以往的故障案例或者经验进行梳理,也可以通过算法自动对场景进行分类抽象。
再回到CPU使用率高的问题上,如果CPU使用率在某个工作窗口上的某一次或者几次突然升高,并不一定是数据库系统或者应用出现了必须由运维人员干预的问题,不过如果CPU使用率持续高于平时的情况,或者突然CPU使用率远远低于某个基准,这时候意味着系统出现问题的机会远远高于某个或者某几个采样点出现高值。因此我们就不应该直接使用CPU使用率这个指标来进行告警,而是通过实时计算,生成一个CPU使用率过高风险或者CPU使用率异常风险这样的指标来进行预警,这样会有更好的效果。当然,在实际的实现中,可以构建出一系列的规则模型或者专家模型,通过这些模型来描述一个场景,比把每个场景都做成指标成本要低得多。
一些通用型的故障场景,往往可以做成独立的指标,从而降低分析的复杂性。
而对于一些非通用的,和系统有关的,或者用户私有的故障模型,则可以通过其他的方式去构建。一旦这些故障模型被构建起来之后,我们就可以不去关注指标和基线的预警了。运维人员只需要面对故障模型的预警去做闭环管理,这样也是实现故障告警收敛的一种实现方法。在一个实际的案例中,一个具有100多套系统,数百个数据库、中间件的运行环境中,每天只会收到数十个告警,其中需要立即闭环处理的事件基本上是个位数。
当然这种方法也存在缺陷,那就是会遗漏一些未知的风险。我们采取了健康模型告警的方式来做弥补。当系统的健康度急剧下降的时候,会产生一种模糊状态报警。这种报警需要运维人员去做状态巡检,从而定位问题。如果定位出了明确的问题,那么就可以再次抽象成新的故障模型。通过这样不断的迭代,让我们的运维告警越来越精准。