路线图

28-可观测性方案整合

星辉 2026-07-02 阅读 3 min 473 字 路线图
28-可观测性方案整合 封面

前三章分别讲了指标、日志、追踪三支柱。单独看任何一个支柱都是片面的,三者联动才能快速定位根因。本章把三支柱缝合成一张可下钻的网,覆盖统一 Labels 关联、Grafana 统一界面、告警收敛与降噪。

监控 vs 可观测性#

  • Monitoring 监控:预先知道要看什么 → 设仪表盘 + 阈值告警,只能回答你提前想到的问题(known unknowns)。
  • Observability 可观测性:系统能让你回答没提前想到的问题(unknown unknowns),不用改代码就能下钻。本质:能否从外部输出反推系统内部状态。

一个只有监控的系统:"API 错误率超过 1%,触发告警" — 我知道系统挂了,但不知道为什么。

一个有可观测性的系统:"API 错误率超过 1%" → 查看错误率折线图 → 跳转到该时间段 Error 日志 → 找到 trace_id → 跳转到 Trace 看完整调用链 → 发现 payment-service → bank-api 这一跳 P99 突然从 200ms 涨到 3000ms → 根因:银行 API 区域性限速。整个过程 10 分钟,不需要猜测。

三支柱联动:下钻漏斗#

三支柱不是三选一,而是下钻漏斗:

text
Metrics 指标(全局,便宜)
  发现"有问题、告警了"
     ↓
Traces 链路(定位)
  告诉你"问题在订单服务调库存那一跳"
     ↓
Logs 日志(细节)
  告诉你"那一刻报了 connection timeout"

能不能走通这个闭环,是检验整套可观测性架构"接缝"设计得好不好的终极标准。

统一 Labels 关联#

三支柱联动的技术基础是共享关联键。如果指标、日志、链路各用各的 label 体系,无法关联。

必须统一的 Labels#

Label指标日志链路
service✓✓✓
namespace✓✓✓
pod✓✓✓
trace_idexemplar字段本身
span_id—字段本身

落地方式#

指标层:Prometheus relabel 把 K8s label 转成 Prometheus label,统一 service/namespace/pod。

日志层:Fluent Bit 的 kubernetes filter 自动注入 kubernetes.namespace_name、kubernetes.pod_name。应用日志 Middleware 从 span context 提取 trace_id/span_id 写入日志字段。

链路层:OTel SDK 的 Resource attributes 设 service.name、service.namespace。

关键:三者的 service 值必须一致——指标里 service="order-service",日志里 service="order-service",链路里 resource.service.name="order-service"。不一致就无法关联。

Grafana 统一界面#

Grafana 是三支柱联动的最佳入口——它只是展示层,连接各 data source 查询并画图。

Data Source Linking 配置#

yaml
datasources:
  - name: Loki
    type: loki
    jsonData:
      derivedFields:
        - datasourceUid: tempo-uid
          matcherRegex: '"trace_id":"(\w+)"'   # 从日志提取 trace_id
          name: TraceID
          url: '$${__value.raw}'

  - name: Tempo
    type: tempo
    uid: tempo-uid
    jsonData:
      tracesToLogs:
        datasourceUid: loki-uid                # trace → 日志
        filterByTraceID: true
        tags: ['service.name', 'pod']
      tracesToMetrics:
        datasourceUid: prometheus-uid          # trace → 指标
        queries:
          - name: 'Request Rate'
            query: 'rate(http_requests_total{service="$${__tags.service}"}[5m])'

  - name: Prometheus
    type: prometheus
    jsonData:
      exemplarTraceIdDestinations:
        - datasourceUid: tempo-uid             # exemplar → trace
          name: traceID

联动效果#

在 Grafana Explore 中:

  • 看 Metrics 时,Exemplar 菱形点击直接跳 Traces
  • 看 Logs 时,trace_id 字段点击直接跳 Traces
  • 看 Traces 时,Service name 点击直接跳同时间段的 Logs 或 Metrics

排障闭环实战#

典型排障流程——把 M1-M5 串起来:

text
1. 告警触发(Metrics)
   Alertmanager: checkout-api 错误率 P0,过去 5 分钟 5xx 率 = 8.3%

