昨秋のSprint 2.0でNGINX Modern Apps Reference Architecture(MARA)プロジェクトを発表した際、一部のアーキテクチャのような「おもちゃ」ではなく、「堅牢で、テスト済みであり、Kubernetes環境で稼働する本番アプリケーションにすぐにデプロイできる」ソリューションを目指していることを強調しました。このようなプロジェクトには、オブザーバビリティツールが不可欠です。MARAチームのメンバーは全員、状態やパフォーマンスを把握できないと、アプリケーションの開発とデリバリーがいかにストレスのたまる作業になるかを身をもって経験しています。そのため、本番環境でのデバッグとトレースに必要な計測機能をMARAに組み込む必要があるという点で、すぐに意見が一致しました。
MARAのもう1つの指針は、オープンソースソリューションを優先することです。本記事では、多機能なオープンソースのオブザーバビリティツールを探す中で、どのようにして「OpenTelemetry」にたどり着いたのかを説明します。さらに、Python、Java、NGINXで構築されたマイクロサービスアプリケーションにOpenTelemetryを統合する際のトレードオフ、設計上の判断、手法、使用したテクノロジーについて詳しく解説します。
私たちの経験が、潜在的な落とし穴を避け、OpenTelemetryの導入を加速する一助となれば幸いです。この記事は、時間の経過とともに内容の鮮度が失われる可能性がある進捗報告であることにご留意ください。ここで取り上げるテクノロジーは、1年以内に成熟すると見込んでいます。また、一部のプロジェクトが現時点で抱える課題にも触れていますが、オープンソースに関わるあらゆる取り組みに心から感謝するとともに、今後の発展を楽しみにしています。
F5のアプリケーション
オブザーバビリティソリューションと統合するアプリケーションとして、Bank of Siriusを選びました。これは、GoogleのサンプルアプリであるBank of Anthosをフォークしたものです。マイクロサービスアーキテクチャを採用したWebアプリで、Infrastructure as Codeを使用してデプロイできます。このアプリケーションには、パフォーマンスと信頼性の面で改善できる点が数多くありますが、ブラウンフィールドアプリケーションとみなせる程度には成熟しています。そのため、OpenTelemetryをアプリケーションに統合する方法を示す好例だと考えています。これは、理論上、分散トレーシングによってアプリケーションアーキテクチャの問題点に関する有益なインサイトが得られるためです。
図に示すように、アプリケーションを支えるサービスは比較的シンプルです。

