Перейти к основному содержимому

7.04. Справочник по Tempo

Разработчику Архитектору Инженеру

Справочник по Tempo

Grafana Tempo — это масштабируемая, экономически эффективная система распределённого трассирования с открытым исходным кодом, разработанная Grafana Labs. Она предназначена для хранения, поиска и анализа трассировок в микросервисных архитектурах. Tempo не индексирует все атрибуты спанов, а вместо этого использует внешние сигналы (логи и метрики) для поиска идентификаторов трассировок, что снижает стоимость хранения и упрощает эксплуатацию.

Tempo тесно интегрируется с экосистемой Grafana: пользователи могут переходить от графиков в Prometheus или логов в Loki к конкретным трассировкам в Tempo без переключения между инструментами. Архитектура Tempo основана на компонентах, которые можно развернуть как единый бинарник (monolithic mode) или как распределённую систему (microservices mode).

Архитектурные компоненты Tempo

Distributor

Принимает входящие трассировки от клиентов (например, OpenTelemetry Collector), проверяет их корректность и перенаправляет в Ingester. Поддерживает несколько протоколов приёма данных:

  • OTLP/gRPC
  • OTLP/HTTP
  • Jaeger Thrift (UDP и HTTP)
  • Zipkin

Конфигурация получателей указывается в блоке distributor.receivers.

Ingester

Буферизует входящие спаны в памяти, группирует их по трассировкам и записывает в хранилище (обычно объектное хранилище, например S3, GCS или MinIO). Ingester управляет жизненным циклом блоков трассировок и отвечает за их фиксацию (flushing).

Querier

Обрабатывает запросы на поиск трассировок по trace ID. Он запрашивает данные из объектного хранилища и из памяти активных Ingester'ов, объединяя результаты.

Query-Frontend

Оптимизирует и параллелизует запросы к Querier'у. Поддерживает кэширование и разбиение временных диапазонов на подзапросы.

Compactor

Выполняет фоновую компактификацию блоков трассировок: объединяет мелкие блоки в более крупные, удаляет дубликаты и применяет политики хранения (retention). Это снижает нагрузку на хранилище и ускоряет поиск.

Ingester-querier (в monolithic-режиме)

В режиме одного процесса функции Ingester и Querier объединены.


Конфигурационный файл (tempo.yaml)

Основной конфигурационный файл Tempo структурирован по модулям. Ниже приведены ключевые секции и параметры.

server

Настройки HTTP/gRPC сервера Tempo.

  • http_listen_port: порт для HTTP-эндпоинтов (по умолчанию 3200).
  • grpc_listen_port: порт для gRPC-эндпоинтов (по умолчанию 9095).
  • log_level: уровень логирования (debug, info, warn, error).

distributor

Управляет приёмом трассировок.

  • receivers: список поддерживаемых протоколов. Пример:
    receivers:
    otlp:
    protocols:
    grpc:
    endpoint: "0.0.0.0:4317"
    http:
    endpoint: "0.0.0.0:4318"
  • max_recv_msg_size: максимальный размер входящего сообщения (в байтах).
  • tenants: конфигурация мультитенантности (если используется).

ingester

Параметры буферизации и записи.

  • max_block_duration: максимальная длительность временного блока перед фиксацией (например, 30m).
  • flush_check_period: интервал проверки необходимости фиксации блоков (например, 1m).
  • complete_block_timeout: время ожидания завершения блока перед принудительной фиксацией.

storage

Определяет тип и параметры хранилища.

  • trace: секция для хранения трассировок.
    • backend: тип хранилища (local, s3, gcs, azure, swift).
    • Для s3:
      s3:
      bucket: "my-tempo-traces"
      endpoint: "s3.amazonaws.com"
      access_key: "..."
      secret_key: "..."
      insecure: false
    • Для local:
      local:
      path: "/tmp/tempo/blocks"

compactor

  • compaction: включить/выключить компактификацию (true/false).
  • block_retention: срок хранения блоков (например, 48h).
  • compaction_cycle: интервал выполнения компактификации (например, 1h).

querier

  • frontend_worker: настройки взаимодействия с Query-Frontend.
  • search_enabled: разрешить поиск по атрибутам (требует дополнительного индекса; по умолчанию false).

query_frontend

  • search: параметры поискового API.
  • cache: конфигурация кэша (Redis, Memcached и др.).

