Dev Study
← SLI を数える — 分母と分子を決める
レッスン 6 / 10·約 9 分·第28期 SLI を数える

誰の要求を分母に入れるか — ヘルスチェック、prober、ボット

リクエストがアプリケーションに届くまで
  1. ブラウザURL入力
  2. DNS名前→IP
  3. ルータ経路選択
  4. ロードバランサ振り分け
  5. Nginx受け口今ここ
  6. アプリ処理今ここ
  7. DB保存

同じログから、分母と分子の決め方の数だけ違う数字が出ます。今回は分母に入る要求の出どころを決めます。

まず結論

アクセスログには利用者以外の要求も並びます。良い=5xx以外に固定したまま分母だけを変えると、同じ5分間の全滅が 91.667% にも 50.000% にも 0.000% にもなりました。

prober の経路だけ無事だった別の5分では、prober だけの分母は 100%、実利用だけの分母は 0% でした。誰の要求を数えるかは、SLI 仕様に書いて決めるものです。

? 読む前に予測

毎秒1件のヘルスチェック(常に 200)と、30秒に1件の実利用などが同じ nginx のログに残ります。/api/ への要求(実利用と prober)が5分間すべて 500 になったとき、その5分をログの全行で数えた可用性(5xx 以外÷全行)はいくつに近いでしょうか。

当てることが目的ではありません。外した予測ほど記憶に残るので、直感で選んでください。

抽象原理

分子を固定し、分母だけを動かす

この回で決めることは、分母に入る要求の出どころです。アクセスログには利用者の要求のほかに、ヘルスチェック、prober(利用者の経路を模した要求を定期的に送り、応答を確かめる仕組み)、ボットの要求が並びます。どれも nginx から見れば同じ1行です。

分子は Workbook 付録A の定義に固定します。

Any HTTP status other than 500–599 is considered successful.

動かすのは分母だけです。第3期『死活監視』で見たとおり無償版 nginx は自分から確認の要求を送らないので、今回のヘルスチェックは nginx の外(kubelet を模したチェッカー)から来ます。

同じログの行を、分母の決め方だけ変えて数える
ヘルスチェック/healthz・毎秒1件
実利用/api/items・30秒に1件
prober/api/ping・15秒に1件
ボット/robots.txt・10秒に1件
すべて1行ずつ
nginx のアクセスログ良い = 5xx 以外(固定)
分母の決め方
A 全行
B 経路で /healthz を除く
B' UA で kube-probe を除く
E /api/ だけ
C 実利用だけ
D prober だけ
  • ・分母を変えても、5xx の行の数は変わらない
  • ・障害の無い時間帯は、6通りとも 100.000% になった
具体実物

同じ5分の全滅を6通りに数える

環境は Docker 28.4.0(arm64)、nginx:1.31.6-alpine、python:3.14-slim(Python 3.14.7)。間隔を固定した要求を18分流し、開始3分後からの5分間は /api/ を全部 500 にしました(以下、集計の窓1)。ヘルスチェックの /healthz はアプリが依存先を見ずに常に 200 を返します。UA はそれぞれ kube-probe/1.37・Mozilla/5.0 (demo-user)・blackbox-prober/1.0・ExampleBot/1.0 です。

access.log の生の行(run1、窓1の開始直後の /healthz 以外の3行を抜粋。列省略なし)コマンド出力
1790604913.249 2026-09-28T14:15:13+00:00 GET /robots.txt 200 - "ExampleBot/1.0 (+https://example.com/bot)"
1790604913.250 2026-09-28T14:15:13+00:00 GET /api/items 500 500 "Mozilla/5.0 (demo-user)"
1790604913.251 2026-09-28T14:15:13+00:00 GET /api/ping 500 500 "blackbox-prober/1.0"
窓1の集計(analyze.py の出力から良い・分母・可用性を抜き出し、見出しを短くした)表
分母の決め方 良い 分母 可用性
A 全行 330 360 91.667%
B /healthz を除く 30 60 50.000%
B' kube-probe UA を除く 30 60 50.000%
E /api/ だけ 0 30 0.000%
C 実利用の /api/ だけ 0 10 0.000%
D prober だけ 0 20 0.000%

