关于 tempo
tempo 是提供 Grafana Tempo 运维和查询指南的技能;Tempo 是面向 OpenTelemetry 的分布式追踪后端。内容涵盖部署、存储、TraceQL、多租户和故障排查,适合运行或管理 Tempo 的团队。
主要功能
- 01说明 Tempo 架构和部署模式
- 02提供基于 Helm 的部署指南
- 03介绍 S3、GCS 和 Azure 存储
- 04提供 TraceQL 查询示例
- 05记录接收协议和端点
- 06涵盖多租户与故障排查
适用场景
- 01规划 Tempo 部署模式
- 02配置追踪数据的对象存储
- 03使用 TraceQL 搜索追踪
- 04诊断数据摄取、查询或授权问题
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ julianobarbosa/ claude-code-skills --skill tempo安装后在 Claude Code 中输入/tempo确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/configuration.mdstorage.mdtraceql.md详细介绍
Grafana Tempo 技能
Grafana Tempo 综合指南——这是一款面向 OpenTelemetry、经济高效且可扩展至高规模的分布式追踪后端。
什么是 Tempo?
Tempo 是一个可扩展至高规模的分布式追踪后端,具有以下特点:
- 基于 Trace ID 的查询模型——不为每个属性建立索引,从而保持快速写入并降低存储成本
- 原生支持 OpenTelemetry——一流支持 OTLP 协议
- 基于对象存储——将追踪数据存储在经济实惠的 S3、GCS 或 Azure Blob Storage 中
- TraceQL 查询语言——受 PromQL 和 LogQL 启发的强大查询语言
- Apache Parquet 格式——与旧格式相比,每次查询拉取的数据量减少 5–10 倍
- 默认支持多租户——通过
X-Scope-OrgID标头内置租户隔离
架构概览
核心组件
| 组件 | 用途 |
|---|---|
| Distributor | 追踪数据的入口,通过一致性哈希环将数据路由到 Ingester |
| Ingester | 在内存中缓冲追踪数据,创建 Parquet 块,并将其刷新到存储中 |
| Query Frontend | 编排查询、对 blockID 空间进行分片,并协调 Querier |
| Querier | 使用布隆过滤器在 Ingester 或存储中定位追踪数据 |
| Compactor | 压缩块、去重数据并管理保留策略 |
| Metrics Generator | 可选:从追踪数据中派生指标 |
数据流
写入路径:
Applications → Collector → Distributor → Ingester → Object Storage
↓
Consistent Hash Ring
(routes by traceID)
读取路径:
Query Request → Query Frontend → Queriers → Ingesters (recent data)
↓ ↓
Block Sharding Object Storage (historical data)
↓ ↓
Parallel Querier Work Bloom Filters + Indexes
部署模式
1. 单体模式(-target=all)
- 所有组件在单个进程中运行
- 适用于:本地测试、小规模部署
- 无法水平扩展组件数量
- 通过增加副本进行扩展
2. 可扩展单体模式(-target=scalable-single-binary)
- 所有组件在一个进程中运行,并支持水平扩展
- 每个实例运行所有组件
- 适用于有扩展需求的开发环境
3. 微服务模式(分布式)——生产环境推荐
# Using tempo-distributed Helm chart
distributor:
replicas: 3
ingester:
replicas: 3
querier:
replicas: 2
queryFrontend:
replicas: 2
compactor:
replicas: 1
Helm 部署
添加仓库
helm repo add grafana https://grafana.github.io/helm-charts
helm repo update
安装分布式 Tempo
helm install tempo grafana/tempo-distributed \
--namespace monitoring \
--values values.yaml
生产环境配置示例
# Storage configuration
storage:
trace:
backend: azure # or s3, gcs
azure:
container_name: tempo-traces
storage_account_name: mystorageaccount
use_federated_token: true # Workload Identity
# Distributor
distributor:
replicas: 3
resources:
requests:
cpu: 500m
memory: 2Gi
limits:
memory: 4Gi
# Ingester
ingester:
replicas: 3
resources:
requests:
cpu: 1000m
memory: 2Gi
limits:
memory: 8Gi # Spikes to 8GB periodically
persistence:
enabled: true
size: 20Gi
# Querier
querier:
replicas: 2
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
memory: 4Gi
# Query Frontend
queryFrontend:
replicas: 2
resources:
requests:
cpu: 100m
memory: 100Mi
limits:
memory: 2Gi
# Compactor
compactor:
replicas: 1
resources:
requests:
cpu: 500m
memory: 2Gi
limits:
memory: 6Gi
# Block retention
compactor:
compaction:
block_retention: 336h # 14 days
# Gateway for external access
gateway:
enabled: true
replicas: 1
# Metrics Generator (optional)
metricsGenerator:
enabled: false
存储配置
Azure Blob Storage(Azure 推荐)
storage:
trace:
backend: azure
azure:
container_name: tempo-traces
storage_account_name: <storage-account-name>
# Option 1: Workload Identity (Recommended)
use_federated_token: true
# Option 2: User-Assigned Managed Identity
use_managed_identity: true
user_assigned_id: <identity-client-id>
# Option 3: Account Key (Dev only)
# storage_account_key: <account-key>
endpoint_suffix: blob.core.windows.net
hedge_requests_at: 400ms
hedge_requests_up_to: 2
AWS S3
storage:
trace:
backend: s3
s3:
bucket: my-tempo-bucket
region: us-east-1
endpoint: s3.us-east-1.amazonaws.com
# Use IAM roles or access keys
access_key: <access-key>
secret_key: <secret-key>
Google Cloud Storage
storage:
trace:
backend: gcs
gcs:
bucket_name: my-tempo-bucket
# Uses Workload Identity or service account
TraceQL 查询语言
基本查询
# Simplest query - all spans
{ }
# Filter by service
{ resource.service.name = "frontend" }
# Filter by operation
{ span:name = "GET /api/orders" }
# Filter by status
{ span:status = error }
# Filter by duration
{ span:duration > 500ms }
# Multiple conditions
{ resource.service.name = "api" && span:status = error }
结构运算符
# Direct parent-child relationship
{ resource.service.name = "frontend" } > { resource.service.name = "api" }
# Ancestor-descendant relationship
{ span:name = "GET /api/products" } >> { span.db.system = "postgresql" }
# Sibling relationship
{ span:name = "span-a" } ~ { span:name = "span-b" }
聚合函数
# Count spans
{ } | count() > 10
# Average duration
{ } | avg(span:duration) > 20ms
# Max duration
{ span:status = error } | max(span:duration)
指标函数
# Rate of errors
{ span:status = error } | rate()
# Count over time
{ span:name = "GET /:endpoint" } | count_over_time()
# Percentile latency
{ span:name = "GET /:endpoint" } | quantile_over_time(span:duration, .99)
# Group by service
{ span:status = error } | rate() by(resource.service.name)
# Top 10 by error rate
{ span:status = error } | rate() by(resource.service.name) | topk(10)
追踪结构
内置字段(冒号分隔)
| 字段 | 描述 |
|---|---|
span:name | 操作名称 |
span:duration | 耗时(例如,“10ms”、“1.5s”) |
span:status | ok、error 或 unset |
span:kind | server、client、producer、consumer、internal |
trace:duration | 追踪总耗时 |
trace:rootName | 根 Span 名称 |
trace:rootService | 根 Span 服务 |
属性作用域(句点分隔)
| 作用域 | 示例 | 描述 |
|---|---|---|
span. | span.http.method | Span 级属性 |
resource. | resource.service.name | 资源属性 |
event. | event.exception.message | 事件属性 |
link. | link.traceID | 链接属性 |
接收器端点
| 协议 | 端口 | 端点 |
|---|---|---|
| OTLP gRPC | 4317 | /v1/traces |
| OTLP HTTP | 4318 | /v1/traces |
| Jaeger gRPC | 14250 | - |
| Jaeger Thrift HTTP | 14268 | /api/traces |
| Jaeger Thrift Compact | 6831 | UDP |
| Jaeger Thrift Binary | 6832 | UDP |
| Zipkin | 9411 | /api/v2/spans |
多租户
# Enable multi-tenancy
multitenancy_enabled: true
# All requests must include X-Scope-OrgID header
# Example:
# curl -H "X-Scope-OrgID: tenant-1" http://tempo:3200/api/traces/<traceID>
Azure 身份配置
工作负载身份联合(推荐)
1. 在 AKS 上启用工作负载身份:
az aks update \
--name <aks-cluster> \
--resource-group <rg> \
--enable-oidc-issuer \
--enable-workload-identity
2. 创建用户分配的托管身份:
az identity create \
--name tempo-identity \
--resource-group <rg>
IDENTITY_CLIENT_ID=$(az identity show --name tempo-identity --resource-group <rg> --query clientId -o tsv)
3. 分配存储权限:
az role assignment create \
--role "Storage Blob Data Contributor" \
--assignee-object-id <principal-id> \
--scope /subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.Storage/storageAccounts/<storage>
4. 创建联合凭据:
az identity federated-credential create \
--name tempo-federated \
--identity-name tempo-identity \
--resource-group <rg> \
--issuer <aks-oidc-issuer-url> \
--subject system:serviceaccount:monitoring:tempo \
--audiences api://AzureADTokenExchange
5. 配置 Helm 值:
serviceAccount:
annotations:
azure.workload.identity/client-id: <IDENTITY_CLIENT_ID>
podLabels:
azure.workload.identity/use: "true"
storage:
trace:
azure:
use_federated_token: true
故障排除
常见问题
1. 找不到容器(Azure)
az storage container create --name tempo-traces --account-name <storage>
2. 授权失败(Azure)
# Verify RBAC assignment
az role assignment list --scope <storage-scope>
# Assign if missing
az role assignment create \
--role "Storage Blob Data Contributor" \
--assignee-object-id <principal-id> \
--scope <storage-scope>
3. 摄取器内存不足
ingester:
resources:
limits:
memory: 16Gi # Increase from 8Gi
4. 查询超时
querier:
query_timeout: 5m
max_concurrent_queries: 20
诊断命令
# Check pod status
kubectl get pods -n monitoring -l app.kubernetes.io/name=tempo
# Check distributor logs
kubectl logs -n monitoring -l app.kubernetes.io/component=distributor --tail=100
# Check ingester logs
kubectl logs -n monitoring -l app.kubernetes.io/component=ingester --tail=100
# Verify readiness
kubectl exec -it <tempo-pod> -n monitoring -- wget -qO- http://localhost:3200/ready
# Check ring status
kubectl port-forward svc/tempo-distributor 3200:3200 -n monitoring
curl http://localhost:3200/distributor/ring
API 参考
轨迹检索
# Get trace by ID
GET /api/traces/<traceID>
# Search traces (TraceQL)
GET /api/search?q={resource.service.name="api"}
# Search tags
GET /api/search/tags
GET /api/search/tag/<tag>/values
健康状态
GET /ready
GET /metrics
参考文档
按主题查看详细配置:
- 存储配置:对象存储、保留策略、缓存
- TraceQL 参考:查询语法和示例
- 配置参考:完整配置清单
外部资源
注意事项
- 保留策略按租户配置;全局保留策略仅作回退——租户配置错误时会被静默覆盖。
- 在 OTel collector 管道末端进行尾部采样,不会从 inflight 缓冲区中释放轨迹——负载较高时,collector 会因即将丢弃的轨迹而内存溢出。
- TraceQL
{}表达式是筛选表达式,而非查询字符串——其语义与 PromQL/LogQL 不同,复制粘贴查询模式会导致不易察觉的问题。 - 通过 X-Scope-OrgID 实现多租户:缺少或无效的标头会落入“fake”租户,与 Loki/Mimir 相同。
- Span 大小上限(默认 1 MB):超过上限的 Span 会在属性中途被静默截断——可检查摄取器指标中的
discarded_spans_total进行排查。 - 按 service.name 与 resource.service.name 搜索:取决于 OTel SDK 将该属性放在 Span 上还是资源上——两者看起来相似,但索引方式不同。
评论
支持 Markdown