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):就是一个数字。比如
1、1024。 - 字符串 (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
做多指标联合查询时,匹配模式就派上用场了。我习惯用 on 和 ignoring 来控制匹配维度。
| 模式 | 说明 | 示例 |
|---|---|---|
| One-to-One | 两边标签完全一致才匹配 | rate(...) + on(instance) rate(...) |
| Many-to-One | 一边多标签,一边少标签 | rate(...) / on(instance) group_left rate(...) |
避坑指南:我曾经在写多指标除法时,忘了加 group_left,结果PromQL直接报错“found duplicate series”。后来我养成了习惯——只要两边标签数量不一致,先想想要不要用 group_left 或 group_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的基础就讲到这里。下一章我们聊聊告警规则怎么写,那才是真正让监控“活”起来的关键。