Grafana Tempo 工具手册
Tempo 3.0 先拆开近期与历史
Grafana Tempo 把长期 Trace 保存为对象存储中的 Parquet 块,TraceQL 再按 trace ID、属性和结构查询这些数据。Tempo 3.0 重做了写入架构:微服务模式由 Distributor 写入 Kafka 兼容缓冲,live-store 服务近期查询,block-builder 构建长期块,backend scheduler/worker 负责压实与保留。它不再使用 2.x ingester 和 compactor 作为主路径。
官方 Tempo 3.0 release notes 和迁移指南明确说明这不是无感升级。本文固定 3.0.2 为实验基线,不能拿 2.x 配置字段拼接成 3.0 生产配置。
单体模式也要证明对象块存在
Tempo 没有独立查询 UI,通常由 Grafana 访问其 HTTP API。先执行 TRACE_LAB_DIR=$(mktemp -d),再创建 $TRACE_LAB_DIR/tempo.yaml;本地 backend 只适用于开发验证:
target: all
stream_over_http_enabled: true
server:
http_listen_port: 3200
distributor:
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
zipkin:
endpoint: 0.0.0.0:9411
storage:
trace:
backend: local
wal:
path: /var/tempo/wal
local:
path: /var/tempo/blocks
live_store:
flush_check_period: 1s
max_trace_idle: 2s
max_trace_live: 5s
compaction:
block_retention: 24h短时间参数只为让实验快速成块,不是生产容量建议。准备一条 Zipkin v2 兼容 Span,并启动命名卷:
TRACE_ID=463ac35c9f6413ad48485a3953bb6124
SPAN_ID=a2fb4a1d1a96d312
NOW_US=$(($(date +%s) * 1000000))
cat > "$TRACE_LAB_DIR/span.json" <<JSON
[{"traceId":"$TRACE_ID","id":"$SPAN_ID","kind":"SERVER","name":"POST /checkout","timestamp":$NOW_US,"duration":820000,"localEndpoint":{"serviceName":"checkout-api"},"tags":{"deployment.environment":"trace-lab"}}]
JSON
docker volume create tempo-lab-data
docker run -d --name tempo-lab \
-p 127.0.0.1:3200:3200 \
-p 127.0.0.1:14317:4317 \
-p 127.0.0.1:14318:4318 \
-p 127.0.0.1:19411:9411 \
-v "$TRACE_LAB_DIR/tempo.yaml:/etc/tempo.yaml:ro" \
-v tempo-lab-data:/var/tempo \
grafana/tempo:3.0.2 -config.file=/etc/tempo.yaml
curl -fsS http://localhost:3200/ready
curl -fsS -X POST http://localhost:19411/api/v2/spans \
-H 'Content-Type: application/json' --data-binary @"$TRACE_LAB_DIR/span.json"
curl -fsS "http://localhost:3200/api/traces/$TRACE_ID"ready 只证明进程可服务,第一次按 ID 取回可能命中 live-store 或 WAL。长期持久化要看到 flush 计数增长、完成队列归零、对象目录出现 meta.json 和 data.parquet,重启后还要能查询同一 trace ID。
curl -fsS -X POST http://localhost:3200/flush >/dev/null
docker exec tempo-lab sh -ec '
find /var/tempo/blocks -type f -name meta.json -print -quit | grep -q .
find /var/tempo/blocks -type f -name data.parquet -print -quit | grep -q .
'
docker restart tempo-lab
until curl -fsS http://localhost:3200/ready >/dev/null; do sleep 1; done
curl -fsS "http://localhost:3200/api/traces/$TRACE_ID"近期可查但重启后丢失时,检查 /var/tempo/blocks 是否实际挂载、failed flush 指标、目录权限和生效配置路径。单机本地盘不适用于分布式模式,因为不同组件看不到同一历史块。
TraceQL 不是零成本扫描
对象块按 tenant 和 block 分隔,块中包含元数据、Parquet 数据与用于缩小候选范围的结构。按 trace ID 可以利用块元数据和过滤结构,任意属性搜索仍可能读取大量 Parquet 页。高频属性可配置 dedicated columns,但列数、基数和查询模式都要从真实负载测量。
每日写入字节 ≈ 请求数 × 采样率 × 每 Trace Span 数 × 平均 Span 字节
长期存储 ≈ 每日写入字节 × 保留天数 × 压实系数
查询成本 ≈ 候选块数 × 每块读取字节 + 对象请求与出网超大 Trace、长字符串属性、TraceQL metrics、Kafka 保留、block-builder scratch disk 和跨区对象访问都要单独预算。对象存储便宜不等于查询免费;宽时间窗和高并发会把 GET、LIST、CPU 与出网成本集中放大。
Tempo 3.0 微服务写路径使用 durable buffer 解耦接收和成块,live-store 与 block-builder 消费各自数据。查询端必须同时看近期和历史;Kafka lag 覆盖查询时间范围时,默认可选择失败而不是返回静默不完整结果。这个取舍应进入 SLO 和告警,而不是被 UI 空白掩盖。
X-Scope-OrgID 不是认证
启用多租户后,写入和查询携带 X-Scope-OrgID,对象也按 tenant 隔离。但客户端可以自行伪造 header,Tempo 不验证调用者身份。生产入口必须由可信网关认证用户或工作负载,丢弃外部传入值,再注入授权后的租户头。
curl -i "http://localhost:3200/api/traces/$TRACE_ID"
curl -i -H 'X-Scope-OrgID: team-b' "http://localhost:3200/api/traces/$TRACE_ID"缺头应被拒绝,错误 tenant 应查不到其他租户数据。Collector 的写身份、Grafana 数据源的读身份、对象存储读写身份和删除权限要分开。租户 overrides 能限制写入速率、Trace 大小、查询并发与保留,但修改时要确认未显式字段不会意外回到零值。
从空查询判断故障层
所有查询都空时,先查应用采样、Collector accepted/refused、exporter send_failed 与 Distributor 拒绝。按 ID 可查而 TraceQL 属性查询为空时,检查属性 scope、时间范围、dedicated columns 与查询限制。近期可查、历史为空时,检查 block-builder lag、对象存储权限、blocklist、backend jobs 和新块格式。
零散根 Span 多半来自 W3C/B3 上下文传播或异步线程,不属于 Tempo 存储问题。Span 中的令牌、Cookie、SQL 参数、完整正文与个人信息应在 SDK 或 Collector 侧删除;对象存储持久化后再治理成本更高。
3.0 迁移不能原地降级
单体部署可以迁移配置后升级,微服务部署应并行运行 2.x 与 3.0,逐步切写入和查询。3.0 移除了 ingester、compactor 及多项旧字段,旧告警和 dashboard 也要同步调整。对象块格式、Kafka offset 和查询完整性验证通过前,不得销毁旧组件。
新旧后端短期双写会增加 Collector 队列、出口带宽和存储费用。比较接收数、完整 Trace 比例、近期与历史查询、错误租户隔离和单位成本后再扩大。回滚是把流量切回仍在运行的 2.x,不是把 3.0 数据卷或对象桶删除。
docker rm -f tempo-lab
docker volume rm tempo-lab-data
if [ -n "${TRACE_LAB_DIR:-}" ] && [ -d "$TRACE_LAB_DIR" ]; then
rm -rf -- "$TRACE_LAB_DIR"
fi清理只属于唯一命名的本地实验。生产 Tempo 的最低证据包括近期查询、对象块落盘、重启历史查询、Kafka lag、backend job、错误租户隔离和保留执行;缺少其中任何一项,都不能仅凭 Grafana 里出现一条 Trace 判断系统已经可靠。
