PromQL 完全指南

Prometheus Query Language (PromQL) 完整教學,涵蓋語法、函式、常用查詢範例與最佳實踐


目錄

  1. 什麼是 PromQL
  2. 資料模型
  3. 基本查詢
  4. 選擇器與標籤
  5. 運算子
  6. 函式
  7. 常用查詢範例
  8. 告警規則
  9. 效能優化
  10. 常見問題
  11. 總結

什麼是 PromQL

PromQL(Prometheus Query Language)是 Prometheus 的查詢語言,用於查詢時序資料、建立儀表板和告警規則。

Prometheus 架構簡介

          ┌─────────────────────────────────────────┐
          │              Prometheus                  │
          │  ┌─────────┐  ┌─────────┐  ┌─────────┐  │
 Targets ─┼─▶│ Scraper │─▶│  TSDB   │◀─│ PromQL  │◀─┼─ Grafana
          │  └─────────┘  └─────────┘  └─────────┘  │
          │                    │                     │
          │              ┌─────▼─────┐              │
          │              │Alertmanager│              │
          │              └───────────┘              │
          └─────────────────────────────────────────┘

PromQL 使用場景

場景 說明
即時查詢 在 Prometheus UI 或 Grafana 查詢當前資料
儀表板 Grafana 圖表的資料來源
告警規則 定義觸發告警的條件
Recording Rules 預先計算並儲存查詢結果

資料模型

時間序列結構

每個時間序列由以下組成:

metric_name{label1="value1", label2="value2"} value timestamp

範例:
http_requests_total{method="GET", status="200"} 1234 1701676800
│                   │                            │    │
│                   │                            │    └─ 時間戳記(Unix 毫秒)
│                   │                            └─ 數值
│                   └─ 標籤(Labels)
└─ 指標名稱(Metric Name)

指標類型

類型 說明 範例
Counter 只增不減的累計值 http_requests_totalerrors_total
Gauge 可增可減的瞬時值 temperaturememory_usage
Histogram 統計分佈(桶) http_request_duration_seconds
Summary 統計分佈(分位數) http_request_duration_seconds

Counter vs Gauge

Counter(計數器):
├── 只會增加或重置為 0
├── 適合:請求數、錯誤數、完成的任務數
└── 常用函式:rate(), increase()

Gauge(儀表):
├── 可以任意增減
├── 適合:溫度、記憶體使用量、當前連線數
└── 直接使用或用 delta()

Histogram 結構

http_request_duration_seconds_bucket{le="0.1"}   1000  # ≤0.1秒 的請求數
http_request_duration_seconds_bucket{le="0.5"}   1500  # ≤0.5秒 的請求數
http_request_duration_seconds_bucket{le="1"}     1800  # ≤1秒 的請求數
http_request_duration_seconds_bucket{le="+Inf"}  2000  # 所有請求數
http_request_duration_seconds_sum                 450   # 總耗時
http_request_duration_seconds_count               2000  # 總請求數

基本查詢

即時向量(Instant Vector)

查詢某個時間點的所有時間序列。

# 查詢所有 http_requests_total 指標
http_requests_total

# 結果:
http_requests_total{method="GET", status="200"}  1234
http_requests_total{method="GET", status="404"}  56
http_requests_total{method="POST", status="200"} 789

範圍向量(Range Vector)

查詢一段時間範圍內的資料。

# 過去 5 分鐘的資料
http_requests_total[5m]

# 結果:
http_requests_total{method="GET"} 1200 @1701676500
http_requests_total{method="GET"} 1210 @1701676560
http_requests_total{method="GET"} 1234 @1701676620
...

時間範圍語法

單位 說明
s
m 分鐘
h 小時
d
w
y
http_requests_total[30s]   # 過去 30http_requests_total[5m]    # 過去 5 分鐘
http_requests_total[1h]    # 過去 1 小時
http_requests_total[7d]    # 過去 7

時間偏移(Offset)

