路线图

25-指标栈

星辉 2026-07-02 阅读 3 min 587 字 路线图
25-指标栈 封面

指标(Metrics)是可观测性三支柱中成本最低、查询最快、最适合告警的信号。本章覆盖 Prometheus 的抓取模型与服务发现、PromQL 常用查询、Grafana 看板设计、Alertmanager 告警路由与降噪,以及从可观测性架构师培养教材提取的能力地图。

能力地图(M1-M6)#

可观测性架构师的能力链分六层,指标栈对应其中的核心环节:

模块主题一句话
M1遥测信号原材料:指标 / 日志 / 链路追踪
M2采集与管道信号怎么从代码流到存储
M3存储与查询时序库原理、查询语言
M4告警与 SRESLO、症状告警、去重路由
M5可视化与排障仪表盘设计、黄金信号、USE/RED
M6架构与治理高可用、联邦、成本、配置即代码

Monitoring vs Observability:监控回答"你提前想到的问题"(known unknowns),可观测性让你回答"没提前想到的问题"(unknown unknowns)。指标告诉你"发烧了",不告诉你"为什么发烧"——那是日志和链路的活。

Metrics 的关键性质#

成本与请求量无关:不管接口被调 10 次还是 1 亿次,一条序列每个抓取周期(如 15 秒)只存一个数。所以指标极廉价,可全量长期保留。

基数 cardinality(头号杀手):基数 = 不同 label 组合的数量 = 时间序列的条数。

  • status(5种) × method(4种) × service(50个) = 1000 条序列,没问题。
  • 把 user_id(百万级)或 request_id(每次都不同)塞进 label → 序列爆炸到千万级 → Prometheus 内存 OOM。

架构师铁律:label 只放低基数维度(环境、服务、接口、状态码);高基数的东西(用户、订单号、trace_id)交给日志和链路。

Prometheus 抓取模型#

Prometheus 是 pull 模型——由 Prometheus 主动去拉取 target 的 /metrics 端点,而不是 target 主动推送。

Pull 模型的优势:监控端掌控频率;抓不到 = 天然知道 target 死了;target 无状态。

注:Prometheus 3.0(2024-11)起内置原生 OTLP 接收端点,可直接接收 OpenTelemetry 推送来的指标(短生命周期任务、Serverless 等 pull 不到的场景);但抓取(pull)仍是主模型。

核心配置:

yaml
scrape_configs:
  - job_name: 'kubernetes-pods'
    kubernetes_sd_configs:
      - role: pod
    relabel_configs:
      # 只抓取有 prometheus.io/scrape: "true" annotation 的 Pod
      - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
        action: keep
        regex: "true"
      # 自定义 metrics path
      - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]
        action: replace
        target_label: __metrics_path__
        regex: (.+)
      # 自定义端口
      - source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port]
        action: replace
        regex: '([^:]+)(?::\d+)?;(\d+)'
        replacement: '$1:$2'
        target_label: __address__
      # Pod labels 转 Prometheus 标签
      - action: labelmap
        regex: __meta_kubernetes_pod_label_(.+)
      - source_labels: [__meta_kubernetes_namespace]
        target_label: namespace
      - source_labels: [__meta_kubernetes_pod_name]
        target_label: pod

Pod 只需加 annotation 即可被自动发现:

yaml
annotations:
  prometheus.io/scrape: "true"
  prometheus.io/port: "8080"
  prometheus.io/path: "/actuator/prometheus"

ServiceMonitor(Prometheus Operator)#

如果使用 kube-prometheus-stack,可以用 ServiceMonitor CRD 提供更高层抽象:

yaml
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: my-service
  labels:
    release: prometheus
spec:
  namespaceSelector:
    any: true
  selector:
    matchLabels:
      app: my-service
  endpoints:
    - port: http-metrics
      path: /metrics
      interval: 30s

不需要改 Prometheus 配置文件,Operator 自动处理服务发现。

PromQL 常用查询#

rate(计数器增长率)#

promql
# 过去 5 分钟每秒请求量
rate(http_requests_total{service="api"}[5m])

# 按状态码分组
sum by (status) (rate(http_requests_total[5m]))

histogram_quantile(分位数)#

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

# 按服务分组 P99
histogram_quantile(0.99,
  sum(rate(http_request_duration_seconds_bucket[5m])) by (le, service)
)

错误率#

promql
# 5xx 错误率
sum(rate(http_requests_total{status=~"5.."}[5m]))
/
sum(rate(http_requests_total[5m]))

常用聚合#

promql
# 每个服务的 QPS
sum by (service) (rate(http_requests_total[5m]))

# Top 10 慢接口
topk(10,
  histogram_quantile(0.99,
    sum(rate(http_request_duration_seconds_bucket[5m])) by (le, path)
  )
)

Grafana 看板设计#

Grafana 只是展示层——本身不存数据,连接各 data source 查询并画图。"Grafana 挂了"不等于"数据丢了"。

设计原则#

  • 别堆图:一屏 50 个图 = 没有重点 = 出事时找不到关键。
  • 分层:概览盘(系统健康,给值班第一眼)→ 服务盘(单服务详情)→ 实例盘(单机排障)。从上往下下钻。
  • 每个图要能回答一个具体问题,不是"因为有这个指标所以画上"。

