CLOVER🍀

That was when it all began.

Jaegerを構成するコンポーネントを見てみる

これは、なにをしたくて書いたもの?

ちょっとOpenTelemetryに興味を持っていまして、トレーシングについてはJaegerを見ていこうと思っているのですが。

とりあえず使ってみる時に、

$ ./jaeger-all-in-one

としか実行したことがなく、そもそも「all-in-one」ってなに?状態だったのでここを少し紐解きたいなと思いまして。

Jaeger

Jaegerは、Uberが開発したオープンソースの分散トレーシングプラットフォームです。

Jaeger: open source, distributed tracing platform

Jaeger is a distributed tracing platform released as open source by Uber Technologies.

Introduction / About

Goで実装されており、以下を特徴としています。

  • OpenTracingにインスパイアされたデータモデル
  • OpenTelemetry互換
  • 複数のストレージバックエンド(Cassandra、Elasticsearch、Kafka、インメモリー)
  • コミュニティによってサポートされている、gRPC経由の外部ストレージバックエンド
  • システムトポロジーグラフ
  • 適応サンプリング
  • サービスパフォーマンスモニタリング(APM)
  • データ収集後の処理

Introduction / Features

今回は、このJaegerの構成をドキュメントから見ていきます。

Jaegerディストリビューション

ところで、Jaegerをダウンロードして展開してみましょう。

$ curl -LO https://github.com/jaegertracing/jaeger/releases/download/v1.49.0/jaeger-1.49.0-linux-amd64.tar.gz
$ tar xf jaeger-1.49.0-linux-amd64.tar.gz
$ cd jaeger-1.49.0-linux-amd64

こういった感じになっています。

$ ll
合計 230948
drwxr-xr-x 2 xxxxx xxxxx     4096  9月  7 23:35 ./
drwxrwxr-x 3 xxxxx xxxxx     4096  9月 10 19:53 ../
-rwxr-xr-x 1 xxxxx xxxxx 21266513  9月  7 23:35 example-hotrod*
-rwxr-xr-x 1 xxxxx xxxxx 24992961  9月  7 23:35 jaeger-agent*
-rwxr-xr-x 1 xxxxx xxxxx 53441192  9月  7 23:35 jaeger-all-in-one*
-rwxr-xr-x 1 xxxxx xxxxx 47551050  9月  7 23:35 jaeger-collector*
-rwxr-xr-x 1 xxxxx xxxxx 41323351  9月  7 23:35 jaeger-ingester*
-rwxr-xr-x 1 xxxxx xxxxx 47876295  9月  7 23:35 jaeger-query*

分散トレーシングで使われる時は「とりあえずjaeger-all-in-oneを起動」みたいな感じになっているのであまり気にしていなかったの
ですが、これだけ含まれていたんですね。

今回はこれらを見ていくことになります。Jaegerのバージョンは1.49.0です。

なお、example-hotrodというのはサンプル用のアプリケーションみたいです。

Jaegerを構成するコンポーネント

Jaegerのアーキテクチャーはこちらに書かれています。

Architecture — Jaeger documentation

まず、スパンやトレースといった用語はこちらを見ておきましょう。

Architecture / Terminology

スパンはオペレーション名、オペレーションの開始時間および期間を持つ論理的な作業単位です。スパンはネストすることができ、
順序付けできます。

トレースはシステム内のデータや実行パスを表したものです。これはスパンのDAG(有向非巡回グラフ)と捉えることができます。

そしてアーキテクチャー。これはデプロイ時の構成パターンですね。

Architecture / Architecture

その前に、Jaegerを構成するコンポーネントの種類と名前を明らかにした方が良さそうです。

Architecture / Components

Tracing SDKs

Jaegerが提供していたトレース用のSDKですが、現在はOpenTelemetry SDKを使うため廃止されるようです。

Architecture / Tracing SDKs

Agent

コンポーネントとしてはjaeger-agentです。

Architecture / Agent

UDP経由で送信されてくるスパンを受信するデーモンで、スパンをバッチ化してjaeger-collectorに送信します。Jaeger Agentは必須の
コンポーネントではなく、かつ現在はOpenTelemetry SDKから直接jaeger-collector送信、またはOpenTelemetry Collactorを介することに
なるため非推奨です。

Collector

コンポーネントとしてはjaeger-collectorです。

Architecture / Collector

トレースを受信し、バリデーションやクリーンアップ、エンリッチメントのためのパイプラインを経由してストレージバックエンドに
保存します。