Режимы развёртывания

Monolithic

Все компоненты работают в одном процессе. Подходит для тестирования и небольших сред.

  • Запуск: tempo -config.file=tempo.yaml
  • Минимальная конфигурация содержит только server, distributor, ingester, storage.

Microservices

Каждый компонент работает как отдельный сервис. Используется в production.

  • Требует оркестрации (Kubernetes, Docker Compose).
  • Позволяет масштабировать компоненты независимо.

Форматы трассировок и совместимость

Tempo принимает трассировки в следующих форматах:

  • OpenTelemetry (OTLP) — рекомендуемый стандарт.
  • Jaeger — через Thrift (UDP/HTTP) или gRPC.
  • Zipkin — через HTTP.

Каждая трассировка состоит из одного или нескольких спанов. Спан содержит:

  • trace_id — глобальный идентификатор трассировки.
  • span_id — уникальный идентификатор спана.
  • parent_span_id — ссылка на родительский спан.
  • name — имя операции.
  • start_time и end_time — временные метки.
  • attributes — произвольные пары ключ-значение (например, http.method, db.statement).
  • events — временные события внутри спана (например, исключения).
  • status — результат операции (OK, ERROR).

Поиск трассировок

Tempo поддерживает два основных способа поиска:

По trace ID

Прямой поиск по известному идентификатору. Это самый быстрый и ресурсоэффективный способ.

Требует настройки querier.search_enabled: true и наличия индекса (например, через Elasticsearch или Tempo Search backend). Включает поиск по таким полям, как:

  • service.name
  • operation
  • duration
  • произвольные теги (http.status_code, user.id и т.д.)

Мониторинг и наблюдаемость самого Tempo

Tempo экспортирует метрики Prometheus, логи и внутренние трассировки [[1]]. В репозитории Tempo доступен mixin, содержащий:

  • Готовые дашборды Grafana.
  • Правила алертинга.
  • Рекомендации по мониторингу.

Ключевые метрики:

  • tempo_ingester_flush_queue_length — длина очереди фиксации.
  • tempo_querier_query_duration_seconds — время выполнения запросов.
  • tempo_distributor_received_spans_total — общее количество принятых спанов.

Ограничения и лучшие практики

  • Не добавляйте избыточные атрибуты в спаны — это увеличивает объём данных и стоимость хранения.
  • Используйте объектное хранилище для production-развёртываний.
  • Настройте retention policy через compactor.block_retention.
  • Избегайте частых flush-операций — они создают множество мелких блоков.
  • При использовании Kubernetes применяйте Helm-чарты (например, от Bitnami) для упрощения развёртывания.

Командная строка Tempo

Tempo может запускаться с помощью CLI-команд. Основные флаги:

  • -config.file <path> — путь к YAML-конфигурации.
  • -target <component> — запуск конкретного компонента (например, distributor, ingester, querier). Используется в микросервисном режиме.
  • -mem-ballast-size-mbs <int> — размер «балласта» памяти для стабилизации сборщика мусора Go.
  • -log.level <level> — уровень логирования (debug, info, warn, error).
  • -server.http-listen-port <port> — HTTP-порт сервера.
  • -server.grpc-listen-port <port> — gRPC-порт сервера.

Пример запуска monolithic-режима:

tempo -config.file=/etc/tempo.yaml

Пример запуска только Ingester’а:

tempo -target=ingester -config.file=/etc/tempo.yaml

Helm-чарт и Kubernetes-параметры

Tempo официально поддерживается через Helm-чарт от Grafana Labs. Ключевые настройки в values.yaml:

Общие параметры

  • fullnameOverride: переопределение имени релиза.
  • image.repository, image.tag: образ и тег контейнера.
  • replicas: количество реплик (для компонентов, поддерживающих масштабирование).

Компоненты

Каждый компонент имеет свой блок:

distributor:
replicas: 2
resources:
requests:
memory: "512Mi"
cpu: "200m"
ingester:
replicas: 3
persistence:
enabled: true
size: "10Gi"
querier:
replicas: 2
compactor:
enabled: true
resources:
requests:
memory: "1Gi"

Хранилище

  • storage.type: s3, gcs, azure, filesystem.
  • Для S3:
    storage:
    s3:
    bucket: "my-tempo-traces"
    endpoint: "s3.us-east-1.amazonaws.com"
    access_key: "..."
    secret_key: "..."

