Distributed Tracing Best Practices’の日本語訳は以下の通りです: 分散トレーシングのベストプラクティス

「分散トレーシングのベストプラクティス」という文の日本語訳は以下の通りです:「分散トレーシングのベストプラクティス」

分散トレーシングは、現代の監視スタックで欠かせない存在となっています。マイクロサービスへの移行に伴い、サービス間の相互作用を観測する新しい方法が必要になりました。分散トレーシングは、リクエストのトレース、つまり分散システム内のコンポーネント間でリクエストを追跡することを可能にします。現在、分散トレーシングはパフォーマンスのボトルネックの特定、問題のデバッグ、およびシステムのプロダクション環境での相互作用の理解に使用されています。

ただし、分散トレーシングの実装は複雑であり、チームがそれから得る価値は実装方法にかなり依存します。どのコンポーネントがインストゥルメンテーションされるか、サンプリング率、トレースの可視化の品質などの実装のメカニクスは、トレーシングから企業が得る価値に影響を与えます。さらに、この領域は絶えず進化しており、新しいツールや技術が常に登場しています。

本記事では、2023年の分散トレーシングのベストプラクティスについて見ていきましょう。

分散トレーシングとは?

分散トレーシングとは、分散環境で複数のサービスを通過する単一のリクエストを追跡するメカニズムを指します。

なぜ分散トレーシングが必要なのか。

これを実現するために、分散トレーシングツールは各リクエストのヘッダに一意のトレースコンテキスト(トレースID)を挿入し、リクエストパス全体でトレースコンテキストが伝播するようなメカニズムを実装します。

リクエストパス内で行われる各ネットワーク呼び出しはキャプチャされ、スパンとして表現されます。スパンはトレース内の単一のイベントを表す基本単位であり、トレースには1つまたは複数のスパンが存在します。スパンにはログメッセージ、時間関連のデータ、およびその他の属性が含まれており、追跡対象の操作に関する情報を提供します。

分散トレースの解剖学。

独自のビューを通じて、分散トレーシングはいくつかの新しいユースケース/既存のユースケースの改善を可能にします。それはサービス間の依存関係を理解することを可能にし(たとえば、私のサービスを呼び出しているのは誰ですか)、パフォーマンスのボトルネックを特定することができます(具体的なDB呼び出しがレイテンシを低下させていますか?)、デバッグのための障害点を迅速に特定することができます(このAPIが500の問題を引き起こしていますか?)、また、より細かいSLO(サービスレベル目標)を設定することができます。

分散トレーシングシステムのコンポーネント

分散トレーシングシステムを実装するために、以下の4つの異なるコンポーネントをインストールします:

  1. インストゥルメンテーションライブラリ
  2. コレクタ(プリプロセッサ)
  3. ストレージバックエンド
  4. 可視化レイヤー

現在、これらのコンポーネントのそれぞれにはいくつかのオプションがあります。4つすべてを1つのプラットフォームで実現するか、異なるコンポーネント用に異なるソリューションを組み合わせて分散トレーシングフレームワークを構築することができます。

トレーシングシステムのコンポーネント。

インストゥルメンテーションライブラリ

これは各アプリケーションまたはサービスに統合される部分です。アプリケーションが実行されるとき、インストゥルメンテーションライブラリは各リクエストにトレースIDを追加したり、トレースコンテキスト(トレースID)を次のスパンに伝播させたりします。ライブラリはこのデータをコレクタに送信します。

コレクタ

コレクタはインストゥルメンテーションライブラリとストレージバックエンドの間の中継者です。コレクタはトレースを収集し、それらを処理(スパンの集約、サンプリングなど)し、ストレージの準備を行います。

ストレージバックエンド

ストレージバックエンドはトレースデータを永続化し、インデックス化します。通常、大量のデータを処理できる分散ストレージシステムを使用し、効率的なクエリと取得を可能にします。

可視化レイヤー

これは分散トレーシングシステムのユーザーインターフェースです。開発者やオペレーターがトレースデータと対話することができます。このレイヤーは、さまざまな基準に基づいてトレースデータをクエリ、検索、フィルタリングするためのツールを提供します。トレースデータをトレースグラフやタイムラインとして視覚的に意味のある方法で表示し、イベントのシーケンスを分析し、ボトルネックや問題を特定することができます。

