PromQLのクエリを八つ書く
目標
PromQLのクエリ8つをファイルとして書きながら、rateの順序・leの保持・最小トラフィックのゲートといった実戦の規律を身につけます。試験の比重が28%で最も大きいドメインであり、ここで出るミスの多くは、エラーなしに間違った答えを返す種類です。
なぜ重要なのか
PromQLが難しい理由は、文法ではなく、間違えても静かだという点です。sumをrateの外側に置かないと値が低く出て、by (le)を抜かすと分位数ではなくでたらめな数字が出て、最小トラフィックのゲートがないと、明け方の低トラフィックの時間帯ごとに幽霊アラートが出ます。3つとも、ダッシュボードでは正常に見えます。そのため、クエリは「動作するか」ではなく「どんな条件で嘘をつくか」を基準にレビューする必要があります。このラボは、そのレビュー項目をクエリ1つ1つに仕込んであります。
ステップ
/root/pca-promql/01-request-rate.promqlに、ルートごとの毎秒のリクエスト率を書きます。メトリクスはhttp_requests_total、ウィンドウは[5m]、集計ラベルはrouteです。/root/pca-promql/02-error-ratio.promqlに、ルートごとの5xxエラー率を書きます。分子はstatus_class="5xx"でフィルタしたrate、分母は全体のrateで、両方ともby (route)で集計して割ります。/root/pca-promql/03-p99-route.promqlに、ルートごとのp99レイテンシを書きます。histogram_quantile(0.99, ...)の中で、http_request_duration_seconds_bucketに[5m]のrateをかけ、by (le, route)で集計します。/root/pca-promql/04-cardinality-topk.promqlに、時系列が最も多いメトリクスの上位10個を取り出すクエリを書きます。topk(10, ...)の中でcount by (__name__)を使い、対象のセレクターは{__name__=~".+"}です。/root/pca-promql/05-disk-predict.promqlに、ディスク枯渇の予測を書きます。predict_linear(node_filesystem_avail_bytes{mountpoint="/data"}[6h], 4 * 3600) < 0に、現在の空き比率が< 0.2という条件(node_filesystem_avail_bytesをnode_filesystem_size_bytesで割った値)を、andでつなぎます。/root/pca-promql/06-nan-guard.promqlに、低トラフィックのガードが付いたエラー率のアラート式を書きます。ステップ2と同じ比率が> 0.01で、同時にsum(rate(http_requests_total[5m])) by (route) > 1をandでつなぎます。/root/pca-promql/07-scrape-health.promqlに、スクレイプ健全性の確認を書きます。up{job="checkout-api"} == 0とabsent(up{job="checkout-api"})をorでつなぎます。/root/pca-promql/08-burn-rate.promqlに、複数ウィンドウのバーンレートを書きます。job:slo_errors:ratio_rate1h{job="checkout-api"} > (14.4 * 0.001)、job:slo_errors:ratio_rate5m{job="checkout-api"} > (14.4 * 0.001)、job:http_requests:rate5m{job="checkout-api"} > 1の3つの項を、andでつなぎます。
参考
- 採点は、空白と
#コメントを無視して、文字列を照合します。複数行にきれいに書いてもかまいませんが、メトリクス名・ラベル・ウィンドウ・数字は、指示されたとおりに書いてください。 - よくある間違い1:
rate(sum(...))の順序です。採点が、この形を明示的に拒否します。 - よくある間違い2: ステップ3で
by (route)だけを書いて、leを抜かしてしまうことです。 - よくある間違い3: ステップ2で、分子だけに
by (route)を付けてしまうことです。割り算は、両側のラベルセットがマッチする必要があります。
ルートごとの毎秒のリクエスト率
/root/pca-promql/01-request-rate.promqlに、ルートごとの毎秒のリクエスト率を書きます。メトリクスはhttp_requests_total、ウィンドウは[5m]、集計ラベルはrouteです。
カウンターはそのまま描くと右上がりの直線です。rateを先に適用して、その結果を集計してください。逆にすると、Pod再起動のリセットが補正されません。
ルートごとの5xxエラー率
/root/pca-promql/02-error-ratio.promqlに、ルートごとの5xxエラー率を書きます。分子はstatus_class="5xx"でフィルタしたrate、分母は全体のrateで、両方ともby (route)で集計して割ります。
比率なので、分子と分母がそれぞれ必要です。2つのベクトルを割るにはラベルセットがマッチする必要があるので、両方とも同じ次元で集計する必要があります。
ルートごとのp99レイテンシ
/root/pca-promql/03-p99-route.promqlに、ルートごとのp99レイテンシを書きます。histogram_quantile(0.99, ...)の中で、http_request_duration_seconds_bucketに[5m]のrateをかけ、by (le, route)で集計します。
バケットはカウンターなので、rateを先にかけます。集計でleを失うとバケットが潰れて、エラーなしに無意味な数字が出ます。分位数を平均する形は、絶対に使わないでください。
カーディナリティ上位10個の診断
/root/pca-promql/04-cardinality-topk.promqlに、時系列が最も多いメトリクスの上位10個を取り出すクエリを書きます。topk(10, ...)の中でcount by (__name__)を使い、対象のセレクターは{__name__=~".+"}です。
メトリクス名ごとに時系列がいくつあるかを数えるには、countを__name__でまとめます。すべてのメトリクスを選ぶセレクターは、名前ラベルに正規表現をかける方式です。topkで上位だけを残します。
ディスク枯渇の予測
/root/pca-promql/05-disk-predict.promqlに、ディスク枯渇の予測を書きます。predict_linear(node_filesystem_avail_bytes{mountpoint="/data"}[6h], 4 * 3600) < 0に、現在の空き比率が< 0.2という条件(node_filesystem_avail_bytesをnode_filesystem_size_bytesで割った値)を、andでつなぎます。
predict_linearは、ゲージの最近のトレンドを線形回帰で外挿します。2つ目の引数は秒単位です。トレンドだけを見ると、余裕が十分なディスクでも発火することがあるので、現在の空き比率の条件をANDで一緒にかけます。
低トラフィックの幽霊アラートを防ぐ
/root/pca-promql/06-nan-guard.promqlに、低トラフィックのガードが付いたエラー率のアラート式を書きます。ステップ2と同じ比率が> 0.01で、同時にsum(rate(http_requests_total[5m])) by (route) > 1をandでつなぎます。
5分間にリクエストが3件入る時間帯に1件失敗すると、エラー率は33%です。比率の条件だけでは、明け方ごとにアラートが出ます。最小トラフィックの条件をANDで付けてください。リクエストがそもそも0なら、比率はNaNになって、条件が静かに消えます。
スクレイプ健全性の確認
/root/pca-promql/07-scrape-health.promqlに、スクレイプ健全性の確認を書きます。up{job="checkout-api"} == 0とabsent(up{job="checkout-api"})をorでつなぎます。
upが0の状況と、upの時系列自体が消えた状況は違います。後者は、値の比較では絶対に捉えられません。時系列がないときに1を返す関数を、ORでつないでください。
複数ウィンドウのバーンレート
/root/pca-promql/08-burn-rate.promqlに、複数ウィンドウのバーンレートを書きます。job:slo_errors:ratio_rate1h{job="checkout-api"} > (14.4 * 0.001)、job:slo_errors:ratio_rate5m{job="checkout-api"} > (14.4 * 0.001)、job:http_requests:rate5m{job="checkout-api"} > 1の3つの項を、andでつなぎます。
長いウィンドウは「この程度で消費しているか」を、短いウィンドウは「今も進行中か」を判定します。短いウィンドウがないと、事故が終わったあとも、長いウィンドウの長さの分だけアラートが残ります。ここに最小トラフィックのゲートまで加えて、3つの項をANDでつないでください。レコーディングルールの時系列名は、そのまま参照してください。