2. 定位范围(Metrics)
   Grafana 看 http_requests_total 按 path 分组
   → 只有 /api/checkout 出问题,其他接口正常
   → 问题发生时间:14:28 开始

3. 查看日志(Logs)
   LogQL: {service="checkout-api", level="error"} 时间范围 14:25-14:35
   → 找到 500 错误日志,message: "Payment failed: bank API timeout"
   → 日志里有 trace_id: "4bf92f3577b34da6a3ce929d0e0e4736"

4. 追踪调用链(Traces)
   用 trace_id 在 Tempo 查询
   → Flame Graph 显示 processPayment → callBankAPI 耗时 3050ms
   → 银行 API 正常 SLA 是 200ms,这次超时

5. 根因确认
   跨服务查看 payment-svc 的日志(同时间段)
   → "bank API returned 429 Too Many Requests"
   → 促销活动导致下单量激增,触发了银行 API 限速

整个过程 Metrics → Logs → Traces 三次跳转,每次跳转都在缩小范围、深入细节。10 分钟定位根因,不需要猜测。

告警收敛与降噪#

告警是监控唯一会主动打扰人的部分,质量直接决定监控系统是被信任还是被无视。

告警疲劳#

告警一天响 200 条,清一色"CPU>80%",大家早就静音了——真出事那次反而没人看。这是最危险的状态。

四件套#

Alertmanager 的四个核心能力治"告警疲劳":

  1. 分组 grouping:一次发布挂了 50 个 pod,合并成一条通知而不是轰炸 50 条。
  2. 去重 dedup:多个 Prometheus 副本发的同一告警合并。
  3. 抑制 inhibition:整个集群挂了,别再报每个 pod 挂了。
  4. 路由 routing:按团队/严重级发到不同群。

症状告警 > 原因告警#

  • 症状型(✅):基于用户感受到的——错误率涨、延迟高、下单失败。不管根因,用户疼了就响。
  • 原因型(❌):基于内部某个量——CPU>80%、内存高。要么漏(没想到的根因)要么吵(CPU 高但用户没事,狼来了)。

SRE 铁律:会 page(呼叫值班人)的告警必须是症状型;原因型指标留着排障下钻用,不直接打扰人。

SLO 驱动的告警#

有了 SLO 才有客观标准回答"什么时候该告警":

  • 快速烧预算(1h 烧 2% 月预算)→ 紧急 page
  • 慢速烧→ 工单提醒

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

死人开关#

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

建设优先级#

从零开始建设可观测性,按什么顺序?

第一步:Metrics(最高 ROI)#

采集成本低、查询快、告警成熟。先把所有服务的基础指标接入:

  • HTTP 请求数(按状态码分组)
  • HTTP 请求延迟(Histogram,有 P50/P95/P99)
  • 错误率
  • 服务实例数/可用性
  • K8s 基础设施(CPU/内存/Pod 重启/OOM)

先有 Metrics,才能设 SLO,才有告警,才有 On-call 触发点。

第二步:结构化日志(中等 ROI)#

把日志改成 JSON 格式,统一包含 trace_id、service、level、timestamp。用 Middleware/Interceptor 统一注入,减少各服务的改造成本。

第三步:Traces(前提:服务间调用链复杂)#

Traces 的价值在于跨服务调用。单体应用价值不大;5 个以上服务互相调用才值得投入。从核心链路(用户下单/支付等)开始,不需要一次接入所有服务。

优先级总结#

text
单体应用:      Metrics > Logs > Traces(Traces 可能不需要)
微服务(<5个): Metrics > Logs > Traces(有用但不紧迫)
微服务(>5个): Metrics > Traces > Logs(Traces 比完整日志更有性价比)

小结#

可观测性的精华不是三支柱各自多强,而是它们能联动——Metrics 发现问题、Logs 理解细节、Traces 定位根因。联动的技术基础是统一 Labels(service/namespace/pod/trace_id 三处一致)+ Grafana Data Source Linking(一键互跳)。告警收敛靠 Alertmanager 四件套(分组/去重/抑制/路由),会 page 的告警必须是症状型。建设顺序先 Metrics(ROI 最高)→ 结构化日志(必带 trace_id)→ Traces(微服务 5+ 才紧迫)。检验整套架构的标准:能不能从一条告警一路下钻到代码行。