第四章:PromQL 查询语言

深入讲解 Prometheus Query Language (PromQL),包括选择器、聚合运算符、时间序列函数等核心语法

最后更新: 2024-01-01
页面目录

第四章:PromQL 查询语言

4.1 PromQL 概述

PromQL (Prometheus Query Language) 是 Prometheus 的强大查询语言,用于选择和聚合时间序列数据。

4.1.1 基本概念

# 时间序列格式
<metric name>{<label name>=<label value>, ...}

示例:

# 查询所有 HTTP 请求
http_requests_total

# 带标签过滤
http_requests_total{method="GET", status="200"}

# 带范围选择
http_requests_total[5m]

4.2 选择器

4.2.1 即时选择器

返回当前时刻的时间序列:

# 匹配指标名
prometheus_tsdb_head_samples

# 匹配标签
prometheus_tsdb_head_samples{job="prometheus"}

# 多个标签
prometheus_tsdb_head_samples{job="prometheus", zone="us-east"}

# 正则匹配标签
prometheus_tsdb_head_samples{job=~"prometheus.*"}

# 排除标签
prometheus_tsdb_head_samples{job!="node"}

4.2.2 范围选择器

返回一段时间内的数据点:

# 最近 5 分钟
http_requests_total[5m]

# 最近 1 小时
http_requests_total[1h]

# 最近 2 小时 30 分钟
http_requests_total[2h30m]

# 最近 7 天
http_requests_total[7d]

4.2.3 时间偏移

# 5 分钟前的值
http_requests_total offset 5m

# 1 天前的请求量
rate(http_requests_total[5m])[1d:1h]

# 组合使用
http_requests_total{job="api"}[5m] offset 1h

4.3 运算符

4.3.1 算术运算符

运算符 说明 示例
+ 加法 a + b
- 减法 a - b
* 乘法 a * b
/ 除法 a / b
% 取模 a % b
^ 幂运算 a ^ 2
# 计算 CPU 使用百分比
100 * (1 - avg by(instance)(rate(node_cpu_seconds_total{mode="idle"}[5m])))

# 内存使用量 (字节转 GB)
node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes

4.3.2 比较运算符

运算符 说明
== 等于
!= 不等于
> 大于
< 小于
>= 大于等于
<= 小于等于
# 过滤 CPU 使用率 > 80%
rate(node_cpu_seconds_total[5m]) > 0.8

# 过滤内存使用 > 90%
(node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) / node_memory_MemTotal_bytes > 0.9

4.3.3 逻辑运算符

运算符 说明
and 交集
or 并集
unless 补集
# 找出同时有 CPU 和内存告警的实例
CPU告警_instance and 内存告警_instance

# 找出有 HTTP 请求但没有错误的服务
http_requests_total and not http_requests_total{status=~"5.."}

4.4 聚合运算符

4.4.1 聚合函数

函数 说明
sum() 求和
avg() 平均值
min() 最小值
max() 最大值
stddev() 标准差
stdvar() 方差
count() 计数
count_values() 值计数
bottomk() 最小 k 个
topk() 最大 k 个
percentile() 百分位数
# 按 Job 聚合求和
sum by(job)(http_requests_total)

# 按 Job 和 Status 聚合
sum by(job, status)(http_requests_total)

# 计算平均 CPU 使用率
avg by(instance)(rate(node_cpu_seconds_total[5m]))

# 找出请求量最低的 5 个服务
bottomk(5, sum by(service)(rate(http_requests_total[5m])))

4.4.2 without 和 by

# without: 从结果中移除指定标签
sum without(zone)(http_requests_total)
# 等价于
sum by(job, status)(http_requests_total)

4.4.3 聚合修饰符

# 保留原始标签
sum without(instance)(rate(http_requests_total[5m])) keep_common

# 分位数聚合
quantile by(le)(0.95, http_request_duration_seconds_bucket)

4.5 内置函数

4.5.1 Rate 和 Increase

# 计算每秒增长率
rate(http_requests_total[5m])

# 计算增长量
increase(http_requests_total[5m])

# irate: 瞬时增长率 (适合快速变化指标)
irate(http_requests_total[5m])

4.5.2 聚合函数

# 滚动窗口平均值
avg_over_time(http_requests_total[5m])

# 滚动窗口最大值
max_over_time(node_memory_MemAvailable_bytes[5m])

# 滚动窗口最小值
min_over_time(node_memory_MemAvailable_bytes[5m])

# 滚动窗口求和
sum_over_time(http_requests_total[5m])

4.5.3 预测函数

# 线性预测 (用于容量规划)
predict_linear(node_filesystem_free_bytes[2h], 3600 * 6)