OpenTelemetryを選んだ理由
OpenTelemetryの選定に至るまでには、紆余曲折があり、いくつかの段階を経ました。
機能の要望リストの作成
利用可能なオープンソースのオブザーバビリティツール自体を評価する前に、オブザーバビリティのどの側面を重視するかを明確にしました。これまでの経験を踏まえて、以下のリストを作成しました。
- ロギング – ここでいうロギングとは、アプリケーションから従来型の改行区切りメッセージ群を生成することです。Bank of Siriusアプリでは、ログをBunyan形式
- 分散トレーシング – アプリケーション全体を構成する各コンポーネントの処理時間とメタデータ。アプリケーションパフォーマンス管理(APM)ベンダーが提供する情報に相当します
- メトリクス – 一定期間にわたって取得され、時系列データとしてグラフ化された測定値
- 例外/エラーの集約と通知 – 最も頻繁に発生する例外とエラーを集約したコレクションです。どのアプリケーションエラーが最も多いかを特定できるよう、検索可能である必要があります
- ヘルスチェック – アプリケーション内でサービスが正常に機能しているかどうかを確認するために、サービスへ定期的に送信されるプローブ
- ランタイム状態のイントロスペクション – 管理者のみが利用でき、アプリケーションのランタイム状態に関する情報を返す一連のAPI
- ヒープ/コアダンプ – サービスのランタイム状態を包括的に記録したスナップショットです。ここで重要なのは、オンデマンドまたはサービスのクラッシュ時に、これらのダンプをどれだけ容易に取得できるかです
希望する機能とツールの機能を比較
もちろん、単一のオープンソースツールやアプローチがこれらの機能をすべて備えているとは考えていませんでしたが、少なくとも、利用可能なツールを比較するうえで目標となる基準にはなりました。各ツールのドキュメントを参照し、ウィッシュリストに挙げた7つの機能のうち、どれをサポートしているかを確認しました。次の表に調査結果をまとめます。
テクノロジー ロギング 分散トレーシング メトリクス エラー集約 ヘルスチェック ランタイムイントロスペクション ヒープ/コアダンプELK + Elastic APM ✅ ✅ ✅ ✅ ✅ ❌ ❌Grafana ✅ ✅ ✅ ✅ ✅ ❌ ❌Graylog ✅ ❌ ❌ ❌ ❌ ❌ ❌Jaeger ❌ ✅ ❌ ✅ ❌ ❌ ❌OpenCensus ❌ ❌ ✅ ❌ ❌ ❌ ❌OpenTelemetry ベータ ✅ ✅ ✅ ✅ * ❌ ❌Prometheus ❌ ❌ ✅ ❌ ❌ ❌ ❌StatsD ❌ ❌ ✅ ❌ ❌ ❌ ❌Zipkin ❌ ✅ ❌ ✅ ❌ ❌ ❌
* 拡張機能として
この表を作成する過程で、厳しい現実を突きつけられました。各種ツールは機能も用途も大きく異なるため、すべてを同じカテゴリーに分類することはできませんでした。まるでリンゴとトースターを比べるようなものです。
たとえば、ELK(Elasticsearch-Logstash-KibanaにFilebeatを加えたもの)とZipkinでは、担う役割が根本的に異なるため、比較しようとするとかえって混乱を招きます。さらに残念なことに、「ミッション・クリープ」によって状況は一層わかりにくくなっています。おそらくユーザーの要望に応じて、ツール本来の主目的から外れた二次的な機能が追加され、ほかのツールとの機能の重複が生じているためです。表面的には、ELKはログの保存と可視化を担い、Zipkinは分散トレーシングを担います。しかし、Elasticの製品ポートフォリオを少し掘り下げると、分散トレーシングをサポートし、Elastic APMさらにはJaegerとの互換性も備えたElastic APMがすぐに見つかります。
本来の目的から機能が拡大していくという問題に加え、多くのツールは相互に統合できるため、コレクター、アグリゲーター、ダッシュボードなどをさまざまに組み合わせることができます。テクノロジーによって、相互に互換性があるものとないものがあります。
定性的調査の実施
そのため、この比較表だけでは、選定の根拠とするのに十分なほど正確な全体像を把握できませんでした。プロジェクトの価値観が私たちの価値観に近いほど、長期にわたって互換性を維持できる可能性が高いと考え、各プロジェクトの目標、基本原則、今後進む可能性のある方向性を定性的に調査する必要がありました。各プロジェクトのページを確認すると、この点はOpenCensusのページですぐに見て取れました。
OpenCensusとOpenTracingは統合され、両者の次期メジャーバージョンにあたるOpenTelemetryが誕生しました。OpenTelemetryは既存のOpenCensusインテグレーションとの後方互換性を提供します。また、既存のOpenCensusライブラリについては、今後2年間にわたりセキュリティパッチの提供を継続します。
これは、私たちにとって重要な判断材料でした。選択したものが将来にわたって通用するとは保証できないと分かっていましたが、少なくとも今後、コミュニティから確かな支持を得られることは確認したいと考えていました。この情報を踏まえ、OpenCensusを候補から外すことができました。また、Jaegerの採用も適切ではないと考えられました。現在は正式に非推奨となっている「OpenTracing」プロジェクトのリファレンス実装であり、新たなコントリビューションの大半はOpenTelemetryに集約されるためです。
そこで、OpenTelemetry Collectorについて詳しく調べました。
OpenTelemetry Collectorは、テレメトリデータの受信、処理、エクスポートを行うためのベンダーに依存しない実装を提供します。また、オープンソースのテレメトリデータ形式(Jaeger、Prometheusなど)に対応し、複数のオープンソースまたは商用バックエンドにデータを送信するために、複数のエージェントやコレクターを実行、運用、保守する必要がなくなります。
OpenTelemetry Collectorはアグリゲーターとして機能し、さまざまなオブザーバビリティデータの収集方法や計装方法を、異なるバックエンドと組み合わせて使用できます。たとえば、アプリケーションでZipkinを使用してトレースを収集し、Prometheusからメトリクスを収集して、構成可能なバックエンドに送信し、Grafanaで可視化できます。この設計にはほかにもさまざまな組み合わせがあるため、複数のアプローチを試し、ユースケースに適したテクノロジーを見極めることができます。
今後に向けたOpenTelemetryの統合
要するに、理論上はオブザーバビリティ技術を切り替えられるという点に魅力を感じ、OpenTelemetry Collectorの採用を決めました。このプロジェクトはまだ比較的成熟していませんが、技術を実際に使うことこそが全体像を理解する唯一の方法だと考え、オープンソースのインテグレーションのみを使用してOpenTelemetryを大胆に導入することにしました。
ただし、OpenTelemetry Collectorには不足している機能もあるため、それらについては他のテクノロジーに頼る必要があります。以降のセクションでは、採用したテクノロジーとその選定理由をまとめます。
ロギングの実装
ロギングは、オブザーバビリティの中では一見単純に思えますが、すぐに複雑な判断が必要になる要素です。コンテナからログ出力を収集するだけという点では単純ですが、その後、データの保存先、その保存先への転送方法、有効活用するためのインデックス作成方法、保存期間を決める必要があるため、複雑になります。ログファイルを有効に活用するには、さまざまな検索者のニーズを満たせるよう、十分に多様な条件で簡単に検索できる必要があります。
OpenTelemetry Collectorのロギングサポートを検討しましたが、執筆時点ではまだベータ版の初期段階です。他の選択肢の調査を続けながら、当面はロギングにELKを使用することにしました。
特に使用を避けるべき明確な理由がなかったため、デフォルトでElasticsearchツールを採用しました。これにより、デプロイを取り込みノード、調整ノード、マスターノード、データノードに分割できました。デプロイを容易にするため、Bitnamiチャートを使用しました。データ転送には、Kubernetes DaemonSetの一部としてFilebeatをデプロイしました。また、Kibanaをデプロイし、事前に読み込まれたインデックス、検索、可視化、ダッシュボードを活用することで、検索機能を追加しました。
このソリューションは機能したものの、デフォルト構成ではリソース消費量がかなり多く、K3SやMicrok8sのようなリソース規模の小さい環境では実行が難しいことが、ほどなくして明らかになりました。各コンポーネントのレプリカ数を調整できるようにすることで、この問題には対処できましたが、リソースの枯渇や過剰なデータ量が原因と考えられる障害もいくつか発生しました。
この結果に落胆するどころか、構成を変えてロギングシステムのベンチマークを実施し、Grafana LokiやGraylogなどの選択肢を検証する機会だと捉えています。軽量なロギングソリューションでは、より多くのリソースを消費するツールが備えている、一部のユーザーに必要な機能をすべて提供できない可能性もあります。MARAはモジュール式であるため、ユーザーの選択肢を増やせるよう、これらに対応する追加モジュールを構築する可能性があります。
分散トレーシングの実装
必要なトレーシング機能を提供するツールを選定するだけでなく、ソリューションの実装方法と、統合が必要なテクノロジーについても検討する必要がありました。
まず、どのような計装を行っても、アプリケーション自体のサービス品質に悪影響が及ばないようにしたいと考えました。私たちは全員、ログのエクスポート時に1時間ごとに決まってパフォーマンスが低下するシステムを扱った経験があり、同じ経験を繰り返したくはありませんでした。この点で、ホストごとに1つのインスタンスを実行できるOpenTelemetry Collectorのアーキテクチャは魅力的でした。各Collectorは、ホスト上で実行されているさまざまなアプリケーション(コンテナ化されているかどうかを問わず)のクライアントやエージェントからデータを受信します。Collectorはデータを集約し、必要に応じて圧縮してからストレージバックエンドに送信するため、理想的だと考えました。
次に、アプリケーションで使用している各プログラミング言語とフレームワークにおけるOpenTelemetryのサポート状況を評価しました。ここでは、少し事情が複雑になりました。表に示す2つのプログラミング言語と関連フレームワークしか使用していないにもかかわらず、複雑さは予想以上でした。
言語 フレームワーク サービス数Java Spring Boot 3Python Flask 3
言語レベルのトレーシングを追加するため、まずOpenTelemetryの「自動計装」エージェントを試しましたが、その出力は情報が多すぎて分かりにくいことが判明しました。自動計装ライブラリの成熟に伴って改善されると確信していますが、現時点ではOpenTelemetryエージェントの採用を見送り、コードにトレーシングを組み込むことにしました。
コードにトレーシングを直接実装する前に、まずOpenTelemetry Collectorを接続し、すべてのトレースデータをローカルで実行しているJaegerインスタンスに出力して、結果を確認しやすくしました。これは非常に有用でした。OpenTelemetryを完全に統合する方法を検討しながら、トレースデータの表示方法を試行錯誤できたためです。たとえば、HTTPクライアントライブラリが依存サービスの呼び出し時にトレースデータを含めていないことが判明した場合、その問題をすぐに修正リストへ追加しました。Jaegerでは、1つのトレースに含まれるさまざまなスパンを見やすく表示できます。

