New Relic Now+ New Relic’s most transformative platform update yet with 20+ product launches.
Watch the event on-demand now.

すでにKubernetesでアプリケーションを実行していて、OpenTelemetryを利用してアプリとクラスタの健全性とパフォーマンスに関する情報を取得することを検討している場合は、OpenTelemetry Operatorと呼ばれるKubernetes Operatorの実装を考えるとよいでしょう。

OpenTelemetry Operatorにはさまざまな機能があるため、ほとんど手間のかからないOpenTelemetry管理に最適です。しかし、どんな強力なツールでもそうですが、問題が起きたらどうなるのでしょうか?

このブログ記事では、OpenTelemetry Operator(以下、「オペレーター」)について、またインストール、コレクターのデプロイ、自動インストゥルメンテーションでよく発生する問題について説明します。また、これらの問題を解決する方法を学ぶことで、オペレーターを実行するための準備を整えることができます。

オペレーターの概要

オペレーターの主な機能を詳しく見てみましょう。

OTelコレクターの管理

オペレーターはコレクターのデプロイを自動化し、コレクターが正しく設定され、クラスタ内でスムーズに実行されるようにします。オペレーターは、大規模なデータ収集エージェント群をリモートで管理するためのネットワークプロトコルであるOpen Agent Management Protocol(OpAMP)を使用して、コレクター群全体の設定も管理します。このプロトコルはベンダーに依存しないため、一貫したオブザーバビリティ設定が確保され、異なるベンダーのエージェント間での管理が簡素化されます。

Pod内の自動インストゥルメンテーションの管理

オペレーターは、アプリケーションに自動インストゥルメンテーション機能を自動的に挿入して設定するため、ソースコードを変更せずにテレメトリーデータを収集できます。アプリケーションがまだOpenTelemetryで計装されていない場合、これは一石二鳥でアプリケーションテレメトリーの生成と収集を開始できる素晴らしいオプションです。

オペレーターのインストール

当然のように思えるかもしれませんが、オペレーターをインストールする前に、Kubernetes 1.23以降を実行している、オペレーターをインストールできるKubernetesクラスタが必要です。特定のバージョン要件については、互換性マトリックスを確認してください。minikubek0sKinDなどのローカルKubernetesツールを使用してマシン上でクラスタを起動することも、クラウドプロバイダーサービスで実行されているクラスタを使用することもできます。

次に、そのクラスタにcert-managerというコンポーネントがすでにインストールされている必要があります。このコンポーネントは、証明書が有効かつ最新であることを確認することで、Kubernetesの証明書を管理します。cert-managerとオペレーターの両方を、kubectlまたはHelmチャート経由でインストールできます。

ヒント:いずれの場合も、オペレーターのインストールを開始する前に、cert-managerのインストールが完了するまで待つ必要があることに注意してください。そうしないと、オペレーターのインストールが失敗します。

kubectlを使用したインストール

次のコマンドを実行し、cert-managerをインストールします。

kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.10.0/cert-manager.yaml

次に、オペレーターをインストールします。

kubectl apply -f https://github.com/open-telemetry/opentelemetry-operator/releases/latest/download/opentelemetry-operator.yaml

Helmを使用したインストール

cert-managerをインストールするために、まずHelmリポジトリを追加します。

helm repo add jetstack https://charts.jetstack.io --force-update

次に、Helmチャートを使用しcert-managerをインストールします。

helm install \
  cert-manager jetstack/cert-manager \
  --namespace cert-manager \
  --create-namespace \
  --version v1.16.1 \
  --set crds.enabled=true

cert-managerのインストールには数分かかることが想定されます。このリンクの手順に従ってcert-managerのインストール状況を確認するか、次のコマンドを実行してデプロイ状況を確認してください。

kubectl get pods –namespace cert-manager

オペレーターをインストールします。インストールを行うにはHelm 3.9以降が必要であることに注意してください。まず、リポジトリを追加します。

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

次に、オペレーターをインストールします。

helm install  --namespace opentelemetry-operator-system \
  --create namespace \
  opentelemetry-operator open-telemetry/opentelemetry-operator

OTelコレクターのデプロイ