分散トレーシングシステムの実装は複雑です

分散トレーシングシステムの実装にはいくつかの利点がありますが、(特に適切に)実装することはまだ容易なタスクではありません。実装チームがいくつかの決定を行い、それらの決定がトレーシングからエンジニアリングチーム全体が得る価値に影響を与える必要があります。企業が分散トレーシングを実装し、年間50万ドル以上の費用を支払い、平均開発者が年に2回しか使用しないのは珍しいことではありません。以下は、トレーシングを適切に実装するためのベストプラクティスのいくつかです。

分散トレーシングのベストプラクティス

計測のためにOTelを選択する

OpenTelemetry、Jaeger、およびZipkinなど、いくつかの人気のあるオープンソースのトレースフレームワークがあります。2023年現在では、OTelは以下の理由から明らかな選択肢となっています:

  • 広範なカバレッジ:OTelには、さまざまなプログラミング言語とフレームワーク向けの計測ライブラリとSDKがあり、幅広いカバレッジがあります。OTelがサポートしている内容については、こちらをご覧ください。
  • ベンダー中立:ほとんどのベンダーは現在、OTelの計測をサポートしています。したがって、OTelで計測を行い、データを自分の選んだベンダーに送信することができます。ベンダー間の互換性と将来の移植性が確保されます(ベンダーを変更する場合にも)。OTelデータをネイティブでサポートしている観測性ベンダーの一覧はこちら、OTelを他のベンダーと接続するためのライブラリやプラグインの登録はこちらです。
  • 成熟度と安定性:OTelは数年間にわたって成熟してきており、広範なコミュニティのサポートを受けています。CNCFエコシステムにおいて、Kubernetesに次ぐ2番目の規模のプロジェクトとなっています。強力なコミュニティの存在により、OTelは継続的に進化し、新しい技術へのサポートを迅速に追加しています。

可能な限り自動計測を活用する

OpenTelemetryは、コードをアプリケーションやコンポーネントに計測するための2つの方法を提供しています – マニュアル計測と自動計測。Kubernetes上でJava、NodeJS、またはPythonのほとんどのサービスを使用している場合は、自動計測を広範に活用することで実装の手間を減らすことができます。

マニュアル計測

OTelのコードは開発者によってアプリケーションに追加する必要があるため、コードの変更が必要です。マニュアル計測では、スパンやトレースのカスタマイズがより可能です。ほとんどの言語はマニュアル計測に対応しており、C++、.NET、Go、Java、Pythonなどが含まれます。最新のリストについてはこちらを参照してください。

自動計測

これは、コードの変更やアプリケーションの再コンパイルを行わずにアプリケーション/サービスに計測を追加する方法です。インテリジェントなエージェントがアプリケーションにアタッチされ、そのアクティビティを読み取り、トレースを抽出します。これはKubernetes上で可能です。OTelは現在、Java、NodeJS、Pythonなどに対して自動計測をサポートしています(最新のリストについてはこちらを参照してください)。自動計測ではスパンやトレースのカスタマイズは限られていますが、ほとんどのユースケースには十分です。

重要なパスから始め、そこから拡大する

大規模な分散システムのすべてのサービス/コンポーネントに一度に計測を行うことは現実的ではないため、どのパスを最初に計測するか、どのように拡大するかを慎重に選択することが重要です。以下はここで従うべきガイドライン/原則のいくつかです:

外から内に向かって進む/ユーザーに近い場所から始める

外側から内側に向かって進むことが最も良い場合があります。つまり、リクエストがアプリケーションに入るポイント、ユーザーや外部クライアントからの着信リクエストから始めることです。エントリーポイントから始めることで、リクエストがシステムをどのように流れるかを総合的に把握することが容易になります。

システム内で最も重要なパスを選び、最初に計測する

一般的なガイドラインは、システム内で最も重要なリクエストパスを特定することです。これらは、最も頻繁にアクセスされるか、アプリケーション全体のパフォーマンスに最も大きな影響を与える可能性があるパスです。まずはこれらの重要なパスに計測を行い、全体の組織に価値を示し、それからそこから拡大していきます。

