同じ 12 時間なのに可用性が 98.9% と 85.0% に割れた
目標
同じ12時間のデータを4つのSLI定義で実際に測って数字がどれだけ開くかを見て、1つを選んで目標とともに宣言し、その定義でデプロイを許可するか止めるかを判断します。
なぜ重要なのか
SLOを何パーセントにするかは、何を数えるかが決まったあとの問題です。良いイベントと有効なイベントをどう決めるかによって、同じデータから98.9%も85.0%も出ます。分母にヘルスチェックを入れると、ユーザーが体験した障害が薄められ、遅い成功を成功として数えると、ユーザーが離れた時間が記録に残りません。イベントの単位をリクエストから時間に変えると、明け方の障害と昼の障害を同じ重さで数えることになります。これらの選択は、あとでデプロイを止めるか止めないかという形で返ってくるので、定義を変えるたびに過去の期間を測り直し、その数字で運用していけるかを確認する習慣が必要です。
ステップ
/root/obs-sli-events/01-events.txtに3行を書いてください。metric=の後ろにはイベントを数えるのに使うカウンターのメトリクス名、failure_label=の後ろにはそのメトリクスで失敗かどうかを分けるラベル名、valid_12h=の後ろには直近12時間の有効なイベント数を整数で書きます(jobはshop-apiです)。値は、自分でクエリを投げて得てください。/root/obs-sli-events/a-request.promqlに「直近12時間の5xxではないリクエストの割合」を出すPromQLを1行以上で書き、その結果を/root/obs-sli-events/a-request.txtに小数第4位まで、数字1つで書いてください。コメント(#)は残してもかまいません。- 同じ12時間を、「2xxの応答だけが良いイベント」として測り直してください。クエリは
/root/obs-sli-events/b-strict.promql、値は/root/obs-sli-events/b-strict.txtに小数第4位まで書きます。分母は、前のステップと同じでなければなりません。 - 「100ミリ秒以内に終わったリクエスト」を良いイベントと見る定義で、12時間を測ってください。クエリは
/root/obs-sli-events/c-latency.promql、値は/root/obs-sli-events/c-latency.txtに小数第4位まで書きます。そして/root/obs-sli-events/04-note.txtに、「この定義では、ステータスコードとレイテンシを1つのクエリで一緒に見ることはできない」という事実とその理由を1行で書いてください。reason=で始め、40文字以上にする必要があります。 - 1分のウィンドウをイベントとする定義で、同じ12時間を測ってください。ある1分のあいだの5xx率が1%未満なら、その1分を良いイベントと見ます。クエリは
/root/obs-sli-events/d-window.promql、値は/root/obs-sli-events/d-window.txtに小数第4位まで書きます。そして/root/obs-sli-events/05-badminutes.txtに、12時間(720分)のうち悪い分が何分かを整数で書いてください。 /root/obs-sli-events/budget.tsvを作成してください。ヘッダーなしで4行、各行はタブで区切った3列<id> <가용성> <30일 허용 다운타임 분>です(プレースホルダーはid、可用性、30日間の許容ダウンタイム(分)です)。idは順にa、b、c、dで、可用性は前のステップで書いた値、3列目はその可用性なら30日(43200分)のあいだに悪くてもよい時間が何分かを、小数第1位まで書きます。/root/obs-sli-events/choice.txtに4行を書いてください。sli=の後ろに選んだid(a・b・c・dのどれか)、query=の後ろにその定義のクエリファイル名(例:d-window.promql)、target=の後ろに設定する目標を0と1の間の小数で、reason=の後ろになぜその定義なのかを60文字以上で書きます。採点ツールは、query=が指すファイルを実際に投げて、sli=と合っているかを確認します。/root/obs-sli-events/decision.txtに2行を書いてください。各行はtarget=<목표> consumed=<소진비율> release=<allow|hold>で(プレースホルダーは目標、消費比率、allowまたはholdです)、目標は1行目が0.99、2行目が0.95です。消費比率は(1 − 測定された可用性) ÷ (1 − 目標)で小数第3位まで求め、判断は、消費比率が1以上ならhold、1未満ならallowです。測定された可用性は、ステップ7で選んだ定義の値を使います。
参考
- 作業ディレクトリは
/root/obs-sli-eventsです。なければ先に作成してください。 - クエリは
promq "<PromQL>"ですぐに投げて試せ、元のJSONはpromq -rで得られます。スクリプトではcurl -sG --data-urlencode "query=..." http://127.0.0.1:9090/api/v1/queryを使います。 - PodのPrometheusには、12時間分があらかじめ入っています。その中に、20分間のエラー急増が1回入っています。
- よくある間違い: カウンターをincreaseなしでそのまま割ること。カウンターは累積値なので、比率が全期間の平均にならされてしまいます。
- よくある間違い: レイテンシのヒストグラムにステータスコードのラベルがあると仮定してしまうこと。このラボのステップ4が、まさにその壁です。
- Implementing SLOs (SRE Workbook)・Service Level Objectives (SRE Book第4章)・Querying basics・Query functions・Histograms and summaries
何を1つと数えるかから決める
/root/obs-sli-events/01-events.txtに3行を書いてください。metric=の後ろにはイベントを数えるのに使うカウンターのメトリクス名、failure_label=の後ろにはそのメトリクスで失敗かどうかを分けるラベル名、valid_12h=の後ろには直近12時間の有効なイベント数を整数で書きます(jobはshop-apiです)。値は、自分でクエリを投げて得てください。
どんなメトリクスがあるかは、promq "{__name__=~\"http.*\"}"やcurl -s http://127.0.0.1:9090/api/v1/label/__name__/values | jqで見ます。12時間のあいだに増えたカウンターの量は、increaseで求めます。ラベル名は、値ではなく名前だけを書きます。
リクエスト基準: 5xxだけを失敗として数える
/root/obs-sli-events/a-request.promqlに「直近12時間の5xxではないリクエストの割合」を出すPromQLを1行以上で書き、その結果を/root/obs-sli-events/a-request.txtに小数第4位まで、数字1つで書いてください。コメント(#)は残してもかまいません。
カウンターは累積なので、区間の増加量に変える必要があります。分子と分母をそれぞれsumで合算してから割ります。5xxを選ぶラベルのマッチには、正規表現マッチャーを使います。
400番台も失敗として数えると、どれだけ変わるか
同じ12時間を、「2xxの応答だけが良いイベント」として測り直してください。クエリは/root/obs-sli-events/b-strict.promql、値は/root/obs-sli-events/b-strict.txtに小数第4位まで書きます。分母は、前のステップと同じでなければなりません。
400番台はたいていクライアントの落ち度なので、サービスの失敗として数えないほうが普通ですが、認証失敗が急増する事故のように、自分たちの責任である4xxもあります。定義を変えると、数字がどちらへ動くかを見てください。
遅い成功は成功か
「100ミリ秒以内に終わったリクエスト」を良いイベントと見る定義で、12時間を測ってください。クエリは/root/obs-sli-events/c-latency.promql、値は/root/obs-sli-events/c-latency.txtに小数第4位まで書きます。そして/root/obs-sli-events/04-note.txtに、「この定義では、ステータスコードとレイテンシを1つのクエリで一緒に見ることはできない」という事実とその理由を1行で書いてください。reason=で始め、40文字以上にする必要があります。
ヒストグラムのバケットは累積です。leがどの値のバケットが「その値以下で終わったリクエストの数」なのかを見てください。分母に使う全リクエスト数は、ヒストグラムのcount系列にあります。2つのメトリクスのラベルの集合が互いに違うことが、核心です。
リクエストではなく、分を数えてみる
1分のウィンドウをイベントとする定義で、同じ12時間を測ってください。ある1分のあいだの5xx率が1%未満なら、その1分を良いイベントと見ます。クエリは/root/obs-sli-events/d-window.promql、値は/root/obs-sli-events/d-window.txtに小数第4位まで書きます。そして/root/obs-sli-events/05-badminutes.txtに、12時間(720分)のうち悪い分が何分かを整数で書いてください。
サブクエリ(subquery)[12h:1m]で1分間隔の値を作り、比較演算子の後ろにboolを付けると、真が1、偽が0の系列になります。その系列の平均が、そのまま良い分の割合です。悪い分の数は、720から逆算して数えます。
4つの定義を30日間の許容ダウンタイムに換算する
/root/obs-sli-events/budget.tsvを作成してください。ヘッダーなしで4行、各行はタブで区切った3列<id> <가용성> <30일 허용 다운타임 분>です(プレースホルダーはid、可用性、30日間の許容ダウンタイム(分)です)。idは順にa、b、c、dで、可用性は前のステップで書いた値、3列目はその可用性なら30日(43200分)のあいだに悪くてもよい時間が何分かを、小数第1位まで書きます。
許容ダウンタイムは(1 − 可用性) × 43200です。4行の数字がどれだけ開くかが、このステップの核心です。定義を1つ変えるだけで、運用チームが引き受けなければならない時間が何倍にも変わります。
選んだ定義を機械が読める形で宣言する
/root/obs-sli-events/choice.txtに4行を書いてください。sli=の後ろに選んだid(a・b・c・dのどれか)、query=の後ろにその定義のクエリファイル名(例: d-window.promql)、target=の後ろに設定する目標を0と1の間の小数で、reason=の後ろになぜその定義なのかを60文字以上で書きます。採点ツールは、query=が指すファイルを実際に投げて、sli=と合っているかを確認します。
正解は1つではありません。ただし、選んだ根拠が前のステップの数字とつながっている必要があります。たとえばレイテンシ基準を選ぶなら、30日間の許容ダウンタイムが引き受けられるかをステップ6の表で確認してから選んでください。
同じデータ、異なる目標: デプロイを許可するか
/root/obs-sli-events/decision.txtに2行を書いてください。各行はtarget=<목표> consumed=<소진비율> release=<allow|hold>で(プレースホルダーは目標、消費比率、allowまたはholdです)、目標は1行目が0.99、2行目が0.95です。消費比率は(1 − 測定された可用性) ÷ (1 − 目標)で小数第3位まで求め、判断は、消費比率が1以上ならhold、1未満ならallowです。測定された可用性は、ステップ7で選んだ定義の値を使います。
消費比率1は、「この期間に使えるエラーバジェットをちょうど使い切った」という意味です。同じデータでも、目標をどこに設定するかによって、デプロイの決定が覆ります。そのため目標は、数字ではなく合意です。