🔭

OpenTelemetry Collectorの設定を考える - トレース計装初回導入時のHow to

に公開

サービスへの OpenTelemetry Collector によるトレース計装の初回導入時設定をどう考えながら決めていくか?

ココナラでは、オブザーバビリティの獲得のために、OpenTelemetry ベースのトレース計装を進めています。

モニタリングやオブザーバビリティは運用を通しての日々の改善も重要ですが、今回はトレース計装の初回導入時に OpenTelemetry Collector 設定をどう考えるかにフォーカスして紹介します。

はじめに

こんにちは。
株式会社ココナラのプロダクトプラットフォーム部インフラ・SREチーム所属の Kou です。

本記事では、OpenTelemetry Collector によるトレース計装の初回導入時に設定する項目と内容をどう考えながら決めていくかをご紹介します。

TL;DR

  • OpenTelemetry Collector を使うことでワークロードへの影響を最小化する
  • 責任範囲に基づいて OpenTelemetry Collector 設定の管理場所を決める
  • Collector の 3 つの役割の中で、Processor で安全性とオブザーバビリティのバランスを確保する

対象読者

  • OpenTelemetry (特に AWS Distro for OpenTelemetry、以降は ADOT と記載する) を用いたトレース計装に興味がある方
  • OpenTelemetry Collector の設定をどう決めて良いか悩まれている方
  • 障害対応/障害調査やパフォーマンス改善に課題を持つ方

本記事の前提条件

  • Observability Backend には、AWS X-Ray を使用する
  • OpenTelemetry SDK、および Collector は、AWS 向けにプリセットされた ADOT を使用する
  • コンピュートリソースとしては ECS を使用する

テレメトリパイプライン

OpenTelemetry によるテレメトリ取得には、大きく分けて 3 つのトポロジーがあります。

  • Collector を使用しない
    • アプリケーションで計装を行う SDK から直接 Observability Backend に接続する
    • トレースに複雑な処理を加える場合、トレースに対する処理とアプリケーション処理が同一コンピュートリソース上で競合する可能性がある
    • Observability Backend に送出するテレメトリに処理を加えない場合に検討の余地がある
  • アプリケーションと同じマシン上で Local Collector を実行する
    • 以下に記述するメリットから OpenTelemetry を使用した計装の初期段階に適している
      • 後述する Resource Detection Processor を使用することで、クラウドプロバイダなどの情報が取得できるため、特定の AZ やノードで障害が発生しているといった切り分けに必要な情報が得られる
      • アプリケーションがクラッシュした場合でも、Local Collector に転送されていれば、クラッシュ直前までのテレメトリを Observability Backend に転送できる
      • アプリケーションと OpenTelemetry Collector の設定を分離して管理できるため、ストリームアラインドチームとプラットフォームチームの責任分解が明確になる
  • Collector Pool を構成する
    • Local Collector からのテレメトリを、ロードバランサーと Collector Group で処理し、Observability Backend に接続する
    • テレメトリ処理の負荷分散、CPU/メモリなどのリソース管理などメリットは多いが、運用管理にもパワーが必要になる
      • 大規模なシステムで使用する場合に検討する

ココナラでは、アプリケーションと同じマシン上で Local Collector を実行する方式を選択しました。
理由としては、以下の通りです。

  • コンテナ毎のリソース制限設定によるワークロードのサービス信頼性の確保が必要
  • マイクロサービスの各々への導入を考えた時に「アプリケーションコードと Collector 設定の分離」による責任分解が必要

OpenTelemetry Collector 設定の管理・運用

OpenTelemetry Collector 設定の管理には、責任分解によって 2 通りが考えられます。

  • アプリケーションリポジトリで管理
  • 専用のリポジトリ/プラットフォームチームのリポジトリで管理

先述の通り、マイクロサービスの各々に導入することを考えた時に「アプリケーションと Collector 設定の分離」による責任分解が必要だと考えているため、後者を選択しました。

AWS X-Ray と ADOT の組み合わせで運用する場合