トレースが途切れないように常にリクエストパスをエンドツーエンドで計測する

選択したパスが、リクエストパス内の各サービスとコンポーネントがコンテキスト(トレースID)を伝播し、必要に応じてスパンを生成するように計測されていることを確認してください。ギャップがあると、不完全または途切れたトレースが生じ、上流サービスへの計測の取り組みが無駄になります。

サンプリングについて意図的に行う

ほとんどの場合、企業はトレースをサンプリングしたいと考えています。これは、すべてのトレースを保存すると、膨大な量のデータを保存および管理することになるためです。

例を挙げましょう。各スパンが500バイト(タグ付けとログを含む)であるとします。アプリケーションが1秒間に2000件のリクエストを処理し、20の異なるサービスがある場合、単純な20サービスのセットアップでは、1秒間に20MB、1時間あたり72GB、1日あたり1TBのデータが生成されます。

これがなぜほとんどの企業が分散トレースのサンプルを保存することになるのか説明します。コストをコントロールしながら、興味のあるデータを可視化するために適切なサンプリング戦略を選択することが重要です。

大まかに言えば、2つのサンプリングのカテゴリがあります:

1. 前もって/ヘッドベースのサンプリング

これは、特定のリクエストに対してスパンが生成される前に、どのスパンを保持するかを決定する簡単な方法です。これはヘッドベースのサンプリングと呼ばれ、決定はリクエストの最初または「ヘッド」で行われます。リクエストを見ることなく決定される場合、無バイアスサンプリングとも呼ばれます。ヘッドベースのサンプリングには、以下のようないくつかの一般的に使用されているメカニズムがあります。

  • 確率的または固定レートサンプリング:固定のサンプリング率(例:1%)に基づいてトレースのサブセットをランダムに選択する
  • レートリミットサンプリング:時間単位ごとのトレースするリクエストの固定制限を設定します。たとえば、レート制限が1分あたり100リクエストに設定されている場合、その1分間で最初の100リクエストのみがトレースされます。
  • 優先ベースのサンプリング:優先度ベースのサンプリングは、リクエストに異なる優先度を割り当て、サンプリング率を適応させます。優先度の高いリクエスト(例:重要なトランザクション)は高いサンプリング率を持ち、優先度の低いリクエストは低いサンプリング率を持ちます。

2. テールベースのサンプリング

テールベースのサンプリングは、トレース内の応答に基づいてサンプリングの決定を行う方法です。たとえば、レイテンシが高い場合やエラーが発生した場合にサンプリングを行います。この方法により、「興味深い」リクエストがトレースされるようになりますが、全体のサンプリング率が低い場合でも実現するのは難しいです。なぜなら、レスポンスが返ってくるまですべてのトレースをバッファに保存する必要があるからです。このガイドでは、テールベースのサンプリングについて詳しく説明しています。

ほとんどの組織では、通常、サンプリング率が1〜3%の単純なヘッドベースの確率的サンプリングメカニズムを使用します。OTelで固定レートサンプリングを設定する方法については、こちらを参照してください。

カスタムトレースの実装には選択的になりましょう

分散トレースは、カスタムトレーススパンを報告できることで強力です。カスタムスパンを使用すると、追加のドメイン固有情報を分散トレースに組み込むことができ、トレースデータをより有意義にすることができます。

エラーステートをスパンの一部としてキャプチャしてログに記録したり、サービスの動作をさらに説明する子スパンを作成したりすることができます。適切にタグ付けされたスパンは、コードで必要なログステートメントの量を大幅に減らすことができます。

トレースの文脈において、幅はインストゥルメント化されるサービスまたはコンポーネントの数を指し、深さは各スパンでキャプチャされる詳細レベルを指します。幅と深さの適切なバランスを取ることは、効果的なトレースメカニズムを実装する上で重要です。

一般的には、可能な限り幅広く、深く進む場所を選択することが良いアイデアです。

トレースを監視およびログシステムに統合する

