OpenTelemetry OpenTelemetry

OpenTelemetry Operator を Collector と自動計装に使う

Collector と計装を Kubernetes のリソースとして宣言し、Pod のアノテーションでエージェントを注入します。

15 min learn.level.上級

OpenTelemetry Operator は、2 つのものを Kubernetes のリソースとして管理します。Collector(OpenTelemetryCollector オブジェクト)と、自動計装(Instrumentation オブジェクトと、Operator にエージェントを注入させる Pod のアノテーション)です。アプリケーションのチームは、Dockerfile を編集するのではなく、アノテーションを追加することでテレメトリを得られ、プラットフォームチームは設定を Git の 1 か所に保てます。

Operator をインストールする

Operator は admission webhook を使うため、TLS 証明書が必要です。最も簡単な方法は、チャートがデフォルトで想定している cert-manager です。cert-manager がない場合は、Helm に自己署名証明書を生成させます。

helm repo add open-telemetry https://open-telemetry.github.io/opentelemetry-helm-charts
helm repo update

helm install my-opentelemetry-operator open-telemetry/opentelemetry-operator \
  --namespace opentelemetry-operator-system --create-namespace \
  --set "manager.collectorImage.repository=otel/opentelemetry-collector-k8s" \
  --set admissionWebhooks.certManager.enabled=false \
  --set admissionWebhooks.autoGenerateCert.enabled=true

cert-manager がすでにインストールされている場合は、証明書の設定をデフォルトのままにするか、admissionWebhooks.certManager.issuerRef で独自の issuer を参照できます。--version でチャートのバージョンを固定し、値は --set フラグではなく、ファイルまたは Flux の HelmRelease に置きます。

Collector を宣言する

apiVersion: opentelemetry.io/v1beta1
kind: OpenTelemetryCollector
metadata:
  name: demo
  namespace: observability
spec:
  mode: deployment        # deployment、daemonset、statefulset、または sidecar
  replicas: 2
  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: 20
      batch: {}
    exporters:
      debug: {}
    service:
      pipelines:
        traces:
          receivers: [otlp]
          processors: [memory_limiter, batch]
          exporters: [debug]

config ブロックは、これまで書いてきたのと同じ Collector の YAML で、リソースに埋め込まれています。Operator は、ワークロードと、receiver が使うポートを公開する <name>-collector という名前の Service(ここでは demo-collector)を作成します。利用可能な mode の値は、デプロイのガイドのパターンに対応しています。エージェントには daemonset、ゲートウェイには deployment、アプリケーションの Pod に注入される Collector には sidecar です。リリース間で API バージョンが変わっているため、お使いのクラスターで利用可能な CRD のバージョンを確認してください(kubectl get crd opentelemetrycollectors.opentelemetry.io)。

計装の設定を宣言する

Instrumentation リソースは、アノテーションされた Pod に Operator が注入する SDK の設定を保持します。

apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation
metadata:
  name: demo-instrumentation
  namespace: webapp
spec:
  exporter:
    endpoint: http://demo-collector.observability.svc.cluster.local:4318
  propagators:
    - tracecontext
    - baggage
  sampler:
    type: parentbased_traceidratio
    argument: "0.25"
  java:
    env:
      - name: OTEL_INSTRUMENTATION_COMMON_DEFAULT_ENABLED
        value: "true"

重要な詳細:

  • exporter.endpoint は、省略するとデフォルトで http://localhost:4317 になり、通常は何も届きません。常に Collector の Service に設定してください。
  • 別の namespace の Collector には、完全な DNS 名 <service>.<namespace>.svc.cluster.local を使います。
  • 文書化された例は、.NET、Go、Java、Python にはポート 4318(HTTP)、Node.js には 4317(gRPC)を使っています。ポートを、言語のエージェントが使うプロトコルに合わせてください。
  • 言語固有の環境変数は、spec.java.env や spec.python.env のように、spec.<language>.env の下に置きます。

アプリケーションより先に Instrumentation を作成してください。 Operator は、Pod が作成されるときにエージェントを注入します。リソースがまだ存在しないと、Pod は init コンテナなしで起動し、再起動する必要があります。