# 1 小時前的資料
http_requests_total offset 1h

# 1 天前的 5 分鐘範圍
http_requests_total[5m] offset 1d

@ 修飾符(指定時間點)

# 查詢指定時間戳的資料
http_requests_total @ 1701676800

# 查詢開始時間的資料
http_requests_total @ start()

# 查詢結束時間的資料
http_requests_total @ end()

選擇器與標籤

標籤匹配器

運算子 說明 範例
= 完全匹配 method="GET"
!= 不等於 status!="200"
=~ 正則匹配 method=~"GET|POST"
!~ 正則不匹配 status!~"5.."

標籤選擇範例

# 完全匹配
http_requests_total{method="GET"}

# 不等於
http_requests_total{status!="200"}

# 正則匹配(GET 或 POST)
http_requests_total{method=~"GET|POST"}

# 正則匹配(所有 5xx 錯誤)
http_requests_total{status=~"5.."}

# 多條件組合
http_requests_total{method="GET", status="200", job="api-server"}

# 排除某些值
http_requests_total{status!~"2.."}

內建標籤

標籤 說明
__name__ 指標名稱
job 抓取任務名稱
instance 抓取目標位址
# 使用 __name__ 查詢多個指標
{__name__=~"http_requests_total|http_errors_total"}

# 查詢特定 job 的所有指標
{job="api-server"}

運算子

算術運算子

運算子 說明
+ 加法
- 減法
* 乘法
/ 除法
% 取餘數
^ 次方
# 計算錯誤率
http_errors_total / http_requests_total * 100

# 記憶體使用百分比
node_memory_Active_bytes / node_memory_MemTotal_bytes * 100

# 單位轉換(bytes → MB)
node_memory_MemTotal_bytes / 1024 / 1024

比較運算子

運算子 說明
== 等於
!= 不等於
> 大於
< 小於
>= 大於等於
<= 小於等於
# 篩選 CPU 使用率 > 80% 的實例
node_cpu_usage > 80

# 保留數值但只顯示符合條件的
http_requests_total > bool 1000

邏輯運算子

運算子 說明
and 交集
or 聯集
unless 差集
# 交集:CPU > 80% 且 記憶體 > 80%
node_cpu_usage > 80 and node_memory_usage > 80

# 聯集:任一條件符合
node_cpu_usage > 90 or node_memory_usage > 90

# 差集:符合 A 但不符合 B
http_requests_total unless http_requests_total{status="200"}

向量匹配

# 一對一匹配(相同標籤)
http_errors_total / http_requests_total

# 忽略某些標籤
http_errors_total / ignoring(status) http_requests_total

# 只使用指定標籤匹配
http_errors_total / on(method, job) http_requests_total

# 一對多匹配
sum by (job) (http_errors_total) / on(job) group_left sum by (job) (http_requests_total)

函式

速率函式(Rate Functions)

rate()

計算 Counter 的每秒平均增長率(最常用)。

# 每秒請求數(QPS)
rate(http_requests_total[5m])

# 每秒錯誤數
rate(http_errors_total[5m])

irate()

計算最後兩個資料點的瞬時增長率(更敏感)。

# 瞬時每秒請求數
irate(http_requests_total[5m])

increase()

計算時間範圍內的總增長量。

# 過去 1 小時的請求增長量
increase(http_requests_total[1h])

# 過去 24 小時的錯誤數
increase(http_errors_total[24h])

rate vs irate vs increase

函式 用途 特點
rate() 平均速率 平滑,適合告警
irate() 瞬時速率 敏感,適合看趨勢細節
increase() 總增長量 適合統計總量

聚合函式(Aggregation Functions)

# 總和
sum(http_requests_total)

# 平均
avg(http_requests_total)

# 最大值
max(node_cpu_usage)

# 最小值
min(node_memory_available)

# 計數(有多少時間序列)
count(http_requests_total)

# 標準差
stddev(http_request_duration_seconds)

