⚙️

OpenTelemetry CollectorをGateway(多段構成)にする

2023/12/07に公開

最近たまたまなのか聞かれることが多くあったので半分メモです。
バックエンドにテレメトリーデータを送る際には、通常OpenTelemetry Collector(以下、Otel Collector)を使用します。[1]

Otel Collectorは以下のような多段構成を取れます。

Otel CollectorのGateway化の何が嬉しいでしょうか。考えられるパターンとしては:

  • セキュリティの理由などで送信元を絞りたいとき
  • Processor/Exporterを一ヶ所で管理したいとき
  • 何らかの理由でOtel Collector Agent側で諸々隠蔽したいとき

とりあえず覚えておいて損はない技かと思います。

参考:https://opentelemetry.io/docs/collector/deployment/gateway/

Gatewayとは

別に特別なOtel Collectorが用意されている訳ではなく、単にExporter / Receiverの組み合わせです。
Exporterには今時点でotlp exporterloadbalancing exporterが利用できます。

よく登場する図にも伏線?が張られています。

出典:https://opentelemetry.io/docs/collector/

それぞれの設定を具体的に見ていきましょう。

パターン①:otlp exporter

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

Coreに含まれるExporterです。OTLP(OpenTelemetry Protocol)によるgRPC送信を行います。
シンプルなGateway化をするにはこれで十分です。

exporters:
  otlp:
    endpoint: <Otel Collector as Gateway>:4317
    tls:
      insecure: true #TLS暗号化をしない場合(デフォルトはfalseであり、cert_file/key_fileが必須)

パターン②:loadbalancing exporter

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

otlp exporterとは別の選択肢です。比較的最近登場したContribのものです。
Gatewayが複数あり負荷分散を行いたいときに便利です。

なお、otlp exporterにも通常のLB(gRPC: HTTP/2)をかますことができます。
このexporterを使うべき場合は、例えばtail base samplingを行う場合などに同一トレースIDのスパンを同じGatewayに送る必要があるとき、ということのようです。

以下のようにrouting_keyとしてtraceIDservice(service.name)を指定することで同じ値であるものは同じGatewayに送ることができます(デフォルトはTraceID)。
他にもmetric(metric名)、resourceで振り分けることもできます。

exporters:
  loadbalancing:
    routing_key: "service" 
    protocol:
      otlp: #今はotlpのみサポート
        tls:
          insecure: true
    resolver:
      static:
        hostnames:
        - <Otel Collector as Gateway1>:4317
        - <Otel Collector as Gateway2>:4317
        - <Otel Collector as Gateway3>:4317

otlp receiver

https://github.com/open-telemetry/opentelemetry-collector/tree/main/receiver/otlpreceiver

Coreに含まれるreceiverです。
otlp exporter / loadbalancing exporter(もちろんOtel SDKも)からのテレメトリーデータを受け取ります。

receivers:
  otlp:
    protocols:
      grpc:
      http:

設定例

超単純にまとめるとこうです。

Agent側

exporters:
  otlp:
    endpoint: <Otel Collector as Gateway>:4317
    tls:
      insecure: true

service:
  pipelines:
    traces:
      receivers: [<適当なreceiver>]
      processors: [<適当なprocessor>]
      exporters: [otlp]
    metrics:
      receivers: [<適当なreceiver>]
      processors: [<適当なprocessor>]
      exporters: [otlp]
    logs:
      receivers: [<適当なreceiver>]
      processors: [<適当なprocessor>]
      exporters: [otlp]

Gateway側

receivers:
  otlp:
    protocols:
      grpc:
      http:

service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [<適当なprocessor>]
      exporters: [<適当なexporter>]
    metrics:
      receivers: [otlp] #少なくとも自身のhostmetricsも取った方がいいけど
      processors: [<適当なprocessor>]
      exporters: [<適当なexporter>]
    logs:
      receivers: [otlp]
      processors: [<適当なprocessor>]
      exporters: [<適当なexporter>]

GatewayからはProxy通したいのだが

はい、このページの通り環境変数にセットすればOKです。

HTTP_PROXY: Address of the HTTP proxy
HTTPS_PROXY: Address of the HTTPS proxy
NO_PROXY: Addresses that must not use the proxy

Gatewayの負荷は?

Gatewayかどうかに限らず、このような方針が提示されています。
https://opentelemetry.io/docs/collector/scaling/

otelcol_processor_refused_spansotelcol_exporter_enqueue_failed_spansでSpanの取りこぼしを見るか、
otelcol_exporter_queue_capacityotelcol_exporter_queue_size でExporterのキューを見てやばかったらスケールさせてね、ということです。

Otel Collectorにもオブザーバビリティ!

まとめ

Otel Collectorなら多段構成も簡単に組めます。

Otel collectorはreceiver / exporterで自由自在にパイプラインを作れるから柔軟性がとんでもないですよ、の話の一つでした。
色々パイプラインに詰め込んでいったらOtel Collectorの設定がこんがらがってしまった?
OTelBinをどうぞ!

https://zenn.dev/kntr_nkgm/articles/6b58326d3e599b

脚注
  1. Otel Collectorを使用しなくても、OpenTelemetry SDKから直接バックエンドにデータを送信することは可能です。 ↩︎

Discussion