本記事で前提にしている AWS X-Ray と ADOT Collector の組み合わせでは、AWS Systems Manager Parameter Store に設定ファイルを登録し、ECS タスク定義で参照できます。
ココナラではこれを活用し、設定ファイルを Terraform を管理するリポジトリ内で管理しています。

https://aws-otel.github.io/docs/setup/ecs/config-through-ssm

Collector の 3 つの役割

OpenTelemetry Collector には、 "Receiver", "Processor", "Exporter" の 3 つの役割があります。
以下が設定ファイルのサンプルです。

https://github.com/aws-observability/aws-otel-collector/blob/main/config/ecs/ecs-xray.yaml

  • receivers, processors, exporters で、それぞれの処理の詳細を定義します
  • service.pipelines.traces で、それぞれの処理の順序を定義します

"Receiver", "Processor", "Exporter"、それぞれの大まかな役割は以下の通りです。

Receiver

  • テレメトリデータの受信エンドポイント
  • アプリケーションから送出されたテレメトリデータの受信設定を行う

Processor

  • テレメトリデータの変換・加工・フィルタリング・サンプリング処理

Exporter

  • 処理されたテレメトリデータを Observability Backend に送出する処理
  • 送信先の Observability Backend に応じて選択する

理想のオブザーバビリティを実現するために重要な Processor の設定

理想のオブザーバビリティを実現するためには、上記の 3 つの役割のうち、Processor が重要な役割を果たします。
以降では初回導入において、Processor の設定項目と内容をどう考えるかを紹介します。

主要な Processor

ADOT Collector で使用できる Processor の一覧が以下に記述されています。

https://github.com/aws-observability/aws-otel-collector#adot-collector-built-in-components

中でも、トレースを扱う場合に主要な Processor には以下があります。

  • Memory Limiter Processor
  • Filter Processor
  • Probabilistic Sampling Processor / Tail Sampling Processor
  • Resource Detection Processor
  • Batch Processor

メモリ制限 - Memory Limiter Processor

  • OpenTelemetry Collector のメモリ使用量を制限し、OOM Killer を防ぎます
    • 本番へのリリースにあたっては設定した方が良いと思います
    • アクセススパイク時に、作成されるトレース量も合わせてスパイクし、アプリケーションのワークロードに悪影響を与えるリスクを低減してくれます

フィルタリングとサンプリング

フィルタリング - Filter Processor

  • ヘルスチェックのパスや、フロントエンドのアセットのパスへのリクエストのトレースをフィルタリングして除外します
    • 分析が必要なトレースのみを Observability Backend に送出することで、データ量の削減とコスト最適化に繋がります

サンプリング - Probabilistic Sampling Processor / Tail Sampling Processor

  • サンプリングレートを制限してテレメトリデータの量を最適化します
    • 分析に必要十分な量のトレースを Observability Backend に送出することで、コスト最適化を行います
    • シンプルで軽量な確率サンプリングと、エラーやレイテンシーの高いトレースなどの条件を設定できるテイルベースサンプリングがあります
      • 初回導入時においては、トレースの需要が正確に把握できている場合以外は、確率サンプリングが適していると考えます
  • サンプリングは、フロントエンドか、BFFやバックエンドかによっても設定を考える必要があります
    • 既にフロントエンドで計装されているシステムの場合は、Observability Backendで各マイクロサービスから送信されたトレース同士を紐づけるために、フロントエンドでそのトレースがサンプリングされたかどうかによって、BFFやバックエンドでサンプリングするかどうかを決めるParent-Basedなサンプリングの採用を推奨します

サンプリングの Next Step

Probabilistic Sampling Processor(確率サンプリング)をヘッドベースサンプリング、Tail Sampling Processor をテイルベースサンプリングとして、対となる概念で扱うこともあります。

  • ヘッドベースサンプリング
    • トレースの最初のスパン(ヘッド)が受信された時点で、そのトレース全体をサンプリングするかを決める
    • ステートレスで、オーバーヘッドが小さいのでコンピュートリソース効率が良い
    • エラーが起きたり、レイテンシーの高いリクエストのトレースが見落とされる可能性がある
  • テイルベースサンプリング
    • トレースの全スパンをバッファし、トレースが完了した後(テイル)でサンプリングするかを決める
    • エラーが起きたり、レイテンシーの高いトレースを指定して Observability Backend に送出できる
    • ステートフルで、オーバーヘッドが大きいのでコンピュートリソースの負荷が高い

