🐔

Prometheus の relabel_configs と metric_relabel_configs の違いをようやく理解した

2023/08/02に公開

はじめに

Prometheus のリラベリング(ラベルに対する様々な操作)の設定を書く場所には relabel_configsmetric_relabel_configs と言う 2 つのものがある。
これらの 2 つは設定の書き方は完全に一緒なのでどちらに何を書いても良さそうだが、実際には処理内容によって片方にしか書けないものがある。(どちらでも大丈夫なものもある)
一体コイツらは何が違うのだろうか?

結論

いきなり結論を書く。

  • relabel_configs はスクレイピングターゲットを発見するたびに、ターゲットのラベルに対して、ターゲット 1 箇所について 1 回ずつ実行される。
  • metric_relabel_configsスクレイピングするたびに、メトリクスのラベルに対して、メトリクス 1 つについて 1 回ずつ実行される。

これで理解できればこの記事をこれ以上読む必要は無い。
しかし、これを見てもオレのように「はぁ?」となったらこの先を読むとよい。
多分しっかり理解できる。…かもしれない。

公式サイトの記載

何はともあれまずは Google 先生に聞くと公式サイトの Configuration ページを見ると、先程と同じような事が書いてある。

<scrape_config> より抜粋

Additionally, relabel_configs allow advanced modifications to any target and its labels before scraping.

てきとー訳:更に、relabel_configs は任意のターゲットとそのラベルに対してスクレイピング前に高度な変更を可能とする。

<relabel_config> より抜粋

Relabeling is a powerful tool to dynamically rewrite the label set of a target before it gets scraped.

てきとー訳:リラベリングはターゲットがスクレイピングされる前にターゲットのラベルセットを動的に書き換えるための強力なツールである。

<metric_relabel_config> より抜粋

Metric relabeling is applied to samples as the last step before ingestion.

てきとー訳:メトリックリラベリングは取り込み前の最終ステップとしてサンプルに適用される。

つまり、

  • relabel_configs はスクレイピング前に適用される。
  • metric_relabel_configs は TSDB への取り込み前に適用される。

と言う事だ。
誤解の余地はない。これで解決だ。

スクレイピング前にリラベリングってどういうこと?

だが待って欲しい。relabel_configs の「スクレイピング前に適用される」とは一体どういうことなのか?

ラベルってのはメトリクスにくっついてるもんじゃないのか?実際 Prometheus の Web UI とか Grafana とかで見るとメトリクスにいろんなラベルが付いてるのが確認できるし。
じゃあ何でスクレイピング前にリラベリングの処理ができるんだ?

そう考えてずっと混乱していたのだが、これこそが最大の勘違いだった事にようやく気付いた。

ラベルはスクレイピングターゲットに付いている

そもそもラベルはスクレイピングターゲット自体に付いていたのだ。そして、relabel_configs と言うのは、その「スクレイピングターゲットのラベル」をリラベリングするためのものだったのだ。

いや Prometheus 使ってるヤツには常識なのかもしれない。「えぇ~そんなことも知らずに Prometheus 使ってたのプークスクス」と言う声が聞こえてきそうだが、悲しいことに今までずっとこれに気付いていなかったのだ。

実際、上に戻って(あるいは公式サイトに行って)ドキュメントを見れば確かに「ターゲットとそのラベルに対して」とか「ターゲットのラベルセットを」とかちゃんと書いてある。これまでこの「ターゲット」と言うのを「取ってきたメトリクス」を指しているのかと勝手に思い込んでいたのだが、この場合はそうじゃなくて「スクレイピングターゲット」と言う意味だった。思い込み怖い…

さて、1 つのターゲットからスクレイピングで取得できるメトリクスは通常複数あるが、「スクレイピングターゲットのラベル」はその言葉通りスクレイピングターゲットに付いているラベルなので、それら複数のメトリクスに対して共通の 1 セットしかない。しかも、ターゲットが決まってしまえば何度スクレイピングしようが変わりようがない。

これはスクレイピングターゲットのラベルの内容を見ると良く分かる。
たとえば、サービスディスカバリの種類によらずあらゆるターゲットで使用できるラベルは以下のものだ。

ラベル名
job ジョブ名(scrape_config.job_name に指定したヤツ)
__scheme__ ターゲットのスキーム(http とか https とか)
__address__ ターゲットの <host>:<port>
__metrics_path__ ターゲットのパス(/metrics とか)
__param_<name> リクエストに与えられるパラメータ<name>の最初の値

見ての通り、変わりようがない。それどころか、スクレイピングしなくても決定できる物だと言う事が分かるだろう。

と言う訳で、スクレイピングしなくても決定できるラベルなんだから、スクレイピング前にリラベリングすることができるのだ。つまりこれが relabel_configsスクレイピング前に処理される理由だ。

いやまぁ恐らく実際は因果が逆で relabel_configs をスクレイピング前に処理できるようにラベルが決定されているのだろう。

relabel_configs はスクレイピングターゲット毎に 1 回しか実施されない

さて、スクレイピングターゲットに付いているラベルは変わりようが無いと言う事が分かったが、それならrelabel_configs はスクレイピングターゲット毎に 1 回実施すれば事足りるだろう事も予想できる。
そして、実際 relabel_configs はスクレイピングターゲット毎に 1 回しか実施されていなかった。

