OpenTelemetry OpenTelemetry

Collector を本番対応にする:メモリ制限、バッチ処理、リトライ

過負荷や障害の間もテレメトリが生き残るように、processor、キュー、永続ストレージを設定します。

12 min learn.level.中級

ノート PC で動作する Collector も、本番では行き詰まることがあります。トラフィックのスパイクがメモリを使い果たす、バックエンドの障害でデータが失われる、再起動で転送中のすべてが失われるなどです。解決策はすべて設定です。このガイドでは、すべての本番の Collector が持つべき processor と exporter の設定、そしてそれらを置く順序を説明します。

ベースのパイプライン

processors:
  memory_limiter:
    check_interval: 1s
    limit_percentage: 80
    spike_limit_percentage: 20
  batch:
    timeout: 5s
    send_batch_size: 8192

service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [memory_limiter, batch]
      exporters: [otlp/backend]

順序は重要です。processor は、列挙された順に実行されます。memory_limiter を最初に置き、他のものがメモリを消費する前に、バックプレッシャーが receiver に届くようにします。batch は、フィルタリングやエンリッチメントの後の最後に置き、バッチが最終的なデータから作られるようにします。

memory_limiter

Collector のメモリを監視し、使用量が高すぎるときは新しいデータを拒否します。そのため、プロセスはオペレーティングシステムに強制終了されるのではなく、減速します。

processors:
  memory_limiter:
    check_interval: 1s
    limit_mib: 4000
    spike_limit_mib: 800
  • check_interval は、メモリを測定する頻度です。1s が推奨され、デフォルトの 0s は、定期的なチェックを無効にします。
  • limit_mib は、ヒープメモリのハードリミットです。プロセス全体は、通常、それよりやや多く使用します。
  • spike_limit_mib は、チェック間の想定される最大のジャンプで、デフォルトは制限の 20% です。ソフトリミットは、limit_mib から spike_limit_mib を引いたものです(ここでは 3200 MiB)。
  • limit_percentage と spike_limit_percentage は、同じ制限を、利用可能なメモリに対する割合として表します(cgroup を持つ Linux)。メモリ制限が Kubernetes によって設定されるコンテナに適しています。limit_mib も設定されている場合は、それが優先されます。

ソフトリミットを超えると、processor は前のコンポーネントにエラーを返してデータを拒否し、行儀のよい送信者はリトライするか、速度を落とします。ハードリミットを超えると、ガベージコレクションも強制します。カーネルより先に動作するように、コンテナのメモリ制限より少し低く設定してください。

batch

バッチ処理は、エクスポートが少なく、大きくなるように項目をグループ化し、ネットワークとバックエンドの負荷を節約します。

processors:
  batch:
    timeout: 5s            # バッチがいっぱいでなくても、この時間後に送信する
    send_batch_size: 8192  # 目標のバッチサイズ
    send_batch_max_size: 0 # 0 は上限なしを意味する

レイテンシーのために timeout を、スループットのために send_batch_size を調整します。最近の Collector のバージョンでは、exporter のキュー内でもバッチ処理ができます。お使いのバージョンの exporter helper のドキュメントを確認してください。

exporter のキューとリトライ

ネットワーク経由で送信する exporter には、送信キューとリトライポリシーがあります。これらは processor ではなく exporter の中にあり、バックエンドの短い停止から身を守ってくれるものです。

exporters:
  otlp/backend:
    endpoint: backend.example.com:4317
    sending_queue:
      enabled: true
      queue_size: 5000        # デフォルトは 1000
    retry_on_failure:
      enabled: true
      initial_interval: 5s
      max_interval: 30s
      max_elapsed_time: 10m   # デフォルトは 300s

数値の考え方:

  • キューは、バックエンドが遅いまたはダウンしている間、バッチをバッファリングします。大きなキューはより長いインシデントに耐えられますが、メモリを多く使います。
  • retry_on_failure は、max_elapsed_time まで、増加する遅延でリトライします。その後、データは破棄されます。
  • 損失なしに耐えたい最長の停止と、ご自身のボリュームに合わせて、両方のサイズを決めます。

永続キュー:再起動に耐える

デフォルトでは、キューはメモリ内にあるため、クラッシュするとキューに入っていたものが失われます。file_storage extension でディスクを裏付けにします。

extensions:
  file_storage:
    directory: /var/lib/otelcol/storage

exporters:
  otlp/backend:
    endpoint: backend.example.com:4317
    sending_queue:
      storage: file_storage

service:
  extensions: [file_storage]
  pipelines:
    traces:
      receivers: [otlp]
      processors: [memory_limiter, batch]
      exporters: [otlp/backend]

3 つの要素が必要です。extension を定義し、exporter で参照し、service.extensions で有効にします。そのディレクトリに永続ボリューム(たとえば StatefulSet 用の PersistentVolumeClaim)をマウントします。ディスクがいっぱいになるか故障した場合、あるいはバックエンドがリトライの制限を超えてダウンし続けた場合には、それでもデータが失われる可能性があるため、ディスクの使用量を監視してください。

基本を超えて有用な processor

属性を追加または変更する:

processors:
  resource/env:
    attributes:
      - key: deployment.environment.name
        value: production
        action: upsert
  attributes/scrub:
    actions:
      - key: http.request.header.authorization
        action: delete
      - key: user.email
        action: hash

resource は、プロデューサーを記述する属性(バッチ全体に適用)を編集し、attributes は、スパンごと、メトリクスのデータポイントごと、ログレコードごとの属性を編集します。これらを使って、環境のラベルを追加し、データがネットワークを出る前に、機密性のある値を削除またはハッシュ化します。

OpenTelemetry Transformation Language(OTTL)で書かれた filter processor で、ノイズを破棄する:

processors:
  filter/health:
    error_mode: ignore
    traces:
      span:
        - 'attributes["url.path"] == "/healthz"'
        - 'attributes["url.path"] == "/ready"'

transform processor で、データを変換する:

processors:
  transform/normalize:
    error_mode: ignore
    trace_statements:
      - context: span
        statements:
          - set(attributes["team"], "payments") where resource.attributes["service.name"] == "checkout"

OTTL は強力なので、本番で有効にする前に、データのコピーに対して debug exporter でステートメントをテストしてください。ステートメントの構文と利用可能なコンテキストは、バージョン間で変わるため、お使いのバージョンの processor の README を確認してください。これらの processor は、contrib ディストリビューションにあります。

Collector 自体を守る

  • Kubernetes のリソースの requests と limits を設定し、memory_limiter を limit より低く保ちます。
  • health_check を追加し、liveness と readiness の probe に使います。
  • キューのサイズ、破棄された項目、拒否されたデータについて、ポート 8888 の Collector 自身のメトリクスを監視します。otelcol_exporter_queue_size が容量に近づいたとき、または exporter が送信の失敗を報告したときに、アラートを出します。
  • ゲートウェイには、Service の背後で複数のレプリカを実行し、想定するバーストに合わせて、単一のレプリカのサイズを決めます。

チェックリスト

  • memory_limiter が、すべてのパイプラインの最初の processor であること。
  • batch が、最後の processor であること。
  • ネットワークの exporter に、停止への許容度に合わせたサイズの、送信キューとリトライポリシーがあること。
  • データの損失が許されない場所に、永続キューが設定されていること。
  • 機密性のある属性が、エッジで削除またはハッシュ化されること。
  • ヘルスチェック、リソースの制限、Collector のメトリクスが揃っていること。

人気のガイド