用示例学习!利用PromQL灵活绘制图表(Prometheus + Grafana)

背景 –
背景说明

尽管使用Prometheus和Grafana开始进行资源监控是个好主意,但Grafana Labs上的仪表板总感觉不太合适。而且,每个仪表板的查询语句都略有不同,不知道哪个是正确的!
只有一个选项:
使用Prometheus和Grafana开始资源监控后,发现Grafana Labs提供的仪表板不太符合我的需求。而且,每个仪表板的查询语句都不太相同,让我不知道哪个才是正确的!

只要自己好好写查询语句尝试一下!鉴于这一点,我将写一下。如果掌握了这里介绍的三种查询语句,基本上可以应用到各种场景中。

请阅读以上内容。

虽然是基本的事情,但在Grafana绘制图表时所输入的查询语句是Prometheus的PromQL。(起初以为是Grafana的查询语法…)

    Querying basics | Prometheus

node-exporter的指标,如果使用curl打开,会附带帮助信息。还有一个演示网站,你也可以在那里尝试。

    demo.robustperception.io:9100/metrics

Grafana模板化

使用Grafana的模板功能,将变量嵌入到查询中。在定义以下变量的前提下进行描述。

変数名説明サンプル値nodeクエリの対象とするノード。Prometheusが自動的に付けるinstanceラベルに対して使用することを想定localhost:8080intervalクエリで表示する値の単位時間5m

CPU利用率

スクリーンショット 2017-11-09 16.39.44.png

查询

avg(irate(node_cpu{instance="$node",mode!="idle"}[$interval])) without(cpu)

摘要

显示指定实例($node)在单位时间($interval)内每秒的CPU使用率平均值。另外,对于空闲状态,不显示因为它表示空闲。

普罗米修斯的原始数据片段

# HELP node_cpu Seconds the cpus spent in each mode.
# TYPE node_cpu counter
node_cpu{cpu="cpu0",instance="docker104:9100",job="node",mode="iowait"} 1.57
node_cpu{cpu="cpu0",instance="docker104:9100",job="node",mode="system"} 42.51
node_cpu{cpu="cpu0",instance="docker104:9100",job="node",mode="user"}   74.37
node_cpu{cpu="cpu1",instance="docker104:9100",job="node",mode="iowait"} 5.13
node_cpu{cpu="cpu1",instance="docker104:9100",job="node",mode="system"} 34.1
node_cpu{cpu="cpu1",instance="docker104:9100",job="node",mode="user"}   72.7

每个实例的每个CPU上的CPU使用时间(以秒为单位)以mode为单位存储在node_cpu度量中。

查询解释

    1. 需要的数据是指定实例的mode不为idle的CPU使用时间的最近$interval分钟的数据。

node_cpu{instance=”$node”, mode!=”idle”}[$interval]

此时,将返回mode数量乘以CPU核心数的记录,并将数据作为数组存储为$interval分钟的数据。

将返回的数据转换为每秒的平均增长值。

irate()

此时,将返回mode数量乘以CPU核心数的记录,并将value转换为每秒的平均增长值。

计算所有CPU的平均值。

avg() without(cpu)

无需计算的标签在without子句中指定。这次的标签是cpu、instance、job和mode,我们将忽略cpu,并计算每个模式的平均值。最终将得到所有cpu的平均值。

平均值

avg算子返回每个记录存储的标量值的平均值。如果记录的value是一个数组(范围向量),则不能应用该算子。

rate()和irate()

rate()和irate()函数都用于计算在一定时间范围内获取的数据每秒平均增加了多少。

只需一种选项,以下是中文本地化的释义:

鉴于增量,只有保留某种合计值的指标,诸如node_cpu或http_requests_total等,适用于此函数。

rate(v range-vector)计算范围向量中时间序列的每秒平均增长率。
irate(v range-vector)计算范围向量中时间序列的每秒瞬时增长率。

查询功能 | Prometheus

没有和通过

如上所述,without子句会忽略指定的标签并应用聚合函数。实际执行without(cpu)的情况下,原始数据将变为以下状态,即缺少cpu标签。

{instance="docker104:9100",job="node",mode="user"}  0.0005000000000002558

反过来,通过“by”语句,即忽略其他标签,仅针对指定的标签应用聚合函数。执行“by(mode)”会使除mode之外的所有标签都消失。

{mode="user"}   0.0005000000000002558

这次有4个标签,实例和作业标签是固定的。换句话说,只通过查看返回的记录中的值,无CPU和按模式分类的结果将是相同的。

CPU核心数量

スクリーンショット 2017-11-09 16.38.52.png

以下的查询都会返回相同的值。

count(count (node_cpu{instance="$node"}) by(cpu))
count(node_cpu{instance="$node", mode="system"})

简要梗概

没有直接返回CPU核心数的指标。node_cpu指标按照每个CPU的使用率返回,可以利用它来计算。

查询解释

count(count (node_cpu{instance="$node"}) by(cpu))
    1. 获取指定实例的最近的node_cpu指标。

 

    1. node_cpu{instance=”$node”}。

 

    1. 在这个时间点上,将返回模式数 x CPU核心数的记录,并将最近的数据存储为标量值。

 

    1. 按CPU计算指标的数量。

 

    1. count() by(cpu)。

 

    1. 在这一点上,将按每个CPU返回system,user等CPU使用率数据的数量。由于这个数量不是目标值,所以将其忽略。

 

    1. 计算CPU的数量。

 

    count()。
count(node_cpu{instance="$node", mode="system"})
    1. 获取指定实例的mode=”system”的指标

 

    1. node_cpu{instance=”$node”, mode=”system”}

 

    1. 此时,会返回每个CPU核心的system使用率

 

    1. 数CPU的数量

 

    count()

可用内存

スクリーンショット 2017-11-09 16.39.59.png
( avg_over_time(node_memory_MemFree{instance=~"$node"}[$interval])
  + avg_over_time(node_memory_Buffers{instance=~"$node"}[$interval])
  + avg_over_time(node_memory_Cached{instance=~"$node"}[$interval])
) / node_memory_MemTotal{instance=~"$node"} * 100

概述

如果您所使用的Linux内核版本在3.14及以上,您可以使用node_memory_MemAvailable指标来检查可用内存量。但需要考虑到可能存在一些不符合该条件的主机。

解释查询

由于重复的原因,只解释以下部分。

avg_over_time(node_memory_MemFree{instance=~"$node"}[$interval])
    1. 获取指定实例在最近的$interval分钟内的node_memory_MemFree指标

node_memory_MemFree{instance=~”$node”}[$interval]
在此时刻,将返回一个记录,其中value数组中包含了$interval分钟的所有数据

获取获取到的value的平均值

avg_over_time()

平均值的时间内 ()

如果您想要获取在某个时间范围内获取的数据中,每个数据的平均值,可以使用avg_over_time()函数。上述的rate()函数系列可能会出现很多示例,可能会让人难以理解,但这个函数可以简单地计算出时间范围的平均值。

概括起来

在Prometheus的指标中,存在不同的数据类型,即使我们说“平均”,计算的方法也有很多种。另外,指标既可以表示当前值,也可以表示总计值,因此只要理解这些方面,就可以轻松地编写代码了。

bannerAds