2026年7月1日

2026年7月1日

KubernetesでOpenTelemetryの分散トレーシングを始める|Collectorの配置・自動計装・サンプリング

Kubernetesで分散トレーシングを始めるには、アプリがOpenTelemetry(OTel)の形式でトレースを出し、クラスター内のOpenTelemetry Collectorがそれを受け取って保存先に送る、という構成を作ります。アプリが保存先を直接知る必要がなくなり、Podの情報(名前空間やDeployment名)もCollector側で付けられます。この記事では、Collectorの置き方(DaemonSetとゲートウェイ)、設定ファイルの書き方、アプリから送る方法(自動計装と環境変数)、WordPress(PHP)の場合、サンプリングの考え方を説明します。

OpenTelemetryは開発が活発で、Collectorの設定項目やHelmチャートの値、言語ごとの対応状況は版によって変わります。この記事の内容は2026年10月現在の情報をもとにした例なので、導入時は公式ドキュメントと各リポジトリのリリースノートを確認してください。

分散トレーシングで分かること

1つのリクエストがIngress、WordPress、外部API、データベースと渡っていくとき、どこで何ミリ秒かかったかを1本のタイムラインで見られるのが分散トレーシングです。1つのリクエスト全体を「トレース」、その中の各処理を「スパン」と呼びます。

サービスをまたいでスパンをつなげるには、トレースIDを次のサービスに引き継ぐ必要があります。OpenTelemetryでは既定でW3C Trace Contextの traceparent ヘッダーを使います。途中にあるプロキシやアプリがこのヘッダーを捨ててしまうと、トレースがそこで途切れます。

構成の全体像

基本の構成は次の3層です。

  1. アプリ:OpenTelemetryのSDKや自動計装でスパンを作り、OTLP(OpenTelemetry Protocol)で送る。ポートは gRPC が4317、HTTP が4318。
  2. Collector:受け取ったデータに情報を付け、まとめて保存先に送る。
  3. 保存先(バックエンド):Jaeger、Grafana Tempo、各社のオブザーバビリティサービスなど。多くがOTLPを直接受け付けます。

Collectorの置き方には2つの型があります。

  • エージェント(DaemonSet):各ノードに1つずつ置き、同じノードのPodから受け取る。Podの情報を付けやすく、ノード内で通信が完結する。
  • ゲートウェイ(Deployment):クラスターに数台だけ置き、全体のデータを集めて送る。サンプリングや送信先の認証情報の管理を1か所にまとめられる。

小さく始めるならゲートウェイだけでも動きます。規模が大きくなったら、エージェントで受けてゲートウェイに集める2段構成にします。

Collectorを入れる

Collectorは、OpenTelemetryの公式Helmチャートで入れるのが手軽です。

helm repo add open-telemetry https://open-telemetry.github.io/opentelemetry-helm-charts
helm repo update
helm install otel-gateway open-telemetry/opentelemetry-collector \
  -n observability --create-namespace -f values.yaml

values.yaml ではモード(deployment、daemonset など)と、使うイメージを指定します。Collectorには機能の少ない標準版と、多くの部品を含む contrib 版、Kubernetes向けの k8s 版といった配布物があり、使いたいプロセッサーが含まれている配布物を選びます。

# values.yaml(例)
mode: deployment
replicaCount: 2
image:
  repository: otel/opentelemetry-collector-k8s
config:
  receivers:
    otlp:
      protocols:
        grpc:
          endpoint: 0.0.0.0:4317
        http:
          endpoint: 0.0.0.0:4318
  processors:
    memory_limiter:
      check_interval: 1s
      limit_percentage: 80
      spike_limit_percentage: 25
    k8sattributes: {}
    batch: {}
  exporters:
    otlp:
      endpoint: tempo.observability.svc.cluster.local:4317
      tls:
        insecure: true   # クラスター内の検証用。本番ではTLSを設定する
  service:
    pipelines:
      traces:
        receivers: [otlp]
        processors: [memory_limiter, k8sattributes, batch]
        exporters: [otlp]

設定は「受け取る(receivers)」「加工する(processors)」「送る(exporters)」を service.pipelines でつなぐ形です。定義しただけでパイプラインに書いていない部品は使われません。

つまずきやすい点が3つあります。

  • 待ち受けのアドレス:最近のCollectorはreceiverの既定の待ち受けが localhost になっているため、0.0.0.0 を明示しないとほかのPodから届きません。
  • プロセッサーの順番:memory_limiter は先頭に置きます。Collectorのメモリ不足によるPodの再起動を防ぐためです。Pod側の resources.limits.memory も設定しておきます。
  • k8sattributes の権限:Podの情報を引くために、Pod・名前空間・ReplicaSetなどを読むRBACの権限が必要です。Helmチャートには、この権限をまとめて作る設定(プリセット)が用意されています。

