3. PromQL 入门:基本语法、数据类型与选择器基础

PromQL(Prometheus Query Language)是 Prometheus 生态中用于实时数据查询与分析的核心语言。在容量水位阈值设定与复核场景中,PromQL 是连接原始指标与可执行告警规则的桥梁。本章将系统讲解 PromQL 的基本语法结构、四种核心数据类型以及选择器的使用方式,为后续编写精确的容量阈值表达式打下坚实基础。

3.1 PromQL 基本语法结构

PromQL 表达式由指标名称、标签选择器、时间范围、运算符和函数组合而成。一个完整的 PromQL 查询通常遵循以下结构:

<metric_name>{<label_selector>}[<time_duration>] @ <timestamp>

各组成部分说明:

组成部分 说明 示例
指标名称 标识被监控的指标项,如 CPU 使用率、内存用量 node_cpu_seconds_total
标签选择器 用花括号包裹,用于过滤特定维度的数据 {mode="idle", instance="web-01"}
时间范围 方括号内指定回溯的时间窗口,仅用于 Range Vector [5m]
时间偏移 使用 @ 符号指定查询的基准时间点 @ 1710000000
提示:在容量水位阈值场景中,指标名称通常对应资源使用率(如 container_cpu_usage_seconds_total),标签选择器用于区分不同服务、实例或容器组。

3.2 四种核心数据类型

PromQL 定义了四种数据类型,理解它们的区别是正确编写查询的前提。在阈值复核中,最常使用的是 Instant Vector 和 Range Vector。

数据类型 定义 典型用途 示例
Instant Vector 一组时间序列,每个序列包含一个最新采样值 实时告警判断、当前水位快照 node_memory_MemAvailable_bytes
Range Vector 一组时间序列,每个序列包含一段时间窗口内的多个采样值 趋势分析、速率计算、分位数统计 node_memory_MemAvailable_bytes[5m]
Scalar 单一的数值常量,没有时间维度 阈值比较、数学运算中的固定值 1024、0.8
String 字符串常量,使用较少 标签值匹配、注释 "production"
关键区别:Instant Vector 返回的是“当前时刻的一个值”,而 Range Vector 返回的是“过去一段时间内的一组值”。在计算 CPU 使用率时,必须使用 Range Vector 获取时间窗口内的增量数据,再通过 rate() 函数转换为瞬时速率。

3.3 选择器基础

选择器用于从 Prometheus 时间序列数据库中精确筛选目标数据。根据匹配方式的不同,选择器分为以下四种:

  • 精确匹配(=):标签值必须完全等于指定值。
    node_cpu_seconds_total{mode="idle"}
  • 不等匹配(!=):标签值不等于指定值。
    node_cpu_seconds_total{mode!="iowait"}
  • 正则匹配(=~):标签值匹配正则表达式。
    node_cpu_seconds_total{mode=~"user|system"}
  • 正则排除(!~):标签值不匹配正则表达式。
    node_cpu_seconds_total{mode!~"idle|steal"}
注意:正则表达式使用 RE2 语法,不支持回溯引用和环视。在容量场景中,常用正则匹配批量选择一组实例,例如 {instance=~"web-.*"} 匹配所有 web 前缀的实例。

3.4 选择器与数据类型的组合关系

选择器可以与 Instant Vector 和 Range Vector 组合使用,形成不同的查询模式。以下 SVG 图展示了选择器如何从指标存储中筛选数据,并生成不同的向量类型。

选择器与数据类型组合关系 Prometheus 指标存储 node_cpu_seconds_total {mode="idle", instance="a"} {mode="user", instance="a"} {mode="idle", instance="b"} {mode="system", instance="b"} ... 选择器过滤 选择器类型 精确匹配 {mode="idle"} 不等匹配 {mode!="iowait"} 正则匹配 {mode=~"user|system"} 正则排除 {mode!~"idle|steal"} 输出:匹配的时间序列 Instant Vector 每个序列返回最新值 node_cpu_seconds_total{mode="idle"} → 当前空闲 CPU 时间 Range Vector 每个序列返回窗口内多个值 node_cpu_seconds_total{mode="idle"}[5m] → 过去 5 分钟空闲 CPU 序列

3.5 选择器在容量阈值场景中的应用

在容量水位阈值设定中,选择器的精确使用直接影响告警的准确性和覆盖范围。以下表格对比了不同选择器在典型场景中的应用:

场景 选择器示例 说明
单实例 CPU 水位 node_cpu_seconds_total{instance="web-01", mode="user"} 精确匹配特定实例和 CPU 模式
排除空闲 CPU node_cpu_seconds_total{mode!="idle"} 只关注非空闲 CPU 时间,用于计算使用率
批量选择 Web 实例 node_cpu_seconds_total{instance=~"web-.*"} 正则匹配所有 web 前缀实例,适合集群水位聚合
排除特定环境 node_memory_MemAvailable_bytes{env!~"staging|dev"} 只关注生产环境的内存可用量

3.6 常见错误与避坑指南

  • 混淆 Instant Vector 与 Range Vector:在 rate()、increase() 等函数中必须使用 Range Vector,传入 Instant Vector 会导致语法错误。
  • 正则表达式性能问题:避免使用过于复杂的正则表达式,如 .* 开头或嵌套分组,会导致查询性能下降。
  • 空结果处理:当选择器没有匹配到任何时间序列时,查询返回空结果。在阈值告警中,空结果可能导致告警规则失效,建议使用 absent() 函数兜底。
  • 标签值大小写敏感:Prometheus 标签值区分大小写,{mode="Idle"} 与 {mode="idle"} 是不同的选择器。
实战建议:在编写容量阈值 PromQL 时,先在 Prometheus 的 Graph 页面中验证选择器返回的数据是否符合预期。使用 count() 函数可以快速检查匹配的时间序列数量,例如 count(node_cpu_seconds_total{mode="idle"}) 返回匹配的序列总数。

3.7 本章小结