Prometheus / Grafana / Loki / Tempo / OpenTelemetry 可观测栈实战
0. 元信息
- 主题路径:
docs/topics/observability-and-sre/subtopics/prometheus-grafana-otel-stack/README.md - 父主题:
observability-and-sre - 主分类:工程技术
- 辅助分类:计算机基础
- 适合对象:会用 Docker / Linux、能写 Python 或 Go 后端服务的开发者
- 建议周期:1~2 周(每周 8~10 小时,重点是 PromQL 与告警规则)
- 前置知识:
observability-and-sre父主题;metrics-logs-traces;Linux / Docker - 最终目标:能独立搭起 Prometheus + Grafana + Loki + Tempo + OTel Collector + Alertmanager 的完整可观测栈,写 5 条 PromQL、5 条告警规则、5 个 Grafana 面板,并用 traceid 在 Grafana 中三向跳转
1. 学习路线
Prometheus 数据模型(metric + label + sample)
→ PromQL(rate / histogram_quantile / sum by / 聚合)
→ Recording Rule 与 Alert Rule
→ Alertmanager 路由 / 抑制 / 静音
→ Grafana 仪表盘(panels + variables + templating)
→ Loki 日志标签与 LogQL
→ Tempo Trace 后端与 TraceQL
→ 三向跳转(指标 / 日志 / Trace)
→ 远端存储(Mimir / Thanos / Cortex)
2. 阶段周数分配(45 周,每天 1.52 小时)
精简子主题按”Prometheus → Grafana → 日志/Trace → 远端存储”四段推进。
| 阶段 | 主题 | 周数 | 备注 |
|---|---|---|---|
| 1 | Prometheus 数据模型与 PromQL | 1 周 | rate / histogram_quantile |
| 2 | Recording / Alert Rule | 0.5 周 | 告警与预聚合 |
| 3 | Alertmanager 路由 | 0.5 周 | 抑制 / 静音 / 分组 |
| 4 | Grafana 仪表盘 | 1 周 | panels / variables / templating |
| 5 | Loki 与 Tempo | 0.5 周 | LogQL / TraceQL |
| 6 | 远端存储 | 1 周 | Mimir / Thanos / Cortex |
| 7 | 综合项目(全栈 dashboard) | 1 周 | 含 README + 复盘 |
选 4 周方案时把第 4/5 阶段压成 1 周。每周留 0.5 天复盘。
3. 九阶段表
| 阶段 | 核心知识 | 实践产出 | 可观察学会标准 |
|---|---|---|---|
| 1 | Prometheus 数据模型 | 一个 Python / Go exporter | 暴露 RED 指标 |
| 2 | PromQL 基础 | 5 条 PromQL | 算 P99 / 错误率 |
| 3 | Recording Rule | 1 条 Recording Rule | 加速聚合 |
| 4 | Alert Rule | 5 条告警规则 | 覆盖 Sev 1/2/3 |
| 5 | Alertmanager | 路由 / 抑制 / 静音 | 告警不雪崩 |
| 6 | Grafana 仪表盘 | 5 个面板 + 变量 | RED + USE + SLO |
| 7 | Loki + LogQL | 日志标签 + 查询 | traceid 反查日志 |
| 8 | Tempo + TraceQL | Trace 检索 + 跳转 | traceid 反查指标 |
| 9 | 远端存储(Mimir / Thanos) | Remote Write 配置 | 长期保留 |
关键陷阱:高基数 label 撑爆 TSDB;告警阈值随手设;不调优 Alertmanager;Loki 标签过多;Trace 全采样。
4. 第一周任务
| 日 | 任务 | 当天交付 |
|---|---|---|
| Day 1 | 起 Prometheus + Grafana + Alertmanager Compose | 一份 Compose |
| Day 2 | 写 5 条 PromQL(rate / histogram_quantile / sum by) | 一份 PromQL 集 |
| Day 3 | 写 5 条 Alert Rule | 一份告警规则 |
| Day 4 | 配置 Alertmanager 路由 + 抑制 | Alertmanager 配置 |
| Day 5 | 装 Loki + Tempo + OTel Collector | 三件套 Compose |
| Day 6 | 用 Grafana 配置 Loki / Tempo 数据源,做三向跳转 | 看板 JSON |
| Day 7 | 步骤 A:跑通「完整可观测栈」(指标 + 日志 + Trace + 告警 + 仪表盘);步骤 B:补齐 4 类边界(Prometheus 重启 / OTel Collector 重启 / Loki 标签过多 / Tempo 索引丢失) | 完整栈 + 故障记录 |
5. 阶段通用验收
- 不看答案独立写出 5 条 PromQL 与 5 条告警规则;
- 用自己的话解释 Recording Rule 与 Alert Rule 区别;
- 画一张图:服务 → Prometheus / Loki / Tempo → Grafana;
- 测试正常路径、抓取失败、告警噪声、标签过多;
- 至少准备 3 组自定义指标 / 日志 / Trace;
- 记录 P99、错误率、SLO 命中率、burn rate;
- 能修改既有服务加 exporter / 加告警。
6. 最终验收
- 独立画出完整可观测栈架构图;
- 完成至少 8 个实验;
- 写 5 条 PromQL + 5 条告警规则;
- 用 traceid 在 Grafana 反查日志与指标。
7. 综合项目
为微服务 Demo 搭完整可观测栈:Prometheus + Grafana + Loki + Tempo + OTel Collector + Alertmanager,写告警规则与仪表盘。成果合入父主题首选综合项目。
本主题贡献
Prometheus + Grafana + Loki + Tempo + OTel Collector + Alertmanager 是云原生可观测的事实栈,关键在 PromQL 调优与三向跳转。本子主题负责讲清 Recording Rule 与 Alert Rule 区别、Loki 标签与高基数代价、Tempo TraceQL 与 traceid 关联、Mimir / Thanos 远端存储取舍,并把 PromQL 5 条 + 告警 5 条 + 仪表盘 5 个面板作为最小交付物。
3 职责
- 用 5 条 PromQL(RPS / 错误率 / P99 / burn rate / 饱和度)覆盖 RED + USE,写 Recording Rule 预聚合 + Alert Rule 5 条告警。
- 用 Grafana 配 Prometheus / Loki / Tempo 三数据源,配置 tracesToLogsV2 + tracesToMetrics 做三向跳转。
- 用 Loki LogQL(label 低基数)与 Tempo TraceQL(trace_id 关联)做日志 + Trace 反查,metrics 走 Mimir Remote Write 长期存储。
4 交付物
- 一份 Compose 全栈(Prometheus + Grafana + Loki + Tempo + Alertmanager + OTel Collector),端口与卷挂载清单一清二楚,含 retention 与 remote_write 配置。
- 一份 Recording Rule + Alert Rule 集合(5 条 PromQL + 5 条 alert),含 SLO burn rate 多窗口与
histogram_quantileP99 SLI。 - 一份 Grafana 仪表盘 JSON(RED + USE + SLO + 三向跳转),变量
$service/$trace_id模板化,含 tracesToLogsV2 + tracesToMetrics 配置。 - 一份 Mimir / Thanos 远端存储对比与 Remote Write 配置,含 cardinality budget 控制与 multi-tenancy 说明。
3 指标
- PromQL 高频查询命中率 ≥ 90%(Recording Rule 命中数 / 总查询数)。
- TSDB 高基数 label 增长 < 100 / 序列(label cardinality budget 控制)。
- Grafana 三向跳转 traceid 命中率 100%(任意 traceid 都能跳到对应 metric / log)。
Prometheus Documentation、Grafana Documentation、Loki Documentation、Tempo Documentation、Alertmanager Documentation。复制前核对 LICENSE。
8. 推荐资料
Prometheus Documentation、Grafana Documentation、Loki Documentation、Tempo Documentation、Alertmanager Documentation。复制前核对 LICENSE。
9. 学习资料汇聚(v0.3 自包含)
9.1 背景与动机
Prometheus 2014 年借鉴 Google Borgmon 思路发布,把 pull-based 时序数据库、PromQL、多维标签写成事实标准。Grafana 2014 年开源做可视化,2019 年起把 Loki(日志)与 Tempo(Trace)纳入 Grafana Stack。Mimir / Thanos / Cortex 解决 Prometheus 长期存储与水平扩展问题。今天主流云原生可观测栈以 Grafana Stack 为中心。
9.2 概念地图
flowchart LR
App[服务] --> Exporter[prometheus_client / OTel SDK]
Exporter --> Prom[Prometheus scrape]
Prom --> PromDB[(Prometheus TSDB)]
Prom --> RemoteWrite[Remote Write]
RemoteWrite --> Mimir[(Mimir)]
App --> OTel[OTel Collector]
OTel --> Loki[(Loki)]
OTel --> Tempo[(Tempo)]
PromDB --> Grafana
Loki --> Grafana
Tempo --> Grafana
Mimir --> Grafana
Prom --> Alert[Alertmanager]
Alert --> Pager[PagerDuty / Slack]
9.3 基础知识讲解
9.3.1 论文 / 规范
| 资料 | 用法 |
|---|---|
| Prometheus Query Specification | PromQL |
| OpenMetrics | Expose 格式 |
| Alertmanager Spec | 路由 / 抑制 / 静音 |
| TraceQL | Tempo 查询语言 |
9.3.2 书
| 书 | 用法 |
|---|---|
| Brian Brazil, Prometheus: Up & Running | 入门 |
| Brendan Gregg, Systems Performance | 第 6 章 |
9.3.3 博客 / 文档
| 资料 | 用法 |
|---|---|
| Prometheus Blog | PromQL 实战 |
| Grafana Blog | Loki / Tempo 案例 |
| Robust Perception | PromQL 进阶 |
9.3.4 人物
| 人物 | 关注点 |
|---|---|
| Björn Rabenstein | Prometheus 核心 |
| Frederic Branczyk | Prometheus / OpenMetrics |
| Bryan Boreham | Grafana Pyroscope / Faro |
| Julius Volz | Prometheus 创始 |
9.3.5 方法
- Label cardinality budget:每个 label 基数预算 < 100;
- Recording for hot queries:高频查询走 Recording Rule;
- Tenant-aware remote write:多租户用 Mimir;
- Dashboards as code:用 Grafonnet / jsonnet。
9.3.6 重点训练材料
- Prometheus 官方文档
- Grafana 官方文档
- Robust Perception 博客
- Alertmanager 配置模板
9.4 经典问题与经典案例
| # | 问题 | 最简答案 |
|---|---|---|
| 1 | histogram_quantile 怎么用 | histogram_quantile(0.99, sum by (le) (rate(http_request_duration_seconds_bucket[5m]))) |
| 2 | Recording Rule vs Alert Rule | Recording 物化查询;Alert 触发告警 |
| 3 | Alertmanager 抑制怎么配 | inhibit_rules 用 source / target matchers |
| 4 | Loki 标签怎么设计 | 低基数(service / level);高基数走 Trace |
| 5 | Tempo 索引怎么省 | 用 TraceQL + trace_id 关联 |
| 6 | Mimir vs Thanos | Mimir 兼容 PromQL;Thanos 兼容 Prometheus |
| 7 | 三向跳转怎么做 | 用 traceID 变量 + Loki / Tempo 数据源 |
| 8 | 告警噪声怎么治理 | 路由 + 抑制 + 静音 |
| 9 | PromQL 怎么调优 | 看 Recording Rule 与 cardinality |
| 10 | 仪表盘怎么做 | 用面板模板 + 变量 |
9.5 学习难点
| 难点 | 为什么会卡 | 突破路径 |
|---|---|---|
| PromQL 聚合函数 | rate / sum by / histogram_quantile 选错 | 看 Robust Perception 博客 |
| 高基数 label | TSDB 索引膨胀 | 用 cardinality budget |
| Alertmanager 路由 | 路由树混乱 | 用抑制规则 + 优先级 |
| Grafana 变量 | 模板写错 | 用 ${var} 语法 |
9.6 技术标准与接口
9.6.1 Entity
| 名称 | 版本 | 组织 | 状态 |
|---|---|---|---|
| Prometheus | 2.x | 社区 | 活跃 |
| Grafana | 10.x | Grafana Labs | 活跃 |
| Loki | 2.x | Grafana Labs | 活跃 |
| Tempo | 2.x | Grafana Labs | 活跃 |
| Mimir | 2.x | Grafana Labs | 活跃 |
| Alertmanager | 0.27+ | Prometheus | 活跃 |
9.6.2 Scope
Prometheus 抓取指标;Grafana 可视化;Loki 存日志;Tempo 存 Trace;Alertmanager 路由告警;Mimir 长期存储。
9.6.3 Structure
PromQL:{__name__="metric", label="value"};Recording Rule:物化查询;Alert Rule:expr + for + labels + annotations;Grafana:panels + variables + templating。
9.6.4 Ecosystem
监控:Prometheus / Datadog;日志:Loki / ELK;Trace:Tempo / Jaeger;告警:Alertmanager / PagerDuty。
9.6.5 Depth Tiers
| 层级 | 能力 |
|---|---|
| L0 | 知道 Prometheus / Grafana |
| L1 | 能读懂 PromQL |
| L2 | 能装完整栈 + 写告警 |
| L3 | 能调优 + 多租户 |
| L4 | 能设计可观测平台 |
本子主题目标:L3。
9.6.6 Source
- Prometheus Documentation
- Grafana Documentation
- Loki Documentation
- Tempo Documentation
- 引用版本快照日期:2026-07-30。
10. 常见误区
- 高基数 label 撑爆 TSDB;
- 告警阈值随手设;
- 不调优 Alertmanager;
- Loki 标签过多;
- Trace 全采样;
- 仪表盘没有变量;
- 不监控 Collector / Prometheus 自身;
- Recording Rule 与 Alert Rule 混用;
- 仪表盘不导出 JSON;
- 不做三向跳转。
11. 所有知识点分类(统一规则)
- 编程语言;2. 数据结构与算法;3. 计算机基础;4. 工程技术;5. Web 与后端;6. 前端与客户端;7. 数据与人工智能;8. 项目与职业能力;9. 安全与可靠性。
本计划归属:工程技术 主 + 安全与可靠性 辅。
代码块 1:5 条核心 PromQL
# 1. 服务请求率(RPS)
sum by (service) (rate(http_requests_total[5m]))
# 2. 错误率
sum by (service) (rate(http_requests_total{status=~"5.."}[5m]))
/
sum by (service) (rate(http_requests_total[5m]))
# 3. P99 延迟
histogram_quantile(0.99,
sum by (le, service) (rate(http_request_duration_seconds_bucket[5m]))
)
# 4. SLO 预算燃烧率(多窗口)
(
sum(rate(http_requests_total{status=~"5.."}[1h]))
/
sum(rate(http_requests_total[1h]))
) > (14.4 * 0.001)
# 5. 活跃连接饱和度
node_netstat_Tcp_CurrEstab / node_netstat_Tcp_MaxConn
代码块 2:Recording Rule
# rules/recording.yml
groups:
- name: api.recording
interval: 30s
rules:
- record: api:request_rate:5m
expr: sum by (service) (rate(http_requests_total[5m]))
- record: api:error_rate:5m
expr: |
sum by (service) (rate(http_requests_total{status=~"5.."}[5m]))
/
sum by (service) (rate(http_requests_total[5m]))
- record: api:p99_latency:5m
expr: |
histogram_quantile(0.99,
sum by (le, service) (rate(http_request_duration_seconds_bucket[5m]))
)
代码块 3:Grafana Loki / Tempo 数据源 + Trace 跳转
# grafana datasources
apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
url: http://prometheus:9090
- name: Loki
type: loki
url: http://loki:3100
- name: Tempo
type: tempo
url: http://tempo:3200
jsonData:
httpMethod: GET
tracesToLogsV2:
datasourceUid: loki
tags: ['job', 'service']
mapTagNamesEnabled: true
tracesToMetrics:
datasourceUid: prometheus
tags: [{ name: 'service.name', value: 'service' }]
代码块 4:Compose 完整可观测栈
# compose.yaml
services:
prometheus:
image: prom/prometheus:v3.6.1
volumes: [./prometheus.yml:/etc/prometheus/prometheus.yml:ro]
ports: ["9090:9090"]
alertmanager:
image: prom/alertmanager:v0.28.0
ports: ["9093:9093"]
grafana:
image: grafana/grafana:12.1.0
environment:
GF_INSTALL_PLUGINS: grafana-clock-panel,grafana-piechart-panel
ports: ["3000:3000"]
loki:
image: grafana/loki:3.5.0
ports: ["3100:3100"]
tempo:
image: grafana/tempo:2.6.0
ports: ["3200:3200"]
otel-collector:
image: otel/opentelemetry-collector-contrib:0.116.0
volumes: [./otel-collector-config.yaml:/etc/otelcol-contrib/config.yaml:ro]
ports: ["4317:4317", "4318:4318"]