PromQL 计算 CPU 使用率

Table of Contents

本文主要介绍如何使用 PromQL 计算 CPU 的使用(利用)率。

CPU 模式

在介绍之前,先了解下 CPU 的模式有哪些。在 Linux 机器上,使用 top 命令:

~# top
top - 12:13:21 up 93 days, 14:10,  1 user,  load average: 0.00, 0.02, 0.00
Tasks: 132 total,   1 running, 131 sleeping,   0 stopped,   0 zombie
%Cpu(s):  1.0 us,  0.3 sy,  0.0 ni, 98.7 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st

可以看到 CPU 一共有八种模式(状态),后面跟的数值是该模式的使用率,模式分别是:

  • us: user 模式
  • sy: system 模式
  • ni: nice 模式
  • id: idle 模式
  • wa: iowait 模式
  • hi: hardware interrupt 模式
  • si: software interrupt 模式
  • st: steal 模式

其中,user、system 和 idle 是 CPU 主要的模式。

注:准确说 CPU 一共是十种状态,还有两种:guest、guest_nice,它们的数值包含在 user 和 nice 状态中

CPU 时间

在 Prometheus 中,node_exporter 会抓取 node_cpu_seconds_total 指标,该指标会列出每种 CPU 模式占用的总共时长,单位是秒,如:

由于机器较多,并且每个机器的上有多个 CPU,所以先看一台机器上一个 CPU 的数据,使用 CPU 和 instance 标签过滤下:

可以看到,正好有八行记录,label 中的 mode 分别对应八种 CPU 模式,value 是自机器开机以来每种模式占用的总时长。根据上图第一个序列得知,IP 为 172.22.21.143 的机器的第 0 个 CPU idle 状态时长为:9286146.67s。

计算 CPU 使用率

到这里我们能够通过 PromQL 拿到一个 CPU 的每种模式的使用时长,而我们想要的是 CPU 使用率。

那么如何定义 CPU 的使用率?CPU 使用率 = 1 - CPU 空闲率,即:

CPU 使用率 = (1 - 所有空闲状态 CPU 时间总和 / 所有状态 CPU 时间总和) * 100%

为了简单,先计算一个机器上一个 CPU 在 2 分钟内处于空闲状态的时长,即:

increase(node_cpu_seconds_total{cpu="0",instance="172.22.21.143:9100",mode="idle"}[2m])

这里用到了 promQL 的 increase 函数,该函数是计算一个时间范围内,Counter 指标类型的增量值。这里使用 increase 函数,计算出该 CPU 在 2 分钟内,空闲状态的时长,即 81.80s。

那么根据公式可得该 CPU 使用率:

1 - increase(node_cpu_seconds_total{cpu="0",instance="172.22.21.143:9100",mode="idle"}[2m]) / 120

使用率为:32.93%。

或者使用:

1 - sum(increase(node_cpu_seconds_total{cpu="0",instance="172.22.21.143:9100",mode="idle"}[2m])) / sum(increase(node_cpu_seconds_total{cpu="0",instance="172.22.21.143:9100"}[2m]))

能达到同样的目的。该查询的分母:

sum(increase(node_cpu_seconds_total{cpu="0",instance="172.22.21.143:9100"}[2m]))

其实就是 120 秒。

其实不用这么麻烦,promQL 提供了 rateirate 函数,用来计算变化率:

1 - rate(node_cpu_seconds_total{cpu="0",instance="172.22.21.143:9100",mode="idle"}[2m])

分别查看一个机器上每个 CPU 使用率,即:

1 - sum by (cpu) (increase(node_cpu_seconds_total{mode="idle",instance="172.22.21.143:9100"}[2m])) / sum by (cpu) (increase(node_cpu_seconds_total{instance="172.22.21.143:9100"}[2m]))

查看一个机器上所有 CPU 的使用率,即:

1 - sum (increase(node_cpu_seconds_total{mode="idle",instance="172.22.21.143:9100"}[2m])) / sum (increase(node_cpu_seconds_total{instance="172.22.21.143:9100"}[2m]))

查看所有机器的 CPU 的使用率,即:

1 - sum by (instance)(increase(node_cpu_seconds_total{mode="idle"}[2m])) / sum by (instance)(increase(node_cpu_seconds_total[2m]))

也可以使用:

1 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[2m])))

查看所有机器的 CPU 使用率: