linux下CPU的指标

node_cpu_seconds_total指标的思考

当对节点cpu进行监控时,会经常用到下面这条PromQL

1
2
3
4
5
6
7
8
- alert: HighCpuLoad
expr: 100 - (avg by(instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80
for: 5m
labels:
severity: warning
annotations:
summary: "High CPU load (instance {{ $labels.instance }})"
description: "CPU load is > 80%\n VALUE = {{ $value }}\n LABELS: {{ $labels }}"

可以看到核心指标是用到了node_cpu_seconds_total{mode=”idle”},那么为什么要使用条件为mode=”idle”的数据,以及这个条件代表了什么意思,查询原始指标数据如下

1
node_cpu_seconds_total{cpu="0",endpoint="metrics",instance="127.0.0.1:9100",job="node-exporter",mode="idle",namespace="default",pod="c2-monit-prometheus-node-exporter-zz475",service="monit-prometheus-node-exporter"}

cpu这个标签一般表示的是节点上cpu的核当前编号,一般有几个核cpu的序号就会有几个

而mode这个标签则是表达了cpu的使用情况的一个状态

/proc/stat

node_export采集的数据应该是基于/proc/stat中的数据计算出来的

1
2
3
4
5
6
7
8
9
10
11
12
13
$ cat /proc/stat
cpu 30512019 2905 18888929 5215060855 449961 258 322293 482253 0
cpu0 12054132 723 5666598 1297356736 439476 258 173174 175261 0
cpu1 6256562 718 4332274 1305529992 4073 0 50163 105721 0
cpu2 6252205 723 4470475 1305772598 3466 0 49552 102278 0
cpu3 5949118 739 4419581 1306401527 2944 0 49403 98992 0
intr 10488180092 119 7 0 0 0 0 0 0 1 0 0 33 104 0 0 68 0 0 0 0 0 0 0 0 0 10319942 0 336 0 18155452 0 14 0 265289852 3907 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
ctxt 18254375560
btime 1516246663
processes 13216259
procs_running 1
procs_blocked 0
softirq 3948723530 0 1488253637 8488 455883603 17 0 179 392363322 13619548 1598594736

第一行的数值表示的是CPU总的使用情况,cpu0、cpu1、cpu2、cpu3分别指每个cpu核心的cpu使用情况,下表解析第一行各数值的含义(单位:jiffies):

名称 表达的内容
user 从系统启动开始累计到当前时刻,用户态的CPU时间,不包含nice值为负进程
nice 从系统启动开始累计到当前时刻,nice值为负的进程所占用的CPU时间
system 从系统启动开始累计当前时刻,核心时间
idle 从系统启动开始累计到当前时刻,除IO等待时间以外其它等待时间
iowait 从系统启动开始累计到当前时刻,IO等待时间
irq 从系统启动开始累计到当前时刻,硬中断时间
softirq 从系统启动开始累计到当前时刻,软中断时间
stealstolen 当一台物理机有多个虚拟机时,该cpu在其他虚拟机运行的时间
guest 在cpu内核控制下,提供给在上面运行虚拟机占用的cpu时间

因为/proc/stat中的数值都是从系统启动开始累计到当前时刻的积累值,所以需要在不同时间点t1和t2取值进行比较运算,当两个时间点的间隔较短时,就可以把这个计算结果看作是CPU的即时利用率。
其他参数含义
名称 | 表达的内容

  • | -
    ctxt | 上下文切换次数
    btime | 系统启动到当前的时间(秒)
    process | 自启动以来,创建任务个数
    procs_running | 当前运行的任务数
    procs_blocked | 阻塞的任务数

cpu重要指标的计算

  • cpu的平均利用率

1- (当前时间对应的cpu.idle值 )/ (当前时间对应的cpu.total值),cpu.total就是cpu那一行所有项的加和

  • 系统平均负载(cpu.load)

系统平均负载被定义为在特定时间间隔内运行队列中(在CPU上运行或者等待运行多少进程)的平均进程数

在Linux中,进程分为三种状态,一种是阻塞的进程blocked process,一种是可运行的进程runnable process,另外就是正在运行的进程running process

比如现在系统有2个正在运行的进程,3个可运行进程,那么系统的load就是5

cpu.load是基于/proc/loadavg进行统计

1
0.27 0.36 0.37 4/83 4828/

前三个指1、5、15分钟内的平均进程数(可以简单理解为每五秒统计一次,其实真实计算比较复杂。https://blog.csdn.net/jlds123/article/details/7617132)。后面两个指(正在运行的进程数/进程总数)和最近运行的进程ID号。

如要求接口响应时间尽可能快的,最好确保cpu.load/cores不超过1,而对时间敏感性要求不太高时,一般要求cpu.load/cores不超过3

参考

https://awesome-prometheus-alerts.grep.to/rules

https://www.cnblogs.com/aspirant/p/9766992.html