prometheus / promtool —— 监控数据查询和工具
一句话定义
prometheus 是 K8s 生态最主流的时序数据库 + 监控系统,组件本身在 K8s 里作为 Deployment 跑。它没有"日常 CLI"——所有查询走 PromQL 通过 HTTP API。但 prometheus 自带的 promtool 提供本地工具:验证配置、查询 API、测告警规则。
典型场景
- 看哪些 target 没采集到:
curl http://prom:9090/api/v1/targets - 验证 prometheus 配置语法:
promtool check config prometheus.yml - 验证告警规则语法:
promtool check rules rules.yml - 命令行查询 PromQL:
promtool query instant http://prom:9090 'up' - 排查"指标没看到":sum + by + 命名 + scrape job 全链路
Prometheus 的核心概念(理解了这个再用 CLI)
target ──scrape──► prometheus ──store──► TSDB
▲ │
│ └──query──► PromQL / API
│
service discovery
(K8s pod, kube-sd, file-sd, ...)
四个核心:
- Target —— 被采集的 endpoint(pod 上
:9100/metrics) - Scrape —— 周期性(默认 15s)pull target,存数据
- Series —— 一条时序:
metric_name{label1=v1,label2=v2} -> [(ts, value), ...] - PromQL —— 查询语言
CLI 工作主要围绕:确认 target up、看 series、跑 PromQL。
promtool —— Prometheus 自带的工具
装 prometheus 时自带:
# 单独装
curl -L https://github.com/prometheus/prometheus/releases/download/v2.51.0/prometheus-2.51.0.linux-amd64.tar.gz | tar xz
mv prometheus-*/promtool /usr/local/bin/
promtool --version
# promtool, version 2.51.0 ...
promtool check config —— 验证配置语法
promtool check config /etc/prometheus/prometheus.yml
# Checking /etc/prometheus/prometheus.yml
# SUCCESS: 0 rule files found
promtool check rules /etc/prometheus/rules/*.yml
# Checking /etc/prometheus/rules/recording.yml
# SUCCESS: 12 rules found
CI 流水线里改 prometheus 配置之前必跑,避免改错让 prometheus 重启失败。
promtool query —— 命令行跑 PromQL
# 瞬时查询
promtool query instant http://prom:9090 'up'
# 返回 { up{instance="...",job="..."} => 1 ... }
# 范围查询
promtool query range http://prom:9090 'rate(http_requests_total[5m])' \
--start='2026-05-27T00:00:00Z' \
--end='2026-05-27T01:00:00Z' \
--step=1m
# 看时序的所有 label
promtool query labels http://prom:9090 job
在没有 grafana / web UI 时调试 PromQL 用。
promtool tsdb —— 看 TSDB 状态(在 prometheus pod 里跑)
promtool tsdb analyze /prometheus/ # 看磁盘 / series 数 / chunk 等
promtool tsdb list /prometheus/ # 列 block
排查"prometheus 磁盘暴涨" / "series 太多" 必备。
直接 curl Prometheus HTTP API
Prometheus 暴露 REST API(端口默认 9090)。CLI 友好的方式是 curl:
看 targets
curl -s http://prom:9090/api/v1/targets | jq '.data.activeTargets[] | {job: .labels.job, instance: .labels.instance, health}'
# {"job": "kubelet", "instance": "m1:10250", "health": "up"}
# {"job": "kubelet", "instance": "m4:10250", "health": "down"} ← 这个失败了
排查"prometheus 看不到指标"第一步:看 target health。
跑 PromQL
# 瞬时
curl -s --data-urlencode 'query=up' http://prom:9090/api/v1/query | jq
# {"status":"success","data":{"resultType":"vector","result":[...]}}
# 范围
curl -s --data-urlencode 'query=rate(http_requests_total[5m])' \
--data-urlencode 'start=2026-05-27T00:00:00Z' \
--data-urlencode 'end=2026-05-27T01:00:00Z' \
--data-urlencode 'step=1m' \
http://prom:9090/api/v1/query_range | jq
看 series / labels / metadata
curl -s 'http://prom:9090/api/v1/label/__name__/values' | jq '.data | length'
# 5000 → 集群有 5000 个不同 metric
curl -s 'http://prom:9090/api/v1/labels' | jq '.data'
# 所有 label 名
curl -s 'http://prom:9090/api/v1/series?match[]=up' | jq
# 拥有 up 这个 metric 的所有 series
Reload / Quit
# 让 prometheus 重新读配置(要启动时加 --web.enable-lifecycle)
curl -X POST http://prom:9090/-/reload
# 查看 build info
curl -s http://prom:9090/api/v1/status/buildinfo | jq
PromQL 速查(实战必背)
基础
up # 所有 target 健康(1=up, 0=down)
up == 0 # 只看挂的
up{job="kubelet"} # 过滤 job
node_cpu_seconds_total{mode="idle"} # 多 label
rate / irate(速率)
rate(http_requests_total[5m]) # 5 分钟均速(QPS)
irate(http_requests_total[1m]) # 即时速率(最近 2 个采样点)
rate 给平均,irate 给瞬时。alerting 用 rate(稳)、dashboard 实时用 irate(敏感)。
sum / by / without(聚合)
sum(rate(http_requests_total[5m])) # 所有 series 加起来
sum by (job) (rate(http_requests_total[5m])) # 按 job 聚合
sum without (instance) (rate(http_requests_total[5m])) # 除了 instance 全保留
by 保留指定 label、without 删除指定 label。后者更稳——加新 label 不影响。
topk / bottomk
topk(5, rate(http_requests_total[5m])) # CPU top 5
topk(10, container_memory_working_set_bytes) # 内存 top 10
histogram_quantile(P95 / P99)
histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m])) # P95 延迟
histogram_quantile(0.99, sum by (le) (rate(http_request_duration_seconds_bucket[5m])))
PromQL 必备技能——SRE 面试常考。
常用查询模板
# 节点 CPU 利用率
(1 - rate(node_cpu_seconds_total{mode="idle"}[5m]))
# 节点内存利用率
(node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) / node_memory_MemTotal_bytes
# 节点磁盘剩余
(node_filesystem_avail_bytes{fstype!~"tmpfs|overlay"} / node_filesystem_size_bytes{fstype!~"tmpfs|overlay"})
# K8s pod 重启次数(最近 1 小时)
increase(kube_pod_container_status_restarts_total[1h])
# pod CPU 使用率
sum by (pod) (rate(container_cpu_usage_seconds_total{container!=""}[5m]))
# pod 内存使用
sum by (pod) (container_memory_working_set_bytes{container!=""})
# 5xx 错误率
sum(rate(http_requests_total{status=~"5.."}[5m])) / sum(rate(http_requests_total[5m]))
排查"prometheus 看不到指标"
# 1. target 在不在
curl -s http://prom:9090/api/v1/targets | jq '.data.activeTargets[] | select(.labels.job=="my-job")'
# 如果空,scrape config 没匹配上
# 2. target 是不是 up
curl -s http://prom:9090/api/v1/targets | jq '.data.activeTargets[] | select(.labels.job=="my-job") | {health, lastError}'
# health: down / lastError: "connection refused" → 应用没在 /metrics 暴露
# 3. service / pod 是不是有正确 annotation(K8s sd)
kubectl get pod my-pod -o yaml | grep -A 5 annotations
# prometheus.io/scrape: "true"
# prometheus.io/port: "9090"
# 4. metric 名对不对(应用真的暴露了吗)
kubectl port-forward my-pod 9090:9090
curl http://localhost:9090/metrics | grep -i my_metric_name
# 5. PromQL 拼错?
promtool query instant http://prom:9090 'my_metric_name'
看告警规则评估
# 看所有规则
curl -s http://prom:9090/api/v1/rules | jq
# 看 firing 的告警
curl -s http://prom:9090/api/v1/alerts | jq '.data.alerts[] | {labels, state}'
或者 web UI /alerts 页面更直观。
规则评估测试
promtool test rules tests.yml
tests.yml 例子:
rule_files:
- rules.yml
tests:
- interval: 1m
input_series:
- series: up{job="test"}
values: '1 1 0 0 0 0'
alert_rule_test:
- eval_time: 5m
alertname: TargetDown
exp_alerts:
- exp_labels:
severity: critical
job: test
CI 跑这个能验证你的告警规则在特定输入下是否真的会触发。
TSDB 操作
看 prometheus 数据目录占用
# 在 prometheus pod 里
kubectl exec -it prometheus-prom-0 -n monitoring -- df -h /prometheus
kubectl exec -it prometheus-prom-0 -n monitoring -- du -sh /prometheus
或者用 promtool 分析:
kubectl exec -it prometheus-prom-0 -n monitoring -- promtool tsdb analyze /prometheus
# Block ID: 01HVKZ...
# Duration: 2h
# Series: 50000
# Label Pairs: ...
# Distinct Label Names: 200
# ...
看 high cardinality series
kubectl exec -it prometheus-prom-0 -n monitoring -- \
promtool tsdb analyze /prometheus | head -50
"Highest cardinality metric names" / "Label pairs most involved in churning series" 是排查 cardinality 爆炸的金矿。
常见踩坑
坑 1:target health=down
curl http://prom:9090/api/v1/targets | jq '.data.activeTargets[] | select(.health=="down")'
# {lastError: "...connection refused"}
应用没在 /metrics 暴露 / 端口不对 / 网络挡。
# 节点上手动测
kubectl port-forward my-pod 9090:<port>
curl http://localhost:9090/metrics
坑 2:series 数爆炸
# 看 series 总数
curl -s 'http://prom:9090/api/v1/status/tsdb' | jq '.data.headStats'
# {numSeries: 5000000, ...} ← 太多
通常是 label cardinality 爆炸——label value 是 user ID / request URL 等 unbounded 集合。
promtool tsdb analyze /prometheus | head
# Highest cardinality metric names
修法:
- 改应用 / exporter,把高基数 label 拿掉
- 加 metric_relabel_configs drop 掉
- 否则 prometheus 内存爆 OOM
坑 3:PromQL rate 用错时间窗口
rate(http_requests_total[5m])
[5m] 至少要 4 倍 scrape 间隔(默认 scrape 15s → 至少 60s,安全 5m)。窗口太短,新 series 还没 2 个采样点,rate 返回 NaN。
坑 4:histogram_quantile 没加 by (le)
histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))
要 sum by (le, ...) 才能正确计算分位数。否则不同 series 的 bucket 拼一起得到错误结果。
histogram_quantile(0.95, sum by (le, route) (rate(http_request_duration_seconds_bucket[5m])))
坑 5:/-/reload 不工作
curl -X POST http://prom:9090/-/reload
# {"status":"error","errorType":"unavailable","error":"Lifecycle API is not enabled"}
启动时没加 --web.enable-lifecycle。要 reload 时 kill -HUP 也行:
kubectl exec -n monitoring prometheus-xxx -- kill -HUP 1
坑 6:误把 up == 0 配成告警 + 持续触发
alert: TargetDown
expr: up == 0
for: 5m
某 service 永远停服时,告警永远 firing。要么加 silence、要么加 unless on(job) ... 排除特定 job。
坑 7:promtool 检查通过但 prom 起不来
promtool check config prometheus.yml
# SUCCESS
# 但 prom 起来报错
kubectl logs prometheus-xxx
# Error opening query log file
promtool check 只验证 yaml 语法 + scrape config。不验证:
- 数据目录权限
- service discovery 连不到
- 引用的文件存在
要看 prometheus pod 自身日志才能定位运行时问题。
坑 8:长期保留打爆磁盘
retention: 90d # 默认 15d
K8s 集群 5000 个 series × 15s × 90d = 几十 GB。规划好 PVC 大小、或者用 Thanos / VictoriaMetrics 做长期存储。
关联命令
- curl —— 调 prom API
- jq —— 处理 prom API JSON 输出
- helm —— 装 prom 全家桶 (kube-prometheus-stack)
- alertmanager —— prom 的告警下游
- grafana —— prom 的可视化前端
amtool—— alertmanager CLI(详见 alertmanager.md)thanos/victoriametrics-cli—— prom 长期存储