# 分位數(P95)
quantile(0.95, http_request_duration_seconds)

# 前 N 名
topk(5, http_requests_total)

# 後 N 名
bottomk(5, http_requests_total)

by 與 without

# 按 method 分組求和
sum by (method) (http_requests_total)

# 按 method 和 status 分組
sum by (method, status) (http_requests_total)

# 排除 instance 標籤,其他都保留
sum without (instance) (http_requests_total)

時間函式

# 當前時間戳
time()

# 指標的時間戳
timestamp(http_requests_total)

# 距離上次抓取的秒數
time() - timestamp(up)

# 每天的小時(0-23)
hour()

# 每週的第幾天(0=週日)
day_of_week()

數學函式

# 絕對值
abs(temperature)

# 向上取整
ceil(value)

# 向下取整
floor(value)

# 四捨五入
round(value, 0.1)  # 精確到 0.1

# 自然對數
ln(value)

# 指數
exp(value)

# 平方根
sqrt(value)

標籤函式

# 替換標籤值
label_replace(up, "host", "$1", "instance", "(.*):.*")
# instance="server:9090" → host="server"

# 合併標籤
label_join(up, "full_name", "-", "job", "instance")
# 建立新標籤 full_name = "job-instance"

Histogram 函式

# 計算 P95 延遲
histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))

# 計算 P99 延遲
histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[5m]))

# 按 job 分組計算 P95
histogram_quantile(0.95, sum by (job, le) (rate(http_request_duration_seconds_bucket[5m])))

其他常用函式

# 判斷是否存在資料
absent(up{job="api-server"})  # 如果不存在,回傳 1

# 限制範圍
clamp(cpu_usage, 0, 100)        # 限制在 0-100 之間
clamp_min(value, 0)             # 最小值為 0
clamp_max(value, 100)           # 最大值為 100

# 排序
sort(http_requests_total)       # 升序
sort_desc(http_requests_total)  # 降序

# 變化
changes(up[1h])                 # 過去 1 小時變化了幾次
delta(temperature[1h])          # Gauge 的變化量
deriv(temperature[1h])          # Gauge 的導數(變化速率)

# 預測
predict_linear(node_filesystem_avail_bytes[1h], 3600 * 24)
# 根據過去 1 小時的趨勢,預測 24 小時後的值

常用查詢範例

CPU 監控

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

# 每個 CPU 核心的使用率
sum by (cpu) (irate(node_cpu_seconds_total{mode!="idle"}[5m])) * 100

# 系統負載
node_load1   # 1 分鐘負載
node_load5   # 5 分鐘負載
node_load15  # 15 分鐘負載

記憶體監控

