2. PromQL 基础回顾:数据类型、选择器与聚合操作

在进入水位录制规则设计之前,必须牢固掌握 PromQL 的四种数据类型、标签选择机制以及基础聚合操作。这些是构建任何录制规则表达式的底层语言基础。

2.1 PromQL 四种数据类型

PromQL 表达式求值后返回以下四种类型之一。理解它们的区别是正确使用函数与操作符的前提。

类型 英文名称 说明 典型示例
瞬时向量 Instant Vector 一组时间序列,每个序列包含一个最新采样值,时间戳相同 node_cpu_seconds_total
区间向量 Range Vector 一组时间序列,每个序列包含一段时间窗口内的多个采样值 node_cpu_seconds_total[5m]
标量 Scalar 一个单纯的数字浮点值,没有维度(标签) 1024、3.14
字符串 String 一个简单的字符串值,在 PromQL 中主要用于标签操作,不常用作查询结果 "prod"
水位规则关键点:录制规则(Recording Rule)的右侧表达式必须返回 瞬时向量。区间向量不能直接用于规则赋值,必须先通过聚合函数(如 avg_over_time)降维成瞬时向量。

2.2 选择器与标签匹配

选择器用于从时间序列数据库中筛选出目标序列。标签匹配是 PromQL 最灵活的过滤手段,分为三种匹配操作符。

2.2.1 匹配操作符对比

操作符 含义 示例 匹配行为
= 完全相等 job="api-server" 标签值必须精确匹配
!= 不相等 job!="api-server" 排除指定标签值的所有序列
=~ 正则匹配 instance=~"10\\.0\\.1\\..*" 标签值匹配正则表达式
!~ 正则排除 instance!~"10\\.0\\.1\\..*" 标签值不匹配正则表达式

2.2.2 选择器语法结构

# 瞬时向量选择器:直接指定指标名 + 标签过滤
node_memory_MemAvailable_bytes{env="prod", instance=~"web-.*"}

# 区间向量选择器:在瞬时向量基础上加 [时间窗口]
node_memory_MemAvailable_bytes{env="prod"}[5m]

# 空标签选择器:匹配所有包含该标签的序列(无论值是什么)
node_memory_MemAvailable_bytes{env=""}

# 标签存在性匹配:使用正则 .* 匹配任意值
node_memory_MemAvailable_bytes{env=~".*"}
性能建议:录制规则中尽量使用 = 精确匹配代替 =~ 正则匹配。正则匹配在标签基数高时会导致查询引擎扫描大量序列,增加规则评估延迟。

2.3 基础聚合操作

聚合操作将多个时间序列合并为更少的序列,是水位规则中“降维”和“归一化”的核心手段。

2.3.1 常用聚合函数

函数 作用 水位场景示例
sum 求和 聚合所有实例的 CPU 使用总量
avg 平均值 计算集群平均内存使用率
max 最大值 找出实例组中的最高水位
min 最小值 找出实例组中的最低水位
count 计数 统计满足条件的实例数量
quantile 分位数 计算 P99 延迟水位
stddev 标准差 评估水位波动离散程度

2.3.2 聚合语法:by 与 without

聚合时必须指定保留哪些标签维度。两种子句控制维度保留方式:

  • by:显式列出要保留的标签,其余标签被丢弃。
  • without:显式列出要移除的标签,其余标签全部保留。
# 按 job 和 env 分组求和,丢弃 instance 等其余标签
sum by (job, env) (node_memory_MemAvailable_bytes)

# 等价写法:移除 instance 和 device 标签,保留其他所有标签
sum without (instance, device) (node_memory_MemAvailable_bytes)
常见陷阱:忘记使用 by 或 without 时,聚合会返回一个无标签的标量结果。在水位录制规则中,这会导致丢失所有维度信息,无法按实例或集群进行后续告警分派。始终显式指定保留维度。

2.4 数据类型与聚合流程总览

下图展示了从原始指标到录制规则结果的完整数据流,以及各阶段涉及的数据类型转换:

PromQL 数据类型与聚合流程 原始指标 Instant Vector 区间向量 Range Vector 聚合降维 avg_over_time / sum 选择器 + [5m] 聚合函数 录制规则结果 Instant Vector by / without 保留维度 标签匹配层 = / != / =~ / !~ 规则输出携带标签 水位规则核心约束 右侧表达式必须返回 Instant Vector

2.5 实战案例:从原始指标到水位规则

以下是一个完整的水位录制规则表达式拆解,综合运用了选择器、区间向量和聚合操作:

# 规则名称:instance:node_memory_usage:ratio_avg5m
# 表达式含义:每台实例过去5分钟的平均内存使用率

# 步骤1:原始瞬时向量(内存总量)
node_memory_MemTotal_bytes{job="node-exporter"}

# 步骤2:原始瞬时向量(可用内存)
node_memory_MemAvailable_bytes{job="node-exporter"}

# 步骤3:计算瞬时使用率(标量运算,结果仍为瞬时向量)
(1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)

# 步骤4:转换为区间向量,取5分钟平均值
avg_over_time(
  (1 - node_memory_MemAvailable_bytes{job="node-exporter"}
        / node_memory_MemTotal_bytes{job="node-exporter"})[5m]
)

# 步骤5:最终录制规则(已包含 by 保留 instance 标签)
- record: instance:node_memory_usage:ratio_avg5m
  expr: |
    avg by (instance) (
      avg_over_time(
        (1 - node_memory_MemAvailable_bytes{job="node-exporter"}
              / node_memory_MemTotal_bytes{job="node-exporter"})[5m]
      )
    )
水位规则设计要点:
  • 始终使用 avg_over_time 等区间聚合函数将原始数据平滑化,避免瞬时抖动导致水位误判。
  • 聚合时通过 by 明确保留维度(如 instance、job),确保规则结果可被后续告警规则按实例路由。
  • 标签选择器尽量精确,避免正则匹配带来的性能开销。