3. PromQL 进阶:聚合操作、子查询、Recording Rules 在容量分析中的应用

在容量压测与巡检场景中,原始指标往往无法直接反映系统瓶颈。PromQL 的聚合操作、子查询与 Recording Rules 是构建容量分析模型的三项核心能力。本章将逐一拆解其语法、适用场景及编排优化策略。

3.1 聚合操作:从多维数据中提取容量特征

聚合操作通过 by 或 without 子句对标签维度进行归并,是容量分析中最常用的数据降维手段。

3.1.1 常用聚合函数与容量语义

聚合函数 容量分析语义 典型场景
sum() 计算资源总量或请求总量 集群 CPU 总使用率、总 QPS
avg() 平均负载水平 平均响应时间、平均磁盘 IO 等待
max() 峰值压力点 单机最高内存使用率、最大延迟
quantile() 分位数分布 P99 延迟、P95 请求大小
topk() 识别异常热点 CPU 使用率最高的前 5 个容器

3.1.2 聚合操作在压测巡检中的典型用法

# 计算集群整体 CPU 使用率(按 instance 聚合后取平均)
avg by (cluster) (rate(node_cpu_seconds_total{mode!="idle"}[5m]))

# 找出内存使用率超过 80% 的前 10 个 Pod
topk(10, container_memory_working_set_bytes / container_spec_memory_limit_bytes > 0.8)

# 按机房维度统计 P99 延迟
quantile by (datacenter) (0.99, http_request_duration_seconds)
容量巡检最佳实践: 在压测脚本中,优先使用 by 保留关键分组标签(如 cluster、service),避免 without 意外丢弃维度导致数据混淆。

3.2 子查询:实现时间窗口内的二次计算

子查询允许在 PromQL 中对一个时间范围内的数据进行“查询中的查询”,常用于计算窗口内的聚合趋势或异常检测。

3.2.1 子查询语法结构

<instant_query> [<range>:<resolution>] [offset <duration>]
  • instant_query:内层即时查询表达式
  • range:外层时间窗口,如 [30m]
  • resolution:内层计算步长,如 :1m

3.2.2 容量分析中的子查询场景

场景 子查询表达式 说明
过去 1 小时内的最大 CPU 峰值 max_over_time( rate(node_cpu_seconds_total[5m]) [1h:1m] ) 每 1 分钟计算一次 5m 速率,再取 1h 最大值
检测持续 15 分钟以上的高内存 min_over_time( (node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) / node_memory_MemTotal_bytes [15m:1m] ) > 0.9 确保 15 分钟内每个 1m 采样点都超过 90%
压测期间平均 QPS 的波动范围 stddev_over_time( rate(http_requests_total[1m]) [10m:30s] ) 评估流量抖动程度
性能警告: 子查询会大幅增加 Prometheus 计算开销。在压测巡检脚本中,建议将子查询结果通过 Recording Rules 固化,避免每次查询都重复计算。

3.3 Recording Rules:预计算与查询加速

Recording Rules 允许将复杂的 PromQL 表达式预先计算并存储为新的时间序列,是容量分析脚本编排优化的核心手段。

3.3.1 Recording Rules 配置结构

groups:
  - name: capacity_analysis
    interval: 30s
    rules:
      - record: cluster:cpu_usage_avg:5m
        expr: avg by (cluster) (rate(node_cpu_seconds_total{mode!="idle"}[5m]))

      - record: service:p99_latency:1h
        expr: quantile by (service) (0.99, rate(http_request_duration_seconds_sum[5m]) / rate(http_request_duration_seconds_count[5m]))

      - record: instance:memory_pressure:1m
        expr: (node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) / node_memory_MemTotal_bytes > 0.85

3.3.2 容量分析中的 Recording Rules 设计原则

原则 说明 反例
按分析粒度分层 集群级、服务级、实例级分别定义规则 将所有聚合写在一个规则中
设置合理的评估间隔 压测场景用 15-30s,巡检场景用 1-5m 所有规则统一使用 15s
命名规范可溯源 使用 level:metric:window 格式 随意命名如 rule1
避免过度预计算 只固化高频查询或高开销表达式 对简单 rate() 也做 Recording Rule

3.4 三者协同:容量压测巡检脚本编排模型

聚合操作、子查询与 Recording Rules 并非孤立使用,而是形成一套从原始数据到告警阈值的完整链路。

编排流程: 原始指标 → 聚合操作(降维) → 子查询(窗口检测) → Recording Rules(固化) → 巡检脚本(阈值判断)
容量压测巡检脚本编排模型 原始指标 node_cpu / http_requests 聚合操作 sum / avg / quantile 子查询 max_over_time Recording Rules 预计算固化 巡检脚本 阈值判断 / 告警 编排优化要点 1. 聚合降维减少数据量 2. 子查询检测持续异常 3. Recording Rules 加速查询 容量报告 趋势 / 瓶颈 / 建议

3.5 实战案例:压测脚本中的容量阈值编排

以下是一个完整的压测巡检脚本片段,展示聚合、子查询与 Recording Rules 的协同使用。

3.5.1 定义 Recording Rules

groups:
  - name: stress_test_capacity
    interval: 30s
    rules:
      - record: stress:cluster:cpu_peak:15m
        expr: max_over_time( avg by (cluster) (rate(node_cpu_seconds_total{mode!="idle"}[2m]) ) [15m:30s] )

      - record: stress:service:mem_sustained:10m
        expr: min_over_time( (container_memory_working_set_bytes / container_spec_memory_limit_bytes) [10m:1m] )

3.5.2 巡检脚本中的阈值判断

# 判断集群 CPU 峰值是否超过 85%
stress:cluster:cpu_peak:15m > 0.85

# 判断服务内存持续压力是否超过 90%
stress:service:mem_sustained:10m > 0.9

# 结合子查询检测突发流量(过去 5 分钟内 QPS 增长超过 200%)
rate(http_requests_total[1m]) / avg_over_time(rate(http_requests_total[1m])[30m:1m]) > 3
脚本编排建议: 将 Recording Rules 的评估间隔与压测脚本的巡检周期对齐(如均为 30s),避免因时间窗口错位导致误告警。同时,在脚本中优先引用预计算指标,减少实时 PromQL 计算对 Prometheus 的压力。

3.6 本章小结

  • 聚合操作是容量分析的基石,通过 by/without 控制维度粒度,使用 quantile/topk 识别异常。
  • 子查询提供时间窗口内的二次计算能力,适用于持续异常检测和峰值分析,但需注意性能开销。
  • Recording Rules 将高频或高开销查询预计算固化,是压测巡检脚本性能优化的关键手段。
  • 三者协同形成“原始指标 → 聚合降维 → 窗口检测 → 预计算固化 → 阈值判断”的完整编排链路。