# 記憶體使用率
(1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100

# 可用記憶體(GB)
node_memory_MemAvailable_bytes / 1024 / 1024 / 1024

# Swap 使用率
(node_memory_SwapTotal_bytes - node_memory_SwapFree_bytes) / node_memory_SwapTotal_bytes * 100

磁碟監控

# 磁碟使用率
(1 - node_filesystem_avail_bytes / node_filesystem_size_bytes) * 100

# 磁碟剩餘空間(GB)
node_filesystem_avail_bytes{mountpoint="/"} / 1024 / 1024 / 1024

# 磁碟 I/O(每秒讀寫 bytes)
rate(node_disk_read_bytes_total[5m])
rate(node_disk_written_bytes_total[5m])

# 預測磁碟何時滿(秒)
predict_linear(node_filesystem_avail_bytes[1h], 3600 * 24 * 7)

網路監控

# 網路流量(bytes/s)
rate(node_network_receive_bytes_total[5m])
rate(node_network_transmit_bytes_total[5m])

# 網路流量(Mbps)
rate(node_network_receive_bytes_total[5m]) * 8 / 1000 / 1000

# 網路錯誤
rate(node_network_receive_errs_total[5m])
rate(node_network_transmit_errs_total[5m])

HTTP 服務監控

# QPS(每秒請求數)
sum(rate(http_requests_total[5m]))

# 按狀態碼分組的 QPS
sum by (status) (rate(http_requests_total[5m]))

# 錯誤率
sum(rate(http_requests_total{status=~"5.."}[5m])) / sum(rate(http_requests_total[5m])) * 100

# P95 延遲
histogram_quantile(0.95, sum by (le) (rate(http_request_duration_seconds_bucket[5m])))

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

# 平均延遲
rate(http_request_duration_seconds_sum[5m]) / rate(http_request_duration_seconds_count[5m])

容器監控(cAdvisor)

# 容器 CPU 使用率
sum by (container) (rate(container_cpu_usage_seconds_total[5m])) * 100

# 容器記憶體使用
container_memory_usage_bytes{container!=""}

# 容器記憶體使用率
container_memory_usage_bytes / container_spec_memory_limit_bytes * 100

# 容器網路流量
rate(container_network_receive_bytes_total[5m])
rate(container_network_transmit_bytes_total[5m])

Kubernetes 監控

# Pod 重啟次數
sum by (pod) (kube_pod_container_status_restarts_total)

# 最近 1 小時 Pod 重啟次數
sum by (pod) (increase(kube_pod_container_status_restarts_total[1h]))

# Pod 狀態
kube_pod_status_phase{phase="Running"}

# 節點狀態
kube_node_status_condition{condition="Ready", status="true"}

# Deployment 可用副本數
kube_deployment_status_replicas_available

# HPA 當前副本數 vs 期望副本數
kube_horizontalpodautoscaler_status_current_replicas
kube_horizontalpodautoscaler_status_desired_replicas

告警規則

告警規則格式

groups:
  - name: example-alerts
    rules:
      - alert: HighCPUUsage
        expr: 100 - (avg by (instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "CPU 使用率過高"
          description: "實例 {{ $labels.instance }} CPU 使用率 {{ $value | printf \"%.2f\" }}%"

常用告警範例

groups:
  - name: node-alerts
    rules:
      # 實例宕機
      - alert: InstanceDown
        expr: up == 0
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "實例 {{ $labels.instance }} 宕機"

      # CPU 使用率過高
      - alert: HighCPUUsage
        expr: 100 - (avg by (instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "CPU 使用率 {{ $value | printf \"%.2f\" }}%"

      # 記憶體不足
      - alert: LowMemory
        expr: (1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100 > 90
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "記憶體使用率 {{ $value | printf \"%.2f\" }}%"

      # 磁碟空間不足
      - alert: LowDiskSpace
        expr: (1 - node_filesystem_avail_bytes / node_filesystem_size_bytes) * 100 > 85
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "磁碟使用率 {{ $value | printf \"%.2f\" }}%"

      # 磁碟即將滿
      - alert: DiskWillFillIn24Hours
        expr: predict_linear(node_filesystem_avail_bytes[1h], 3600 * 24) < 0
        for: 1h
        labels:
          severity: warning
        annotations:
          summary: "磁碟預計 24 小時內將滿"

  - name: http-alerts
    rules:
      # 高錯誤率
      - alert: HighErrorRate
        expr: sum(rate(http_requests_total{status=~"5.."}[5m])) / sum(rate(http_requests_total[5m])) * 100 > 5
        for: 5m
        labels:
          severity: critical
        annotations:
          summary: "錯誤率 {{ $value | printf \"%.2f\" }}%"

      # 高延遲
      - alert: HighLatency
        expr: histogram_quantile(0.95, sum by (le) (rate(http_request_duration_seconds_bucket[5m]))) > 1
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "P95 延遲 {{ $value | printf \"%.2f\" }} 秒"

效能優化

查詢最佳實踐

建議 說明
使用標籤過濾 先過濾再聚合,減少計算量
避免過長時間範圍 [5m][1h] 效率高
使用 Recording Rules 預先計算常用查詢
避免高基數標籤 如 user_id、request_id
使用 without 而非 by 當要排除的標籤較少時

Recording Rules

預先計算並儲存查詢結果,提升效能。

groups:
  - name: recording-rules
    rules:
      # 預計算 QPS
      - record: job:http_requests:rate5m
        expr: sum by (job) (rate(http_requests_total[5m]))

      # 預計算錯誤率
      - record: job:http_error_rate:rate5m
        expr: sum by (job) (rate(http_requests_total{status=~"5.."}[5m])) / sum by (job) (rate(http_requests_total[5m]))

      # 預計算 P95 延遲
      - record: job:http_latency_p95:rate5m
        expr: histogram_quantile(0.95, sum by (job, le) (rate(http_request_duration_seconds_bucket[5m])))

避免的反模式

# ❌ 不好:沒有標籤過濾,計算所有資料
sum(rate(http_requests_total[5m]))

# ✅ 好:先過濾再聚合
sum(rate(http_requests_total{job="api-server"}[5m]))

# ❌ 不好:過長的時間範圍
rate(http_requests_total[24h])

# ✅ 好:使用適當的時間範圍
rate(http_requests_total[5m])

# ❌ 不好:高基數標籤
http_requests_total{user_id="..."}

# ✅ 好:避免高基數標籤,改用 Histogram 統計

常見問題

問題 1:rate() 回傳空值

原因:時間範圍內資料點不足(至少需要 2 個點)

解決:
1. 增加時間範圍(如 [5m] → [10m])
2. 檢查 scrape_interval 設定
3. 時間範圍應至少是 scrape_interval 的 4 倍

問題 2:Counter 重置導致負數

# rate() 和 increase() 會自動處理 Counter 重置
# 不需要額外處理

# 如果仍有問題,可能是資料異常
# 檢查 resets() 函式
resets(http_requests_total[1h])

問題 3:標籤不匹配無法運算

# 問題:兩個向量標籤不同,無法除法
http_errors_total{method="GET"} / http_requests_total

# 解決 1:使用 ignoring
http_errors_total / ignoring(status) http_requests_total

# 解決 2:使用 on
http_errors_total / on(method) http_requests_total

# 解決 3:先聚合
sum by (method) (http_errors_total) / sum by (method) (http_requests_total)

問題 4:Histogram 分位數不準確

原因:分位數是估算值,精度取決於 bucket 定義

解決:
1. 調整 bucket 邊界,讓它們更接近實際分佈
2. bucket 越多越準確(但儲存成本越高)
3. 對於精確需求,考慮使用 Summary

總結

函式速查表

函式 用途 範例
rate() Counter 每秒速率 rate(requests[5m])
irate() 瞬時速率 irate(requests[5m])
increase() 總增長量 increase(requests[1h])
sum() 求和 sum by (job) (requests)
avg() 平均 avg(cpu_usage)
max() / min() 最大/最小 max(memory)
topk() 前 N 名 topk(5, requests)
histogram_quantile() 分位數 histogram_quantile(0.95, ...)
predict_linear() 線性預測 predict_linear(disk[1h], 86400)
absent() 檢查是否缺失 absent(up{job="x"})

常用查詢模式

需求 查詢
QPS sum(rate(http_requests_total[5m]))
錯誤率 sum(rate(errors[5m])) / sum(rate(requests[5m])) * 100
P95 延遲 histogram_quantile(0.95, sum by (le) (rate(duration_bucket[5m])))
CPU 使用率 100 - avg(irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100
記憶體使用率 (1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100
磁碟使用率 (1 - node_filesystem_avail_bytes / node_filesystem_size_bytes) * 100

時間範圍建議

場景 建議範圍
即時監控 [1m] ~ [5m]
告警規則 [5m] ~ [15m]
趨勢分析 [1h] ~ [24h]
容量規劃 [7d] ~ [30d]

建立日期:2025-12-04 最後更新:2025-12-04

🔗相關文章