Prometheus数学consule使用
Linux系统中底层计算CPU占用率的方法
简单的总结如下:
Linux系统开启后,CPU开始进入工作状态,每一个不同状态的CPU使用时间都是从零开始累计
而我们在被监控客户端安装的node_exporter会抓取并返回给我们常用的八种CPU状态的累积时间数值
用户态CPU
用户态CPU通常占用整个CPU状态,最多的类型,当然也有个别的情况,内核态或ID等待占用的更多
top =>user%
12:00开机后 一直到12:30截止
这30分钟的过程中(当前我们先暂时忽略是几核CPU 就按1核来说)
CPU被使用在用户态的时间一共是8分钟
CPU被使用在内核态的时间一共是1.5分钟
CPU被使用在IO等待状态的时间一共是0.5分钟
CPU被使用在Idle(空闲状态)的时间一共是20分钟
(Idle空闲状态的CPU时间 其实就是CPU没事干的时间)
CPU被使用在其他的几个状态时间是0
上面的这些数据为了我们计算CPU在这段30mins时间的使用率提供了单位数据基础
CPU的使用率=(所有非空闲状态的CPU使用时间总和)/(所有状态CPU时间的总和)
有了这个公式后 就可以得出如下的计算公式
(user(8mins)+sys(1.5mins)+iowa(0.5mins)+0+0+0+0)/(30mins)=10分钟/30分钟
=30%
Counter数据类型(虚拟的数据类型,针对返回值,他的使用途径)
node_exporter=>node_cpu给我们返回的是Counter的数据(CPU底层是时间的累积)
Counter是一个一直持续增长的数值
30分钟内CPU使用时间持续增长UP,我们需要截取其中一段增长的增量值
如果我们能获得1分钟的增量值,然后那这个数值再去使用刚才同样的计算公式
就能得到1分钟的平均值。
Prometheus的数学查询命令行 计算函数
increase()函数
increase函数在Prometheus中,是用来针对Counter这种持续增长的数值,截取其中一段时间的增量
increase(node_cpu[1m])=》这样就获取了CPU总使用时间在1分钟内的增量
实际工作中的CPU大多数是多核的
如下图Node_exporter给我们截图回来的
八种CPU状态->每一个核的使用率
采集的数据精细到每一个核的CPU时间
不过我们在运维实习监控中 并不太关注每一个CPU核表现如何
而是关注整个CPU的表现
(一般生产服务器 CPU 都有 16 20 32 40 48 核)
如果每一个CPU核都单独来一个监控曲线图 意义不大而且看着图太混乱了
Prometheus解决办法
Prometheus提供了另一个sum()函数 很频繁使用
sum() 起到value加合的作用
sum( increase(node_cpu[1m]) )
外面套用一个sum即可把所有核数值加合
拆分并解释这个运算公式
(1-((sum(increase(node_cpu{mode="idle"}[1m])) by (instance)) /
(sum(increase(node_cpu[1m])) by (instance)))) * 100
(1-((sum(increase(node_cpu{mode="idle"}[1m])) by (instance)) /
(sum(increase(node_cpu[1m])) by (instance)))) * 100
这个prometheus的计算公式 其实就是 咱们最后 那个 使⽤
100%- (空闲时间 / 总时间) 的⽅法
不过这个公式 直接拿来看 还是有点痛苦, 咱们来学⼀下 拆
分
rate函数的使用
rate函数可以说是Prometheus提供的最重要的函数之一
rate()
rate(v range-vector) calculates the per-second
average rate of increase of the time series in the range
vector. Breaks in monotonicity (such as counter resets due
to target restarts) are automatically adjusted for. Also, the
calculation extrapolates to the ends of the time range,
allowing for missed scrapes or imperfect alignment of
scrape cycles with the range's time period.
The following example expression returns the per-second
rate of HTTP requests as measured over the last 5 minutes,
per time series in the range vector:
rate(http_requests_total{job="api-server"}
[5m])
上面这一段是官网提供的解释
简单翻译一下
rate()函数是专门搭配counter类型数据使用的函数
它的功能是按照设置一个时间段,取counter在这个时间段中的平均每秒的增量
这个例⼦ 使⽤的 node_exporter
key node_network_receive_bytes
rate(node_network_receive_bytes[1m])
node_network_receive_bytes 本⾝是⼀个counter类型 字⾯意
思 也很好理解
⽹络接收字节数
咱们之前也学习过了 对于这种 持续增长的 counter数据,直
接输⼊key 是没有任何意义的
我们必须要 以获取单位时间内 增量的⽅式 来进⾏加⼯ 才能
有意义
那么 对于counter数据, 进⾏第⼀步的初始化的 增量获取 加
⼯
通常的使⽤发放 就是直接⽤ rate() 包上。(increase(). 也是
可以的 我之后会讲到)
node_network_receive_bytes 被rate(. [1m])包上以后
就可以获取到 在1分钟时间内,平均每秒钟的 增量
得到的图
这样以来 数据就变得有意义了
强调
所以说 我们以后在使⽤任何counter数据类型的时候,永远记
得 别的先不做 先给它加上⼀个 rate() 或者 increase()
接下来我们把rate()做的事情 更加细化的 咱们来解释⼀下
⽐如上⾯这个图, ⽹络接收字节数 ⼀直不停的累加
从 23:44开始 到 23:45
⽐如累积量 从440011229804456 到了 -> 440011229805456
1分钟内 增加了 1000bytes (假设)
从 23:45开始 到 23:50
⽐如累积量 从440011229805456 到了 -> 440011229810456
5分钟内 增加了 5000bytes(假设)
加⼊rate(. [1m]) 之后
会把 1000bytes 除以 1m*60秒 , =~16bytes/s
就是这样 计算出 在这1分钟内,平均每秒钟增加 16bytes
这个还是⽐较好理解的
接下来 咱们修改 1m => 5m
变成这样 rate(. [5m])
这样就变成 把5分钟内的增量 除以 5m*60
5分钟的增量 假如是 5000 , 那么除以300 以后 也还是约等于
=~ 16bytes/s
感觉好像是⼀模⼀样的?
那么我们来看下输出 rate[5]
啊? 感觉图形发⽣了⼀定的变化 怎么回事?
明明是⼀样的 平均 16/s 啊 怎么图形变了呢?
事实是这样的
如果 我们按照 rate(1m)这样来取,那么是取1分钟内的增量 除
以秒数
如果 我们按照 rate(5m)这样来取,那么是取5分钟内的增量 除
以秒数
⽽这种取法 是⼀种平均的取法 ⽽且是假设的
刚才我们说 counter在 ⼀分钟 5分钟 之内的增量 1000 和 5000
其实是⼀种假设的理想状态
事实上 ⽣产环境 ⽹络数据接收量 可不是这么平均的
有可能在 第⼀分钟内 增加了 1000 , 到 第⼆分钟 就变成增加
了2500 ….
所以 rate(1m) 这样的取值⽅法 ⽐起 rate(5m) ,因为它取的时
间段短,所以 任何某⼀瞬间的凸起或者降低
在成图的时候 会体现的更细致 更敏感
⽽ rate(5m) 把整个5分钟内的 都⼀起平均了,那么当发⽣瞬时
凸起的时候 ,会显得图平缓了⼀些 (因为 取的时间段长 把
波峰波⾕ 都给平均消下去了)
那么我们再放⼤⼀些 看看 rate(20m) 会怎么样
哈哈 � 是不是就更平缓了
在我们的⼯作中 取1m 还是取5m
这个取决于 我们对于监控数据的敏感性程度来挑选
说到这⾥ 我们对rate() 函数 应该也有了⼀定的了解了
接下来 咱们继续学习 第⼆个重要的函数
(三) increase函数 使⽤
increase 函数 其实和rate() 的概念及使⽤⽅法⾮常相似
rate(1m) 是取⼀段时间增量的平均每秒数量
increase(1m) 则是 取⼀段时间增量的总量
⽐如
increase(node_network_receive_bytes[1m])
取的是 1分钟内的 增量总量
和
rate(node_network_receive_bytes[1m])
取的是 1分钟内的增量 除以 60秒 每秒数量
从这两个图 我们可以看到 其实曲线的⾛势 基本是⼀样的
但是 显⽰出来的数量级bytes 可不⼀样
137303978 * 60 = 8238238680 (发现)
正好是 60倍
也就很好理解了,increase() 是不会取⼀秒的平均值的
incraese() rate()
监控 获取采集数据源
频率
5m =》 rate()
形成图 断链
increase(5m)
rate() -> CPU 内存 硬盘 IO ⽹络流量
counter
(四) sum()函数的学习
sum()函数的使⽤ , 我们在上节课 讲CPU拆分公式的时候 已经
讲过了
sum就是 总取合
sum 会把结果集的输出 进⾏总加合
⽐如
rate(node_network_receive_bytes[1m]) 显⽰的结果集 会包含如
下内容
从标签 我们就不难看出,有好多台服务器 都返回了 这个监控
数据
当我们使⽤ sum()包起来以后
sum(rate(node_network_receive_bytes[1m])) 就变成下⾯这样了
变成⼀条线了 …
等于是 给出了 所有机器的 每秒请求量..
我们之前也说过,如果要进⾏下⼀层的拆分
需要在 sum() 的后⾯ 加上 by (instance)
才可以按照 机器名 拆分出⼀层来
sum() 加合 其实还有更多巧妙使⽤
instance
sum () by (cluster_name)
如果是 by instance 那么 其实跟 不加sum()的输出结果是⼀样
的
本来 rate(node_network_receive_bytes[1m]) 就已经是按照每台
机器 返回了
但是如果 我们希望 按集群总量输出呢?
⽐如 我们返回了20台机器的数据
其中 有6台 属于 web server
10台属于 DB server
其他的 属于⼀般server
那么我们这时候 sum() by (cluster_name) 就可以帮我们实现 集
群加合并分三条曲线输出了
100 - 1000 CPU
顺带⼀提的是 (cluster_name) 这个标签,默认node_exporter
是没有办法提供的
node_exporter只能按照 不同的机器名 去划分
如果希望 ⽀持cluster_name 我们需要⾃⾏定义标签 �
往后的课程 我们会涉及到这个内容
(五) topk()函数的学习
定义:取前⼏位的最⾼值