送信がうまくいかないときは、exporters に debug を追加してパイプラインに入れると、受け取ったスパンがCollectorのログに出ます。Collectorまで届いているのか、保存先への送信で失敗しているのかを切り分けられます。

アプリからトレースを送る

環境変数で送信先を決める

OpenTelemetryのSDKは、言語をまたいで共通の環境変数で設定できます。Deploymentに次のように書くと、コードを変えずに送信先やサービス名を切り替えられます。

env:
  - name: OTEL_SERVICE_NAME
    value: wordpress
  - name: OTEL_EXPORTER_OTLP_ENDPOINT
    value: http://otel-gateway-opentelemetry-collector.observability.svc.cluster.local:4318
  - name: OTEL_EXPORTER_OTLP_PROTOCOL
    value: http/protobuf
  - name: OTEL_PROPAGATORS
    value: tracecontext,baggage
  - name: OTEL_RESOURCE_ATTRIBUTES
    value: deployment.environment=production

Serviceの名前(ここではHelmのリリース名から作られた名前)は環境によって変わるので、kubectl get svc -n observability で確認してください。DaemonSetのエージェントに送る場合は、Downward API の status.hostIP でノードのIPを環境変数に入れ、それを送信先に使う方法がよく使われます。

OpenTelemetry Operator の自動計装

OpenTelemetry Operator を入れると、Instrumentation というカスタムリソースと、Podへのアノテーションだけで計装用のライブラリを注入できます。Java、Node.js、Python、.NETなどの言語に対応しています。

metadata:
  annotations:
    instrumentation.opentelemetry.io/inject-python: "true"

Operatorはアドミッションwebhookを使うため、既定では証明書の管理に cert-manager が必要です。対応言語や注入の方式は版によって変わるので、Operatorのドキュメントで確認してください。

WordPress(PHP)の場合

PHPは、上記のOperatorによる自動注入の主な対象言語には含まれていません(2026年10月現在)。PHPでは、PECLの opentelemetry 拡張をイメージに入れ、Composerで SDK と OTLP のエクスポーター、自動計装のパッケージを追加する方法が一般的です。OpenTelemetryのPHP向けcontribリポジトリには、WordPress向けの自動計装パッケージも用意されています。

FROM wordpress:php8.3-apache
RUN pecl install opentelemetry && docker-php-ext-enable opentelemetry

PHPの自動計装を有効にするには、環境変数 OTEL_PHP_AUTOLOAD_ENABLED=true も設定します。Composerのパッケージ名と、WordPressのどの処理がスパンになるかは、パッケージの版ごとにREADMEで確認してください。WordPressのコアやプラグインのファイルを直接書き換える方法は、更新で消えるので避けます。導入後はまず検証環境で、ページの表示時間がどれだけ増えるかも測っておくと安心です。

サンプリングで量を抑える

すべてのリクエストのトレースを保存すると、保存先の容量と通信量が膨らみます。量を抑える方法は2つあります。

  • ヘッドサンプリング:リクエストの最初に、保存するかどうかを確率で決める。SDKの環境変数で OTEL_TRACES_SAMPLER=parentbased_traceidratio、OTEL_TRACES_SAMPLER_ARG=0.1 とすると、おおよそ10件に1件を残します。軽い反面、エラーになったリクエストも同じ確率で捨てられます。
  • テールサンプリング:トレースが終わってから、エラーや遅いリクエストを優先して残す。contrib 版などに含まれる tail_sampling プロセッサーで行います。同じトレースのスパンが同じCollectorに集まる必要があるため、ゲートウェイを複数台にするときは、トレースIDで振り分ける構成(loadbalancing エクスポーター)を前段に置きます。

最初はヘッドサンプリングで始め、エラーの調査で困るようになったらテールサンプリングを検討する、という順番が無理のない進め方です。

まとめ

  • アプリはOTLPでCollectorに送り、Collectorが情報を付けて保存先に送る。サービスをまたぐには traceparent ヘッダーの引き継ぎが必要。
  • Collectorはゲートウェイだけでも始められ、規模に応じてDaemonSetのエージェントを足す。
  • receiver は 0.0.0.0 で待ち受け、memory_limiter を先頭に置き、k8sattributes にはRBACの権限を渡す。届かないときは debug エクスポーターで切り分ける。
  • 送信先やサービス名は共通の OTEL_* 環境変数で決める。PHPは拡張とComposerのパッケージで計装する。
  • 量はヘッドサンプリングで抑え、必要に応じてテールサンプリングに進む。

お気軽にご相談ください

お見積りへ お問い合わせへ
▲