文章

Metrics 与 Prometheus 实战

Metrics 与 Prometheus 实战

一句话:Prometheus 是”拉模型”的时序数据库——它定时去每个目标抓 /metrics,存成带标签的数值时间序列。理解它,先从”数据模型”和”标签基数”两个命门开始。

Prometheus 架构(核心心智)

graph LR
    T1[Target: /metrics] --> P[Prometheus Server]
    T2[Target: exporter] --> P
    P --> TSDB[(本地 TSDB)]
    P --> R[Recording/Alerting Rule]
    R --> AM[Alertmanager]
    P --> GF[Grafana 查询]
    P -.远程写.-> LONG[Thanos/Mimir]
  • Pull 模型:Server 主动 scrape,不是 agent 推。好处是目标只需暴露 HTTP 端点,故障隔离好。
  • TSDB:本地时序库,2 小时一个 block,压缩 + 索引。不适合长期存储(单点、难扩)。
  • Service Discovery:K8s 下自动发现 Pod/Service 作为 scrape target。

数据模型:四种指标类型

类型语义例子能用什么函数
Counter只增不减的累计值请求总数、错误总数rate() / increase()
Gauge可增可减的瞬时值内存使用、温度、队列长度max() / min() / delta()
Histogram分桶统计(含 _count/_sum/_bucket)请求时延分布histogram_quantile()
Summary客户端算好的分位数时延分位(类似 histogram 但服务端不可聚合)直接读 quantile
# Counter 必须包 rate,否则看到的是累计跳变
rate(http_requests_total[5m])

# Histogram 算 P99 时延(le=上界桶)
histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[5m]))

经典坑:对 Counter 直接 avg 毫无意义;对 Gauge 用 rate 也无意义。类型决定算法。

标签基数(cardinality)是头号杀手

一个时间序列 = 指标名 + 所有标签值的唯一组合。如果某个标签取值爆炸(如 user_idiprequest_id),序列数指数膨胀,Prometheus 内存和磁盘直接被打爆。

标签是否安全原因
status_code (200/404/500)安全少量离散值
method (GET/POST)安全少量
path (/api/v1/order)谨慎路由数可能上百
user_id (UUID)危险每用户一个序列 → 百万级

规则:标签只放”用于分组的低基数维度”,高基数维度留给 Logs/Traces。

PromQL 常用套路

# 1. 选择 + 标签匹配
up{job="kubernetes-pods", namespace="prod"}

# 2. 速率(Counter 必包)
rate(http_requests_total[5m])

# 3. 分位数(Histogram)
histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[5m]))

# 4. 聚合(without 去掉某标签后聚合)
sum by (namespace) (rate(http_requests_total[5m]))

# 5. 对比/差值
node_memory_MemFree_bytes / node_memory_MemTotal_bytes

# 6. 预测(资源将满)
predict_linear(node_filesystem_avail_bytes[1h], 4*3600) < 0

K8s 集成:三类指标源

组件暴露什么用途
kube-state-metricsK8s 对象状态(Pod 数、Deployment 副本、Pending)“系统状态”类指标
cAdvisor容器级资源(CPU/内存/网络/文件系统)“容器用量”类指标
node_exporter节点硬件(CPU/内存/磁盘/网络)“主机”类指标

你的 cgroup v2 详解 里 PSI 指标,cAdvisor 也会以 container_cpu_pressure_* 形式暴露——可观测性把 cgroup 信号接到了统一面板。

规则:Recording 与 Alerting

groups:
  - name: example
    rules:
      # Recording Rule:预聚合,缩短查询、降负载
      - record: job:http_inprogress_requests:sum
        expr: sum by (job) (http_inprogress_requests)
      # Alerting Rule
      - alert: HighErrorRate
        expr: rate(http_requests_total{code=~"5.."}[5m]) > 0.05
        for: 10m
        labels: { severity: page }
        annotations:
          summary: "高错误率 {{ $labels.job }}"

长期存储与高可用

单 Prometheus 不适合存久、也不耐故障。生产用:

方案思路
ThanosSidecar 读 TSDB + 对象存储(S3),Query 层全局去重
Mimir / Cortex分布式、多租户,原生支持长期存储
VictoriaMetrics高性能单/集群版,PromQL 兼容

你的 LLM 推理服务化/推理性能基准测试与调优 提到的压测指标,长期留存用 Thanos/Mimir 接对象存储最顺。

关联知识

参考资源

  • Prometheus Docs: Querying / Data model
  • Julius Volz (Prometheus 作者) 演讲: cardinality 治理

学习时间

内容日期状态
Metrics 与 Prometheus2026-07-24完成:四类型、基数陷阱、PromQL、K8s 三类源、规则、长期存储

状态

  • 架构与数据模型
  • 标签基数陷阱
  • PromQL 套路
  • K8s 指标源
  • 规则与长期存储