PromQL 新手完全手册
PromQL 是 Prometheus 的查询语言。本文从数据类型与选择器讲起,覆盖算术/比较/逻辑运算、rate/increase/histogram_quantile 等核心函数与聚合,附可直接运行的示例。
PromQL 是 Prometheus 的查询语言——看懂仪表盘背后的查询、写出自己的告警规则,都绕不开它。这篇手册从最小概念开始,搭一条从"能读懂"到"能写"的最短路径。
先备好实验环境
本地用 Docker Compose 起一个 Prometheus + Node Exporter 沙箱即可:
# docker-compose.yml
services:
prometheus:
image: prom/prometheus:latest
ports: ["9090:9090"]
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
node-exporter:
image: prom/node-exporter:latest
ports: ["9100:9100"]
# prometheus.yml
scrape_configs:
- job_name: node
static_configs:
- targets: ['node-exporter:9100']
docker compose up -d 后访问 http://localhost:9090,在 Table/Graph 页签里就可以逐条试本文的查询。
四种数据类型
PromQL 表达式的结果总是这四类之一:
| 类型 | 例子 | 说明 |
|---|---|---|
| 瞬时向量(Instant Vector) | up |
一组时间序列,每个序列当前时刻一个值 |
| 区间向量(Range Vector) | up[5m] |
一段时间窗口内的多个值,不能直接画图 |
| 标量(Scalar) | 42 |
单个数字 |
| 字符串 | "abc" |
极少用 |
选择器语法:metric_name{label="value", other=~"正则"}。匹配符:= 等于、!= 不等于、=~ 正则匹配、!~ 正则不匹配。
node_cpu_seconds_total{mode="idle"} # 精确匹配
http_requests_total{status=~"5.."} # 正则:5xx
http_requests_total{job!="test"} # 排除
运算符
算术运算(+ - * / % ^)
- 标量与向量:逐序列运算。
node_memory_MemAvailable_bytes / 1024^3把字节换成 GiB; - 向量与向量:按标签匹配后两两运算(需要
on/ignoring控制匹配维度):
# 内存使用率 = 1 - 可用/总量
1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)
比较运算(> < == != ...)
做过滤用——只保留满足条件的序列:
# 只看使用率超过 80% 的文件系统
node_filesystem_avail_bytes / node_filesystem_size_bytes < 0.2
逻辑运算(and / or / unless)
# 使用率高 and 增长快
(rate(node_cpu_seconds_total{mode="idle"}[5m]) < 0.2) and (predict_linear(...))
核心函数(必会清单)
rate(http_requests_total[5m]) # Counter 每秒增量,最常用
increase(http_requests_total[1h]) # 窗口内总增量
irate(node_cpu_seconds_total[1m]) # 瞬时速率(抓尖刺)
avg_over_time(up[1h]) # 窗口平均
histogram_quantile(0.99, sum by (le) (rate(http_request_duration_seconds_bucket[5m]))) # 分位数
predict_linear(node_filesystem_avail_bytes[6h], 4*3600) # 线性预测:4小时后磁盘剩多少
聚合操作
sum(rate(http_requests_total[5m])) # 全部加总
sum by (service) (rate(http_requests_total[5m])) # 按服务分组加总
topk(5, node_load1) # 负载最高的 5 台
count(up == 0) # 有多少目标挂了
quantile by (job) (0.9, latency_seconds) # 分组分位数
by 是保留列出的标签;without 相反——扔掉列出的标签再聚合。
三条实战规则
- Counter 必套 rate/increase,原始值没有分析意义;
- 窗口别太短:
rate(x[1m])在 15s 抓取间隔下只有 4 个点,噪声大;常用[5m]起步; - 先写查询、看图、再设告警——在 Graph 页观察几天曲线的正常波动,阈值才不会拍脑袋。
观测云对照
观测云既支持 PromQL 查询接入的 Prometheus 指标,也提供更友好的可视化查询构造器——不熟悉 PromQL 的同事也能通过点选完成聚合与过滤;指标可直接用于监控器告警与仪表盘,查询与告警规则一处定义处处复用。
常见问题(FAQ)
Q:为什么我的 rate() 图上有毛刺断点?
A:多半是抓取间隔与窗口不匹配(窗口内点数太少)或目标重启。把窗口调到抓取间隔的 4 倍以上。
Q:sum by (a, b) 和 sum without (c, d) 怎么选?
A:要保留的标签少就用 by,要扔掉的少就用 without。警惕 without 扔掉标签后意外合并了不该合并的序列。
Q:PromQL 能查历史某天某个时刻的值吗?
A:可以。表达式浏览器里选时间(Table 视图的 Evaluation time),或用 @ 修饰符:http_requests_total @ 1700000000。