窓1の 360 行のうち 300 行(83.3%)がヘルスチェックで、障害中も 200 でした。全行の分母は 100% から 8.333 ポイント下がっただけで、実利用の落ち幅 100 ポイントの 1/12 です。この比は今回の間隔の組み合わせで決まった値で、一般則ではありません。

Workbook 第2章は、単純な GET で測る代わりに use a health-checking handler that exercises more functionality of the system と書きます。依存先を見ない浅いチェックは、壊れていても 200 を返します。

2回並走させた run1・run2 で、件数と6つの値は一致しました。

✓ ここまでの確認

窓1で、全行の分母は 91.667%、実利用の /api/ だけの分母は 0.000% でした。この差を生んだ主な理由はどれですか。

抽象原理

自分の要求は、原典の中でも扱いが分かれる

ヘルスチェックと prober はどちらも自分で出す要求ですが、目的が違います。

ヘルスチェックは、そのインスタンスが応答できるかを知るための要求です。Kubernetes では readiness の失敗で the EndpointSlice controller removes the Pod's IP address from the EndpointSlices of all Services that match the Pod(Pod Lifecycle)。kubelet の HTTP プローブは既定で kube-probe/<major>.<minor> を名乗ります(request.go の userAgent()、httpHeaders で上書き可)。この UA は kubelet のコンテナプローブのもので、クラウドの LB などのヘルスチェックが何を名乗るかは製品ごとで、確かめていません。

prober は利用者の経路を模して、体験の代理を狙います。原典の扱いは向きが分かれます。

  • SRE Book 第4章は、標準テンプレートに書けば個々の SLI 仕様から省ける項目の例として Which requests are included: “HTTP GETs from black-box monitoring jobs” を挙げます。推奨ではなく例です。
  • Art of SLOs 参加者ハンドブック(印字頁17)は prober の短所の1つに – Probe traffic can drown out real traffic. を挙げます(PDF の合字を通常の文字に直して引用)。
  • Workbook 第5章は、実利用が少ないサービスに Generate artificial traffic to compensate for the lack of signal from real users. と書きます。
  • Art of SLOs 進行役ハンドブック(印字頁21)は、prober に固有の UserAgent を名乗らせ、ログの集計で ignore those requests as invalid とする例を挙げます(PDF 抽出の語割れを直して引用)。ただし同じ頁の仕様の箇条は Valid requests have a UserAgent of /^wooden-stake v[\d.]+$/ とあり、文面どおりなら逆に読めます。

一方、「ヘルスチェックを分母から外せ」「ボットを外せ」と書いた文は、SRE Book 第4・6章、Workbook 第2・5章・付録A、Art of SLOs の2冊、Google Cloud の概念ページを確かめた範囲に見つかりませんでした。書けるのは、参加者ハンドブックの validity is determined by request parameters such as hostname or request path を当てはめた自分たちの判断と、窓1の数字までです。

具体実物

prober の経路だけ無事な5分(追加実験)

開始10分後からの5分間は /api/items だけを 500 にしました(窓2)。prober が叩く /api/ping は無事です。

窓2の集計(analyze.py の出力から抜き出し、見出しを短くした)表
分母の決め方 良い 分母 可用性
A 全行 350 360 97.222%
B /healthz を除く 50 60 83.333%
E /api/ だけ 20 30 66.667%
C 実利用の /api/ だけ 0 10 0.000%
D prober だけ 20 20 100.000%

窓1では D も C と同じ 0% で、prober は実利用の代理になっていました。窓2では D が 100%、C が 0% です。Workbook 第5章が人工トラフィックの欠点として書くことが、そのまま起きています。

