4. PromQL查询语言:从基础到实战

PromQL,说白了就是Prometheus的“SQL”。你想想看,监控数据采集回来了,怎么查?怎么聚合?怎么报警?全靠这门查询语言。我个人觉得,掌握PromQL是玩转Prometheus的核心门槛。今天我就带你把这套东西捋清楚。

4.1 PromQL基础语法:先搞懂数据类型

PromQL里有四种核心数据类型,我刚开始学的时候也绕了一阵子。咱们一个个说:

  • 瞬时向量 (Instant Vector):某个时间点的一组时间序列。比如 node_cpu_seconds_total 查的就是当前这一瞬间的CPU数据。
  • 区间向量 (Range Vector):一段时间内的数据。比如 node_cpu_seconds_total[5m] 就是过去5分钟的数据。
  • 标量 (Scalar):就是一个数字。比如 11024
  • 字符串 (String):这个用得少,暂时忽略也行。

重点记住:瞬时向量是最常用的。你写报警规则、做图表,大部分时候都在跟它打交道。

举个例子,我在项目中排查过一个问题:有个同事写了个查询,返回结果总是空的。我一看,他用了区间向量去接报警规则,但报警规则只认瞬时向量。嗯,这里要注意——不同场景下数据类型不能混用

4.2 选择器与匹配模式:怎么精准捞数据

光知道数据类型还不够,你得学会怎么“挑”数据。PromQL的选择器有三种:

4.2.1 精确匹配

=!=。比如:

node_cpu_seconds_total{instance="192.168.1.1:9100", mode="idle"}

这就是精确匹配,只拿指定实例的空闲CPU数据。

4.2.2 正则匹配

=~!~。比如我想查所有web服务器的CPU:

node_cpu_seconds_total{instance=~"web.*:9100"}

这个在集群规模大的时候特别好用。我曾经接手过一个项目,有200多台机器,标签命名乱七八糟。我靠正则匹配一把捞出来,省了多少事。

4.2.3 匹配模式:One-to-One vs Many-to-One

做多指标联合查询时,匹配模式就派上用场了。我习惯用 onignoring 来控制匹配维度。

模式说明示例
One-to-One两边标签完全一致才匹配rate(...) + on(instance) rate(...)
Many-to-One一边多标签,一边少标签rate(...) / on(instance) group_left rate(...)

避坑指南:我曾经在写多指标除法时,忘了加 group_left,结果PromQL直接报错“found duplicate series”。后来我养成了习惯——只要两边标签数量不一致,先想想要不要用 group_leftgroup_right

4.3 聚合操作与函数:让数据说话

数据捞出来了,怎么汇总?怎么计算?这就轮到聚合操作和函数登场了。

4.3.1 常用聚合操作

  • sum:求和。比如所有CPU核心的使用率加起来。
  • avg:平均值。比如集群平均内存使用率。
  • max / min:最大/最小值。找热点机器时特别有用。
  • count:计数。比如统计有多少台机器CPU超过80%。
  • topk / bottomk:取前K或后K。我经常用 topk(5, ...) 快速定位资源消耗最高的机器。

举个例子:

# 按机房聚合,求每个机房的平均CPU使用率
avg by (datacenter) (rate(node_cpu_seconds_total{mode="idle"}[5m]))

4.3.2 常用函数

PromQL的函数库很丰富,我挑几个最常用的:

函数作用实战场景
rate()计算每秒增长率(适合Counter)QPS、网络流量
irate()计算瞬时增长率(更灵敏)突发流量检测
increase()计算一段时间内的增量过去1小时请求总数
histogram_quantile()计算分位数P99延迟

注意rate()irate() 只能用在Counter类型指标上。如果你用在Gauge上,结果会非常奇怪。我见过有人把内存使用率用 rate() 包了一层,查了半天才发现问题。

4.4 常用PromQL实战案例

光说不练假把式。我直接给你几个我项目里常用的查询,你拿去就能用。

4.4.1 CPU使用率

100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)

这个公式我几乎天天用。先算空闲率,再用100减,就是CPU使用率。

4.4.2 内存使用率

(1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100

注意这里用的是 MemAvailable 而不是 MemFree。因为Linux会把缓存也算作可用内存,用 MemFree 会虚高。

4.4.3 磁盘IO等待

rate(node_disk_io_time_seconds_total[5m]) * 100

这个值超过20%就要警惕了。我遇到过一台数据库服务器,IO等待飙到60%,查了半天发现是日志盘满了在疯狂重试。

4.4.4 网络流量

rate(node_network_receive_bytes_total[5m]) * 8

乘以8是把字节转成比特,方便跟带宽对比。比如千兆网卡,这个值超过100Mbps就要注意了。

4.4.5 服务可用性

up{job="api-server"} == 0

这个查询直接返回所有宕机的实例。我把它写进报警规则里,一旦有实例挂了,立刻通知。

核心总结:PromQL其实不难,关键是理解数据类型、掌握选择器、熟悉常用函数。我建议你从最简单的查询开始,比如 up,然后慢慢加条件、加聚合。多写几次,自然就熟了。

好了,PromQL的基础就讲到这里。下一章我们聊聊告警规则怎么写,那才是真正让监控“活”起来的关键。