开发者学堂课程【3天吃透 Prometheus:Prometheus 监控系统】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/1244/detail/18452
Prometheus 监控系统
1. CPU 使用率
我们继续来描述。这个target我们现在能够正常监控了,于是我们就可以过滤节点级的数据了,比如像 nodes 可以看到会多出来很多指标,自动能够进行补全了。其中有一个像 CPU 相关的node CPU seconds.execute,你会发现我们这个主机上一共有四个核心,它们分别被标示为CP0、1、2、3,每一个核心分别有多种不同状态或者多种不同模式下的时间占用,比如空闲的有多少,io wait 的状态有多少,刚才我们可以都看到了,他就能展示到这了。那我们接下来可以自己在这来进行过滤了,比如我们只看一看所谓空闲比例有多大?我们可以定义 node e=idle,来做一个execute 调查,现在就只有 idle , CPU 或者 CPU 核心的空闲比例有多少,这叫空闲时长,空闲比例你可以这么理解,因为它是个 seconds ,如果我们要想知道我们 CPU 的使用率有多高,那我们就可以进行计算了,用 CPU 自己减去它的已用,然后再除以100,这不就是一个所谓的百分比了吗?他再乘上100,就是百分比的实际数字了。那因而我们来看,如果我们要期望能够对我们的 PromQL 或者对我们 Prometheus 中的这些指标数据,投射到刚才我们讲到的监控方法论当中的,比如像 Use上去大概怎么做,我这里专门给出了说明,以便于各位后面自己参考这个来使用。
比如说我们看看 CPU 使用率,每台主机 CPU 在5分钟之内的平均使用率应该怎么计算,看这个公式。
首先我们可以计算一下我们每一个节点或者每一颗CPU,甚至说我们按节点为类别进行计算,你无论有多少个核心,就都算在同一颗CPU也可以,那这个表达式就来让我们获取到每个主机上的 CPU 的使用率。能看懂这个公式吗?我来给大家做个简单的解释,因为这也是我们下一次课的重中之重。因此我们这里先要有一个基本的了解,稍微有点难度。第一, node_cpu_seconds_total 这是我们的指标名称,就是刚才各位在看的指标,所以我们过滤一下我们所关注的模式的指标,叫 node e=idle ,就能过滤出来一个所谓的几个指标时间序列,然后我们对它做速率计算,这是一个函数叫 irate ,它是一个灵敏度非常高的速率计算函数,然后5m五分钟表示我们对每一个时间序列来讲,取出来,从此刻开始往前倒推五分钟之内的所有样本数据,对这些样本数据做速率计算,你可以认为说是每一个样本减去它的前一个样本,你可以这么去理解吧,就类似于这种格式,或者是每个样本和它的前面样本之间要取一个差叫做△,如果说它是个累加型的数据,该样本减去前一个样本还要去除以时长来计算速率,大概是这样一个逻辑。那因此这个 irate 就可以理解为像类似这种格式就,一个样本减去前个样本除以时间,再用这个样本再减前一个样本除以时间,就类似这种格式让我们可以计算出速率来。事实上 irate 你可以理解为就是最后两个计算的,他没有那么多时间,所以说即便无论你指多长时间,所以我们认为它是一个灵敏度更高的这个函数.
接着我们对这两个的数据取平均值,平均完以后然后再做聚合,怎么聚合?我们基于每一个实例聚合,就是如果是同一台主机上的 CPU ,不管你有几颗,我们这些对这些CPU 做平均计算,那就得到的是我们真正的这个 CPU 的负载,而不是每个核心的负载的。用1减去空闲的,那就是使用的部分,乘以100,就可以换算成百分之几的概念了。比如1.06就1.06%就是这意思。否则的话你可能得到数据是0.0106。图上输入的数据是正常情况下要求的数据,接下来我们要给它做速率计算,因而我们要指明一个时间范围,这个时间范围就代表了所谓的叫做区间向量也叫范围向量,它会取到一堆的样本,对这一堆的样本我们可以做速率计算,那这个速率可以是rate,也可以是 irate ,当然rate可能不精准,使用 irate 得到这个速率应该更精准一点 。接着对 irate 的计算结果,我们还可以给他求平均值,大家计算出来是四个值,那么一个核心的负载可能不一样,因而我现在要给他去取平均值,那就叫 avg 这就是做聚合计算,那么聚合的时候基于什么进行聚合?那么使用avg去 by 比如我们每一个实例上面,你无论拥有多少个核心,我们都要对它做聚合计算。
各位看对于这个实例而言,它的四个核心在 idle 模式也就是空闲比例,做一个平均值,就得到这么一数据:
这是空闲的,因为它本身其实你可以理解就是个百分比。那我减一下得到的就是叫使用的,叫使用率,但这个使用率数字它不是一个百分数,所以我们可以对整个数据再给他去乘上100,你可以认为这个乘后的结果就是一个直接所应该能够得到的百分比数据,那就意味着我们当前 CPU 使用率是0.2%。
Prometheus 本来就是用来替代 Zabbix的,它是一个完整意义上的监控系统。所以我们随着课程的展开就知道,它本来就是一个双精度浮点数,其实我们在展示的时候可以基于各种各样的取舍,每个 Instance 刚才讲过,其实就代表了一个 target ,只不过在不同语境当中的概念不一样。不同语境指的是如果我们要作为被监控目标进行配置的时候,它就叫target,而配置出来之后就叫 Instance 。我这样讲,大家是不是可以听明白,但事实上之所以非要去区别 target 和 Instance 在于有些target尤其是服务发现配置,只配置一个target,但我通过服务发现可以发现多个,所以 target 严格意义上和 Instants 不是等同的概念,你可以认为每个 Instants 就是一个真正能暴露、能输出、能吐出来指标数据的实例。 target 更像是我们配置出来能够让我们的 Prometheus 找到 Instants 的入口,就是学 MySQL 时学的自由即责任,我们把这东西搞明白了,才能更好地使用 Prometheus 。这可能就是大家发现这个所谓的 Prometheus 内建的 UI 的坏处,我们辛辛苦苦写的 PromQL 一刷新它就没了,它不会保存下来,以后想再用,你还得再写一遍,就很悲催。所以我们要正常用一些外置的,比如像各种展示界面或者叫记录规则,我们把它保存下来,以便于以后能复用,这才是我们所需要的,那这个时候我们需要部署一个 Garafana 来进行展示,不过我们回头再说 Garafana ,我们把当前这个话题给大家说完。
2. CPU 的饱和度
刚才我们通过这个方式给大家讲到了如何去获取CPU的使用率,大家不要着急,我下一节课会详细讲PromQL 它的格式和具体怎么用、有多少种聚合函数、有多少种内置函数,以及向量匹配的时候如何进行,还是那句话,你把那个东西搞明白了,其实 Prometheus 最难的一关已经过去了,至于说像高可用之类的,对运维工程师、对于架构师来讲,这难道能是什么障碍吗?我觉得应该不是。 PromQL 就是 Prometheus 自己内建的。刚才已经说到了我们如何去评估 CPU 的使用率的,大概就是这种方式。
下一个我们怎么去评估 CPU 的饱和度?
什么叫饱和度?你可以理解为就是CPU的平均负载、跟踪 CPU 的平均负载本身就能获得关于CPU 的饱和度,就是 CPU 在他的单位时间内,他的工作的满载率有多高?比如说你在上班的时候,你的老板说你工作不饱和,意思就是你没有所有时间内都在工作,一定有一些空闲时间在那玩手机了摸鱼了之类的,那这种就表示不饱和,那因而我们去评估的就是在用于正常工作的时间比例有多大,这叫饱和度。那因此对于我们 CPU 来讲,它其实就是将主机上的CPU数量考虑在内的一段时间内的平均运行队列的长度。这个长度应该是多长合适,其实有个非常简单的办法,就是我们使用 node 自己内建的有 load 开头的几个指标,比如 load1、load5、load15。各位应该已经明白了,这表示节点上过去一分钟的平均负载、过去五分钟的平均负载和过去十五分钟的平均负载。这里显示了我们当前的实例它CPU 过去一分钟的平均负载。点 Graph ,它会绘一个图出来,各位可以看到这个线状图,还能输出为面积图。因为我这里只有一个node,所以它只显示出来一个图形,如果配置多个 node 的话,每个 node 如果负载不一样,可能会有多个图形显示,如果要使用堆叠图、堆叠面积图的话,他们应该会堆起来,然后还能有一个很好的对比效果来进行显示。这个时候对于这个数据很关键,这个数据到底多大算是 CPU 很饱和,一般来讲应该是正常这个数据不能长时间大于 CPU 核心数量。你比如说我们当前节点上一共有四个核心,然后这个数值是8那我们就认为当前的 CPU 已经是非常饱和了的工作逻辑。就正常情况下一个核心在某一时刻时时刻刻都在运行任务,你比如说我们 CPU 没有空闲时间,所以它但凡只要大于 CPU 的数量,而且是长时间大于,我们就认为它是饱和,这个队列可能就会不断的累积,而且会越来越长。要想看出哪个 CPU 占用最高的,刚才第一个我们就已经解释出来了, CPU 如果不做聚合的话,它会算出来每一个核心的使用率,聚合以后,会得出来所有 CPU平均下来的这个所谓使用率,这是我们的饱和度评估。
当然,我们还可以写很复杂的方式来进行计算饱和度。你比如说上述图片中涉及的表达式:node_load1>on(instance) 可能更复杂,那么还是那句话,可能等到下节课大家才能真正把它搞明白。我这里给大家做个简单的解释:他的意思就是说我们去计算一下 CPU 在过去一分钟的平均负载所取得的结果,是不是大于该节点上 CPU 的所有核心数量的二倍。如果是,而且长时间是,我们就认为这个 CPU 就是处于高负荷的状态下。那像这种一旦满足条件了的,我们就认为该报警了,因为你的 CPU 实在是压力太大了,很有可能你的应用程序出bug了,或者是访问量,或者你CPU的性能有点弱了,那我们需要去扩充,或者我们需要去扩展我们的应用规模了等等。如果说我们有中央控制器的话,比如我们配置在 Kubernetes 之上,这时候 Kubernetes 甚至能够基于这个所谓采集过来的节点上的 CPU 的饱和度,来判定我们是不是应该加节点了。如果所有的CPU所有的主节点的CPU的饱和度都很高,那他这个时候可以调用云控制器或者云底层的那个公用云的 API 加一些节点进来,把我们的应用程序更好的负载到、分摊到多个不同节点上去,就能实现某种意义上的自动化运维的逻辑。
3. 内存使用率
下一个我们看怎么去评估内存使用率,还是那句话,这是 USE 方法当中让我们关注的个重点指标,我们通过介绍让大家知道 Prometheus 怎么去使用指标的。
noed _exporter 要暴露多个以 node _memory 为前缀的指标,我建议各位可以重点关注一下几个:比如 node _memory_MemTotal 总内存空间、MemFree 空闲内存,不过这个空闲是MemTotal 减去真正使用的,而且减去了 Buffers 还减去了 Cached 。所以到底我们还有多少内存可以使用?可以这么来算:真正可用的内存应该是这三个和,加Free 加 Buffers 加Catched,这其实是我们的可用内存量。用 MemTotal 减去这三个的值,我们认为这才是真正的已用内存量。因此我们要想去计算内存使用率,可以是这三个之和,第一个减去后三者之和,再除以第一个就是内存使用率了。
底下这个图里边的这个表达式更长,但它比第一个容易理解多了。他的意思就是总内存空间减去空闲空间,再减去用于 Buffer 的空间,再减去用作 Catched 的空间。但凡学过 linux 的同学应该都理解这个概念,然后我们再用这个值去除以总空间,再乘上100,其实就是我们内存使用率的概念。这是小学算术,是非常容易计算的。Available的值不是刚才说了吗? MemFree + Buffers + Catched 。怎么放 Garafana 的出图,我们后面会讲,其实你就把这一个 PromQL 在 Garafana 上点击创建图形,把这个表达式写进去保存,它就会直接生成图了,就这么简单。所以我们说你只要把这个 PromQL 写好了,就能生成,或者再生成图就不是什么麻烦事了。 Prometheus 就是自己的最大劣势就在于他自己内建的这个 UI是没办法让我们持久长久去使用这样的语句的。关键是要会写公式,你要先知道它是怎么运行的,我们是怎么用的才行。鉴于时间关系,我就不去再去输入了,因为太耽误时间了。
4. MySQL exporter
如果我们要想监控 MySQL 怎么办,这个就不演示了,还是那句话,鉴于时间关系我给大家说清楚。
我们怎么去监控 MySQL ,比如现在有个 MySQL 的主从复制的集群,一主两从。现在我要想监控 MySQL服务怎么办?正常情况下话,应该是同样的逻辑,这三个主机上分别运行 MySQL 进程, MySQL 自己并没有内建 Prometheus 键入的测量系统,所以我们就不得不在每一个主机上部署一个专门的组件叫做 MySQL exporter ,因为 node_export只能导出系统级的指标,它不能导出 MySQL的指标,比如你执行过多少个 select 语句,执行了多少个update语句,内部的InnoDB Buffer Catch 有多大,这些他们都没办法知道,因而我们需要一个专门的暴露器来暴露 MySQL 的这些指标,那每一个节点都应该装一个叫做MySQL exporter 。这个 MySQL exporter 其实就是 MySQL 的客户端,他应该能够连到 MySQL 上,有权限以某个用户的身份连入 MySQL 去读取 MySQL 内键各种状态数据,把这个数据取出来以后,由它转换为 Prometheus 兼容的指标格式。转换成这个指标格式以后, Prometheus Server 就可以周期性去抓取,抓取的的时候,像 MySQL Exporter 抓取的意思就是给我一个指标数据,这个时候 MySQL Exporter 就会实时的去向 MySQL 发一次查询,把数据拿过来在本地做计算,再把计算好的结果报告给 Prometheus Server ,每一个实例都是如此。所以这时候你可以理解为这三个实例很有可能是通过同一个target配置发现的,是三个instance。然后对应的这每一个实例都是有一个IP加一个端口来进标示的,我们把它称作一个target,可以这么理解,当然我把它称为叫instance更合适,希望大家能理解。如果是 Java 程序的话怎么监控?很显然那我们应该去做使用 Jvm 的 Exporter ,事实上 Jvm 之上通常还有一定程序,比如像 Tomcat 、Elastisearch 对于那些对应的应用程序,还应该做进一步的监控,这点各位也要知道。 Prometheus 提供了大量的 Exporter ,有的是他自己提供的,有的是第三方机构提供的。他自己提供的,你可以理解为是官方认证的比较关键的, Prometheus 的官方站点上直接能看到下载的页面,在这能找到 node Exporter 、 MySQL Exporter 、memcatchedd_exporter 、hadoop_exporter ,这里没有列出来的,有些也支持,可能我们下载的时候需要到 githab 上去下。其实这个 Exporter 也不是什么难事,很多公司很有可能都自己研发了这样的 Exporter ,使用 GO 语言或者使用 Python 编程,写一个 Exporter 应该是很不麻烦的,因为它有 client library ,我们直接调这个 client library,使用 Python 去写一个 Exporter ,去暴露几个指标数据,简直不要太简单了。我们可能要装很多 Exporter ,但事实上在生产环境当中,如果是略具规模的企业,怎么可能在一个主机上装太多应用。那因而通常一个被监控的主机之上那至少应该会有两个以上的 Exporter :第一,应该有我们的节点的node Exporter ,如果运行了MySQL 那应该还有个 MySQL Exporter,运行 MySQL 还不够吗?打算在上面还跑什么别的应用程序,一般而言,大家知道我们很多服务都是 Dedicated , Dedicated 就表示专用服务器。如果不是专用的没关系,比如再有一个 Nginx ,那应该还有一个 Nginx Exporter 。再运行一个 Prometheus , Prometheus 就不用了, Prometheus 自己有Exporter,因为它内置的有 instrumentation 。如果是 Docker ,我们可能需要借助 cAdvisor ,其实 Docker 现在自己内置的也有它的监控接口,直接就可以抓取它这个所谓的 Exporter 。 Nginx 的话,选 VTS 就更好了,使用 VTS 这种方式会更合适。有的同学也肯定就想明白了,既然如此,那是不是说我有个一百来台主机,我的监控抓的指标可能会上万了?没错。所以我的 Prometheus 在存储方面,不光是 Prometheus ,所有的监控系统,只要指标足够多,那在存储方面压力就很大, Zabbix最大缺陷在于它默认使用的存储系统 SQL 类型的存储系统,MySQL 、PostgreSQL 、或者 Oracle 系统,这种系统内置支持事务还有各种约束,那每一次指标数据的插入都要各种约束、检查之类的。即便只做索引扫描和检查,这个评估也不是一个小的负载,所以我们使用 Zabbix 监控如果没有充分优化的话,很快就会遇到性能瓶颈,以至于很多大厂后来就不得不运行多套这样 Zabbix 监控系统,很尴尬,他们只好自研,阿里的是自研的,小米是自研的,已经开源了在这了,OpenFilename、大众点评资源叫cat等等,这些都是基础设施,大家也不要觉得说装一些 Exporter 包是什么大不了的事,有些像分布式链路追踪系统,我们甚至还要自己在被跟踪的应用内部打点的,做埋点的,不做埋点怎么去跟踪、调用内部的数据,都必须要有自省的逻辑,你要买个 Exporter ,你要么打点,这个我相信对于很多朋友来讲,应该不是什么特别难理解的事。坦率的讲,我这可能没办法把每个概念都要解释一下,你可以理解为对 Prometheus 而言,他每个 target 如果自己内置了instrumentation,这个instrumentation就是我们监控系统埋的一个探针或者埋的一个点,所以我们可以理解就这个概念。那如果是分布一定追踪,那它应该是一个专门用来做性能追踪的,做调用追踪的客户端库的这个内置的程序模块,那我们也称为叫埋点。
很显然介绍到这里,我相信大家应该有所了解了:一个完整意义上的监控系统,它通常应该监控的指标非常多,刚才已经讲到这个概念,这是第一个;第二个我们监控系统是 IT 系统的基础设施。彼得德鲁克就说过:“你如果不能监控,你就不能管理。”所以对我们运维工程师来讲,哪怕我们架构师来讲,对我们 DevOps 工程师来讲,如果我们运行了很多系统或者叫组件,这些组件如果我们不能监控它,你就没办法管理它,因为你不知道它什么时候出问题了,也不知道内部到底运行什么状态,那我们作何管理?所以我们认为监控系统是我们 IT 信息系统的基础设施之一。即便是我们不用分布式调用链接跟踪,即便是我们不用日志存储和搜索系统,但监控系统通常是必不可少的。有句话虽然略具夸张的概念:“无监控不运维。”那事实上对于 SRE 工程。这个 SRE 叫系统站点可靠性工程。到如此重要的今天,监控系统的重要性几乎又上了一个台阶,所以这也是我们应该掌握的系统的最重要、最核心组件之一。大家要注意,当然如果做事前监控,后面我们讲 PromQL 的时候,我会给大家讲一些比如做线性分析,就是基于所谓的叫做回归测试来做简单分析的,我们真正要做事前监控的话,恐怕也得到 DevOps ,自己要研发一些算法,基于机器学习的方式来做事先监控,否则的话可能这些数据就算我们采集到的数据,你也很难知道它的真正意义是什么。