既存の監視およびログシステムとトレースを接続して、開発者がトラブルシューティング時に3つのデータセットを相関させやすくすることを確認してください。通常、これは次の方法で行われます:

  • ログインジェクション:ログフレームワークやライブラリを使用して直接トレースID/スパンIDをログに挿入します。これにより、各ログメッセージには特定のトレースをクエリするために使用できるトレースIDが含まれます。
  • メトリクスタグ付け:メトリクスの記録時にトレース関連のタグやラベルを含めることができます。これらのタグには、トレースID、スパン名、その他のトレース固有のメタデータが含まれます。これにより、開発者はトレースデータをフィルタリングおよび集計し、分散システムを理解しやすくすることができます。

OpenTelemetryなどのプロトコルを使用することで、これを簡単に実現できます。

モダンなトレース可視化フロントエンドを選択する

フロントエンドには、ソリューション間で意味のある違いがあります。トレースデータを収集した後、それを視覚化できる必要があります。良いトレースの可視化では、システム内のトレースリクエストのフローを見ることができ、パフォーマンスのボトルネックを特定することができます。

ただし、すべてのトレースソリューションがデータを直接視覚化および分析するための直感的で使いやすい方法を提供しているわけではありません。一部のツールはトレースデータの収集と保存に優れていますが、基本的な可視化機能(例:Jaeger、Zipkin、AWS XRay)しか提供していません。一方、他のツールはトレースデータから洞察を提供することに重点を置いており、その結果、より洗練された可視化および分析機能(例:Honeycomb、Lighstep、Helios)に投資しています。

良い可視化ツールは、サービス依存関係マップを自動的に提供し、ガントチャートやウォーターフォールトレースの可視化を行い、トレースの詳細なクエリとフィルタリングを可能にするべきです。この記事は、分散トレースにおける可視化に関する包括的な視点を提供しています。

AIとトレースを組み合わせた次世代ツールを探索する

OTelが急速に成熟するにつれて、計器化はかなり標準化されてきました。同様に、ストレージとクエリも、過去数年間にわたり、オブザーバビリティ業界全体で広く商品化されてきました。現在、可視化と分析のレイヤーにはいくらかの違いがありますが、それ自体は意味を持ちません。

問題の原因に関する推論を生成するために分散トレースデータにAIを使用する新しいクラスのソリューションが出現しています。これらのソリューションは、最も現代的なトレーススタックを持ち、実装と管理を劇的に簡素化します。たとえば、ZeroKのようなソリューションでは、次の操作が可能です:

  • コードの変更なしに、すべてのコンポーネントに分散トレースを一括でインストールできます。すべてのサービス、DB、キューはOTelとeBPFを使用してすぐにカバーされます。
  • サンプリングの必要性をなくし、トレースの100%を処理し、AIを使用して異常/「興味深い」トレースを自動的に特定して保存します(エラートレース、高遅延トレースなど)。
  • 必要に応じて、異常なトレースに追加のコンテキスト(ログなど)を追加してデバッグを支援します。
  • これらのトレースにLLMを適用して、プロダクションの問題の可能な原因を自動的に特定します。

開発者のオンボーディングに投資する

これは、しばしば見過ごされがちですが、組織内での分散トレースの成功に重要な要素です。分散トレースは複雑であり、新しい開発者が効果的に使用する方法に追いつくのは困難です。トレースデータを解釈し、異なるマイクロサービス間の関係を理解し、分散トレースツールを使用して問題をトラブルシューティングする方法を開発者に教える必要があります。一貫した命名規則、適切な計器化、トレースコンテキストの伝播などのベストプラクティスについてのガイドを受ける必要があります。分散トレースのための開発者のオンボーディングを計画することは、戦略的な投資です。これにより、トレースのシステム内への統合が加速されるだけでなく、開発者がシステムの可視性、信頼性、パフォーマンスの継続的な改善の積極的な参加者となる文化が育まれます。

結論

分散トレースのベストプラクティスと、旅を容易にするための対策について見てきました。分散トレースはもはや目新しいものではありません。それはオブザーバビリティスタックの重要な一部に進化しています。

We will continue to update VoAGI; if you have any questions or suggestions, please contact us!

Share:

Was this article helpful?

93 out of 132 found this helpful

Discover more