Additionally, if an issue affects real users but doesn’t affect artificial traffic, the successful artificial requests hide the real user signal, so you aren’t notified that users see errors.

E(経路だけで /api/ に絞る)は C と D の間の値でした。/api/ に絞っても、誰の /api/ かまで決めないと値が決まりません。prober が実利用と同じ経路を叩いた場合に D が C に近づくかは、今回は試していません。

外し方の書き方でも数字は動きます。全期間では B(経路で /healthz を除く)が 179/219 = 81.735%、B'(UA で除く)が 180/220 = 81.818% でした。開始時の確認用に curl で送った smoke-test UA の /healthz 1行が、経路では外れ、UA では残ったためです。

ボットの 108 行を UA で外すなら、UA は自己申告だという前提が付きます。RFC 9110 §10.1.5 は If a user agent masquerades as a different user agent の場合を想定しています。

nginx には access_log off; で記録しない方法もあります。今回は全行を残し、集計側で外しました。残しておけば別の分母で数え直せます。

✓ ここまでの確認

窓2(/api/items だけ 500)で、prober だけの分母は 100%、実利用だけの分母は 0% でした。これが示すものはどれですか。

⇄ 2つを見比べる
具体例 A

ヘルスチェック(/healthz・kube-probe)

依存先を見ずに 200 を返す要求が窓1の行の 83.3% を占め、全行の分母は 91.667% に留まりました。外すと 50.000% です。

窓1表
分母 良い/分母 可用性
全行 330/360 91.667%
/healthz 除く 30/60 50.000%
具体例 B

prober(/api/ping・blackbox-prober)

利用者の代理として分母にする理由があります。ただし経路が実利用と違い、窓2では prober だけの分母が 100% で、実利用は 0% でした。

窓2表
分母 良い/分母 可用性
prober だけ 20/20 100.000%
実利用だけ 0/10 0.000%

片方は外すと値が下がり、もう片方は頼ると値が上がりすぎました。共通する原理は何でしょうか。

それぞれの要求が、利用者と同じものを経験しているかを見てください。

この章のまとめ

  • 良い=5xx以外に固定し分母だけを変えると、同じ5分の全滅が 91.667% / 50.000% / 0.000% / 0.000% になった。
  • 全行の分母の落ち幅は実利用の 1/12。ヘルスチェックが行の 83.3% を占め、障害中も 200 を返したため。比は今回の構成の値。
  • prober の経路だけ無事な窓では prober 100%・実利用 0%。Workbook 第5章の hide the real user signal の実演。
  • SRE Book 第4章のテンプレート例は black-box monitoring jobs の要求を含め、Art of SLOs 進行役ハンドブックは prober を UA で invalid にする例を挙げる(同じ頁の箇条は逆に読める)。「ヘルスチェックやボットを外せ」の明文は確かめた範囲に無い。
  • 外したあとの分母は、経路で外すと 219 件、UA で外すと 220 件。UA は自己申告。何で外すかを SLI 仕様に書く。

自分の現場で確かめる

読んだだけでは身につきません。手元の環境で実際に見てみてください。

環境:

理解度チェック

読んだ直後は「分かった」と感じやすいものです。実際に解いて確かめてください。

問題 1 / 3正解: 0

全期間で、/healthz という経路で外したあとの分母は 219 件、kube-probe の UA で外したあとの分母は 220 件でした。1件の差の正体はどれですか。

用語集(3語)
ヘルスチェック
ロードバランサや kubelet が、そのインスタンスが応答できるかを知るために送る定期要求。利用者の体験を代表させる要求ではない。
prober
利用者の経路を模した要求を定期的に送り、応答を確かめる仕組み。Art of SLOs 参加者ハンドブックの `Synthetic Clients (Probers)`。
User-Agent
要求を出したソフトウェアが自分で名乗る値(RFC 9110 §10.1.5)。kubelet の HTTP プローブは既定で `kube-probe/<major>.<minor>` を名乗る。