クラスタにcert-managerとオペレーターを設定したら、コレクターをデプロイできます。コレクターは、さまざまなソースからテレメトリーを取り込み、受信したテレメトリーを設定に基づいてさまざまな方法で変換し、処理されたデータをOpenTelemetryデータ形式(OpenTelemetry Protocolの略であるOTLP)を受け入れるバックエンドにエクスポートできる多目的コンポーネントです。

コレクターは、「パターン」と呼ばれるさまざまな方法でデプロイできます。どのパターンをデプロイするかは、テレメトリーのニーズと組織のリソースによって異なります。このトピックはこのブログ記事の範囲外ですが、このリンクから詳細をご覧いただけます。

コレクターカスタムリソース

カスタムリソース(CR)は、デフォルトのKubernetesインストールでは必ずしも利用できるとは限らない、特定のKubernetesインストールのカスタマイズを表します。CRは、Kubernetesをよりモジュール化するのに役立ちます。

オペレーターには、OpenTelemetryCollectorと呼ばれるコレクターのデプロイメントを管理するためのCRがあります。以下は、OpenTelemetryCollectorリソースのサンプルです。

apiVersion: opentelemetry.io/v1beta1
kind: OpenTelemetryCollector
metadata:
  name: otelcol
  namespace: opentelemetry
spec:
  mode: statefulset
  config:
    receivers:
      otlp:
        protocols:
          grpc: {}
          http: {}
      prometheus:
        config:
          scrape_configs:
            - job_name: 'otel-collector'
              scrape_interval: 10s
              static_configs:
              - targets: [ '0.0.0.0:8888' ]

    processors:
      batch: {}

    exporters:
      logging:
        verbosity: detailed

    service:
      pipelines:
        traces:
          receivers: [otlp]
          processors: [batch]
          exporters: [logging]
        metrics:
          receivers: [otlp, prometheus]
          processors: []
          exporters: [logging]
        logs:
          receivers: [otlp]
          processors: [batch]
          exporters: [logging]

OpenTelemetryCollectorリソースには、インスタンス化の計画方法に応じて多くの設定オプションがありますが、基本的な設定では以下が必要です。

  • modeは、deploymentsidecardaemonsetstatefulsetのいずれかである必要があります。modeを省略すると、デフォルトでdeploymentが使用されます。
  • configは、コレクターのYAML設定なので、見たことがあるかもしれません。

コレクターのデプロイに関する一般的な問題とトラブルシューティングのヒント

期待したデータが表示されない場合、または何かが正しく機能していないと思われる場合は、次のトラブルシューティングのヒントをお試しください。

コレクターリソースが適切にデプロイされていることを確認する

OpenTelemetryCollector YAMLがデプロイされると、Kubernetesに次のオブジェクトが作成されます。

  • OpenTelemetryCollector
  • コレクターポッド:
    • サイドカー以外のmodeを指定した場合は、<collector_CR_name>-collector-<unique_identifier> という名前のDeploymentStatefulSetDaemonSetリソースを探します。
    • modesidecarとして指定すると、コレクターサイドカーコンテナがotc-containerという名前のアプリポッドに作成されます。
  • ターゲットアロケーターポッド:
    • ターゲットアロケーターを有効にした場合は、<collector_CR_name>-targetallocator-<unique_identifier>という名前のリソースを探します。
  • コレクター設定のConfigMap
    • サイドカー以外のモードを指定した場合は、<collector_CR_name> -collector-<unique_identifier>という名前のDeploymentStatefulSetDaemonSetリソースを探します。
    • モードをsidecarとして指定した場合、コレクター設定が環境変数として含まれることに注意してください。

OpenTelemetryCollectorリソースをデプロイするときは、前述のオブジェクトが作成されていることを確認してください。

リソースの確認方法

 

まず、OpenTelemetryCollectorリソースがデプロイ済みであることを確認します。

kubectl get otelcol -n <namespace>

OpenTelemetryCollectorリソースを使用してコレクターをデプロイすると、コレクターの設定YAMLを含むConfigMapが作成されます。ConfigMapがコレクターと同じネームスペースに作成され、設定自体が正しいことを確認します。

ConfigMapを一覧表示します。

kubectl get configmap -n <namespace> | grep <collector-cr-name>-collector

