prometheus.io/scrape などのAnnotations について調べてみた

kameneko
penguin-lab
Published in
9 min readMay 26, 2020

こんにちは、かめねこです。
Kubernetes上でPrometheusを扱う際に、 prometheus.io/scrape のようなAnnotationsを指定するというTipsを知りました。しかし、公式にはそれらしい記述がなかったので調べてまとめてみました。

概要

Prometheus on Kubernetesな環境で、PrometheusがTargetの情報を取得する方法は色々とありますが、定番はServiceDiscoveryの kubernetes_sd_configs を使う方法でしょう。このとき、TargetとなるPodのDeploymentなどに .metadata.annotations.prometheus.io/scrape:true と指定するTips?を教えてもらいました。これについて、知らなかったので調べてみたところ、なぜか公式にはそれらしいドキュメントがありませんでした。ということで、詳しく調べてみたという記事です。

prometheus.io/scrapeとは?

このAnnotationsを利用して、より簡単にServiceDiscoveryを実現する方法です。具体的には以下のとおりです。

apiVerison: v1
kind: Deployment
metadata:
annotations:
prometheus.io/scrape: true
prometheus.io/path: /metrics
prometheus.io/port: 9100

こんな感じのAnnotationsを書いたDeploymentをデプロイし、以下のようなRelabelingを書きます。

kubernetes_sd_configs:
- role: pod
relabel_configs:
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
action: keep
regex: true
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]
action: replace
target_label: __metrics_path__
regex: (.+)
- source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port]
action: replace
regex: ([^:]+)(?::\d+)?;(\d+)
replacement: $1:$2
target_label: __address__

こうすることで、PrometheusはTargetのラベルを意識せずとも、このAnnotationsが付与されたPodをScrapeすることができます。便利そう。

実は適切ではないケースが存在する

パット見はTarget側がAnnotationsを指定することで、簡単にServiceDiscoveryの対象とすることができる便利な方法のようにみえます。しかし、これは特定のユースケースでは適切ではないことがあります。詳しくは以下のIssueで指摘されています。

たとえば、以下のような複数のポートを持つPodが展開され、それぞれのエンドポイントに対してScrapeを行いたい場合、これはAnnotationsでは実現できません。

apiVersion: v1
kind: Deployment
metadata:
name: nginx
labels:
app: nginx
spec:
replicas: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
port:
- containerPort: 80
- containerPort: 8080

ほかにも、以下はNginxとサイドカーとしてFluentdを展開するPodのDeploymentです。この場合、Nginx/Fluentdともに /metrics を参照したい場合、これもAnnotationsでは表現できません。

apiVersion: v1
kind: Deployment
metadata:
name: nginx
labels:
app: nginx
spec:
replicas: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
port:
- containerPort: 80
- name: fluentd
image: fluentd:latest
port
- containerPort: 24224

このように、マルチコンテナやマルチポートで構成されたPodには利用できないため、不適切だと指摘されています。

公式のExampleからも消されてた

調べてみたところ、もともと公式のリポジトリのExampleに記載があったのですが、以下のPRで削除されたようです。

このPRでは、「この方法はマルチコンテナをサポートしていないにもかかわらず、あたかも公式/慣例的な方法としてExampleで示してしまっている」ことについて取り上げていました。

あくまでも、この方法がNGというわけではなく、一部のユースケースで不適切な方法になってしまうにもかかわらず、それに関する説明がないことを指摘しています。ですので、最終的にはこれらのAnnotationsを使った方法をコメントアウトし、適切に説明書きをつけることでこのPRはMergeされていました。また、Annotationsも prometheus.io/scrape から example.io/scrape に変わっていました。

Annotationsでの制御は不適切なのか?

さて、こうなるとAnnotationsを使ったServiceDiscoveryの指定方法が不適切かどうかという問題に当たります。この答えは、「場合による」です。

というのも、シングルコンテナやシングルポートな環境では、適切に動作しますし、何より非常に分かりやすいです。逆に、上で挙げたような複数のコンテナや複数のポートを展開するような環境では適切に動作しないため、不適切となります。

結局の所、これらはアプリケーションの展開ポリシーによりますので、ご自身の環境に合わせて適切に使用していく必要があります。

もし、Annotationsでの制御が難しいが、簡略化したいということであれば、Prometheus OperatorのServiceMonitorを利用するとよいでしょう。これは、ターゲットのラベルを指定するだけで簡単にScrapeすることができます。Prometheus Operatorを利用する必要がありますが、Prometheus on Kubernetesな環境であれば、ぜひ一度検討してみてはいかがでしょう?

終わりに

今回、たまたまこれらのAnnotationsでの制御に関して知ったのですが、中々興味深いHistoryがありました。私の環境では、このAnnotationsを利用するよりも、ServiceMonitorを(すでに使っているというのもあって)利用するのが適切に感じたので、このままこちらを利用し続けようと思います。

本記事執筆にあたって

本記事の内容を調査・執筆するに当たって以下のお二人にご協力をいただきました。ここに感謝いたします。ありがとうございます!🙏

--

--

kameneko
penguin-lab

PrometheusとかKubernetesとか物理、配信とかが好きなしがないエンジニアです。さくらインターネットという会社であれこれしています。ペンギンがとても、とても好き。