はじめまして、2023/6からfreeeのEnabling SREチームに所属している大木竜勝(ryu)です。 この記事はfreee Developers Advent Calendar 2023 - Adventar 3日目です。 この記事ではenvoyの分散トレーシングを用いてオブザーバビリティの向上を実現した取り組みについての記事になります。
背景
freeeではAmazon Web Services (AWS) Elastic Kuerbentes Service (EKS) クラスタ上にアプリケーションが載っておりその構成としてはenvoyが前段に存在し、後段に各アプリケーションPodが存在する構成となっています。
上記の構成においてクラスタの単位はfreee会計やfreee人事労務といったプロダクト毎にクラスタが分かれている構成となっています。
そのため、他プロダクトとの連携でアプリケーションPodがクラスタの別れたPodにリクエストをおくるとApp Pod => LB => envoy => App Pod
という経路でリクエストが届くようになっています。
また、freeeではDatadogにトレース情報を送信することでサービス間の関係性を把握したり処理のボトルネックを把握していますがこれまでのfreeeではアプリケーションPodのみがトレース情報を送信しておりenvoyはトレース情報を出していませんでした。
そのためPodにリクエストが届かない際や届くのに時間がかかっている際にLBとenvoyどちらが原因なのか切り分けが非常に難しいという問題がありました。
そこでenvoyからもトレース情報を送るようにすることでオブザーバビリティを向上させる必要がありました。
どのようにトレーシングを導入したか
設定は非常に簡単でenvoyのConfigurationファイルに以下のようなfilterとclusterの設定を追加するだけでした。
- filters: - name: envoy.filters.network.http_connection_manager typed_config: "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager generate_request_id: true request_id_extension: typed_config: "@type": type.googleapis.com/envoy.extensions.request_id.uuid.v3.UuidRequestIdConfig use_request_id_for_trace_sampling: false tracing: provider: name: envoy.tracers.datadog typed_config: "@type": type.googleapis.com/envoy.config.trace.v3.DatadogConfig collector_cluster: datadog_agent service_name: xxx-app-envoy ~~~ - name: datadog_agent connect_timeout: 1s type: STRICT_DNS lb_policy: ROUND_ROBIN load_assignment: cluster_name: datadog_agent endpoints: - lb_endpoints: - endpoint: address: socket_address: address: datadog.datadog.svc.cluster.local port_value: 8126
このような設定をデプロイすることにより簡単にenvoyのトレース情報を見ることが出来るようになりました。
気をつけた点
今回の設定を行う上で気をつけた点としては以下の2点です
- トレース情報を出すことによってenvoyのパフォーマンスの劣化が起きないか
- kubernetes環境でenvoyからdatadog agentにトレース情報を送る際の設定方法について
トレース情報を出すことによってenvoyのパフォーマンスの劣化が起きないか
今回envoyの分散トレーシングを導入する上でパフォーマンスに悪化がないかは特に気になるポイントでした。 そのため以下のようなことに注意しながら導入を進めていくことで大きな問題なくデプロイする事ができました
- staging環境でメトリクスを確認しパフォーマンスに影響がないことを確認する
- envoyのレスポンスタイムに変化がないか
- CPUやメモリの使用率に変化がないか
- 比較的小さめのプロダクトから導入する
- 影響の少ない時間にデプロイを行うようにし、問題があった場合もすぐに切り戻せるようにする
kubernetes環境でenvoyからdatadog agentにトレース情報を送る際の設定方法について
envoyのConfigurationファイルはDatadogの公式Docを参考に設定を進めていましたが、datadog agentのアドレスとして何を設定すべきかについて悩んでいました。
具体的には以下の2つの選択肢があり得ると考えていました。
- Datadog Agentがnodeに開けているportであるhostportにリクエストを送るようにする
- Datadog AgentのClusterIP Serviceに対してリクエストを送るようにする
当初、Datadog Agentがhostportを用意していること等から1番の方が良いのかと考えておりそのためにenvoyが存在しているNodeのhostipをenvoyのConfigurationファイルに設定する必要がありました。 しかしながら、freeeではenvoyのConfigurationファイルはConfigMapで管理しておりDownward APIによるPodへの環境変数の導入では実現できそうにありませんでした。 代替案を探すためにも改めてkubernetesの古いissueなども見てみたのですがConfigMapにはDownward APIから値を受け取って値を代入することは出来ず、init containerを使ってenvoyのConfigurationファイルを修正する必要がありそうでした。
init containerを使う手法は個人的にはあまりシンプルではなく設定がConfigMapで完結しなくなってしまうので出来れば避けたいと考えました。 そこで、Datadogのサポートに1番と2番の方法どちらが良いのかまた1番の方法のほうが良い場合どのように設定するのがベストプラクティスなのかを問い合わました。 数日のうちに返ってきた回答としては2番の手法でClusterIP Serviceを利用すべきという回答を頂きinit containerを作成する手戻りなどなくスムーズにトレース情報を取得する事ができました。
まとめ
SREチーム内課題に感じていたenvoy周りのオブザーバビリティの向上を実現した方法とその際に気をつけた点について簡単にですが紹介しました。この設定は現状いくつかのプロダクトに導入されている段階ですべてのプロダクトにはまだ入っていないので今後スピード感を持って横展開していきオブザーバビリティの高い状況を作っていきたいと考えています!
明日のfreee Developers Advent Calender 2023は、freee 会計のエンジニア jaxx さんの記事になります!
最後に私事ですが私がfreeeに転職して来てからちょうど半年ほどで分からないことも多い中、Enabling SREのメンバー・他SREチームの方々・プロダクトチームの皆様には多くのサポートを頂くことで実現できたかなと思っています。本当にありがとうございました。