また、コレクターのmodeに基づいて適切なコマンドを実行して、コレクターポッドを確認することをお勧めします。

  • DeploymentStatefulSetDaemonsetモード:
kubectl get pods -n <namespace> | grep <collector_CR_name>-collector
  • sidecarモード:
kubectl get pods <pod_name> -n opentelemetry -o jsonpath='{.spec.containers[*].name}'

これにより、コレクターサイドカーコンテナを含む、ポッドで作成されたすべてのコンテナが一覧表示されます。コレクター設定は、コレクターサイドカーコンテナに環境変数として含まれています。

コレクターCRバージョンを確認する

使用しているOpenTelemetryCollectorのCRバージョンを確認してください。利用可能なバージョンはv1alpha1v1beta1の2つです。

2つのコレクターCRバージョンの違いを示すスクリーンショット。

これら2つのAPIバージョンには、主に2つの違いがあります。

  1. configセクションが異なります。v1beta1の場合、設定値はCR設定の一部であるキーの値のペアですが、v1alpha1の場合、設定値は1つの長いテキスト文字列です。テキスト文字列は依然としてYAML形式に従う必要があることに注意してください。
  2. v1beta1を使用している場合は、コレクター設定の値を空のままにすることはできません。スカラー値の場合は空の中括弧({})を指定し、配列の場合は空の角括弧([ ])を指定する必要があります。v1alpha1を使用している場合、これは必要ありません。

コレクターのベースイメージを確認する

デフォルトでは、OpenTelemetryCollector CRはコレクターのコアディストリビューションを使用します。コアディストリビューションは、OpenTelemetry開発者が開発およびテストするためのコレクターの必要最低限のディストリビューションです。拡張機能、コネクタ、レシーバー、プロセッサ、エクスポーターの基本コンポーネントセットが含まれています。

コアで提供されるコンポーネントよりも多くのコンポーネントにアクセスしたい場合は、代わりにコレクターのKubernetesディストリビューションを使用できます。このディストリビューションは、KubernetesとKubernetesで実行されているサービスをモニターするために、Kubernetesクラスタで使用することを目的として作成されています。これには、コアおよびcontribディストリビューションのコンポーネントのサブセットが含まれています。あるいは、独自のコレクターディストリビューションを構築することもできます。

次の例のように、spec.imageでimage属性を指定することで、コレクターのベースイメージを設定できます。

apiVersion: opentelemetry.io/v1beta1
kind: OpenTelemetryCollector 
metadata:
  name: otelcol
  namespace: opentelemetry
spec:
  mode: statefulset 
  image: otel/opentelemetry-collector/contrib:0.102.1
config: 
  receivers: 
    otlp:
      protocols: 
       grpc: {}
       http: {}
  processors: 
    batch: {}
  exporters: 
    otlp:
      endpoint: https://otlp.nr-data.net:4318

ライセンスキーを確認する

テレメトリーをNew Relicアカウントに送信するために必要な適切なNew Relicアカウントライセンスキーが設定されていることを確認します。プレーンテキストとして表示されないようにするには、環境変数としてエクスポートするか、Kubernetesシークレットを作成して保存します。オプションで、シークレットプロバイダーまたは独自のクラウドプロバイダーのシークレットプロバイダーを使用できます。

New Relicエンドポイントの設定を確認する

エクスポーター設定で、リージョンに適切なOTLPエンドポイントが設定されていることを確認します。

インストゥルメンテーション

インストゥルメンテーションとは、ソフトウェアにコードを追加して、テレメトリー信号(ログ、メトリクス、トレース)を生成するプロセスです。OpenTelemetryを使用してコードを計装するにはいくつかのオプションがあり、主な2つはコードベースとゼロコードソリューションです。

コードベースのソリューションでは、OpenTelemetry APIを使用してコードを手動で計装する必要があります。実装には時間と労力がかかりますが、このオプションを使用すると、コードのどの部分をどのように計装するかを高度に制御できるため、深いインサイトが得られ、テレメトリーをさらに強化できます。