なお、あくまでも「スクレイピングターゲット毎に 1 回」であって、ジョブ毎に(つまり scrape_config 1 つにつき)1 回と言う訳では無い事には注意が必要だ。

たとえば scrape_configstatic_config があって targets に複数のホストが書かれていればスクレイピングターゲットは複数になるので、それぞれのスクレイピングターゲット毎に 1 回と言う事である。また、kubernetes_sd_config であれば当然スクレイピングターゲットは複数になる上に動的に追加されることもあるだろうから、そのたびに 1 回と言う事になる。

また、処理の中には dropkeep と言ったメトリクスを廃棄(drop)するアクションがある(
「リラベル」とは何だったのか…)。と思っていたが、実はこれも勘違いだった。dropkeep は「メトリクスを廃棄」するアクションではなく「ターゲットを廃棄」するアクションだった。

これもちゃんと公式リファレンスに書いてある。以下抜粋。

keep: Drop targets for which regex does not match the concatenated source_labels.
drop: Drop targets for which regex matches the concatenated source_labels.

今までちゃんと理解できていなかった(ドキュメントは見ていたはずだが読めていなかった)のだが、「ターゲットを廃棄」と言う事は「スクレイピングターゲットそのものを廃棄」するアクションだったわけだ。

したがって、relabel_configs で「廃棄」されたターゲットはスクレイピングそのものが行われない、と言う事だ。これも Prometheus 使ってるヤツにはあたりまえのことなのかもしれないが、今までちゃんと理解できていなかった。

そして、relabel_configs の処理後に廃棄されなかった全ての「ターゲット」に対して instance と言う「ターゲットのラベル」が、ラベル __address__ の値で付けられる。

最後に、__ から始まる全てのラベルは削除される。このため、__ で始まるラベルには relabel_configs 内でしかアクセスできない。これらのラベルの値を取っておきたい場合には replace アクション等を使って __ で始まらないラベルに内容をコピーしておく必要がある。

ラベルはメトリクスにも付いている

ラベルはスクレイピングターゲットに付いていたと言ったな。あれはウソだ。

実はラベルはスクレイピングターゲットに付いているものと、元々メトリクスに付いているものの 2 種類あるのだ。
まぁ後者があるのは今更お前に言われんでも分かっとるわと言う方がほとんどだろう。curl とかでメトリクス用のポートを直接叩けば見られるし…

そして、metric_relabel_configs と言うのはターゲットからメトリクスをスクレイピングした際に「メトリクスのラベル」をリラベリングするためものもというわけだ。頭に metric_ と付いているのは正にこれを表していたのだ。ドキュメントには metric_relabel_configs は「サンプルに適用される」とあったが、これはスクレイピングした結果のメトリクスデータの事を指しているのだろう。

なお、metric_relabel_configs の処理対象である「メトリクスのラベル」と言うのは元々メトリクスに付いているラベル(無いこともある)にターゲットに付いているラベル(relabel_configs の処理結果)を追加した物である。

結局は処理タイミングと処理対象の違いだった

ここまで分かればもう何も難しいことはない。

  • relabel_configs はスクレイピングターゲットを発見するたびに、ターゲットのラベルに対して、ターゲット 1 箇所について 1 回ずつ実行される。
  • metric_relabel_configsスクレイピングするたびに、メトリクスのラベルに対して、メトリクス 1 つについて 1 回ずつ実行される。

分かってしまうと、当たり前の事しか言っていない。

relabel_configs はターゲットのラベルに対する処理だから、処理負荷は軽いがメトリクスに依存するような処理(メトリクス名でのフィルタとか元々メトリクスに付いてるラベルでのフィルタ)はできない。
一方、metric_relabel_configs はメトリクスのラベルに対する処理だから、きめ細かく処理できるが relabel_configs よりも処理負荷は重くなる(何しろスクレイピングしたメトリクスごとに実行されるので)。

結局、relabel_configs で出来ることは relabel_configs でやっておいて、できないことだけ metric_relabel_configs でやればよいのだろう。

relabel_configs の結果を確認する

ところで、Prometheus の Web UI を参照すると最終的にスクレイピングした結果ではなく relabel_configs の結果も簡単に確認することが出来る。Prometheus の Web UI メニューから「Status」⇒「Service Discovery」と行くだけである。

何で画面がリンクと本体の 2 段構えになっているかは良く分からんが、スクレイピングジョブ毎に「Discovered Labels」と「Target Labels」のペアで表示されているので、非常に分かりやすい。

一応説明しておくと、「Discovered Labels」が発見されたスクレイピングターゲットの生のラベルであり、「Target Labels」が relabel_configs で処理した結果のラベルである。

ちなみに、廃棄されたターゲットは「Target Labels」が「Dropped」になっている。

最近流行りの ChatGPT 先生に聞いてみた

最後に、ふと思い出して最近流行りの ChatGPT 先生にそのものずばり聞いてみた。

え、結構分かりやすい説明じゃね?最初から ChatGPT 先生に聞いておけばもっと早く理解できたかもしれない…
いやでもそもそもターゲットのラベルと言う概念を分かってなかったんだからやっぱりダメだったかもしれない…

Discussion