# 预测磁盘空间多久用完
predict_linear(node_filesystem_free_bytes{mountpoint="/"}[1h], 3600 * 24 * 7) < 0

4.5.4 计数和排序

# 统计不同值数量
count_values("version", build_version)

# 时间序列数量
count by(job)({__name__=~".+"})

# 排序
topk(10, sum by(job)(rate(http_requests_total[5m])))
bottomk(5, sum by(job)(rate(http_requests_total[5m])))

4.5.5 时间函数

# 当前时间戳
timestamp(http_requests_total)

# 时间差
delta(cpu_temp[5m])

# 变化率
deriv(http_requests_total[5m])

4.5.6 标签操作

# 删除标签
label_delete(http_requests_total, "version")

# 修改标签
label_replace(http_requests_total, "env", "$1", "job", "(.*)")

# 添加标签
label_join(http_requests_total, "server", "-", "job", "instance")

4.5.7 其他常用函数

函数 说明
abs() 绝对值
absent() 检查是否为空
ceil() 向上取整
floor() 向下取整
round() 四舍五入
sqrt() 平方根
ln() 自然对数
log2() 以 2 为底对数
sort() 升序排序
sort_desc() 降序排序
clamp_max() 限制最大值
clamp_min() 限制最小值
histogram_quantile() 计算直方图分位数
holt_winters() 趋势预测

4.6 常用查询示例

4.6.1 服务监控

# QPS (每秒请求数)
rate(http_requests_total[5m])

# 错误率
sum(rate(http_requests_total{status=~"5.."}[5m])) 
  / 
sum(rate(http_requests_total[5m]))

# P99 延迟
histogram_quantile(0.99, 
  sum by(le, handler)(
    rate(http_request_duration_seconds_bucket[5m])
  )
)

# 活跃连接数
sum by(state)(
  net_conntrack_dialer_connections_total
    or
  net_conntrack_listener_connections_total
)

4.6.2 基础设施监控

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

# 内存使用率
100 * (1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)

# 磁盘使用率
100 * (node_filesystem_size_bytes - node_filesystem_free_bytes) 
  / node_filesystem_size_bytes

# 网络 I/O
rate(node_network_receive_bytes_total[5m])
rate(node_network_transmit_bytes_total[5m])

4.6.3 Kubernetes 监控

# Pod CPU 使用率
sum by(pod)(
  rate(container_cpu_usage_seconds_total[5m])
) / sum by(pod)(
  kube_pod_container_resource_limits_cpu_cores
)

# Pod 内存使用率
sum by(pod)(
  container_memory_working_set_bytes
) / sum by(pod)(
  kube_pod_container_resource_limits_memory_bytes
)

# Deployment 副本数
kube_deployment_spec_replicas

# Ready Pods 数量
kube_pod_status_ready{namespace=~".+"}

4.6.4 告警规则查询

# 连续 5 分钟 CPU > 80%
avg by(instance)(
  rate(node_cpu_seconds_total{mode="idle"}[5m])
) < 0.2

# 连续 3 分钟磁盘空间 < 10GB
node_filesystem_free_bytes{mountpoint="/"} < 10 * 1024 * 1024 * 1024

# 错误率 > 5%
(
  sum(rate(http_requests_total{status=~"5.."}[5m])) 
    / 
  sum(rate(http_requests_total[5m]))
) > 0.05

4.7 子查询

# 查询最近 1 小时内每 5 分钟的 QPS
rate(http_requests_total[5m])[1h:5m]

# 计算子查询结果的标准差
stddev_over_time(
  rate(http_requests_total[5m])[1h:5m]
)

4.8 HTTP API

4.8.1 查询 API

# 即时查询
curl 'http://localhost:9090/api/v1/query?query=up'

# 范围查询
curl 'http://localhost:9090/api/v1/query_range?query=up&start=2024-01-01T00:00:00Z&end=2024-01-01T01:00:00Z&step=60s'

4.8.2 响应格式

{
  "status": "success",
  "data": {
    "resultType": "vector",
    "result": [
      {
        "metric": {
          "__name__": "up",
          "instance": "localhost:9090",
          "job": "prometheus"
        },
        "value": [1704067200, "1"]
      }
    ]
  }
}

4.9 本章小结

本章介绍了 PromQL 查询语言的核心内容:

  1. 选择器 - 即时选择器和范围选择器
  2. 运算符 - 算术、比较、逻辑运算符
  3. 聚合运算符 - sum、avg、max、min 等
  4. 内置函数 - rate、increase、预测函数等
  5. 常用查询 - 服务监控、基础设施监控、K8s 监控示例
  6. HTTP API - 通过 API 进行查询

📖 下一步