RAKUS Developers Blog | ラクス エンジニアブログ

株式会社ラクスのITエンジニアによる技術ブログです。

OSSでオブザーバビリティを実現する (Elastic Stack x OpenTelemetry on Kubernetes)

こんにちは。インフラエンジニアの gumamon です! 最近はSRE的なことも ちょこちょこ やらせて頂いています。

NewRelic、Datadog、モダンな監視(オブザーバビリティ)って良いですよね。 弊社もKubernetes(k8s)等を利用した環境が増えてきた折、そろそろ必要になってきた(と思っている)のですが、NewRelic、Datadog等のクラウドサービスはランニングコストが安くない。 そこで内製できないかやってみよう!ということになり、試行錯誤をした結果どうにか表題の構成で作ることができたのでご紹介をしたいと思います!

この記事では、k8sを観測対象とし、オブザーバビリティを実現した際のアーキテクチャ構成、並びに四苦八苦する中で得た観測の勘所(私見)についてご紹介します。

目次

オブザーバビリティとは

Observabilityと表記され、日本語では「可観測性」と呼ばれる概念です。
より日本語の感覚に寄せた表記をするのであれば、「観測する能力」 (= Observe + Ability)とも言えるかと思います。 観測と監視の違いは何か?と聞かれることがあるのですが、私は「見ている対象が違う」と回答しています。

  • 「顧客体験」を観測する
  • 「システムの正常性」を監視する

言うまでもなく、ビジネス上より価値が高いデータは観測データの方になるかと思います。

近年、クラウドやコンテナ等の普及によりサービスの構成要素はあらゆるところに分散しています。 これら全体を「監視」し続け、ましてやそこから顧客体験を推察するというのは非常に骨の折れる作業であり、これが今オブザーバビリティに注目が集まっている背景ではないかと私は思います。

さて、改めて 「顧客体験」を観測する方法ですが、こちらは「ORILLY 入門監視~モダンなモニタリングのためのデザインパターン~」が参考になるかと思います。 この記事では深く触れませんが、「顧客体験」の観測に関連する要点は下記である、と書いてあるように私には読み取れました。

ユーザが快適に利用できているかを観測するには

  1. ユーザに近い場所から監視せよ
  2. サービス利用時のパフォーマンスを測定せよ
  3. サービス構成要素から漏れなく情報を収集せよ
  4. 収集した情報を分析し、ビジネス自体を観測せよ

さらに、上記を実装イメージに寄せてグルーピングしてみると下記になりました。

  1. 取れるデータは手段を選ばず収集する (1〜3)
  2. 収集した情報を分析し、ビジネス自体を観測する (4)

次のテーマではこれをどう実現したかを見ていきます。

オブザーバビリティ(OSS)の実現事例

全体構成

いきなり結論ですが今回構築した環境の全体像はこうなりました。
k8s上にデプロイしています。

Elastic Stack arch_all

Elastic Stack

緑のコンポーネントがこちらの対象です。

  • Elasticsearch : Elastic Stack(ES)の核となるサービス。永続化データは全てここに保存する。
  • Kibana: ESのユーザーインターフェイス
  • ApmServer: Tracing(後述)データの受け口。OTLPに対応している
  • Fleet: Elastic Agentの管理サーバ
  • Elastic Agent: OS/k8sのMetrics、Log収集を担当(後述)

Elastic Stack を補うサービス

白のコンポーネントがこちらの対象です。

  • kube-system-metrics (KSM): k8s APIをListenし、メトリクスを生成する(単純な)サービス
  • ElastAlert2: 3rdパーティ製のアラートマネージャ。ESのアラートマネージャは要有償ライセンス・・(泣)

OpentTelemetry関連

青のコンポーネントがこちらの対象です。

  • stub: 弊社で内製したスタブアプリ(Go)。OTel用に(計装)をしている
  • Otel-Collector: OTLP準拠の観測データをバックエンドにフォワードする

取れるデータは手段を選ばず収集する

収集対象のデータは、オブザーバビリティでは特にTelemetry(テレメトリ)と呼びます。 Telemetryは特性別に3つに分ける事ができます。

Category Summary
Metrics 定期的にグループ化または収集された測定値の集合。統計情報やCPU使用率など
Logs 履歴や情報の記録。コンポーネントアクセスログ、エラーログ等
Tracing トランザクションの追跡。特定のWEBリクエストにレスポンスが返るまでのレイテンシー、通過コンポーネント、等

上記3つは、何れも「手段を選ばず」収集していきます。
今回は下記の実装となりました。

Metrics

ElasticAgentを介して収集します。
※収集経路をオレンジでハイライトしています。

Elastic Stack arch_metrics

