LIFULL札幌開発拠点で働くエンジニアの村田です。
札幌では本格的に雪が降り始め、寒さが非常に厳しい時期になってきました。
本エントリーは、LIFULL Advent Calendar 2022、12月22日の記事であり、LIFULLのプロダクトの可観測性を向上させた話をさせていただきます。
背景
LIFULLではマイクロサービスプラットフォームとして内製の「KEEL」というPaaSを用意し、それを利用してアプリケーションを開発することで開発者の生産性の向上を図ってきました。
KEELについての詳しい話は以下を参考にしてください。
ログ基盤もKEELが提供する機能の一つで、当時はAWSのフルマネージドサービスであるCloudWatch Logsを利用していました。 特にCloudWatch Logs Insightの体験が良く、これを利用してアプリケーションのログを柔軟に検索することができていました。 しかし、当時のログ基盤周りでは以下の問題点がありました。
ログはCloudWatch Logs、メトリクスはGrafanaで閲覧と、ツールが2つに分かれて利用している状況だった
マイクロサービス毎のログに共通IDが割り振られておらず、特定のリクエストに関連するログの調査コストが高かった
CloudWatch Logsにかかる費用が増大しつつあった
これらの状況を鑑みて、KEELチームはGrafana Lokiを利用し、より利便性の高いログ基盤を再構築する決断に至りました。
Grafana LokiとはGrafana Labが提供するスケーラブルで高可用性なログ集約システムです。 集約されたログはLogQLと呼ばれるクエリで柔軟に検索・集計することが可能であり、ストレージはS3などを利用して費用面でも安く抑えることができます。
CloudWatch Logsとの比較検証
いきなりGrafana Lokiに移行しても、開発者体験が失われてしまっては意味がありません。
KEELチームでは、Grafana Lokiによるログ検索体験がCloudWatch Logsを利用していた時と変わらないか、それ以上のものを提供できるか検証する必要がありました。
まず最初のステップとして、従来のログ基盤に加え、検証対象であるGrafana Lokiにもログを書き込み、KEELチームでその体験を検証することにしました。
たとえばCloudWatch Logs Insightの以下のようなクエリは
fields @timestamp, @message, @logStream | filter structural_log.status >= 499 | sort @timestamp desc | limit 20
Grafana Lokiでは、LogQLを用いて以下のように同様の表現をすることができます。
{grouping="kubernetes.ns.svc"} | json | structural_log_status >= 499
CloudWatch Logs Insightでできる以下のような集計については
stats count(*) by @logStream | filter structural_log.status >= 499
検索したログから、アドホックスタティクスアイコンをクリックすることで簡単な集計結果を得ることができますし
以下のようなクエリで代替する結果を得ることができます。
sum( rate( {grouping="kubernetes.ns.svc"} | json | structural_log_status >= 499 [1m] ) ) by (metadata_pod_name)
上記のようにCloudWatch Logs Insightによるログ検索は、LogQLでほぼ代替することができ、これらの体験はGrafana Lokiでもほとんど損なわれることはないと判断しました。
Chrome ExtentionによるGrafana Lokiの体験向上
CloudWatch Logs Insightでは、fieldに@logStreamを指定することで、該当ログ付近のログを表示するリンクが生成されます。
Grafana Logにも対象ログの前後のログを表示する機能はありますが、少々使い勝手が悪く利用しづらい状態でした。
そこでKEELチームはChrome Extentionを独自に開発して、Grafana LokiのHTMLを書き換え、同等のリンクを作成することに成功しました。
具体的には、Grafana Lokiに表示されるログのtimestampをクリッカブルにして、その前後の時間帯をクエリに加えたログの検索結果に遷移できるようにしました。こうすることでCloudWatch Logs Insightの@logStreamと同じ体験を実現することができました。
このChrome Extentionはこれだけの利用にとどまらず、後述するTraceIDを利用したログ検索への導線を作成したり、エラーログに書かれるスタックトレースからGitHub上の該当コードに飛べるようにするなど、色々応用することができました。
TraceIdの埋め込み
さらなる体験向上を目指し、KEELチームが次に行ったのは、LIFULL HOME'Sへのリクエストに共通のID(TraceId)を割り振り、後続のマイクロサービスにそれを伝播させることでした。
LIFULL HOME'Sは複数のマイクロサービスで構築されており、それぞれのマイクロサービス毎にロググループができていたため、マイクロサービスを横断した関連ログの検索が非常に手間のかかる作業でした。
特定のリクエストに関連したログ全てにTraceIdを付与することで、複数のサービスに散らばったログを横断で絞り込むことができるようになります。
KEELでは、以前からログに共通IDを付与する運用を開発者に推奨してきましたが、LIFULLの主要サービス含めあまり徹底されていませんでした。結果、ログの検索に手間がかかることに繋がっており、これは従来のログ基盤自体の問題というよりは、ログの運用方法の問題といった方が正しいです。
今回のログ基盤刷新を機に、この辺りの運用もしっかりと整備することにしました。
OpenTelemetryを導入することで、比較的容易にTraceIdの伝播を行うことができます。
アクセスログだけでなくエラーログにも可能な限りTraceId等を埋め込み、特定のリクエストと紐付けられるようにしました。
対象となるマイクロサービスの数は少なくはなかったものの、各部署の開発者と協力し作業を進めることで、ほぼ主要なサービスへのTraceIdの導入が終わり、IDによる関連ログを横断検索する体験を提供できるようになりました。
ここでも前述したChrome Extentionを利用し、ログに記載されているTraceIdをクリッカブルにして、TraceIdのリンクを辿るだけで容易にログの絞り込みが行えるようにしました。
リクエストのトレーシング
TraceIdを導入した副産物として、リクエストの分散トレーシングも可能になりました。
以下は、とあるリクエストをトレースした結果になります。ツールはGrafana Tempoを利用しています。
特定のリクエストに対して、裏ではどのサービスが何回呼び出されてそれぞれどの程度時間がかかっているかが視覚的にわかるようになりました。
リクエストのトレーシングができるようになったことで、ボトルネックとなっているサービスが特定しやすくなり、サイトのパフォーマンスチューニングが捗るようになります。
実際、サイトの高速化をはかるPJのメンバーがこの機能を利用することでパフォーマンス改善に役に立ててくれていました。
ログ基盤の切り替えの障壁を下げるために
ある程度ログ基盤の並行運用期間を経て検証を重ね、十分に代替できると判断したタイミングで、CloudWatch Logsへのログの転送をストップし、ログ基盤を切り替えました。
CloudWatch Logsから新しいログ基盤に切り替わることで多少なりとも開発者に学習の負担がかかるので、そのコストを最小限にするためにKEELチームではチュートリアル動画を用意しました
1-2分程度の動画の中で、ログ基盤の検索のチュートリアルを行うことで、すぐに開発者がGrafana Lokiを使いこなせるイメージがわくようにしたのです。
この工夫もあってか、特に大きな混乱もなく開発者は新しいログ基盤を利用してもらえることができています。
加えて、ログ基盤を切り替えたことにより従来のログ基盤にかかっていた費用の約70%を削減することができました。
CloudWatch Logs関連費用のうち、その大半を占めるのがPutLogEventsであり、今回のログ基盤の移行でこのあたりの費用がすべてカットできたのが大きな要因です。
これは年間で換算するとかなり大きなコストカットになり、LIFULLのビジネスにも大きなインパクトを与えることになりました。
まとめ
CloudWatch Logsによる従来のログ基盤をGrafana Lokiに移行した話を紹介させていただきました。
移行後は、Observabilityを構成する要素である、メトリクス、ログ、トレーシングの全ての情報がGrafanaで参照できるようになりました。
さらにGrafana LokiとChrome Extentionを組み合わせることで、CloudWatch Logsと同等、それ以上の体験を開発者に提供できるようになり、LIFULLのプロダクトの可観測性が向上しました。
フルマネージドサービスに比べるとGrafana Lokiを自前で運用する必要があるため、その分の運用コストは増加したものの、上記の体験に加え金額面での大きなコストカットメリットもあり、ログ基盤の移行は大きな価値があったと思っています。
今回お話しさせていただいたログ基盤だけでなく、KEELチームの様々な取り組みを別エントリーで紹介させていただいていますので、ご興味のある方は以下のエントリー一覧をご覧ください。
最後に告知です。LIFULLでは、「あらゆるLIFEを、FULLに。」に実現を目指して共に働いていただける仲間を募集しています。 カジュアル面談という形で、まずは気軽に情報交換、ということも可能ですので、ご興味がある方は以下のページをご覧ください。