三套黄金框架#

框架面向指标
Four Golden Signals服务Latency、Traffic、Errors、Saturation
RED请求驱动服务Rate、Errors、Duration
USE资源(CPU/磁盘/队列)Utilization、Saturation、Errors

实践:给新服务设计监控,先套 RED(服务层)+ USE(资源层),黄金信号兜底。

Alertmanager:告警分拣中心#

Prometheus 只负责判定"该告警了",怎么处理告警是 Alertmanager 的活。

四个核心能力#

  • 分组 grouping:同一类告警(如一次发布挂了 50 个 pod)合并成一条通知。
  • 去重 dedup:多个 Prometheus 副本发的同一告警合并成一条。
  • 抑制 inhibition:高级告警触发时压住低级的——整个集群挂了,别再报每个 pod 挂了。
  • 路由 routing:按 label(团队/严重级)把告警发到不同 on-call 群。

路由树配置#

yaml
route:
  receiver: 'default-ops'
  group_by: ['cluster', 'alertname', 'namespace']
  group_wait: 30s          # 第一批告警等待 30s 聚合
  group_interval: 5m       # 有新告警时等 5 分钟再发
  repeat_interval: 4h      # 未恢复每 4h 重复通知
  routes:
    # Critical → PagerDuty + 钉钉
    - receiver: 'pagerduty-critical'
      matchers: [severity = "critical"]
      group_wait: 10s
      repeat_interval: 30m
      continue: true       # 继续匹配后续路由
    - receiver: 'dingtalk-critical'
      matchers: [severity = "critical"]
    # Warning → 钉钉普通群
    - receiver: 'dingtalk-warning'
      matchers: [severity = "warning"]
      repeat_interval: 8h

抑制规则#

yaml
inhibit_rules:
  # Critical 触发时,抑制同组的 warning
  - source_matchers: [severity = "critical"]
    target_matchers: [severity = "warning"]
    equal: ['alertname', 'cluster', 'namespace']
  # 节点 NotReady 时,抑制该节点上的 Pod 告警
  - source_matchers: [alertname = "KubeNodeNotReady"]
    target_matchers: [alertname =~ "KubePodCrashLooping|KubePodNotReady"]
    equal: ['node', 'cluster']

死人开关(Dead Man's Switch)#

一条永远在触发的告警,反向用——如果没收到它,说明整条告警链路(Prometheus→Alertmanager→通知)自己挂了。每套监控都必须有。

SLO 与错误预算#

  • SLI(服务等级指标):用户体验的量化值,如请求成功率、P99 延迟。
  • SLO(服务等级目标):给 SLI 定的目标,如"成功率 ≥ 99.9%/月"。
  • Error Budget(错误预算) = 1 − SLO = 0.1%。允许失败的额度。

有了 SLO,才有客观标准回答"什么时候该告警、什么值得半夜爬起来"。没有 SLO,所有阈值都是拍脑袋。

多窗口多燃烧率告警#

基于错误预算的高级告警法:

  • 快速烧预算(如 1 小时烧掉一个月额度的 2%)→ 紧急 page
  • 慢速烧→ 工单提醒

兼顾"快响应重大故障"和"不为小波动半夜叫人"。

高可用与长期存储#

Prometheus 单机没有原生 HA。标准做法:跑两个相同配置的副本同时抓,Alertmanager 去重。

多集群全局视图 + 长期存储方案:

方案特点适用
Thanossidecar + 对象存储 + 全局 Query生态成熟
Mimir(Grafana)水平扩展多租户后端大规模
VictoriaMetrics资源省、部署简单、性能高中小规模

本地 15 天不够看季度趋势 → 通过 remote write 把数据吐到长期存储,老数据降采样(15 秒一个点聚合成 5 分钟一个点)省 90% 空间。

成本治理#

可观测性成本能轻松吃掉基础设施账单的两位数百分比。四个抓手(按性价比排序):

  1. 控基数 cardinality:定期扫高基数 label,性价比最高的优化。
  2. 采样:链路和高频日志该采就采。
  3. 分层保留 retention:热(贵、快、短)/ 温 / 冷(对象存储、便宜、长)。
  4. 降采样:老指标降精度长留。

配置即代码#

所有告警规则、记录规则、仪表盘、Collector 配置全进 Git,经 CI/CD 部署。好处:版本化、可 review、可回滚、可审计。"核心告警手动 apply 不在 Git"是典型的治理债。

小结#

指标栈是可观测性中 ROI 最高的部分——采集成本低、查询快、告警成熟。Prometheus 的 pull 模型 + kubernetes_sd_configs 是 K8s 监控的标准答案。PromQL 的 rate 和 histogram_quantile 是最常用的两个算子。Grafana 看板设计要分层、要能回答具体问题,RED + USE 是起步框架。Alertmanager 的分组/去重/抑制/路由是治"告警疲劳"的四件套,配合 SLO 错误预算让告警有客观锚。核心治理底线:配置进 Git + 统一告警分拣 + 死人开关 + 控基数。