コードを変更せずにインストゥルメント化するには(またはソースコードを変更できない場合)、 ゼロコードソリューション(または自動インストゥルメンテーションエージェント)を使用できます。この方法では、shimまたはバイトコードエージェントを使用して、実行時またはコンパイル時にコードをインターセプトし、依存するサードパーティのライブラリとフレームワークにトレースとメトリクスのインストゥルメンテーションを追加します。公開時点では、自動インストゥルメンテーションはJava、Python、.NET、JavaScript、PHP、Goで利用可能です。ゼロコードインストルメンテーションの詳細については、このリンクをご覧ください。

両方のオプションを同時に使用することもできます。エンドユーザーの中には、ゼロコードエージェントから始めて、カスタム属性の追加や新しいスパンの作成などの追加のインストゥルメンテーションを手動で挿入することを選択する人もいます。また、OpenTelemetryは、コードベースおよびゼロコードソリューション以外のオプションも提供します。詳細についてはこのリンクをご覧ください。

オペレーターによるゼロコードインストゥルメンテーション

オペレーターにはInstrumentationと呼ばれるCRがあり、KubernetesポッドにOpenTelemetryインストゥルメンテーションを自動的に挿入して設定できるため、アプリケーションにゼロコードインストゥルメンテーションの利点をもたらします。現在、Apache HTTPD、.NET、Go、Java、nginx、Node.js、Pythonで利用可能です。

以下は、PythonサービスのInstrumentationリソース定義のサンプルです。

apiVersion: opentelemetry.io/v1alpha1 
kind: Instrumentation 
metadata:
  name: python-instrumentation 
  namespace: application
spec:
  env:
    - name: OTEL_EXPORTER_OTLP_TIMEOUT
      value: "20"
    - name: OTEL_TRACES_SAMPLER
      value: parentbased_traceidratio
    - name: OTEL_TRACES_SAMPLER_ARG
      value: "0.85"
exporter:
    endpoint: http://localhost:4317
  propagators:
    - tracecontext
    - baggage 
  sampler:
    type: parentbased_traceidratio 
    value: "0.25"
python: 
    env:
      - name: OTEL_METRICS_EXPORTER
        value: otlp_proto_http
      - name: OTEL_LOGS_EXPORTER
        value: otlp_proto_http
      - name: OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED
        value: "true"
      - name: OTEL_EXPORTER_OTLP_ENDPOINT
        value: http://localhost: 4318

単一の自動インストゥルメンテーションYAMLを使用して、異なる言語で記述された複数のサービスを提供できます(自動インストゥルメンテーションがサポートされている場合)。グローバル環境変数をspec.envの下にリストし、言語固有の環境変数をspec.<language_name>.envの下にリストします。これにより、同じInstrumentationリソース内で、言語固有の環境変数設定を組み合わせて使用できます。

オペレーターの自動インストゥルメンテーション機能を使用するには、Instrumentationリソースをデプロイするだけでは不十分です。自動インストゥルメンテーション設定は、インストゥルメントされるコードに関連付ける必要があります。これは、次の例のように、アプリケーションのDeployment YAMLのテンプレート定義セクションに自動インストゥルメンテーションのアノテーションを追加することによって行われます。

apiVersion: apps/v1
kind: Deployment 
metadata:
  name: my-deployment-with-sidecar 
spec:
  replicas: 1 
  selector:
    matchLabels:
      app: my-pod-with-sidecar
  template:
    metadata: 
      labels:
        app: my-pod-with-sidecar
      annotations:
        sidecar.opentelemetry.io/inject:"true"
        instrumentation.opentelemetry.io/inject-python:"true"
spec:
  containers:
    - name: py-otel-server
      image: otel-python-lab:0.1.0-py-otel-serverports:
    - containerPort: 8082
      name: py-server-port

instrumentation.opentelemetry.io/inject-pythonというアノテーションがtrueに設定されている場合、このポッドで実行されているコンテナにPython自動インストゥルメンテーション(この場合)を挿入するように、オペレーターに指示します。他の言語の場合は、pythonを適切な言語名に置き換えるだけです(Javaアプリの例:instrumentation.opentelemetry.io/inject-java)。この値をfalseに設定すると、インストゥルメンテーションを無効にできます。