アノテーションでワークロードをオプトインする

Deployment の Pod テンプレートにアノテーションを追加します。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: checkout
  namespace: webapp
spec:
  selector:
    matchLabels: { app: checkout }
  template:
    metadata:
      labels: { app: checkout }
      annotations:
        instrumentation.opentelemetry.io/inject-java: "true"
    spec:
      containers:
        - name: checkout
          image: myorg/checkout:1.4.2

言語ごとのアノテーション:

言語アノテーション
Javainstrumentation.opentelemetry.io/inject-java: "true"
Pythoninstrumentation.opentelemetry.io/inject-python: "true"
Node.jsinstrumentation.opentelemetry.io/inject-nodejs: "true"
.NETinstrumentation.opentelemetry.io/inject-dotnet: "true"
Goinstrumentation.opentelemetry.io/inject-go: "true"(さらに、対象の実行ファイルのアノテーション)
SDK の設定のみinstrumentation.opentelemetry.io/inject-sdk: "true"

値は、"true"(この namespace の Instrumentation を使う)、その名前("my-instrumentation")、namespace で修飾された名前("other-ns/my-instrumentation")、または "false" にできます。namespace にアノテーションを付けると、その中のすべてのワークロードが計装されます。

使用する関連のアノテーション:

  • instrumentation.opentelemetry.io/container-names: "app,worker" は、どのコンテナを計装するかを選びます。デフォルトでは、最初のものだけが計装されます。
  • resource.opentelemetry.io/service.name: checkout は、サービス名などのリソース属性を設定します。他には、service.version や deployment.environment.name があります。
  • instrumentation.opentelemetry.io/inject-sdk: "true" は、すでに SDK を含むアプリケーション向けに、環境変数だけを注入します。
  • 1 つのコンテナには、複数の言語を注入することはできません。マルチコンテナ、マルチ言語の構成には、enable-multi-instrumentation の feature flag と、言語ごとのコンテナ名のアノテーションが必要です。
  • Go には、enable-go-instrumentation の feature gate、otel-go-auto-target-exe のアノテーション(または OTEL_GO_AUTO_TARGET_EXE の設定)、特権のあるサイドカーが必要なので、先にセキュリティへの影響を確認してください。

適用して確認する

kubectl apply -f collector.yaml -f instrumentation.yaml
kubectl apply -f checkout-deployment.yaml

kubectl get opentelemetrycollectors,instrumentations -A
kubectl get pod -n webapp -l app=checkout -o jsonpath='{.items[0].spec.initContainers[*].name}'; echo
kubectl logs -n observability deploy/demo-collector | grep -i 'service.name'

アプリケーションの Pod に opentelemetry-auto-instrumentation という名前の init コンテナがあれば、注入が機能したことを意味します。トラフィックを生成すると、Collector の debug exporter が、サービス名を持つスパンを出力するはずです。

トラブルシューティング

  1. Instrumentation リソースはありますか。 kubectl describe otelinst -n <namespace>。
  2. Operator のエラーは? Operator の namespace の manager コンテナのログを読みます。
  3. アプリケーションより先に作成しましたか。 そうでなければ、Deployment を再起動して、Pod が再作成され注入されるようにします。init コンテナについては、kubectl get events -n <namespace> を確認します。
  4. アノテーションは正しいですか。 spec.template.metadata.annotations にある必要があり、言語がアプリケーションと一致している必要があります。
  5. エンドポイントは正しいですか。 間違ったプロトコルやポート、あるいは namespace をまたぐ短い Service 名では、黙って何も送られません。

Operator を優先する場合

多くのチームがクラスターにデプロイしており、設定を中央で管理しつつ、アノテーションでテレメトリをオプトインにしたい場合に使います。Collector だけが必要で、SDK の設定を各アプリケーション自身のマニフェストで処理する場合は、シンプルな Helm チャートを使います。Operator とチャートは共存できますが、同じ Collector を両方で管理しないでください。

人気のガイド