マイクロサービスのボトルネック把握のために 「OpenTelemetry」を用いた、分散トレーシングの実現事例 - ログミーTech
「ABEMA」への「OpenTelemetry」導入事例を発表
shimizukawa.iconやっぱりこれだよねー
ベンダーに依存せずに計装ができる仕組みを持つ
この計装に関して、基本的にベンダーの提供するSDKを用いることになるのですが、これがベンダーロックインにつながります。つまり、「AWS X-Ray」から「Cloud Trace」に乗り換えようとすると、計装のやり直しが必要になります。
すでに稼働しているコードでトレーシングを行うためには数々の対応が必要で、段階的に導入を進めました。
shimizukawa.iconはい
まずはHTTPサーバーです。このようにミドルウェアを追加するだけで計装できます。ヘルスチェックのリクエストはノイズになるため、フィルターするところがポイントです。
shimizukawa.iconなるほど確かに。これやってみて気付いたんだろうな。
先ほどのコードの続きですが、これはCloud Traceにエクスポートするための実装です。万が一初期化に失敗した場合は、何もしないエクスポーターにフォールバックすることで、アプリケーションの予期せぬ起動失敗を防ぎます。私たちは「Wire」でDependency Injectionをすることが多いため、このように実装しています。
shimizukawa.iconここが心配どころ。
shimizukawa.iconもう1つはエクスポーターが負荷増大を招かないかが心配。 -> 後半に話題があった
custom samplerを実装することで、Span名の先頭位置よりフィルターするように実装しました。
shimizukawa.iconなるほど。不要なSPANを除去するのね。
また、OpenTelemetryで使用できるロギングライブラリが限定されているため、すでに導入されているライブラリを使用するには、ブリッジする必要がありました。
shimizukawa.iconなるほど。Pythonなら標準Loggerは対応されてると思うけど(まだExperimentalだと思うけど)、structlogの対応は要りそうかな。 istio-proxyコンテナによって、Trace Contextが付与、伝播されます。istio-proxyが受信してアプリケーションに渡すリクエストに関してはTrace Contextが伝播されますが、アプリケーションが実装の中でコンテキストを伝播していないと、そこでトレースは途切れます。
はい。
今後の展望
まず、「OpenTelemetry Collector」の導入が挙げられます。今は直接Cloud Traceに送信していますが、Collectorを経由させるアーキテクチャに変更することで、これらの恩恵が受けられます。
https://scrapbox.io/files/651611a07ec24b001c4d28ba.png
ここも悩みどころ。
次に、「Grafana Tempo」の導入です。クラウド横断でトレーシングを実現する場合、どちらのクラウドのソリューションを採用するかという問題があります。また、大規模なサービスで利用する際には、ランニングコストの問題もあります。
OpenTelemetryを採用した一番の理由は?
司会者:まず「計測するとなって、OpenTelemetryを採用した一番の理由は何だったのか?」というのを教えていただければなと。 司会者:たぶんほかの選択肢としては、たぶん「Datadog」とか「NewRelic」みたいなサービスがあると思いますが、そこらへんも鑑みて。あとはコストの問題とかもたぶんあると思うんですが、そういった点を考えてOpenTelemetryにされたということですかね。ありがとうございます。 コンテキストが伝播していない部分をどう探し出したのか?
司会者:どうやって伝播していない箇所を探し出したんですか?
宮﨑:今回、トレーシングを導入するにあたって、トレーシングを導入したいサービスというのがそもそも負荷試験をしている段階でけっこう見えていたんですよ。そのサービスを調査するにあたって、そもそもトレーシングを導入する前に、例えばタイムアウトを設定したいとかそういうことがけっこうあって。そのサービスはコンテキストがそもそも伝播されていないということを、けっこう負荷試験を通して知っていたんですよね。
それもあってコンテキストの伝播がされていないことを知ることができて、対応したかたちになります。負荷試験を経験して知ることができたという感じになりますね。
メトリクスのトレースはサンプリングレートで計測している
司会者:次が、メトリクスの……トレースですね。実際に先ほどのトレースのコードを挟んで、データをバックエンドに送ると思うんですが、たくさん送るとやはりデータ量が増えたり、課金の額が増えていったりすると思います。全件トレースを取って送るのか、もしくはサンプリングをしたりしているのかという質問ですね。
宮﨑:まさに、サンプリングをしています。どれぐらいのレートでサンプリングをしているかはちょっと述べられないのですが、ABEMAなのでリクエスト数もかなり多いというのもあって、できる限り少ないサンプリングレートで計測をしていますね。
トレーシングの導入における負荷の問題はないのか?
司会者:次もトレース情報のお話です。要はネットワークの通信が発生すると思うのですが、そういった処理によってアプリケーションへの負荷になることがあったりは……さすがにそれは大丈夫だったんですかね?
宮﨑:トレーシングを導入する時に、一応それは話題にはなったんですが、導入したのが負荷試験をやっている最中だったというのもありますし、そのトレースを導入した後にさらに負荷を上げて負荷試験をやるということもわかっていたので、実際にトレーシングを導入したことが負荷になったかどうかはちょっとわからないんですけど。負荷試験をするから導入しても問題ないんじゃないかという、問題があったら見えてくるだろうというかたちで導入しました。
OpenTelemetry RedisやOpenTelemetry MongoDBは、何をトレース情報として含められるのか?
宮﨑:まず導入の仕方としては、イニシャライズする時にMongoだったらモニタリングみたいな、初期化の設定をするコードがあって、そこに入れ込みます。見えるものとしては、Mongoだったらまさにクエリのfindだったり、そういうものがトレース情報として出てきます。findした部分の名前とその時間がきちんと出てきます。
Redisもまさに同じようなかたちでsetしたりgetしたものがトレース情報として出てきます。
司会者:じゃあ、実際にそのアプリで、例えばユーザーをgetする処理のキャッシュから引っ張ってきた時に、叩いたgetのトレース情報とかがきちんとパッと出てくるみたいな。