mcpField
T
tempo

tempo

github.com/julianobarbosa云与 DevOps15106 次安装4 天前更新
代码仓库

关于 tempo

tempo 是提供 Grafana Tempo 运维和查询指南的技能;Tempo 是面向 OpenTelemetry 的分布式追踪后端。内容涵盖部署、存储、TraceQL、多租户和故障排查,适合运行或管理 Tempo 的团队。

主要功能

  1. 01说明 Tempo 架构和部署模式
  2. 02提供基于 Helm 的部署指南
  3. 03介绍 S3、GCS 和 Azure 存储
  4. 04提供 TraceQL 查询示例
  5. 05记录接收协议和端点
  6. 06涵盖多租户与故障排查

适用场景

  1. 01规划 Tempo 部署模式
  2. 02配置追踪数据的对象存储
  3. 03使用 TraceQL 搜索追踪
  4. 04诊断数据摄取、查询或授权问题

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/julianobarbosa/claude-code-skills --skill tempo

安装后在 Claude Code 中输入/tempo确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
configuration.md
storage.md
traceql.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:statusok、error 或 unset
span:kindserver、client、producer、consumer、internal
trace:duration追踪总耗时
trace:rootName根 Span 名称
trace:rootService根 Span 服务
属性作用域(句点分隔)
作用域示例描述
span.span.http.methodSpan 级属性
resource.resource.service.name资源属性
event.event.exception.message事件属性
link.link.traceID链接属性

接收器端点

协议端口端点
OTLP gRPC4317/v1/traces
OTLP HTTP4318/v1/traces
Jaeger gRPC14250-
Jaeger Thrift HTTP14268/api/traces
Jaeger Thrift Compact6831UDP
Jaeger Thrift Binary6832UDP
Zipkin9411/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

参考文档

按主题查看详细配置:

外部资源


注意事项

  • 保留策略按租户配置;全局保留策略仅作回退——租户配置错误时会被静默覆盖。
  • 在 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