k8s周り
kube-system-metrics(KSM))を介して収集します。
KSMはk8sのコントローラ経由で収集したメトリクスを提供するエンドポイントです。
/sys/fs/cgroup/ 等もマウントし参照します。

OS周り
/proc等をマウントし参照します。
( Metricsではありませんが、/etc/以下もマウントし、ホスト名なども収集します)

Log

ElasticAgentを介して収集します。
※収集経路をオレンジでハイライトしています。

Elastic Stack arch_logs

k8s周り
* コンテナログ: /var/log/contanirsをマウントし収集します(APPのログは標準出力し、左記に格納します)
* システムコンポーネントログ: 半分は前述コンテナログとして取れます。残りは /var/log/messages等をマウントして収集します

OS周り
/var/log/secure等をマウントして収集します。

Tracing

OpenTelemetryを介して収集します。 ※収集経路をオレンジでハイライトしています。

Elastic Stack arch_tracging

OTel SDK
Tracingの起点であり、追跡用のIDを発行します。 今回は Manual Instrumentation という手法で追跡IDを発行しており、ざっくり説明をするとAPPにOTelのライブラリを読み込ませてAPIを叩く都度追跡IDを発行をさせています。

OTel Collector
APPからTracingを受け、APM Serverにフォワードするのが責務です。

APM Server
OTel CollectorからTracingを受け、Elasticsearchに格納するのが責務です。
OTel SDKAPM Serber としても通信は成立するのですが、この場合APPコンテナの設定に APM Serverの情報を含める必要があるなど、プロダクト(を想定したAPP)とESの結合度が高まってしまうため、OTel Collectorを一段挟むことにしました。 では ElasticAgentはどうなのか?という話になるのですが、こちらはそもそもプロダクト(を想定したAPP)が関与しない通信経路であること、 Datadog、NewRelicなどは皆エージェントを持っているというところから、仮にESから他ソリューションに移ることになったとしてもロックインされるリスクは低いと判断し、 Elasticsearchとネイティブに通信できるAgentを使うことを選択しています。

収集した情報を分析し、ビジネス自体を観測する

ここから先は、根こそぎ集めたデータの活用フェイズになります。
「ビジネス自体を監視する」というところはプロダクトが目指す方向性となるため、千差万別です。
ここでは、ユーザーインターフェイス(Kibana)のキャプチャと共に活用例をご紹介します。

特定リクエストのエラー応答を追跡する

OTel SDK が付与した 追跡IDを元に、エラー応答が発生したリクエスト→レスポンス(トランザクション)を追跡します。

Kiabna stub tracing
Kibana stub logs

画面からは以下のことがわかります。

  • サービス stub のエンドポイント /todos/Internal Server Error が発生した
  • 発生時刻は本日 13:56
  • エラーログから、原因は存在しないURI /todos/hogeにアクセスされた為であることがわかった ---※1

※1 ログにもOTel SDKが発行した追跡IDを埋めています(Tracingと一致するID)。これをElastic Stack側のAPMアプリが解釈し、Tracingと関連するLogとして同じアクセスとしてUIに表示しています。

k8s環境のリソース使用状況を確認する

k8sのMetrics状況から、インフラリソースの使われ方、あるいはしきい値の設定が適切かを確認します。

Kibana k8s overview

画面からは以下のことがわかります。

  • メモリが逼迫したPodがいる (これはPod自体に設定したリソースの上限です)

    • Elasticsearch : MEM=max 2GB
    • ElasticAgent: MEM=max 1GB
  • k8sノード全体のメモリ使用量は4GB/16GB とまだ余裕があります。

  • Podのメモリ利用効率を改善するか、メモリ利用上限を引き上げることでリソース逼迫を解消できそうです

まとめ

今回は Elastic Stack x OpenTelemetryを使ったオブザーバビリティ構成についてご紹介させていただきました。
クラウドサービスを使うケースが大多数だとは思いますが、監視対象への実装では似たようなことを行うことになるかなと思います。 何かの参考にしていただけますと幸いです!

※実装方法については当記事では割愛させて頂きますが、Elastic StackはOperatorをインストールし、(OTel等も含め) kustomizeで書きました。 言うに及ばずですが、自力実装をするには結構なつらみがあり、「まずお試しで」ということであれば有償版をご利用されることをお勧め致します!

以上、最後までお読み頂きありがとうございました!

参考

検証環境

  • k8sプラットフォーム
  • オブザーバビリティ
    • kube-state-metrics (v2.10.0)
    • ECK Operator (v2.9.0)
    • Elastic Stack (v8.9.2)
    • OTel Collector (v0.84.0)
    • elastalert2 (v2.13.2)
  • アプリケーション

ドキュメント

ESに関するドキュメント

OpenTelemetry

kube-state-metrics

ElastAlert2

Copyright © RAKUS Co., Ltd. All rights reserved.