先放結論,Prometheus中採集的原始指標無法直接表示CPU使用率,需要通過promQL語言二次計算,計算公式如下:
sum by(instance)(rate(node_cpu_seconds_total{mode!="idle"}[15s])) / sum by(instance)(rate(node_cpu_seconds_total[15s]))
該公式的計算原理與top命令中計算cpu使用率的方法一樣:非idle模式佔用的時間 / 該cpu核心的全部時間。
不同的是,top命令是直接使用單項差值除以總差值,分子分母單位都為ticks。該公式中,是速率除以速率,即每秒單項佔用的秒除以每秒全部佔用的秒,分子分母單位都為秒/秒。
但是想要完全理解公式,還有很多疑點:
- 同樣的數據來源,單位是什麼時候從
ticks轉化成了秒? - 公式中
[15s]是什麼意思? rate(),sum by()又是什麼意思?
1. 單位統一
數據從linux系統中讀取時單位是ticks,由於採集器是以秒為最小精度進行週期性採集,在採集時會給數據打上當下以秒為單位的時間標籤,自從數據單位轉為秒。
所有數據的單位均為秒,因此除以時間步長時,也直接使用秒。單位統一過程如下所示:
/proc/stat(單位:ticks)
↓
node_exporter(轉換 ticks → 秒)
↓
Prometheus 抓取指標(單位:秒)
↓
rate(metric[15s]) → 輸出“秒/秒”
2.時間窗口(range vector)與採樣間隔(scrape interval)
rate() 是promQL中的函數,該函數計算時,不是單純用時間窗口兩頭的值/時間窗口長度,而是用採樣間隔採集到的相鄰數據進行線性迴歸(最小二乘法擬合)。因此rate()函數得到的是該時間窗口內的平均速率。
3.cpu多核心速率聚合
sum by()同樣是promQL中的函數,instance是標籤,通常按主機ip區分,不sum by()就會得到該主機上各個cpu核各自的使用率,同一個instance相加,才能得到所有核的cpu使用率,即整個主機的cpu使用率。
sum by()的相加是對各個核的速率的相加,不是百分比!算出所有核在總時間內,非idle模式使用的總時間。