前言
当 Prometheus 通过 Exporter 采集到相应的监控指标样本数据后,我们就可以通过PromQL 对监控样本数据进行查询,从而对相应的数据样本进行分析以及制定报警规则。
promql的相关知识
PromQL(Prometheus Query Language)是 Prometheus 内置的数据查询语言。支持用户进行实时的数据查询及聚合操作。
Prometheus 基于指标名称(metrics name)以及附属的标签集(labelset)唯一定义一条时间序列
●指标名称代表着监控目标上某类可测量属性的基本特征标识
●标签则是这个基本特征上再次细分的多个可测量维度
基于 PromQL 表达式,用户可以针对指定的特征及其细分的纬度进行过滤、聚合、统计等运算从而产生期望的计算结果
●PromQL 使用表达式(expression)来表述查询需求
●根据其使用的指标和标签,以及时间范围,表达式的查询请求可灵活地覆盖在一个或多个时间序列的一定范围内的样本之上,甚至是只包含单个时间序列的单个样本
2. PromQL数据样本信息的含义理解
Prometheus 中,每个时间序列都由指标名称(Metric Name)和标签(Label)来唯一标识
格式为:
●指标名称:通常用于描述系统上要测定的某个特征
例如,prometheus_http_requests_total 表示接收到的 HTTP 请求总数
●标签:键值型数据,附加在指标名称之上,从而让指标能够支持多纬度特征;可选项
例如,prometheus_http_requests_total{code="200"} 和 prometheus_http_requests_total{code="302"} 代表着两个不同的时间序列
●双下划线的标签(例如 __address__ )是 Prometheus 系统默认标签,是不会显示在 /metrics 页面里面的;
●系统默认标签在 target 页面中也是不显示的,需要鼠标放到 label 字段上才会显示。
常见的系统默认标签:
__address__ | 当前 target 实例的套接字地址 |
__scheme__ | 采集当前 target 上指标数据时使用的协议(http 或 https) |
__metrics_path__ | 采集当前 target 上的指标数据时使用 URI 路径,默认为 /metrics |
__param_ |
传递的 URL 参数中第一个名称为 |
__name__ | 此标签是标识指标名称的预留标签,能够使用标签选择器对指标名称进行过滤 |
指标名称及标签使用注意事项:
●指标名称和标签的特定组合代表着一个时间序列;指标名称相同,但标签不同的组合分别代表着不同的时间序列;不同的指标名称自然更是代表着不同的时间序列
●PromQL支持基于定义的指标维度进行过滤和聚合;更改任何标签值,包括添加或删除标签,都会创建一个新的时间序列;应该尽可能地保持标签的稳定性,否则,则很可能创建新的时间序列,更甚者会生成一个动态的数据环境,并使得监控的数据源难以跟踪,从而导致建立在该指标之上的图形、告警及记录规则变得无效
PromQL 的数据类型
一组时序,每个时序只有一个采样值
一组时序,每个时序包含一段时间内多个采样值
rate(container_cpu_load_average_10s{instance="node01"}[5m])
展示 container_cpu_load_average_10s指标过去每五分钟的采样值。对应的标签是node01
浮点数
一个字符串
总数,在整个promql当中没有直接作用,可以通过指标生成
rate topk increase irate函数来生成样本数据的变化情况。
increase 要结合区间向量
irate:高灵敏度的函数,计算指标的瞬时速率,基于样本范围内的最后两个样本数据进行计算。irate更适合短时间内的速率变化分析。
主要用来存储 可增,可减的指标样本数据。用于求和,求平均数,取在最小值和最大值,也会结合delta 和 predict_linear
delta:计算范围向量中的每个时间序列元素的第一个值和最后一个值之间的差,展示不同时间点上样本值的差值。
predict_linear:用线性回归的模型去预测时间序列x秒之后的变化趋势,,对样本数据进行预测。
predict_linear(node_filesystem_files{instance="master01"[2h],4,3600})
举个例子,前两个小时,第一个小时吃了8个,第二个小时吃了4个,两个小时吃了12个,平均一小时吃6个,所以预测接下来的四个小时每个小时吃6个,所以最终结果就是预测下面6个小时一共吃24个
对一定时间范围内的数据进行采样,通常是请求持续时长和响应大小的类型这一类数据,计入一个可配置的桶中(bucket),通过这个区间对样本进行筛选,也可以统计求和。
node_authorizer_graph_actions_duration_seconds_bucket{instance="20.0.0.61:6443",le="0.0002"}
观察桶的上边界,样本的统计区间,表示所有的样本值小于等于边界值的所有样本数量
le="Inf":最大区间,包含所有样本数量
apiserver_current_inqueue_requests{instance="20.0.0.61:6443"}>=1
快速的了解监控样本的分布情况。
类似于historgram,在客户端于一点时间内(默认10分钟)的每个采样点进行统计,计算并且存储了分位数的值,服务端可以直接
聚合操作符
sum:求和
min:最小值
max:最大值
avg:平均值
stddev:标准差
stdvar:方差
count:元素个数
count values:等于某个值的元素个数
topk;最大元素个数
bottomk:最小的元素个数
quantile:通过分位数给取值做分位排列
中位数可以理解为中间项的指标。作为一个中间值,取值比他小的在它下面,比它大就在它上面
将按照序列进行排列取一个中位数。每个数值都和中位数轮流进行比较。在0-1的区间进行浮动。这样可以展示样本在一段时间之内的分布情况
业务中如何适用语句
1.计算某个节点的所有容器的使用内存的时间序列
sum(container_memory_usage_bytes{instance="node01"}/1024/1024/1024
最近1分钟,所有容器的使用率
sum by (id) (rate (container_cpu_usage_seconds_total{id!="/"}[1m]))
查询k8s集群中最近1分钟,每个pod的cpu使用率
sum by(name) (rate (container_cpu_usage_seconds_total{image!="",name!=""}[1m]))
常用指标
#计算 master01 节点所有容器总计内存:
sum(container_memory_usage_bytes{instance=~"master01"})/1024/1024/1024
#计算 master01 节点最近 1m 所有容器 cpu 使用率:
sum (rate (container_cpu_usage_seconds_total{instance=~"master01"}[1m])) / sum (machine_cpu_cores{ instance =~"master01"}) * 100
#计算最近 1m 所有容器 cpu 使用率
sum by (id)(rate (container_cpu_usage_seconds_total{id!="/"}[1m]))
#查询 K8S 集群中最近 1m 每个 Pod 的 CPU 使用率
sum by (name)(rate (container_cpu_usage_seconds_total{image!="", name!=""}[1m]))
(1)每台主机 CPU 在最近 5 分钟内的平均使用率
(1 - avg(rate(node_cpu_seconds_total{mode="idle"}[5m])) by (instance)) * 100
(2)查询 1 分钟的 load average 的时间序列是否超过主机 CPU 数量 2 倍
node_load1 > on (instance) 2 * count (node_cpu_seconds_total{mode="idle"}) by (instance)
(3)计算主机内存使用率
可用内存空间:空闲内存、buffer、cache 指标之和
node_memory_MemFree_bytes + node_memory_Buffers_bytes + node_memory_Cached_bytes
已用内存空间:总内存空间减去可用空间
node_memory_MemTotal_bytes - (node_memory_MemFree_bytes + node_memory_Buffers_bytes + node_memory_Cached_bytes)
使用率:已用空间除以总空间
(node_memory_MemTotal_bytes - (node_memory_MemFree_bytes + node_memory_Buffers_bytes + node_memory_Cached_bytes)) / node_memory_MemTotal_bytes * 100
(4)计算所有 node 节点所有容器总计内存:
sum by (instance) (container_memory_usage_bytes{instance=~"node*"})/1024/1024/1024
(5)计算 node01 节点最近 1m 所有容器 cpu 使用率:
sum (rate(container_cpu_usage_seconds_total{instance="node01"}[1m])) / sum (machine_cpu_cores{instance="node01"}) * 100
#container_cpu_usage_seconds_total 代表容器占用CPU的时间总和
(6)计算最近 5m 每个容器 cpu 使用情况变化率
sum (rate(container_cpu_usage_seconds_total[5m])) by (container_name)
(7)查询 K8S 集群中最近 1m 每个 Pod 的 CPU 使用情况变化率
sum (rate(container_cpu_usage_seconds_total{image!="", pod_name!=""}[1m])) by (pod_name)
#由于查询到的数据都是容器相关的,所以最好按照 Pod 分组聚合