分散トレースを導入した場合、遠くない未来にこれらのメリット・デメリットを比較しながら、組織のオブザーバビリティ要求を満たすアーキテクチャ決定を求められると思います。

リソース属性の付与 - Resource Detection Processor

  • クラウドプロバイダやコンピュートリソースの情報を取得して、トレースに付与します
    • 他にもユースケースに応じて、必要な情報をトレースに付与できる Processor があるかは適宜確認しましょう

属性の付与の Next Step

属性の付与に関して、次点では次のような Processor の利用が考えられます。

  • Attributes Processor
    • 属性値の追加・編集・削除を行う
    • 個人情報/機密情報のマスキングや属性の正規化が行えます
  • Kubernetes Attributes Processor
    • k8s の属性(pod, deployment, namespace)などをトレースに付与する
    • k8s 上のアプリケーションからトレースを取得する場合はには、障害やパフォーマンス調査のコンテキストが得られます

Processor の実行順序

Processor の実行順序は、OpenTelemetry Collector のリポジトリに推奨される順序の記載があります。

https://github.com/open-telemetry/opentelemetry-collector/tree/main/processor#recommended-processors

  1. memory_limiter
  2. Any sampling or initial filtering processors
  3. Any processor relying on sending source from Context (e.g. k8sattributes)
  4. batch
  5. Any other processors

以下のような理由に基づいており、理になかっています。

  1. メモリ保護のため、まずは Memory Limiter を実行する
  2. 早い段階で、サンプリング/フィルタリングを行うことで、リソース情報の付与などを行うトレースの量を減らす (コンピュートリソースの節約)
  3. 送出を効率化するため、バッチ処理を行う

最終的な設定ファイル

上記を考慮して、作成した設定ファイル例(Processor の箇所のみ抜粋)が以下です。

processors:
  memory_limiter:
    check_interval: 1s
    limit_mib: 512
    spike_limit_mib: 102
  filter/ottl:
    error_mode: ignore
    traces:
      span:
        - 'IsMatch(attributes["http.url"], "{ヘルスチェックパスを表す正規表現}")'
  probabilistic_sampler:
    sampling_percentage: 20
  resourcedetection:
    detectors:
      - env
      - system
      - ecs
  batch/traces:
    timeout: 1s
    send_batch_size: 50

service:
  pipelines:
    traces:
      receivers: [otlp]
      processors:
        [
          memory_limiter,
          filter/ottl,
          probabilistic_sampler,
          resourcedetection,
          batch/traces,
        ]
      exporters: [awsxray]

まとめ

サービスへの OpenTelemetry Collector 初回導入時設定をどう考えながら決めていくか?

  • トレース計装によるサービスへの影響リスクを極小化する
  • システム運用に必要十分なオブザーバビリティを獲得する

この 2 つを達成するために、初回導入時に何を設定するべきか、どう設定するべきかの思考地図を紹介しました。

本番環境導入後には、トレースの使用目的の変化、リソースやコストの状況によって、チューニングが求められます。
一方で、初回導入時には、導入の影響が不透明な中で、安全にリリースされることが求められます。

本記事が、少しでも初回導入の設定に悩んでいる方の力になれば幸いです。


ココナラでは積極的にエンジニアを採用しています。
私たちと一緒に、分散システムのオブザーバビリティを高め、それを元にソフトウェアを改善する楽しさを体感しませんか?

採用情報はこちら。
https://coconala.co.jp/recruit/engineer/

カジュアル面談希望の方はこちら。
まずはココナラの魅力やキャリアパスについて、お気軽にお話ししませんか?
https://open.talentio.com/r/1/c/coconala/pages/70417

Discussion