📌

OpenTelemetry CollectorによるKubernetes上のメトリクス取得構成

2024/04/14に公開

こんにちは、Splunk Observability の導入支援を行っている、kntr_nkgm です。

OpenTelemetry Collector と Kubernetes

アプリケーションへの計装を行う場合、OpenTelemetry Collector に対して一度テレメトリーデータを集約し、バックエンドに送信することが推奨されています。最近だとこのあたりのブログなどでも語られています。
https://opentelemetry.io/blog/2024/otel-collector-anti-patterns/#5--not-using-the-opentelemetry-collector-where-appropriate

そのため、アプリケーションを Kubernetes 環境上で動かしている場合は、OpenTelemetry Collector もコンテナ環境上で稼働させている方も多いのではないでしょうか。

さて、Kubernetes 環境を利用する以上、Kubernetes クラスターやノード、あるいは、Pod 単位などでの状態についてもモニターしていく必要があるはずです。
Kubernetes 環境のメトリクスやログについても、OpenTelemetry Collector によって取得することができます。
OpenTelemetry 公式のドキュメントでは、2タイプ[1]の Collector をデプロイする必要があることを説明していますが、大体こういうものって、どっちがどっちで、どんなものだったかを忘れたり混同したりするんです。
(正直に白状すると、こんなブログ記事を書いているのは、まさにその状況に陥ったからです)
改めてドキュメントを見直しに行くのもいいですが、この場でまとめておきましょう。

簡単にまとめておくと

さて、まずは簡単にまとめてしまいましょう。

  1. DaemonSet としてデプロイする OpenTelemetry Collector

    • Kubernetes クラスタを構成する各ノード、Pod などのメトリクスを取得する
    • 各ノード上のログや、Pod が stdout/stderr に出力するログを取得する
    • 計装されたアプリケーションによって生成されるトレースを集約・整形・処理する
  2. Deployment としてデプロイする OpenTelemetry Collector

    • クラスター全体としての状態に関するテレメトリーを収集する
      (ノード, Pod ステータス, クラスタでのイベントなど)

つまり、DaemonSet としてデプロイすることで、Kubernetes ノードごとに、そのノードとノード上のPodに関するテレメトリを取得しつつ、トレース/スパン生成元のアプリケーションと同じノード上のCollectorでトレース/スパンを受け取れるようにしている一方で、
クラスター全体に関するステータス取得については、Deployment として Collector をデプロイして、クラスター単位でテレメトリー取得すれば十分、ということですね。

構成を概要として図示すると、以下のようになりそうです。
(Splunk distro of OpenTelemetry Collector を利用している前提の表現です。お使いのバックエンドや Distro に基づいて読み替えてください)

Getting Started では

OpenTelemetry 公式の Kubernetes における Getting Started では、DaemonSets, Deployment それぞれの OpenTelemetry Collector に、以下のコンポーネントが含まれているようです。

  1. DaemonSets

    • Kubeletstats Receiver
    • Filelog Receiver
    • OTLP Receiver
    • Kubernetes Attributes Processor
  2. Deployment

    • Kubernetes Cluster Receiver
    • Kubernetes Objects Receiver

https://opentelemetry.io/docs/kubernetes/getting-started/

さて、それぞれが何をやっているのか、もうすこし見てみましょう。

OpenTelemetry Component とワークロードの定義

さて、双方の Collector で構成されている Component について、より詳細に、以下にまとまっています。
https://opentelemetry.io/docs/kubernetes/collector/components/

例えば、Kubeletstats Receiver を見てみます。

  • DaemonSet として構成することが推奨
  • Deployment として構成することは、可能だが、その Pod がデプロイされたノードのメトリクスしか取得できない

という形でまとまっています。

名前から推測できる通り、各ノードで実行されるエージェントである Kubelet からメトリクスを取ってくる Receiver です。
各ノードのメトリクス情報を取得する必要があるので、DaemonSets としてデプロイする方が自然であると理解できますね。

その他にも、Kubernetes Cluster Receiver では、

  • DaemonSet として構成することは、可能だが、データの重複が発生する
  • Deployment として構成することは、可能だが、1より大きいレプリカ数でデプロイするととデータの重複が発生する

となっています。
Kubernetes Cluster Receiver は、Kubernetes API を用いてクラスター全体としてのメトリクスやイベントを集めるものと明記されており、Kubernetes API はクラスタで一つなので、複数の Pod から同じ API から同じテレメトリーデータをとる構成にしても同じデータが取れるだけ、ということですね。

また、Kubernetes Attribute Processor に関しては、

The Kubernetes Attributes Processor automatically discovers Kubernetes pods, extracts their metadata, and adds the extracted metadata to spans, metrics, and logs as resource attributes.

The Kubernetes Attributes Processor is one of the most important components for a collector running in Kubernetes. Any collector receiving application data should use it.

(翻訳)
Kubernetes Attribute Processor は Kubernetes Pod を自動検出し、メタデータを抽出し、スパン、メトリクス、ログに対して resource attributes としてメタデータを付与します。

Kubernetes Attribute Processor は Kubernetes で実行する Collector にとって最も重要なコンポーネントの一つです。アプリケーションのデータを受信するあらゆる Collector がこれを使用するべきです。

とのこと。
Kubernetes に関するメタデータ(Namespace, Pod名, Pod UID, Deployment 名など)を付与したりするもので、最重要なコンポーネントであると位置づけられています。

もっと詳しく知るには

各コンポーネントで取得されるメトリクスの一覧や、付与されるメタデータなどを知りたいですか?
一覧表のようなものを作ろうかとも思ったのですが、膨大になってしまって、却って参照性が厳しいことになってしまいました。

ここから先は、各コンポーネントの GitHub レポジトリを参照していく必要があります。
例えば、kubeletstats receiver の場合はこんな感じに参照できるはずです。

https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/receiver/kubeletstatsreceiver/documentation.md

必要に応じて参照していきましょう。
一方で、メトリクス量があまりに膨大になってしまうと管理が難しくなったり、場合によっては、課金に影響することもあります。
上手にフィルタリングするなどの取り組みが必要になりますが……また、それは別のお話ということで。

まとめ

Kubernetes 環境でも OpenTelemetry Collector を正しく理解して使いこなしていきましょう!

脚注
  1. "2タイプ"というのはややぼかした表現で、厳密には"2回"という表現の方が適切です。 ↩︎

Discussion