OpenTelemetry OpenTelemetry

テレメトリをバックエンドに送り、パイプラインを保護する

Tempo、Loki、Prometheus 向けの OTLP exporter を設定し、TLS、認証、シークレットも扱います。

14 min learn.level.中級

テレメトリを収集することは仕事の半分に過ぎません。もう半分は、それを適切な場所に安全に届けることです。このガイドでは、一般的なオープンソースのバックエンド(例には Grafana のスタックを使います)向けの exporter の設定方法と、TLS、認証、設定ファイルの外に置くシークレットで、Collector への入出力のトラフィックを保護する方法を説明します。

OTLP exporter:gRPC と HTTP

OTLP を話す exporter は 2 つあります。

  • otlp は gRPC を使います。エンドポイントは、スキームなしの host:port で、通常はポート 4317 です。
  • otlphttp は HTTP を使います。エンドポイントは URL で、通常はポート 4318 であり、exporter はそれにシグナルのパス(/v1/traces、/v1/metrics、/v1/logs)を追加します。

同じタイプのものを複数定義するには、名前のサフィックスを使います。

exporters:
  otlp/tempo:
    endpoint: tempo.observability.svc.cluster.local:4317
    tls:
      insecure: true
  otlphttp/loki:
    endpoint: http://loki.observability.svc.cluster.local:3100/otlp
  otlphttp/prometheus:
    endpoint: http://prometheus.observability.svc.cluster.local:9090/api/v1/otlp

知っておくべきバックエンドの詳細:

  • Tempo は、設定で OTLP receiver が有効になっている場合に、自身の receiver のポート(4317 gRPC、4318 HTTP)で、直接 OTLP を受け付けます。
  • Loki は、HTTP ポートの /otlp で OTLP のログを受け付けるため、otlphttp では、最終的な URL は /otlp/v1/logs になります。
  • Prometheus は、/api/v1/otlp/v1/metrics で OTLP のメトリクスを受け付けますが、OTLP receiver を有効にして起動した場合にのみです(--web.enable-otlp-receiver フラグ)。

これらのパスは、お使いのバージョンの各製品のドキュメントで確認してください。その後、各シグナルをそのバックエンドにルーティングします。

service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [memory_limiter, batch]
      exporters: [otlp/tempo]
    logs:
      receivers: [otlp]
      processors: [memory_limiter, batch]
      exporters: [otlphttp/loki]
    metrics:
      receivers: [otlp]
      processors: [memory_limiter, batch]
      exporters: [otlphttp/prometheus]

パイプラインは、複数の exporter を持つことで、同じデータを複数の場所に送れます。たとえば、主要なバックエンドとアーカイブです。

exporter の TLS

信頼できないネットワークを横断するものには、TLS を使います。

exporters:
  otlp/backend:
    endpoint: otlp.example.com:4317
    tls:
      ca_file: /etc/otel/certs/ca.crt        # プライベート CA を信頼するため
      cert_file: /etc/otel/certs/client.crt  # 相互 TLS 用
      key_file: /etc/otel/certs/client.key

パブリックな CA の場合は、システムのルートが使われるため、tls ブロック全体を省略できます。insecure: true は TLS を無効にし、クラスター内での開発専用です。本番では insecure_skip_verify: true を避けてください。TLS が提供する保護が失われるからです。

receiver の TLS と認証

ネットワークポートでリッスンする Collector は、TLS を要求し、制御できないものから到達可能な場合は、認証を要求すべきです。

receivers:
  otlp:
    protocols:
      grpc:
        endpoint: 0.0.0.0:4317
        tls:
          cert_file: /etc/otel/certs/server.crt
          key_file: /etc/otel/certs/server.key
          client_ca_file: /etc/otel/certs/ca.crt   # クライアント証明書を要求する (mTLS)

トークンベースの認証には、認証 extension を使います。bearertokenauth extension は、トークンの送信と確認の両方ができます。

extensions:
  bearertokenauth/client:
    scheme: Bearer
    token: ${env:BACKEND_TOKEN}

exporters:
  otlphttp/backend:
    endpoint: https://otlp.example.com
    auth:
      authenticator: bearertokenauth/client

service:
  extensions: [bearertokenauth/client]

受信リクエストを検証するには、basicauth や oidc のような他の extension があり、receiver から auth: { authenticator: <name> } で参照します。利用可能なオプションは、ディストリビューションとバージョンによって異なるため、extension の README を確認してください。

単純なヘッダーベースの認証情報には、exporter にヘッダーを設定することもできます。

exporters:
  otlphttp/saas:
    endpoint: https://otlp.vendor.example.com
    headers:
      api-key: ${env:VENDOR_API_KEY}

シークレットを設定の外に置く

Git にある設定ファイルに、トークンやパスワードをそのまま書かないでください。環境変数を参照し、シークレットストアから変数を供給します。

exporters:
  otlphttp/backend:
    headers:
      authorization: Bearer ${env:BACKEND_TOKEN}

Kubernetes では、Secret から変数を注入します。

env:
  - name: BACKEND_TOKEN
    valueFrom:
      secretKeyRef:
        name: otel-backend
        key: token

Secret 自体は、Git で暗号化するか(たとえば、Flux のガイドのように SOPS で)、シークレットマネージャーから同期してください。Collector は、マウントされたファイルを読み取る file: プロバイダー(${file:/path/to/secret})もサポートしており、ボリュームとしてマウントされ、プラットフォームによってローテーションされるシークレットに適しています。どのソースを使う場合でも、お使いのディストリビューションでそのプロバイダーが利用可能であることを確認してください。contrib のビルドにはいくつか含まれています。

ネットワークの露出

Collector は、クラスター内で動作することが多いため、そのデフォルトの姿勢が重要です。

  • 意図的にバインドする。 最近のバージョンは、receiver のデフォルトを localhost にしており、安全ですが、他のコンテナからは到達できません。0.0.0.0 は、到達可能であるべきポートにのみ使い、NetworkPolicy、TLS、認証で保護します。
  • 使わないものを無効にする。 使わない receiver と Service のポートを削除して、攻撃対象領域を小さく保ちます。
  • デバッグ用のエンドポイントはオペレーター向け。 zpages と pprof は localhost に保ち、決して公開しないでください。
  • エクスポートの前にマスキングする。 attributes や transform の processor を使って、認証情報、トークン、個人データを、ネットワークを出る前に削除します(本番対応のガイドを参照)。

アプリケーションの namespace だけが Collector に到達できるようにする NetworkPolicy:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-otlp-from-apps
  namespace: observability
spec:
  podSelector:
    matchLabels:
      app.kubernetes.io/name: opentelemetry-collector
  policyTypes: [Ingress]
  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              telemetry: "enabled"
      ports:
        - protocol: TCP
          port: 4317
        - protocol: TCP
          port: 4318

確認する

  1. otelcol validate --config=config.yaml を実行して、YAML とスキーマのミスを見つけます。
  2. Collector を起動し、ログで exporter の接続や TLS のエラーを確認します。
  3. テスト用のスパンを送り、バックエンドで探します。届かない場合は、exporter のプロトコルとポートを、バックエンドが実際にリッスンしているものと比較します。
  4. Collector 自身のメトリクスで、バックエンドがデータを拒否すると増える otelcol_exporter_send_failed_* のカウンターを確認します。

人気のガイド