OpenTelemetryバックエンドとしてPrometheusを使用する

Prometheusは、OTLP(別名「OpenTelemetryプロトコル」)をHTTP経由で取り込むことをサポートしています。

OTLPレシーバーを有効にする

デフォルトでは、OTLPレシーバーは無効になっています。これは、Prometheusが認証なしで動作できるため、明示的に設定されていない限り、着信トラフィックを受け入れるのは安全ではないためです。

レシーバーを有効にするには、フラグ--web.enable-otlp-receiverを切り替える必要があります。

$ prometheus --enable-feature=otlp-write-receiver

OpenTelemetryメトリクスをPrometheusサーバーに送信する

OpenTelemetry SDKおよびインストルメンテーションライブラリは、標準環境変数を介して構成できます。以下は、OpenTelemetryメトリクスをlocalhost上のPrometheusサーバーに送信するために必要なOpenTelemetry変数です。

export OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
export OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=http://localhost:9090/api/v1/otlp/v1/metrics

トレースとログをオフにする

export OTEL_TRACES_EXPORTER=none
export OTEL_LOGS_EXPORTER=none

OpenTelemetryメトリクスのデフォルトのプッシュ間隔は60秒です。以下は、15秒のプッシュ間隔を設定します。

export OTEL_METRIC_EXPORT_INTERVAL=15000

インストルメンテーションライブラリがservice.nameおよびservice.instance.idをすぐに提供しない場合は、それらを設定することを強くお勧めします。

export OTEL_SERVICE_NAME="my-example-service"
export OTEL_RESOURCE_ATTRIBUTES="service.instance.id=$(uuidgen)"

上記は、システムでuuidgenコマンドが利用可能であることを前提としています。service.instance.idが各インスタンスで一意であり、リソース属性が変更されるたびに新しいservice.instance.idが生成されることを確認してください。推奨される方法は、インスタンスの起動ごとに新しいUUIDを生成することです。

順序が異なる取り込みを有効にする

順序が異なる取り込みを有効にする理由は複数あります。

たとえば、OpenTelemetryコレクターはバッチ処理を推奨しており、コレクターの複数のレプリカがデータをPrometheusに送信している可能性があります。これらのサンプルを並べ替えるメカニズムがないため、順序が異なってしまう可能性があります。

順序が異なる取り込みを有効にするには、Prometheus設定ファイルに以下を追加する必要があります。

storage:
  tsdb:
    out_of_order_time_window: 30m

ほとんどの場合、30分の順序が異なる取り込みで十分でしたが、必要に応じてこの値を調整することをためらわないでください。

リソース属性の昇格

私たちのコミュニティとの経験と会話に基づいて、よく見られるすべてのリソース属性の中で、これらはユーザーによって最も頻繁に昇格されるものであることがわかりました。

- service.instance.id
- service.name
- service.namespace
- cloud.availability_zone
- cloud.region
- container.name
- deployment.environment
- k8s.cluster.name
- k8s.container.name
- k8s.cronjob.name
- k8s.daemonset.name
- k8s.deployment.name
- k8s.job.name
- k8s.namespace.name
- k8s.pod.name
- k8s.replicaset.name
- k8s.statefulset.name

デフォルトでは、Prometheusは属性を昇格しません。それらのいずれかを昇格する場合は、Prometheus設定ファイルのこのセクションで行うことができます。

otlp:
  resource_attributes:
    - service.instance.id
    - deployment.environment
    - k8s.cluster.name
    - ...

クエリ時のリソース属性の追加

前のセクションで説明したように、リソース属性を昇格する代わりに、クエリ時にtarget_infoメトリクスからラベルを追加することもできます。

これは概念的には「結合」クエリとして知られています。このようなクエリの例は、次のようになります。

rate(http_server_request_duration_seconds_count[2m])
* on (job, instance) group_left (k8s_cluster_name)
target_info

このクエリで発生することは、rate(http_server_request_duration_seconds_count[2m])から生じる時系列が、同じjobおよびinstanceラベルを共有するtarget_info系列のk8s_cluster_nameラベルで拡張されることです。言い換えれば、jobおよびinstanceラベルは、SQL外部キーと同様に、http_server_request_duration_seconds_counttarget_infoの間で共有されます。一方、k8s_cluster_nameラベルは、OTelリソース属性k8s.cluster.nameに対応します(Prometheusはドットをアンダースコアに変換します)。

それでは、target_infoメトリクスとOTelリソース属性の関係は何でしょうか?PrometheusがOTLP書き込みリクエストを処理し、含まれているリソースに属性service.instance.idおよび/またはservice.nameが含まれている場合、Prometheusはすべて(OTel)リソースに対して情報メトリクスtarget_infoを生成します。このようないずれかのtarget_info系列に、service.instance.idリソース属性の値を持つラベルinstanceと、service.nameリソース属性の値を持つラベルjobを追加します。リソース属性service.namespaceが存在する場合、jobラベル値にプレフィックスが付けられます(つまり、<service.namespace>/<service.name>)。残りのリソース属性もtarget_info系列にラベルとして追加され、名前はPrometheus形式に変換されます(例:ドットがアンダースコアに変換されます)。リソースにservice.instance.idservice.nameの両方の属性がない場合、対応するtarget_info系列は生成されません。

リソースのOTelメトリクスごとに、Prometheusは対応するPrometheus時系列に変換し、(target_infoが生成されている場合)正しいinstanceおよびjobラベルを追加します。

UTF-8

PrometheusのUTF-8サポートはまだ準備ができていないため、Prometheusリモート書き込みエクスポーターとOTLP取り込みエンドポイントの両方が、OpenTelemetryのPrometheus正規化トランスレーターパッケージに依存しています。

したがって、無効な文字をPrometheusに送信している場合、それらはアンダースコア_文字に置き換えられます。

UTF-8機能がPrometheusにマージされたら、これを再検討します。

デルタ一時性

OpenTelemetry仕様では、デルタ一時性と累積一時性の両方がサポートされていると述べています。

デルタ一時性はstatsdやgraphiteのようなシステムで一般的ですが、累積一時性はPrometheusのデフォルトの一時性です。

現在、Prometheusはデルタ一時性をサポートしていませんが、OpenTelemetryコミュニティから学習しており、将来的にはそれをサポートすることを検討しています。

デルタ一時性システムから来ている場合は、OTelパイプラインでデルタから累積へのプロセッサを使用することをお勧めします。

このドキュメントはオープンソースです。問題を提起したり、プルリクエストを送信したりして、改善にご協力ください。