Calendarの9日目の記事です。前回は@moomooyaさんのマイクロサービス化にあたって、gRPCを導入しようとしている話でした。Autumnにて発表された「OpenCensusによるAPMの実現と、未来」というセッション名がかっこよかったので、表現を拝借しました。分散トレーシングの必要性マイクロサービスのような分散アーキテクチャは複数のサービスにまたがって処理されているため、サービス間の通信を追跡することが難しくなります。障害発生時の原因究明が難しくなるパフォーマンス低下の原因究明が難しくなるそこで、分散トレーシングツールで可視化して上記の問題を解決する必要があります。分散トレーシングを学ぶにあたって、以下2つの用語は必ず覚える必要があります。EnvoyなのかEnvoyを使わずとも、ZipkinやJaeger等のトレース可視化プロバイダが提供するツールがあれば、分散トレーシングを実現することは可能です。実現のためには、トレース毎の識別子を生成してそれを伝搬していき、最終的にコレクターというコンポーネントに送ることが必須です。そのために各サービスに言語毎のクライアントライブラリを導入して、専用の実装をする必要があります。Polyglotが前提にある分散アーキテクチャであるマイクロサービスアーキテクチャにおいて、これは大きなコストを生む原因になります。そこで、インバウンドとアウトバウンド双方のトラフィックを前提に作られているEnvoyをサイドカーとして配置しておけば、この問題を解決してネットワークとアプリケーションを分離することが出来ます。このような、全サービス間通信をサイドカープロキシを経由させることによってマイクロサービス固有の課題の解決を行うアーキテクチャをサービスメッシュと呼びます。スパン間の親子関係等のコンテキストを適切に伝搬させるためには、アプリ内で特定の識別子を伝搬させる実装をする必要があります。これに関しては後述します。Envoyのトレーシングアーキテクチャ利用するトレースプロバイダにもよりますが、多くの場合以下のようなコンポーネントで構成されたアーキテクチャとなります。プロバイダによってStorageを提供してくれるものもあれば、自前で運用する必要があるものもあります。分散トレーシングでは通常、トレース内で一意の識別子を伝搬させることでスパンを関連付けていきます。この一連の流れの中で、Envoyの仕事は大きく分けて3つあります。トレースの生成とトレースの伝搬、そしてコレクターへの送信です。生成(ドキュメント)tracingオブジェクトを設定することで、トレースを生成することが可能になります。伝搬(ドキュメント)x-request-idという識別子を伝播して、呼び出されたサービス間のロギングを相関させていきます。前述したように、スパン間の親子関係を明確にするためには別の識別子の伝搬も必要です。Envoyはこの識別子をHTTPリクエストヘッダーに乗せて通信します。そのため、特定のヘッダーから識別子を取り出して次に通信するサービスへのリクエストヘッダーに追加する必要があります。少なからずコードの修正は必要になるということです。Envoyにはインバウンドトラフィックとアウトバウンドトラフィックを関連付ける手段がないので、これはアプリケーション開発者の責任だということです。これはトレース可視化プロバイダ毎に異なる識別子が必要になるため、自分が使うプロバイダのドキュメントをよく読む必要があります。執筆時点(2018/12/9)で対応しているトレース可視化プロバイダは以下です。プラガブルになるよう設計されておりドライバを実装するだけで良いので、新たなプロバイダをサポートすることも難しくありません。Zipkin(フォーマットに互換性があるJaeger等も含む)LightStepDataDogドキュメントに従って、トレースを送信するコレクタークラスタを指定します。Zipkinの場合は以下のように定義します。"/api/v1/spans"触って理解するEnvoyは公式のサンドボックスがいくつか用意されています。今回はこの中のjaeger-tracingを触りながら、分散トレーシングの一連の流れの理解を深めていきたいと思います。いう3つのコンテナが起動します。いう順に通信が行われます。可視化ブラウザでhttp://localhost:16686にアクセスして下さい。複数のスパンが一つのトレースとなって表示されているのが確認できます。サービスの実装を変更サービスのサンプル実装はexamples/front-proxy/service.pyにあります。注目すべき実装は以下の部分で、ここで受け取った識別子をヘッダーに乗せて伝搬させています。Propagationというリポジトリにて詳述されています。試しにこの処理をコメントアウトして、再度リクエストを送ってみましょう。スパンがそれぞれ別のトレースと認識されてしまっているのが分かります。スパン間で識別子を伝搬させないと正しくトレースを取得出来ない事が確認できました。全体的なアーキテクチャに始まり最終的にコードを触ることで、大まかな仕組みを理解して頂けたでしょうか?先日(2018/11/28)、EnvoyはCNCFの卒業プロジェクトに認定されました。その時のブログ内でも繰り返して述べられている通り、Envoyの目標は、アプリケーション開発者からネットワークを抽象化してビジネスロジックに集中できるようにすることです。これはEnvoyに限らず、クラウドネイティブが主流になった現代では多くの人が、アプリケーション開発者が創作活動に集中できる環境を望んでいます。2016年9月にLyftがEnvoyをOSSとして公開した時、本人達の想像を超えるほど反響がありました。これは、クラウドネイティブを推進するにあたってネットワークプロキシが非常に重要なポジションを占めていることを表しています。今後アプリケーションからネットワークを抽象化するようなプロジェクトがどんどん立ち上がるとしても、内部では常にネットワークプロキシがアプリケーションに寄り添っているはずです。そのため、プロキシへの理解を深めておくことはクラウドネイティブ時代において非常に大事だと思います。筆者も微力ながら議論に参加していき、アプリケーション開発者にとっての最高の環境作りに貢献していきたいと思います。*間違いを見つけたり情報が古くなっていたりしたらTwitter等でご指摘頂けると幸いです。(2)月別アーカイブはてなブログをはじめよう!NakaWatchさんは、はてなブログを使っています。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。