これは、なにをしたくて書いたもの?
Grafanaプロジェクトの中に、分散トレーシングのバックエンドとなるGrafana Tempoという製品があります。
こちらを使って分散トレーシングを試してみたいのですが、セットアップがそれなりに大変そうなので、まずは
インストールだけをやってみます。対象はUbuntu Linux 24.04 LTSとします。
Grafana Tempo
Grafana Tempoのページはこちら。
Grafana Tempo OSS | Distributed tracing backend
ドキュメントはこちら。
Grafana Tempo | Grafana Tempo documentation
Grafana Tempoは、OSSの分散トレーシングバックエンドです。
Grafana Tempo is an open-source, easy-to-use, and high-scale distributed tracing backend.
オブジェクトストレージを要求し、Grafana、Grafana Mimir、Prometheus、Grafana Lokiとインテグレーションできます。
また、JaegerやZipkin、OpenTelemetryなどのOSSのトレーシングプロトコルと組み合わせることもできます。
Tempo is cost-efficient and only requires an object storage to operate. Tempo is deeply integrated with Grafana, Mimir, Prometheus, and Loki. You can use Tempo with open source tracing protocols, including Jaeger, Zipkin, or OpenTelemetry.
こちらのページおよびその配下には、トレースやスパンといった分散トレーシングに関する用語の説明や、トレースと
メトリクス、ログといったObservabilityに関する要素およびその関連付けに関する説明が書かれています。
Introduction | Grafana Tempo documentation
基本的な用語、概念の説明ですね。
トレースデータを収集するための構成は、こちらに書かれています。
Get started | Grafana Tempo documentation
クライアント → パイプライン(Grafana Alloy) → バックエンド(Grafana Tempo) → 可視化(Grafana)という構成ですね。
パイプラインであるGrafana Alloyはオプションのようで、クライアントから直接Grafana Tempoにトレースデータを
送信しても大丈夫そうです。
ちなみにGrafana Tempo自体の構成となると、こちらですね。
Tempo architecture | Grafana Tempo documentation
Distributor、Intester、Query Frontend、Querier、Compactor、Metrics Generatorというコンポーネントが出てくるのですが、
Grafana Mimirと似た構成ですね。
Grafana Mimir+MinIOをUbuntu Linux 24.04 LTSにインストールして、Prometheusのリモート書き込み先として使う - CLOVER🍀
ストレージに関しても似ていて、Amazon S3(および互換オブジェクトストレージ)、Azure BLOB、Google Cloud Storageを
選ぶことができます。
Hosted storage | Grafana Tempo documentation
設定ファイルについてはYAMLで記述するようで、その内容はまずはこちらを見るようなのですが…
Configure Tempo | Grafana Tempo documentation
Manifest | Grafana Tempo documentation
「ソースコード見てね」だったり、「サンプルを参考にしてね」だったりとなかなかに最初のハードルが高いです。
https://github.com/grafana/tempo/tree/main/example/docker-compose
このあたりは使いながら慣れていきましょうか。
インストール方法について。Grafana Tempoは、単一のプロセスで動作しデプロイも簡単なモノリシックモード、
コンポーネントが個別のプロセスで実行されコンポーネントごとにスケールさせることもできるものの、
構成が複雑なマイクロサービスモードの2つの インストール方法があります。
Tempo can be deployed in monolithic or microservices modes.
Plan your Tempo deployment | Grafana Tempo documentation
今回はLinux向けのインストール方法で、モノリシックモードとしてインストールすることにします。
Deploy on Linux | Grafana Tempo documentation
お題
今回のお題は、以下とします。
flowchart LR A["アプリケーション"] -- テレメトリーデータ --> B["Grafana Tempo"] B -- データソース --> C["Grafana"] B -- テレメトリーデータ --> D["MinIO"]
簡単なアプリケーションからテレメトリーデータ(トレースシグナル)をGrafana Tempoに送信して、Grafanaで見てみます。
Grafana Tempoのデータの保存先はMinIOとします。
環境
今回の環境はこちら。
$ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 24.04.3 LTS Release: 24.04 Codename: noble $ uname -srvmpio Linux 6.8.0-71-generic #71-Ubuntu SMP PREEMPT_DYNAMIC Tue Jul 22 16:52:38 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux
またGrafana Tempoが動作するサーバーのIPアドレスは、192.168.33.11とします。
アプリケーションはPythonで作成します。
$ python3 --version Python 3.12.3 $ uv --version uv 0.8.8
準備
Grafana Tempoを除く、各構成要素をインストールします。
Grafana。
$ sudo apt install apt-transport-https software-properties-common wget $ sudo mkdir -p /etc/apt/keyrings/ $ wget -q -O - https://apt.grafana.com/gpg.key | gpg --dearmor | sudo tee /etc/apt/keyrings/grafana.gpg > /dev/null $ echo "deb [signed-by=/etc/apt/keyrings/grafana.gpg] https://apt.grafana.com stable main" | sudo tee -a /etc/apt/sources.list.d/grafana.list $ sudo apt update $ sudo apt install grafana $ sudo systemctl enable grafana-server $ sudo systemctl start grafana-server $ grafana-server --version Version 12.1.0 (commit: ccd7b6ce7ea6184b8c7eb1de044174147dd9a648, branch: HEAD)
MinIO。
$ curl -LO https://dl.min.io/server/minio/release/linux-amd64/minio_20250723155402.0.0_amd64.deb $ sudo dpkg -i minio_20250723155402.0.0_amd64.deb $ sudo systemctl enable minio $ sudo useradd -s /bin/false minio-user $ sudo mkdir -p /var/lib/minio $ sudo chown minio-user:minio-user /var/lib/minio
/etc/default/minio
MINIO_ROOT_USER=minioadmin MINIO_ROOT_PASSWORD=minioadmin MINIO_VOLUMES=/var/lib/minio MINIO_OPTS='--console-address :9001'
起動。
$ sudo systemctl start minio
MinIOクライアント。
$ curl -LO https://dl.min.io/client/mc/release/linux-amd64/mcli_20250721052808.0.0_amd64.deb $ sudo dpkg -i mcli_20250721052808.0.0_amd64.deb $ mcli --version mcli version RELEASE.2025-07-21T05-28-08Z (commit-id=ee72571936f15b0e65dc8b4a231a4dd445e5ccb6) Runtime: go1.24.5 linux/amd64 Copyright (c) 2015-2025 MinIO, Inc. License GNU AGPLv3 <https://www.gnu.org/licenses/agpl-3.0.html>
ひとまず、Grafana Tempo以外のミドルウェアはインストールできました。
Grafana Tempoをインストールする
では、こちらに沿ってGrafana Tempoをインストールしていきます。
Deploy on Linux | Grafana Tempo documentation
Grafana TempoのインストーラはGitHub Releasesから取得するようです。
Releases · grafana/tempo · GitHub
今回はdebパッケージを選択します。
$ curl -LO https://github.com/grafana/tempo/releases/download/v2.8.2/tempo_2.8.2_linux_amd64.deb
インストール。
$ sudo dpkg -i tempo_2.8.2_linux_amd64.deb
この時点でsystemdのユニットとして登録され、起動しているようです。
$ sudo systemctl status tempo ● tempo.service - Tempo service Loaded: loaded (/etc/systemd/system/tempo.service; enabled; preset: enabled) Active: active (running) since Sun 2025-08-10 16:11:48 JST; 15s ago Main PID: 2445 (tempo) Tasks: 6 (limit: 9487) Memory: 19.5M (peak: 19.7M) CPU: 107ms CGroup: /system.slice/tempo.service └─2445 /usr/bin/tempo -config.file /etc/tempo/config.yml
パッケージに含まれているファイルを確認。
/etc /etc/systemd /etc/systemd/system /etc/systemd/system/tempo.service /etc/tempo /etc/tempo/config.yml /usr /usr/bin /usr/bin/tempo /usr/bin/tempo-cli /usr/bin/tempo-query
systemdのユニット定義ファイル。
/etc/systemd/system/tempo.service
[Unit] Description=Tempo service After=network.target [Service] Type=simple User=tempo ExecStart=/usr/bin/tempo -config.file /etc/tempo/config.yml # Give a reasonable amount of time for the server to start up/shut down TimeoutSec = 120 Restart = on-failure RestartSec = 2 [Install] WantedBy=multi-user.target
デフォルトの設定ファイル。
/etc/tempo/config.yml
stream_over_http_enabled: true server: http_listen_port: 3200 log_level: info query_frontend: search: duration_slo: 5s throughput_bytes_slo: 1.073741824e+09 metadata_slo: duration_slo: 5s throughput_bytes_slo: 1.073741824e+09 trace_by_id: duration_slo: 5s distributor: receivers: otlp: protocols: grpc: endpoint: "0.0.0.0:4317" metrics_generator: registry: external_labels: source: tempo cluster: docker-compose storage: path: /var/tempo/generator/wal remote_write: - url: http://prometheus:9090/api/v1/write send_exemplars: true traces_storage: path: /var/tempo/generator/traces storage: trace: backend: local # backend configuration to use wal: path: /var/tempo/wal # where to store the wal locally local: path: /var/tempo/blocks overrides: defaults: metrics_generator: processors: [service-graphs, span-metrics, local-blocks] # enables metrics generator generate_native_histograms: both
Grafana Tempoは4317ポートを使うみたいですね。
distributor: receivers: otlp: protocols: grpc: endpoint: "0.0.0.0:4317"
またストレージはローカルファイルシステムを使うようです。
storage: trace: backend: local # backend configuration to use wal: path: /var/tempo/wal # where to store the wal locally local: path: /var/tempo/blocks
こちらを見るとローカルファイルシステムの記述はないのですが
Hosted storage | Grafana Tempo documentation
こちらを見ると使えそうではあります。
Configure Tempo / Storage / Local storage recommendations
オブジェクトストレージとの併用は不可だそうです。
Grafana TempoでMinIOを使うように設定する
Amazon S3などで利用する場合の設定例はこちら。
Configure Tempo / Storage / Storage block configuration example
内容がGrafana Mimirそっくりです。
MinIOのバケットを作成しましょう。
$ mcli alias set myminio http://localhost:9000 minioadmin minioadmin $ mcli mb myminio/tempo-blocks
Grafana Tempoの設定は以下のように変更。
/etc/tempo/config.yml
stream_over_http_enabled: true server: http_listen_port: 3200 log_level: info query_frontend: search: duration_slo: 5s throughput_bytes_slo: 1.073741824e+09 metadata_slo: duration_slo: 5s throughput_bytes_slo: 1.073741824e+09 trace_by_id: duration_slo: 5s distributor: receivers: otlp: protocols: grpc: endpoint: "0.0.0.0:4317" http: endpoint: "0.0.0.0:4318" metrics_generator: registry: external_labels: source: tempo cluster: docker-compose storage: path: /var/tempo/generator/wal remote_write: - url: http://prometheus:9090/api/v1/write send_exemplars: true traces_storage: path: /var/tempo/generator/traces storage: trace: backend: s3 s3: bucket: "tempo-blocks" endpoint: "localhost:9000" insecure: true forcepathstyle: true access_key: "minioadmin" secret_key: "minioadmin" wal: path: /var/tempo/wal # where to store the wal locally overrides: defaults: metrics_generator: processors: [service-graphs, span-metrics, local-blocks] # enables metrics generator generate_native_histograms: both
変更箇所は、まずはストレージの部分から。
storage: trace: backend: s3 s3: bucket: "tempo-blocks" endpoint: "localhost:9000" insecure: true forcepathstyle: true access_key: "minioadmin" secret_key: "minioadmin" wal: path: /var/tempo/wal # where to store the wal locally
ストレージのバックエンドをAmazon S3にしていますが、実体はMinIOです。forcepathstyle
は設定しなくても大丈夫そうでした。
WALはローカルファイルシステムのままにしています。
あとは、トレースデータを受信するプロトコルはhttp/protobuf
も扱えるようにしました。
distributor: receivers: otlp: protocols: grpc: endpoint: "0.0.0.0:4317" http: endpoint: "0.0.0.0:4318"
Grafana Tempoを再起動。
$ sudo systemctl restart tempo
これで準備は完了です。
アプリケーションからテレメトリーデータ(トレースシグナル)を送信して確認してみる
設定が終わったので、今度は確認です。
テレメトリーデータを送信しないとどうにもならないので、PythonとFastAPIで簡単なアプリケーションを作成します。
$ uv init --vcs none tempo-test $ uv add fastapi[standard] $ uv pip install opentelemetry-distro opentelemetry-exporter-otlp $ uv run opentelemetry-bootstrap -a requirements | uv pip install --requirement -
pyproject.toml
[project] name = "tempo-test" version = "0.1.0" description = "Add your description here" readme = "README.md" requires-python = ">=3.12" dependencies = [ "fastapi[standard]>=0.116.1", ]
依存関係の一覧はこちら。
$ uv pip list Package Version ----------------------------------------- -------- annotated-types 0.7.0 anyio 4.10.0 asgiref 3.9.1 certifi 2025.8.3 charset-normalizer 3.4.3 click 8.2.1 dnspython 2.7.0 email-validator 2.2.0 fastapi 0.116.1 fastapi-cli 0.0.8 fastapi-cloud-cli 0.1.5 googleapis-common-protos 1.70.0 grpcio 1.74.0 h11 0.16.0 httpcore 1.0.9 httptools 0.6.4 httpx 0.28.1 idna 3.10 importlib-metadata 8.7.0 jinja2 3.1.6 markdown-it-py 3.0.0 markupsafe 3.0.2 mdurl 0.1.2 opentelemetry-api 1.36.0 opentelemetry-distro 0.57b0 opentelemetry-exporter-otlp 1.36.0 opentelemetry-exporter-otlp-proto-common 1.36.0 opentelemetry-exporter-otlp-proto-grpc 1.36.0 opentelemetry-exporter-otlp-proto-http 1.36.0 opentelemetry-instrumentation 0.57b0 opentelemetry-instrumentation-asgi 0.57b0 opentelemetry-instrumentation-asyncio 0.57b0 opentelemetry-instrumentation-click 0.57b0 opentelemetry-instrumentation-dbapi 0.57b0 opentelemetry-instrumentation-fastapi 0.57b0 opentelemetry-instrumentation-grpc 0.57b0 opentelemetry-instrumentation-httpx 0.57b0 opentelemetry-instrumentation-jinja2 0.57b0 opentelemetry-instrumentation-logging 0.57b0 opentelemetry-instrumentation-requests 0.57b0 opentelemetry-instrumentation-sqlite3 0.57b0 opentelemetry-instrumentation-starlette 0.57b0 opentelemetry-instrumentation-threading 0.57b0 opentelemetry-instrumentation-tortoiseorm 0.57b0 opentelemetry-instrumentation-urllib 0.57b0 opentelemetry-instrumentation-urllib3 0.57b0 opentelemetry-instrumentation-wsgi 0.57b0 opentelemetry-proto 1.36.0 opentelemetry-sdk 1.36.0 opentelemetry-semantic-conventions 0.57b0 opentelemetry-util-http 0.57b0 packaging 25.0 protobuf 6.31.1 pydantic 2.11.7 pydantic-core 2.33.2 pygments 2.19.2 python-dotenv 1.1.1 python-multipart 0.0.20 pyyaml 6.0.2 requests 2.32.4 rich 14.1.0 rich-toolkit 0.14.9 rignore 0.6.4 sentry-sdk 2.34.1 shellingham 1.5.4 sniffio 1.3.1 starlette 0.47.2 typer 0.16.0 typing-extensions 4.14.1 typing-inspection 0.4.1 urllib3 2.5.0 uvicorn 0.35.0 uvloop 0.21.0 watchfiles 1.1.0 websockets 15.0.1 wrapt 1.17.2 zipp 3.23.0
作成したソースコードはこちら。
main.py
import fastapi from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor app = fastapi.FastAPI() @app.get("/foobar") async def foobar(): return {"message": "hello world"} FastAPIInstrumentor.instrument_app(app)
ソースコードはこちらをそのまま使いました。
OpenTelemetry FastAPI Instrumentation — OpenTelemetry Python Contrib documentation
uvとOpenTelemetryのゼロ計装は相性が悪いようで、こちらに沿って設定。
Troubleshooting Python automatic instrumentation issues | OpenTelemetry
このあたりのことですね。ここは主題ではないので、またおいおい見ていきます。
$ uv pip install opentelemetry-distro opentelemetry-exporter-otlp $ uv run opentelemetry-bootstrap -a requirements | uv pip install --requirement -
$ export OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED=true $ export OTEL_TRACES_EXPORTER=otlp $ export OTEL_METRICS_EXPORTER=none $ export OTEL_LOGS_EXPORTER=none $ export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://192.168.33.11:4318/v1/traces $ export OTEL_EXPORTER_OTLP_TRACES_PROTOCOL=http/protobuf $ export OTEL_SERVICE_NAME=app
エンドポイントのパスはこちらから確認しました。
Tempo HTTP API | Grafana Tempo documentation
Push spans with HTTP | Grafana Tempo documentation
アプリケーションを実行。
$ uv run opentelemetry-instrument fastapi run main.py
あとはアプリケーションにリクエストを何回か投げてみます。
$ curl localhost:8000/foobar {"message":"hello world"}
送信したテレメトリーデータをGrafanaから見てみましょう。
データソースにGrafana Tempoを選択。
接続先だけ設定してデータソースを追加。ポートは3200のようです。
結果は、Drilldownから確認。
Exploreからトレースを選ぶと
スパンツリーを見れます。
ひとまず、このくらいでしょうか…。
なお、MinIOはこのようになっていました。
$ mcli ls myminio/tempo-blocks [2025-08-10 16:40:30 JST] 219B STANDARD tempo_cluster_seed.json [2025-08-10 18:04:52 JST] 0B single-tenant/ $ mcli ls myminio/tempo-blocks/single-tenant/ [2025-08-10 18:02:09 JST] 302B STANDARD index.json.gz [2025-08-10 18:02:09 JST] 110B STANDARD index.pb.zst [2025-08-10 18:04:58 JST] 0B fa58253f-d6d2-4d05-a691-d163325b01b1/ $ mcli ls myminio/tempo-blocks/single-tenant/fa58253f-d6d2-4d05-a691-d163325b01b1/ [2025-08-10 17:52:18 JST] 100KiB STANDARD bloom-0 [2025-08-10 17:52:18 JST] 34KiB STANDARD data.parquet [2025-08-10 17:52:18 JST] 42B STANDARD index [2025-08-10 17:52:18 JST] 333B STANDARD meta.json
おわりに
Grafana Tempo 2.8+MinIO+GrafanaをUbuntu Linux 24.04 LTSにインストールして、トレースデータを見るところまで
やってみました。
1番苦労したのは、PythonアプリケーションにOpenTelemetry SDKのゼロ計装を適用するところだったりするので、
ここはまた後で見ておこうと思います…。
それから、Grafana上でどう見たらいいのかもだいぶ迷いました。
これからGrafanaで見ていくことになるので、慣れていかないとですね。