OpenTelemetry Collector、本番はQuick Startのまま置かない

|著者: QUASA編集チーム|2 分で読めます| 1
OpenTelemetry Collector、本番はQuick Startのまま置かない

OpenTelemetry CollectorをKubernetes本番環境に配置するなら、ノード固有の収集をDaemonSet、外部への集中転送をGatewayに分け、両者の間とバックエンドまでの送信経路を設計する。公式Quick Startは基本動作を確かめるローカルデモであり、本番環境の構築を目的としていない。

導入は、収集元と転送先の確定、各シグナルのpipeline接続、メモリ制御、送信キューと再試行、Collector自身の監視という順で進める。特にキューの容量と保持方法は、転送先の停止中にどれだけデータを待たせたいかによって決まる。設定を追加しただけで欠損がなくなるわけではなく、満杯や再試行期限切れも想定に入れる。

DaemonSetで集め、Gatewayから送る

ローカルの単一Collectorと、ノード側・Gateway側に役割を分けたKubernetes構成の比較

Kubernetes向けの公式インストール例は、DaemonSetと単一のGatewayインスタンスを同時に配置する開始点を示し、本番向けには構成の調整が必要だとしている。DaemonSetはノードごとにCollectorを置くため、ノード上のコンテナログやホストのメトリクスを収集する役割に合う。Gatewayは独立した受信口としてOTLPを受け、共通処理やバックエンドへの転送を担う。

基本経路は「アプリケーションやノード上の収集元 → DaemonSetのCollector → Kubernetes Service → GatewayのCollector → 監視バックエンド」と整理できる。Gatewayは別ノードのローカルログファイルを直接読めないため、ファイルを読むreceiverはノード側に置く。一方、バックエンドの宛先や認証情報をGateway側にまとめれば、ノード側の設定を転送先ごとに増やさずに済む。

すべてのアプリケーション信号をDaemonSet経由にする必要はない。アプリケーションからGatewayへ直接OTLPを送る構成も選べる。ただし、ノード由来のログやメトリクスを集める処理と、クラスタ外へ送る処理は分けて定義したほうが、必要な権限、負荷、障害箇所を判断しやすい。

役割別のpipelineをつなぐ

Collectorではreceiver、processor、exporterを定義するだけではデータは流れない。service.pipelinesでtraces、metrics、logsのうち使う信号を選び、それぞれに受信、処理、送信のコンポーネントを結び付ける。初めは実際に使う送信元と転送先だけを残し、不要な受信ポートやpipelineを有効にしない。

  • DaemonSet側:アプリケーションから受けるならOTLP receiverを置く。コンテナログやホストメトリクスを読むなら、それぞれに対応するreceiver、マウント、権限を追加する。処理後はGatewayのServiceを宛先とするOTLP exporterへ渡す。
  • Gateway側:DaemonSetからのOTLPをreceiverで受け、必要な共通処理を通して、バックエンド向けexporterへ送る。バックエンドの認証情報もここで扱う。
  • 両側のservice.pipelines:実際に収集する信号ごとにreceivers、processors、exportersを列挙する。extensionを定義した場合はservice.extensionsでも有効にする。

この構成を最小単位にすると、どこでデータが止まったかを追いやすい。例えばノードのログだけが届かないなら、まずノード側の読み取り設定とlogs pipelineを調べられる。トレースもログもGatewayまでは届くのにバックエンドに現れないなら、Gateway側のexporterとキューを調べる。

ノード由来の収集機能を追加するときは、使うCollectorの配布物に必要なreceiverが含まれるかも確認する。receiver名を設定に書いても、実行イメージにそのコンポーネントがなければ起動できない。収集対象を決めてから配布物、権限、マウントを選ぶ順序が合理的だ。

メモリを制御し、後段でバッチ化する

Collectorのpipelineで受信後にメモリ制御を行い、バッチ処理を経て送信する順序

各pipelineではmemory_limiterを受信直後のprocessorとして置き、その後に必要なフィルタリングや属性処理、batchを続ける。先に不要なデータを落とせば、batchに載せる量を減らせる。batchは送信をまとめて効率を上げる処理であり、転送先の停止中にデータを永続保存する仕組みではない。

memory_limiterの設定は、Collector Podのメモリ制限と整合させる。receiverの処理、batch、exporterのメモリ内キューも容量を使うので、コンテナの上限をそのまま処理に使い切る設定は避ける。メモリ圧迫時には新しいデータの受け入れを抑えるため、送信元が拒否を受けたときに再送できるかも欠損の範囲に関わる。

平常時のメモリ使用量だけで上限を決めると、バックエンド停止中のキュー増加を見落とす。さらに復旧時は、滞留分の送信と新着データの処理が重なる。DaemonSetとGatewayでは入力の種類と流量が違うため、同じメモリ設定を機械的に複製せず、各Podの実際の負荷に合わせて調整する。

各ネットワーク区間にキューと再試行を置く

GatewayのPod再作成後も永続ボリューム上の送信キューを引き継ぐ構成

DaemonSetからGateway、Gatewayからバックエンドへ送るexporterには、それぞれsending_queueとretry_on_failureを設定する。公式の耐障害性ガイドは、送信キューと再試行を使う一方、キュー満杯、再試行期限切れ、永続保存先の障害ではデータが失われ得ると説明している。片方の区間だけを守っても、もう片方の停止には対応できない。

queue_sizeは受信量と許容したい停止時間から決める。小さければ停止中に満杯になり、大きければメモリやディスクの使用量が増す。retry_on_failureのmax_elapsed_timeも短すぎると、キューにデータが残っていても古い送信の再試行が終わる。通常時だけでなくピーク時の流量を見て、容量と期限を組み合わせる。

Collectorの再起動をまたいで未送信データを残したい区間では、file_storage extensionを定義し、exporterのsending_queue.storageに指定して、service.extensionsでも有効にする。保存先は書き込み可能な永続ボリュームに置き、Pod再作成後も対応するCollectorが同じキューを読めるようにする。Podとともに消える保存領域では、再起動時の保護にならない。

Gatewayを複製する場合、各インスタンスのキューと保存先の対応も必要になる。複数のCollectorが同じキューファイルを無造作に共有する構成は避け、各インスタンスが自分の保存領域を引き継げるようにする。永続キューを使っても、ディスク容量の枯渇や保存領域そのものの障害は別に監視する。

Collector自身の状態で切り替えを判断する

バックエンドにデータが見えていても、キューが満杯に近ければ転送経路には余裕がない。Collectorの内部メトリクスを収集し、otelcol_exporter_queue_sizeとotelcol_exporter_queue_capacity、送信失敗、受信拒否、プロセスのメモリ使用量をDaemonSet側とGateway側で分けて見る。health_checkはCollectorの稼働確認に使い、宛先までの到達確認は別に行う。

本番への切り替え前には、各信号が通常時に届くことに加え、下流を一時的に受信不能にしたときの挙動を確かめる。キューが増え、下流の復旧後に減るか、送信失敗や受信拒否が継続していないかを確認する。永続キューを採用した区間では、未送信データを残した状態でPodを再作成し、保存先への再接続と再送を確認する。

判定の要点は、どのpipelineが受け入れを拒否し、どのexporterのキューが詰まり、復旧後に送信を再開できるかを区別できることだ。そこまで観測できれば、容量不足、転送先の停止、ノード側の収集不備を同じ「データが見えない」という症状として扱わずに済む。

関連記事:

共有:

ニュースレターを購読

Web3、AI、暗号資産の最新ニュースを受信箱にお届けします。

0