プラットフォームは自分自身を何で測るのか
一言でいうと
プラットフォームチームが測るべきものは、ノードのCPUではなく、プラットフォームがユーザーにした約束です。セルフサービスのリクエストが成功する割合、デプロイが終わるまでにかかる時間、元に戻す必要があったデプロイの割合が、その約束です。
なぜリソースのメトリクスでは足りないのか
ノードのメトリクスだけを見るダッシュボードは、インシデントが起きても緑ランプのままです。セルフサービスの払い出しがすべて失敗しても、ノードのCPUはむしろ暇だからです。逆に、ノードが忙しくても、ユーザーから見れば何も問題がないこともあります。
そこで、プラットフォームも1つのサービスとして扱います。ユーザーは開発チームで、リクエストは申請の作成やデプロイであり、成功と失敗があり、所要時間があります。こうすると、測るものがはっきりします。
| 何を測るか | なぜそれなのか |
|---|---|
| 払い出しリクエストの成功割合 | セルフサービスが本当にセルフサービスになっているか |
| リクエストから使用可能になるまでの時間 | ゴールデンパスが本当に速いか |
| デプロイ頻度と、元に戻した割合 | デプロイが怖いものかどうか |
| インシデントの復旧までにかかった時間 | 問題に気づくまでにかかる時間と、直すまでにかかる時間 |
どう動くのか
レコーディングルールが先で、アラートがそのあとです
割合をアラートの条件の中で毎回計算すると、同じ式が複数のアラートに散らばります。1か所を直して、ほかの場所を忘れるというミスが、ここで起きます。そのため、割合はレコーディングルールで一度だけ定義し、アラートはその名前を参照します。
groups:
- name: platform-slo
rules:
- record: platform:provision_success:ratio5m
expr: |
sum(rate(platform_provision_total{result="success"}[5m]))
/
sum(rate(platform_provision_total[5m]))
名前に5mが含まれているなら、式の区間も5分でなければなりません。名前と中身がずれると、そのメトリクスを使うすべての人が、誤った前提で判断することになります。
発火までの待ち時間は目的に合わせて決めます
forは、条件が維持される時間を要求します。このラボは10分を使いますが、すぐに対応しなければならない出来事では、省略することもあります。この時間は、Alertmanagerの送信・繰り返しの間隔とは別のものです。アラートの式は、偽のときに系列を取り除く必要があります。vector(0)や비율 < bool 0.95(プレースホルダーは割合です)は、値が0でも系列が残り、アラートが有効になってしまう落とし穴です。公式アラートルールの説明で、pendingとfiringを区別して読んでください。
runbook_urlがないアラートも同じです。午前3時に受け取ったアラートに、次の行動が書かれていなければ、それは情報ではなくノイズです。severityラベルはルーティングが分かれる基準なので、なければすべてのアラートが同じ経路に流れます。
検証したものとデプロイしたものが同じである必要があります
ルールファイルは、promtool check rulesで検証できます。人が読んでも、式の括弧1つは見つけられません。ただし、検証したファイルと、クラスターに上げたPrometheusRuleが別のものなら、その検証は何も保証しません。ファイルからCRを作り、上げたあとにspec.groups全体を突き合わせます。名前だけが同じで式が変わっていれば、別のルールです。APIが保存したからといって、Operatorが選択した、あるいはPrometheusがロードしたと断定しません。今回の環境はOperatorを実行しないため、保存の一致まで検証し、アラートの配信をテストしたとは主張しません。
現場での姿
仮想の事例を考えてみましょう。失敗の経路がメトリクスを残さない払い出しサービスを作った場合、ダッシュボードには成功率100%しか見えないことがあります。分母が成功だけを数えていれば、割合は常に1です。
割合1つだけでは、このような計装の漏れを見分けにくいです。何を数えているかを、式から直接読んで初めて見えます。そのため、新しいメトリクスを作るときは、失敗をわざと一度起こしてみて、その値が動くかを確認する必要があります。アラートも同じです。
文法のあとに、シナリオを入れます
上の単純な割合は、2つの結果の系列がどちらも存在する場合の出発点です。失敗の系列だけがあれば分子が空になり、トラフィックがなければ分母が0になります。続くラボでは、失敗だけがあるときは分子を0で補いつつ、全体のrateが正のときだけ割合を残します。観測の空白は、成功100%ではなく、別の計装の異常として調べる必要があります。インスタンスごとの成功率を単純に平均すると、リクエスト1件のサーバーと1万件のサーバーを同じ重さで数える誤りが生じます。
rateの公式説明に沿って、カウンターごとのrateを先に計算してから合算します。合計を先に作ってからrateを計算すると、1つの系列の再起動が別の系列の増加と混ざり、リセットの解釈が変わります。ラボは、成功カウンターだけが再起動するシナリオを、リセット区間の中でも検査します。
この過程で使う13個のシナリオは、正常99%、継続する失敗80%、境界95%とその前後、3分の障害、障害後の回復、無トラフィック、観測なし、成功だけがある場合、失敗だけがある場合、カウンターのリセット、リクエスト量が異なる2つのインスタンスです。回復17分の成功率と19分の解除も確認して、5分の区間を10分に変えてしまう誤りを見分けます。これは学習用の固定データによるテストであり、あらゆる本番トラフィックに対する証明ではありません。
promtool check rulesは文法を、promtool test rulesは仮想の時系列での値を検査します。公式テスト形式のinput_seriesとeval_timeを読み、実際の待ち時間と区別してください。イメージの3.0.1は、最新のドキュメントのfuzzy_compareをサポートしないため、ヘルパーは割合の誤差を1e-9未満で直接検査します。
その次に読むこと
メトリクスが異常を知らせたあと、その異常をまず何を数えて分類するのかを、続けて見ます。