Python向け分散トレーシング
Pythonコードへのトレースの追加は比較的簡単でした。すべてのサービスから参照される2つのPythonソースファイルを追加し、それぞれのrequirements.txtファイルを更新して、関連するopentelemetry-instrumentation-*依存関係を追加しました。これにより、すべてのPythonサービスで同じトレース設定を使用できるようになりました。また、各リクエストのトレースIDをログメッセージに含め、依存先サービスへのリクエストに埋め込むことも可能になりました。
Java向け分散トレーシング
次に、Javaサービスに目を向けました。グリーンフィールドプロジェクトでOpenTelemetry Javaライブラリを直接使用するのは比較的簡単です。必要なライブラリをインポートし、トレーシングAPIを直接使用するだけです。ただし、F5と同様にSpringを使用している場合は、さらにいくつかの点を判断する必要があります。
Springには、分散トレーシングAPIである「Spring Cloud Sleuth」がすでに用意されています。これは、基盤となる分散トレーシング実装を抽象化するファサードを提供し、ドキュメントに記載されているとおり、次の処理を行います。
- トレースIDとスパンIDをSlf4J MDCに追加するため、ログアグリゲーターで特定のトレースまたはスパンに関連するすべてのログを抽出できます。
- Springアプリケーションの一般的なイングレスおよびエグレスのポイント(サーブレットフィルター、RestTemplate、スケジュールされたアクション、メッセージチャネル、Feignクライアント)を計装します。
- If
spring-cloud-sleuth-zipkinが利用可能な場合、……HTTP経由でZipkin互換のトレースを[生成して報告]します。デフォルトでは、localhost上のZipkinコレクターサービス(ポート9411)に送信します。サービスの場所は、spring.zipkin.baseUrlを使用して設定します。
このAPIを使用すると、@Scheduledアノテーションが付与されたタスクにもトレースを追加できます。
つまり、Spring Cloud Sleuthを使用するだけで、HTTPサービスエンドポイントレベルのトレースをすぐに取得できるという利点があります。このプロジェクトではすでにSpringを使用していたため、すべてをそのフレームワーク内に統一し、提供されている機能を活用することにしました。しかし、Mavenを使用してすべてを連携させる過程で、いくつかの問題が見つかりました。
- The Spring Cloud Sleuth Autoconfigure moduleは、現在もマイルストーンリリースの段階です。
- Spring Cloud Sleuth Autoconfigureモジュールは、古いアルファ版の「
opentelemetry-instrumentation-api」に依存しています。現在、このライブラリには新しい非アルファ版の1.xリリースがありません。 - Spring Cloud Sleuthではマイルストーンリリースの依存関係参照が特定の方法で記述されているため、プロジェクトは親プロジェクトオブジェクトモデル(POM)である「
spring-cloud-build」をSpring Snapshotリポジトリから取得する必要があります。
そのため、Maven Centralに加えてSpringリポジトリからもMavenで取得する必要があり、Mavenプロジェクトの定義はやや複雑になりました。これは、Spring CloudにおけるOpenTelemetryのサポートがまだ初期段階にあったことを明確に示しています。それでも作業を進め、Spring Cloud SleuthとOpenTelemetryを使用して分散トレーシングを構成するための「共通テレメトリモジュール」を作成しました。このモジュールには、テレメトリ関連の各種ヘルパー関数と拡張機能も含まれています。
共通テレメトリモジュールでは、以下を提供することで、Spring Cloud SleuthおよびOpenTelemetryライブラリのトレーシング機能を拡張しています。
- Spring対応の「
Autoconfiguration」クラス。プロジェクトのトレーシング機能と拡張機能を設定し、追加のトレースリソース属性を読み込みます。 - NoOpインターフェースの実装。これにより、すべてのSpring Cloud SleuthインターフェースにNoOpインスタンスを注入し、起動時にトレースを無効化できます。
- トレース名を正規化するための「トレース命名インターセプター」です。
- An エラーハンドラー。エラーをslf4jおよびSpring Cloud Sleuthのトレーシング経由で出力します。
- 各出力トレースに、サービスバージョン、サービスインスタンスID、マシンID、Pod名、コンテナID、コンテナ名、名前空間名などの追加情報をエンコードする、拡張実装のトレース属性。
- Hibernateが発行するSQLステートメントの直前にあるコメントにトレースIDを挿入するトレーシングステートメントインスペクターです。現在では、これはSQLCommenterで実現できるようですが、まだ移行していません。
さらに、サービス間でHTTP呼び出しを行う際に、より多くのメトリクスを取得し、カスタマイズ性を高めるため、Apache HTTP Clientを基盤とするSpring互換HTTPクライアントを実装しました。この実装では、依存サービスの呼び出し時にトレース識別子とスパン識別子をヘッダーとして渡すことで、トレース出力に含められるようにしています。また、OpenTelemetryによって集約されるHTTP接続プールのメトリクスも提供します。
総じて、Spring Cloud SleuthとOpenTelemetryを連携させてトレーシングを構成する作業は困難を極めましたが、それだけの価値はあったと考えています。このプロジェクトと本記事が、同じ道を進もうとする方々の道しるべとなれば幸いです。
NGINX向け分散トレーシング
リクエストのライフサイクル全体にわたり、すべてのサービスを関連付けるトレースを取得するには、OpenTelemetryをNGINXに統合する必要がありました。そのために、OpenTelemetry NGINX module(現在もベータ版)を使用しました。NGINXのすべてのバージョンで動作するモジュールのバイナリを入手するのは難しい可能性があると考え、サポート対象外のNGINXモジュールを組み込んだコンテナイメージのGitHub repositoryを作成しました。毎晩ビルドを実行し、簡単にインポートできるDockerイメージを通じてモジュールのバイナリを配布しています。
このプロセスは、ビルドプロセスにまだ統合されていません。対象は、NGINX Ingress ControllerのMARAプロジェクトです。ただし、近日中に統合する予定です。
メトリクス収集の実装
トレーシングのOpenTelemetry統合が完了した後、次にメトリクスに取り組みました。Pythonベースのアプリケーションには既存のメトリクスがなかったため、現時点では追加を見送ることにしました。Javaアプリケーションについては、Google CloudのBank of Anthosの元のソースコードが、MicrometerとStackdriverを併用してメトリクスをサポートしています。しかし、このコードではメトリクスバックエンドを設定できなかったため、Bank of AnthosをフォークしてBank of Siriusを作成した後に削除しました。それでも、メトリクスフックがすでに存在していたことから、適切なメトリクス統合が必要であることは明らかでした。
構成可能で実用的なソリューションを実現するため、まずOpenTelemetry JavaライブラリとMicrometerのメトリクス対応を調査しました。両テクノロジーの比較を検索したところ、執筆時点ではOpenTelemetryのメトリクス機能がまだアルファ版であるとはいえ、JVMのメトリクスAPIとして使用する場合のOpenTelemetryの短所を列挙した結果が複数見つかりました。MicrometerはJVM向けの成熟したメトリクスファサードレイヤーです。slf4jと同様に、それ自体がメトリクス実装なのではなく、構成可能なメトリクス実装のフロントエンドとなる共通APIラッパーを提供します。興味深いことに、SpringではデフォルトのメトリクスAPIとして採用されています。
この時点で、以下の事実を比較検討しました。
- OpenTelemetry Collectorは、ほぼあらゆるソースからメトリクスを取り込むことができます。これには、Prometheus、StatsD、ネイティブのOpenTelemetry Protocol(OTLP)が含まれます
- Micrometerは、PrometheusやStatsDをはじめ、多数のメトリクスバックエンドにも対応しています
- JVM向けOpenTelemetry Metrics SDKは、OTLP経由でのメトリクス送信をサポートしています
いくつかの実験を経て、MicrometerファサードとPrometheusのバックエンド実装を使用し、OpenTelemetry CollectorがPrometheus APIを介してアプリケーションからメトリクスを取得するように構成するのが、最も現実的なアプローチだと判断しました。多くの記事から、OpenTelemetryに一部のメトリクスタイプがないことで問題が生じる可能性があることは把握していましたが、私たちのユースケースではそれらのタイプは必要ないため、この妥協は許容できるものでした。
OpenTelemetry Collectorについて、興味深い点が1つわかりました。トレースはOTLP経由、メトリクスはPrometheus API経由で受信するように設定していても、OTLPまたはその他のサポート対象プロトコルを使用して、両方の種類のデータを外部のデータレシーバーに送信するよう設定できます。これにより、アプリケーションをLightStepで簡単に試すことができました。
全体として、Javaでのメトリクスの実装は比較的簡単でした。豊富なサンプルやチュートリアルが用意されているMicrometer APIに準拠するように実装したためです。メトリクスとトレーシングの両方でおそらく最も難しかったのは、pom.xmlファイル内のtelemetry-common用Maven依存関係グラフを適切に構成することでした。
エラー集約の実装
OpenTelemetryプロジェクトのミッションには、エラー集約そのものは含まれていません。また、エラーのタグ付けについても、SentryやHoneybadger.ioのようなソリューションほど洗練された実装は提供されていません。それでも、別のツールを追加するのではなく、短期的にはOpenTelemetryをエラー集約に使用することにしました。Jaegerのようなツールでは、error=trueを検索することで、エラー状態を含むすべてのトレースを見つけられます。これにより、少なくとも頻繁に発生している問題の傾向を把握できます。将来的には、Sentryとの統合を追加することも検討する可能性があります。

