外に出るねくら

~ 外に出たって結局やることは自宅と同じ ~

メモ-PrometheusにおけるMetricsのData Type

最近、EKS(Elastic Kubernetes Service)を使ってMSA(Micro Service Architecture)でシステムを運用する場面に出くわして、Observabilityを割と真剣に勉強している
このObservability(=可観測性)については、勉強し始めたらかなり面白くてまた別の機会にまとめようと思っている
今回は、Observabilityの3本柱(Log, Metrics, Trace)のうちの一つであるMetricsを支えるPrometheusについて、
メトリクスのデータタイプがいまいち腹落ちしなかったので、自分の言葉(公式サイトの翻訳)でメモを残しておこうと思う

Prometheusについて(超ざっくり)

RPSやレイテンシ、CPU使用率、Podの死活状態など、サービスとかサーバーの各種メトリクスを集めるためのツール
Kubernetesを使ってMSAでシステムを構築する際、Metricsを実現するためのツールとして現状は デファクトの地位にいる認識(同列でDatadog?)
実際は、Prometheusで取得したメトリクスを可視化するツールとしてGrafanaと一緒に使われることが多くて、Prometheus自体のメトリクス可視化ツールはあまり使われず、Prometheusはあくまで時系列データベースのような形で使われてるイメージ

ちなみに・・・

「現状は」と書いたのは、3, 4年くらい前から上で挙げたObservabilityを向上させるぜという話題は出ていたけど、去年とか今年に入ったあたりから、Observabilityを可能にするための取組みが主要Cloud Serviceで急加速してる印象で、Kubernetesもマネージドサービスで運用するのが主流になっているのでこの状況はいずれ崩れるんじゃないかなーと思ってる
事実、GCPが提供しているAnthosなんかは、デフォルトでCloud LoggingとCloud Monitoringをサポートして、Observabilityの実現を容易にしてくれてるし・・・

メトリクスのデータタイプ

とても話が逸れてしまいましたが、本題のPrometheusのメトリクスのデータタイプについて
Prometheusには用途に合わせて4つのデータタイプが用意されていて、これらから目的の形にデータを加工して可視化することができる

Counter

再起動などのタイミングに0にリセットされることはあっても、単調増加するという性質は変わらない
減少しうる値などには使用できない

Gauge

気温やメモリ使用率など、単一の上下する値のためのメトリクス

Histogram

観測値をサンプリングし、設定可能なバケット毎にカウントする
全観測値の合計も分かる

basenameという名前のHistogramを用意したとすると、

basename_backet{le="<upper inclusive bound>"} : 指定したバケットまでの、バケット毎の累積の数  
basename_sum : 全観測値の合計  
basename_count : 観測されたイベントの回数 (これは、basename_bucket{le="+Inf"}としているのと同様)  

quantileを計算したい場合は、histogram_quantile()を使用することで計算可能

注意点としては、basename_bucketは累積的ヒストグラム(cumulative histogram=累積度数図)であるということ
-> 普段目にするヒストグラムとは異なる
-> Wikiがちゃんとまとめてくれてる

Bucketを採用していることで、Apdex scoreを計算することができる
-> Apdexを計算したい場合はHistogram1択

Summary

Histogram同様、観測値をサンプリングする
Histogram同様、全観測値の合計や観測回数を取得することもできる
Summaryの特徴的な点は、Sliding Time Window方式で、設定したquantileを計算できるということ

basenameという名前のSummaryを用意したとすると、

basename{quantile="φ"} : φ-quantileの観測イベント   
basename_sum : 全観測値の合計  
basename_count : 観測されたイベントの回数  

HistogramとSummary

  • 共通点
    両方とも累積的である点で、本質的にはCounterと同じ
    ただし、負数を扱うこともできる点でCounterとは異なる
    HistogramやSummaryが使われる典型的な場面は、Latencyやレスポンスのサイズのメトリクスを取得するためだが、これらは負数にはならないので一旦負数のことは考えない
    負数を取らない限りにおいて、prometheusのrate関数を使用することができるようになる

  • 相違点
    Histogramは、histogram_quantileを使ってサーバー側で計算する
    Summaryは、クライアント側で計算した結果をサーバーに送る

使い分け

Histogram

  • 良い点
    Histogramは、promQLを使って柔軟にデータを取得できる
    クライアント(実際にサービスが動いているアプリケーションサーバーやウェブサーバー)で処理をする必要がない

  • 良くない点
    いくつのBucketを、いくつ間隔で用意するか、正しく設定できないと有効でない
    5つをBucketを0.01秒ごとに用意すると0.05秒以上は全てまとめてカウントされるし、逆に5つのBucketを1秒ごとに用意すると、1秒以下は全てまとめてカウントされる
    このバランスをどこで取れるかを、事前にある程度分かっていないとうまくメトリクスを取れない

Summary

  • 良い点
    クライアント側で計算できるので、サーバーの負荷はかからない

  • 良くない点
    Summaryは事前にquantileがわかっていないと、後から変更する場合コストが高い
    特にオートスケールなど、複数のインスタンスで同じサービスが動いている場合は、個々のクライアントで計算してprometheusサーバーに送り集約する形だと意味がない、もしくはほとんど意味がわからない
    (「個々のインスタンス」というよりは「同じサービス全体として」のメトリクスを取りたい)

結論

SummaryでできるがHistogramでできないということは基本的にないし、メリデメを比較しても「使い分け」というよりは、特別必要がない限り基本的にHistogramを使う方が良いと思う