🔭

OpenTelemetry Collector のマルチレイヤー構成で Tail-based Sampling を実現する

2024/12/17に公開

はじめに

OpenTelemetry Collector を用いて、Tail-based sampling を実現する方法を紹介します。

今回は OpenTelemetry Collector のアドベントカレンダーなので、分散トレーシングについての説明は割愛します。
https://qiita.com/advent-calendar/2024/opentelemetry

前提

Tail-based sampling とは

分散トレーシングにおいて、全てのリクエストをサンプリングするのではなく、一部のリクエストのみをサンプリングすることを指します。
サンプリング手法には Random sampling や Rate-based sampling などの Head-based sampling がありますが、Tail-based sampling はリクエストのレスポンス時間やステータスコードを考慮してサンプリングを行います。

詳しいサンプリングの説明については OpenTelemetry から公開されているブログ記事を参照してください。
https://opentelemetry.io/blog/2022/tail-sampling/

OpenTelemetry Collector

OpenTelemetry Collector は、複数のデータソースからデータを収集し、処理し、エクスポートするためのプラットフォームです。

今回は OpenTelemetry Collector を用いて Tail-based sampling を実現します。
https://opentelemetry.io/docs/collector/

OpenTelemetry Collector の構成

OpenTelemetry Collector で Head-based sampling を実現するためには tailsamplingprocessor を使用します。
https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/processor/tailsamplingprocessor

単一の OpenTelemetry Collector で Tail-based sampling を実現する場合、この tailsamplingprocessor を利用するだけで実現できます。
しかし、大規模環境下や冗長化目的で複数の OpenTelemetry Collector インスタンスを構築する場合、ひと工夫必要になります。
OpenTelemetry Collector を複数インスタンスで運用している場合、同一トレース ID を持ったスパンが異なるインスタンスに送信される可能性があります。
同一のトレース ID を持ったスパンが異なるインスタンスに送信されると、条件判定が正しく行えなくなり、 Tail-based sampling が正しく行えなくなります。

マルチレイヤー構成

この問題を解決するために、マルチレイヤー構成を導入します。

導入後の構成は以下の通りです。
アプリケーションから直接スパンを受け取る OpenTelemetry Collector インスタンスを gateway とし、その後の処理を行う OpenTelemetry Collector インスタンスを processor とします。

gateway は、スパンを受け取り、トレース ID を元に同一のトレース ID を持つスパンを同一の processor に送信します。
この gateway を用いることで、同一のトレース ID を持つスパンが異なる processor に送信されることを防ぎます。

任意の同一のトレース ID を持つスパンが同一の processor に送信されることで、 processor では Tail-based sampling を正しく行うことができます。

次に、このマルチレイヤー構成を実現する方法を説明します。

マルチレイヤー構成の実現

今回は otlp プロトコルに gRPC を使用します。
また、 Tail-based sampling の設定に直接関係ない設定は割愛します。

gateway の設定

gateway は、以下の設定を適用します。
gateway は、アプリケーションから gRPC でスパンを受け取るため、 otlp プロトコルを使用して receiver を設定します。
そして、 processor に送信するため、 otlp プロトコルを使用して exporter を設定します。
個々の詳しい設定に関しては後述しています。

receivers:
  otlp:
    protocols:
      grpc:
exporters:
  loadbalancing:
    routing_key: "traceID"
    protocol:
      otlp:
        timeout: 1m
        tls:
          insecure: true
    resolver:
      k8s:
        service: otelcol-processor-collector-headless.monitoring
        ports: [4317]
        timeout: 1s
service:
  telemetry:
    logs:
      encoding: json
  pipelines:
    traces:
      receivers: [otlp]
      exporters: [loadbalancing]

loadbalancing の設定

exporter には、loadbalancing を使用します。
この loadbalancing は、トレース ID を元に同一のトレース ID を持つスパンを同一の processor に送信するための設定です。

https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/exporter/loadbalancingexporter

routing_key には、トレース ID を指定することで、同一のトレース ID を持つスパンを同一の processor に送信します。

今回の環境は k8s を使用しているため、resolver には、k8s を使用します。
resolver では processor の IP アドレスのリストを取得する必要があります。
そのため、 service に processor の Headless Service 名を指定します。

processor の設定

processor は、以下の設定を適用します。
processor は、gateway から受け取ったスパンを処理し、Tail-based sampling を行うため、tailsamplingprocessor を設定します。
tailsamplingprocessor の詳しい設定はこの記事では触れませんが、以下の設定を用いることでスパンの http.status_code が 2xx の場合に 1% の確率でサンプリングを行います。

receivers:
  otlp:
    protocols:
      grpc:
processors:
  tail_sampling:
    policies:
      - name: status-code-2xx
        type: and
        and:
          and_sub_policy:
            - name: status-code
              type: string_attribute
              string_attribute:
                enabled_regex_matching: true
                key: http.status_code
                values: '[2][0-9]{2}'
            - name: probabilistic-policy
              type: probabilistic
              probabilistic:
                sampling_percentage: 1 #1%

おわりに

今回は、OpenTelemetry Collector のマルチレイヤー構成で Tail-based sampling を実現する方法を紹介しました。
この方法を用いることで、複数の OpenTelemetry Collector インスタンスで Tail-based sampling を正しく行うことができます。

Tail-based sampling を用いることで、トレースバックエンドに送信するデータ量を削減し、コストを削減できます。
Head-based sampling とは異なり、単純にサンプリングするのではなく、リクエストのレスポンス時間やステータスコードを考慮してサンプリングを行うため、より効率的なサンプリングが可能です。

Discussion