複数のInstrumentationリソースがある場合は、使用するリソースを指定する必要があります。指定しないと、オペレーターはどれを選択すればよいかわかりません。これは次のように実行できます。

  • リソース名で選択する。InstrumentationリソースがDeploymentと同じネームスペースに存在する場合は、これを使用します。たとえば、 instrumentation.opentelemetry.io/inject-java: my-instrumentation my-instrumentationという Instrumentationリソースを検索します。
  • Namespaceとリソース名で選択する。Instrumentationリソースが別のネームスペースに存在する場合は、これを使用します。たとえば、 instrumentation.opentelemetry.io/inject-java: my-namespace/my-instrumentationは、ネームスペースmy-namespace my-instrumentationというInstrumentationリソースを検索します。

注釈付きアプリケーションの前にInstrumentationリソースをデプロイする必要があります。そうしないと、コードは自動的にインストゥルメント化されません。オペレーターは、起動時にアプリケーションのポッドにinitコンテナを追加することで自動インストゥルメンテーションを挿入します。つまり、サービスがデプロイされるまでにInstrumentationリソースを利用できない場合、自動インストゥルメンテーションは失敗します。

一般的なインストゥルメンテーションの問題とトラブルシューティングのヒント

コレクターがデータを処理していないと思われる場合、または自動インストゥルメンテーションが機能していないと思われる場合は、次の手順を試して、問題のトラブルシューティングと解決を行ってください。

インストゥルメンテーションリソースが適切にデプロイされていることを確認する

次のコマンドを実行して、KubernetesクラスタにInstrumentationリソースが作成されたことを確認します。

kubectl describe otelinst -n <namespace>

オペレーターのログを確認する

次のコマンドを実行して、オペレーターログにエラーメッセージがないか確認します。

kubectl logs -l app.kubernetes.io/name=opentelemetry-operator\
  --container manager \
  -n opentelemetry-operator-system --follow

リソースのデプロイメント順序を確認する

Instrumentation CRがDeployment前に デプロイされていることを再確認してください。

自動インストゥルメンテーションンテーションのCRアノテーションを確認する

  1. アノテーションに誤字がないことを確認する
  2. 次の例のように、設定がデプロイメントのメタデータ定義(metadata.annotation)ではなく、ポッドのメタデータ定義(spec.template.metadata.annotation)にあることを確認する
インストゥルメンテーション注釈をtemplate.metadataの下に定義する必要があることを示すスクリーンショット。

エンドポイントの設定を確認する

以下の例のように、spec.exporter.endpointで設定されているエンドポイントが、Kubernetesクラスタ内のテレメトリーの宛先を指しているかを確認します。

テレメトリーエンドポイントが設定されている場所を示すスクリーンショット。

Kubernetesクラスタ内のサイドカー以外のコレクターにテレメトリをエクスポートする場合、この値はコレクターサービスの名前を参照する必要があります。上記の例では、otel-collectorはコレクターKubernetesサービスの名前です。

さらに、コレクターが別のネームスペースで実行されている場合は、コレクターのサービス名にそれを追加する必要があります。たとえば、<namespace>.svc.cluster.local(前の例では、ネームスペースはOpenTelemetryです)。

テレメトリーをサイドカーコレクターにエクスポートする場合、exporter.endpointの値はhttp://localhost:4317(gRPC)またはhttp://localhost:4318(HTTP)になります。

最後に、正しいコレクターポートを使用していることを確認します。通常は、4317(gRPC)または4318(HTTP)のいずれかを選択できますが、Python自動インストゥルメンテーションではgRPCがサポートされていないため、4318のみを使用できます。使用している言語に同様の注意事項があるかどうかを確認してください。

まとめ

OpenTelemetry Operatorは、1つ以上のコレクターのデプロイメントと設定を管理し、Kubernetesポッドにゼロコードインストゥルメンテーションソリューションを挿入して設定します。これにより、OpenTelemetryインストゥルメンテーションを開始できるようになり、アプリケーションに手動インストゥルメンテーションを追加することでテレメトリーをさらに強化できます。

このブログ記事では、一般的なインストール障害から自動インストゥルメンテーションやコレクターのデプロイメントの問題解決まで、オペレーターの詳細について説明しました。詳細なインストール手順とトラブルシューティングのヒントにより、コレクターのデプロイメント、設定、管理、およびサポートされているライブラリの自動インストゥルメンテーションにオペレーターを効果的に活用できるようになります。