Ингрессы и сервисы

  • ingress.enabled: включить Ingress.
  • service.type: тип сервиса (ClusterIP, LoadBalancer, NodePort).

Интеграция с Grafana

Tempo глубоко интегрирован с Grafana:

  • В интерфейсе Grafana можно перейти к трассировке из графика метрик или лога.
  • Поддерживается поиск по trace ID напрямую в панели Explore.
  • Возможна визуализация трассировок в виде временной шкалы (timeline), DAG (Directed Acyclic Graph) и таблицы спанов.

Требования:

  • Grafana версии 7.4+.
  • Установленный datasource Tempo в Grafana.
  • При использовании Loki/Prometheus — настроенные связи между сигналами (например, label traceID в Loki должен совпадать с trace_id в Tempo).

Интеграция с OpenTelemetry Collector

OpenTelemetry Collector — основной способ отправки трассировок в Tempo.

Пример экспортера в otelcol-config.yaml:

exporters:
otlp/tempo:
endpoint: "tempo-distributor:4317"
tls:
insecure: true

service:
pipelines:
traces:
receivers: [jaeger, zipkin]
exporters: [otlp/tempo]

Поддерживаемые получатели (receivers):

  • otlp
  • jaeger
  • zipkin
  • opencensus

Формат хранения трассировок (Parquet + WAL)

Tempo использует собственный формат хранения:

  • Спаны буферизуются в WAL (Write-Ahead Log) на диске.
  • После завершения трассировки данные сериализуются в Parquet-файлы и загружаются в объектное хранилище.
  • Parquet выбран за эффективность сжатия и возможность выборочного чтения колонок.

Структура блока в хранилище:

<tenant>/<block_id>/
├── meta.json
├── index.parquet
└── traces.parquet

Файл index.parquet содержит только trace_id и временные метки — это позволяет быстро находить нужный блок без полного сканирования.


Поиск по атрибутам (TraceQL)

Начиная с Tempo 2.0+, доступен язык запросов TraceQL — аналог PromQL для трассировок.

Примеры запросов:

  • Найти все трассировки с сервисом auth-service:
    {service.name="auth-service"}
  • Найти медленные трассировки (>1s):
    {duration > 1s}
  • Комбинированный запрос:
    {service.name="api-gateway" && http.status_code=500}

Для работы TraceQL требуется:

  • Включённый search_enabled: true.
  • Настроенный search backend (встроенная база или внешняя, например Elasticsearch).

Параметры производительности и масштабирования

Память

  • Ingester потребляет ~1–2 ГБ RAM на 100 тыс. активных трассировок.
  • Querier требует меньше памяти, но зависит от объёма одновременных запросов.

Диск

  • WAL должен быть на быстром SSD/NVMe.
  • Размер WAL регулируется через ingester.wal.config.segment_size_bytes.

Сеть

  • Distributor должен быть защищён от DDoS (например, через rate limiting в Nginx или Istio).
  • gRPC-соединения между компонентами должны использовать keepalive.

Масштабирование

  • Distributor: горизонтально масштабируется без состояния.
  • Ingester: масштабируется с учётом consistent hashing по trace_id.
  • Querier: полностью stateless, легко масштабируется.

Пример минимальной конфигурации (tempo.yaml)

server:
http_listen_port: 3200
grpc_listen_port: 9095

distributor:
receivers:
otlp:
protocols:
grpc:
endpoint: "0.0.0.0:4317"

ingester:
max_block_duration: 30m
wal:
path: /tmp/tempo/wal

compactor:
compaction:
block_retention: 48h

storage:
trace:
backend: local
local:
path: /tmp/tempo/blocks

query_frontend:
search:
duration_slo: 5s

Рекомендации по эксплуатации

  • Не используйте local backend в production — только объектное хранилище.
  • Настройте мониторинг через Prometheus и алерты на основе mixin’ов Tempo.
  • Регулярно обновляйте Tempo — проект активно развивается.
  • При высокой нагрузке включите кэширование в Query-Frontend (Redis).
  • Избегайте отправки трассировок без service.name — это затрудняет анализ.
  • Используйте sampling (например, через OpenTelemetry Collector), если объём данных велик.