いくつかのストレージが使用可能で、カスタムストレージプラグインを実装可能な拡張プラグインフレームワークを備えています。

Query

コンポーネントとしてはjaeger-queryです。

Architecture / Query

ストレージからトレースを取得するためのAPIを公開し、トレースを検索や分析のためのWeb UIを提供するサービスです。Reactが
使われているようですね。

APIはこちら。

APIs — Jaeger documentation

Ingester

コンポーネントとしてはjaeger-ingesterです。

Architecture / Ingester

Kafkaからトレースを読み取り、ストレージバックエンドに書き込むサービスです。入力はKafkaのみとなった、Collectorの簡素版という
扱いのようです。

ここまでで、Jaegerのディストリビューションに含まれる個々の実行ファイルの意味がわかってきました。

デプロイパターン

ここからは、デプロイパターンになります。

Architecture / Architecture

ストレージへ直接保存

Collectorがトレースデータをアプリケーションから受信し、ストレージに直接書き込むように構成したパターンです。保存されたデータの
参照にはQueryを使います。

Architecture / Architecture / Direct to storage

Collectorは短期間であればトラフィックのピークを平滑化するためにインメモリーキューを使用できますが、ストレージが書き込みに
追いつかない場合は高いトラフィックが続くとデータがドロップされる可能性があります。

Kafkaをキューとして配置する

Collectorとストレージの間にKafkaを挟み、ストレージに保存するまでの間にデータが損失するのを防ぐためにKafkaを中間の永続キュー
として使用します。

Collectorからのデータの送信先はKafkaとなり、Kafkaに保存されたデータはIngesterが読み出してストレージに保存します。Ingesterは
複数デプロイしてスケールアウトが可能です。

Architecture / Architecture / Via Kafka

データの参照にQueryを使うのはストレージに直接保存する場合と同じです。

OpenTelemetry Collector

他のテレメトリーデータやトレースデータの収集、処理のためにOpenTelemetry Collectorを配置している場合などは、SDKとCollectorの
間にOpehTelemetry Collectorを配置できます。

OpenTelemetry CollectorはJaegerのCollectorのプロキシとして機能します。

Architecture / Architecture / With OpenTelemetry Collector

OpenTelemetry Collectorのデプロイパターンはいくつかあり、アプリケーションサイドカー、ホストエージェント/デーモン、
中央集権的なクラスターとして実行できます。

なお、JaegerのCollectorはOpenTelemetry SDKからOpenTelemetryデータを直接受信して処理できるため、OpenTelemetry Collectorを
使用する必要はないとされています。特にOpenTelemetryに関するコンポーネントがシステム内にJaegerしかない場合は、わざわざ
OpenTelemetry Collectorを導入する理由が薄い感じになりますね。

all in oneは?

ここまで見ていて、all in oneについての説明が薄いことに気づくわけですが。

アーキテクチャーに少し出てきます。Jaegerの提供するすべてのバックエンドコンポーネントを単一プロセスで実行できるオールインワン
バイナリのことを指しています。

Jaeger can be deployed either as an all-in-one binary, where all Jaeger backend components run in a single process, or as a scalable distributed system.

Architecture / Architecture

また、デプロイメントのページにも少し書かれています。

Jaeger all-in-one is a special distribution that combines three Jaeger components, agent, collector, and query service/UI, in a single binary or container image. It is useful for single-node deployments where your trace volume is light enough to be handled by a single instance. By default, all-in-one starts with memory storage, meaning it will lose all data upon restart.

Deployment / All-in-one

ざっと以下の感じですね。

  • Agent、Collector、Queryを単一のバイナリまたはコンテナイメージにまとめた特殊なディストリビューション
  • トレースデータが単一のインスタンスで処理できるほど軽量な場合に便利
  • デフォルトのストレージはメモリーなので、再起動するとデータは失われる
  • すべてのスパンストレージバックエンドも利用可能だが、All-in-oneインスタンス間でメモリーやバッジのデータは共有できない

およそJaegerの構成要素はわかったのではないかなと思います。

おわりに

Jaegerを構成するコンポーネントを見てみました。

今まで何気なく「all-in-one」を使っていましたが、それぞれの位置づけがわかったのでそのうちコンポーネントごとにプロセスを立てて
試してみたいですね。

それから、Jaegerを使ってOpenTelemetryデータを受信する際には、OpenTelemetry Collectorはなくても構わないということもわかりました。
これからは構成を簡略化して試してみようかなと思います。