ヘルスチェックとランタイムイントロスペクションの実装
このアプリケーションでは、ヘルスチェックによって、サービスが正常か、または起動フェーズを完了したかをKubernetesに通知します。サービスが正常でない場合、インスタンスを終了または再起動するようにKubernetesを構成できます。このアプリケーションでは、ドキュメントが不十分であると判断したため、OpenTelemetryのヘルスチェックを使用しないことにしました。
代わりに、JVMサービスでは、SpringプロジェクトのSpring Boot Actuatorを使用しています。これは、ヘルスチェックエンドポイントに加え、ランタイムイントロスペクションとヒープダンプのエンドポイントも提供します。Pythonサービスでは、Flask Management Endpoints moduleを使用しています。これは、Spring Boot Actuatorの機能の一部を提供するモジュールです。現在提供されているのは、カスタマイズ可能なアプリケーション情報とヘルスチェックのみです。
Spring Boot ActuatorはJVMおよびSpringと連携し、内部状態の確認、監視、ヘルスチェック用のエンドポイントを提供します。さらに、各エンドポイントで提示されるデフォルトデータにカスタム情報を追加するためのフレームワークも提供します。エンドポイントでは、キャッシュの状態、ランタイム環境、データベースのマイグレーション、ヘルスチェック、カスタマイズ可能なアプリケーション情報、メトリクス、定期ジョブ、HTTPセッションの状態、スレッドダンプなど、実行時の内部状態を確認できます。
Spring Boot Actuatorに実装されているヘルスチェックエンドポイントはモジュール式に構成されており、サービスの健全性は、LivenessまたはReadinessに分類される複数の個別チェックで構成できます。すべてのチェックモジュールを表示する完全なヘルスチェックも利用でき、通常はこちらのように表示されます。
情報エンドポイントは、JSONドキュメント内で、単一の最上位JSONオブジェクトと一連の階層的なキーと値として定義されます。通常、このドキュメントには、サービス名とバージョン、アーキテクチャ、ホスト名、OS情報、プロセスID、実行可能ファイル名のほか、マシンIDや一意のサービスIDなど、ホストに関する詳細情報が記載されます。
ヒープダンプとコアダンプの実装
「ツールの機能と要望リストの比較」の表にあるとおり、いずれのツールもランタイムイントロスペクションやヒープダンプ/コアダンプをサポートしていません。ただし、基盤フレームワークであるSpringはどちらもサポートしています。オブザーバビリティ機能をアプリケーションに組み込むには、多少の作業が必要でした。前のセクションで詳しく説明したとおり、ランタイムイントロスペクションにはPythonモジュールとSpring Boot Actuatorを併用しています。
同様に、ヒープダンプについては、Spring Boot Actuatorが提供するスレッドダンプエンドポイントを使用して、必要としていた機能の一部を実現しています。オンデマンドのコアダンプや、理想とする細かな粒度でのJVMヒープダンプは取得できませんが、わずかな追加作業で必要な機能の一部を利用できます。残念ながら、Pythonサービスのコアダンプにはかなりの追加作業が必要となるため、対応は後日に延期しています。
まとめ
大いに悩み、これまでの選択を自問した末、MARAのオブザーバビリティには以下のテクノロジーを使用する方針にまとまりました(以下、OpenTelemetryを「OTel」と表記します)。
- ロギング(すべてのコンテナが対象)– Filebeat → Elasticsearch / Kibana
- 分散トレーシング
- Java – Spring Cloud Sleuth → Spring Cloud Sleuth exporter for OTel → OTel Collector → Jaeger、Lightstep、Splunkなどのプラグイン可能なエクスポーター
- Python – OTel Pythonライブラリ → OTel Collector → プラグイン可能なストア
- NGINXおよびNGINX Plus(NGINX Ingress Controllerはまだサポートされていません)– NGINX OTelモジュール → OTel Collector → プラグイン可能なエクスポーター
- メトリクス収集
- Java – Spring経由のMicrometer → Prometheus exporter → OTel Collector
- Python – まだ実装されていません
- Python WSGI – GUnicorn StatsD → Prometheus(StatsD / ServiceMonitor経由)
- NGINX – Prometheusエンドポイント → Prometheus(ServiceMonitor経由)
- Error Aggregation – OTel distributed traces → pluggable exporter → exporter’s search functionality for finding traces marked with
error - ヘルスチェック
- Java – Spring Boot Actuator → Kubernetes
- Python – Flask Management Endpoints module → Kubernetes
- ランタイムイントロスペクション
- Java – Spring Boot Actuator
- Python – Flask Management Endpointsモジュール
- ヒープ/コアダンプ
- Java – Spring Boot Actuatorによるスレッドダンプのサポート
- Python – 現時点では未対応
この実装は、現時点のスナップショットです。開発の進展に伴い、今後も確実に変更され、進化していきます。近日中に、アプリケーションに対する大規模な負荷テストを実施する予定です。その結果から、オブザーバビリティへのアプローチにおける多くの課題を把握し、オブザーバビリティ機能をさらに追加できると見込んでいます。
ぜひ、Modern Apps Reference Architectureとサンプルアプリケーション(Bank of Sirius)をお試しください。改善に向けたアイデアがございましたら、GitHubリポジトリへのご協力をお待ちしています。
関連記事
この投稿はシリーズの一部です。MARAに順次機能を追加するのに合わせて、その詳細をブログで公開しています。
- 新しいオープンソースのモダンアプリ向けリファレンスアーキテクチャ
- Modern Apps Reference ArchitectureへのOpenTelemetry統合 – 進捗レポート (本記事)
- MARA:お手元のワークステーションで実行可能に
- NGINX Modern Apps Reference Architectureバージョン1.0.0を発表
関連するブログ記事
チュートリアル:NGINXを使用してアプリケーション向けにOpenTelemetryを構成する
OpenTelemetryを使用してNGINXサーバーの状態と健全性をより明確に把握することで、問題のトラブルシューティングを行い、Webアプリケーションのパフォーマンスを向上できます。
AkitaのNGINX Plus認定モジュールでAPIエンドポイントの問題を特定・修正
Akita SoftwareのAPIオブザーバビリティ向け新しいNGINX Plus Certified Moduleを活用して、APIエンドポイントの問題をより迅速に特定し、修正できます。
JavaプロジェクトをスキャフォールディングしてKubernetesネイティブアプリを構築する方法
Red HatのシニアプリンシパルデベロッパーアドボケイトであるDaniel Oh氏が、Javaプロジェクトをゼロから構築するためのひな形を作成し、Kubernetesネイティブアプリケーションとしてビルドする方法を解説します。
F5 NGINXaaS for Azureのご紹介:Microsoft Azureでネイティブに利用できるSaaS型ロードバランシング
NGINXaaS for Azureは、NGINX PlusをAzureネイティブのSaaSとして利用できるサービスです。NGINXの設定を容易にリフト&シフトできるため、クラウド導入とモダンアプリの展開を加速できます。

SELinuxでNGINXおよびNGINX Plusを使用する
Red Hat Enterprise Linux(RHEL)および関連ディストリビューションでSecurity-Enhanced Linux(SELinux)を有効にすると、デフォルト設定によりNGINXとNGINX Plusの一部の操作が制限されます。この記事では、すべての機能を利用できるようにSELinuxの設定を変更する方法について説明します。
NGINX PlusによるAWS Auto Scalingグループの負荷分散
新しいnginx-asg-sync統合ソフトウェアにより、NGINX PlusはAWS Auto Scalingグループの負荷を直接分散できるため、クラウドでの負荷分散がさらに柔軟になります
