アラートの成功基準は検知ではなく対処だ
一言でいうと
アラートルールはinactive → pending → firingのステートマシンを回り、Alertmanagerは受け取ったアラートをWait → Dedup → Retry → Inhibit → Silence → Notifyの順で処理します。この2つのパイプラインのどこでアラートが消えるのかを知っていれば、「なぜアラートが来なかったのか」を3分以内に絞り込めます。
なぜ必要なのか
オンコールが崩壊する典型的な経路はこうです。事故が1つ起きると、振り返りで「これを事前に知っておくべきだった」という結論が出て、アラートが1つ追加されます。2年たつとルールが300個になり、Slackチャンネルには1日400件がたまり、オンコールは夜に3回目を覚まして、3回とも何もせずに再び眠ります。
1日400件のうち、実際に対応が必要なものが4件なら、精度は1%です。この状態で人が学習する最適な戦略は「とりあえず無視して、あとで確認する」であり、それが合理的であるがゆえに、さらに危険です。訓練や覚悟では元に戻せません。
そこで、実務の目標を数字で置きます。12時間のシフトあたりページ2件以下、ページが対応につながる割合70%以上です。この2つの基準を外れていたら、アラートを追加するときではなく、削除するときです。
どう動くのか
アラートのステートマシン
inactive --(표현식 매칭)--> pending --(for 경과)--> firing --(매칭 해제)--> resolved
|
+--(중간에 거짓)--> inactive (타이머 0 으로 초기화)
forの核心は連続です。途中で一度でも偽になると、タイマーが0に戻ります。これがフラッピングを防ぐ原理です。ここでよくある間違ったアドバイスがあります。「誤検知が多いので、forを30分に延ばそう」。動作はしますが、検知が30分遅れ、事故が25分で終わると、アラートがまったく鳴りません。そして、本当の問題は残ります。式自体がノイズを見ているという事実です。
正しい順序は、長いウィンドウのrateでノイズを平滑化し、短いウィンドウをANDでかけて進行中であることを確認し、forは最後に2–5分だけかけて、スクレイプの欠落1、2回を吸収することです。長いウィンドウをすでに使っているのにforが15分を超えるなら、ウィンドウの設計が間違っています。
firingのアラートは、評価周期ごとにAlertmanagerに再送されます。そのときendsAtを、現在時刻に4×evaluation_intervalを加えた値に設定して、次の送信が来る前に期限が切れないようにします。Prometheusが死ぬとアラートが自動的にresolvedになる理由が、この期限の設計です。
Alertmanagerパイプライン
| ステージ | 行うこと | 見落としやすい点 |
|---|---|---|
| Wait | グループが新しくできると、group_waitの間ためます |
既定は30秒です |
| Dedup | すでに送ったアラートかを、notification logで確認します | HAはgossipでこのログを共有します |
| Retry | 失敗したら、指数バックオフで再試行します | |
| Inhibit | sourceがfiringなら、targetを止めます | equalラベルが同じ場合に成立します |
| Silence | 人が作ったサイレンスとマッチさせます | 期限のないサイレンスは、削除すべきアラートのサインです |
| Notify | 実際の送信 |
3つのタイマーの違いが試験の常連です。group_waitは新しいグループの最初の送信前の待機(既定30秒)、group_intervalは既存のグループに新しいアラートが追加されたときの送信間隔(既定5分)、repeat_intervalは変化のないグループをもう一度知らせる間隔(既定4時間)です。
group_byに何を入れるかが、アラートの件数を決めます。インスタンス単位でまとめるとPodの数だけアラートが来て、サービスやSLO単位でまとめて初めて、人が読める件数になります。
抑制とサイレンスはよく混同されます。抑制は、設定ファイルに書かれたルールベースの自動ブロックで、サイレンスは、人がUIやAPIで作る一時的なブロックです。どちらもアラートを止めますが、UIにはそれでも表示されます。
複数ウィンドウのバーンレートは、SREワークブックの標準的な組み合わせです。
| 予算の消費 | 長いウィンドウ | 短いウィンドウ | しきい値のバーンレート | 対応 |
|---|---|---|---|---|
| 2% | 1時間 | 5分 | 14.4 | 即時ページ |
| 5% | 6時間 | 30分 | 6 | 即時ページ |
| 10% | 1日 | 2時間 | 3 | チケット |
| 10% | 3日 | 6時間 | 1 | チケット |
短いウィンドウは、長いウィンドウの12分の1にするのが慣例です。短いウィンドウの役割は感度ではなく解消の速度です。短いウィンドウがないと、事故が終わったあとも、長いウィンドウがウィンドウの長さの分だけアラートを維持します。
現場での姿
for:を書き忘れたルール1つのせいで、1日50件を超えるアラートが降り注いだことがあります。結果は予想どおりでした。人々がそのアラートを無視し始め、無視が習慣になると、同じチャンネルの本物のシグナルも一緒に埋もれました。アラート1つの正確さではなく、オンコール全体の反応速度が壊れたのです。
低トラフィックの時間帯も、繰り返される落とし穴です。5分にリクエスト3件が入る明け方に1件が失敗すると、エラー率は33%になり、すべてのバーンレートのしきい値を一度に超えます。最小トラフィックの条件をANDでかけると、幽霊アラートが消えます。トラフィックがそもそも0なら、比率はNaNになってアラートが静かに消えますが、その場合は、スループット急減のアラートが別に捉える必要があります。
そして、ページにはランブックを必須にします。午前3時に起きた人は、創造力を発揮できる状態ではありません。必要なのは、確認すること3つと、対応2つが書かれた文書です。CIゲートで、severity=pageなのにrunbook_urlがないルールを見つけてビルドを失敗させれば、この規律が人の記憶に依存しなくなります。
次のラボですること
/root/pca-alerting/の下に、Alertmanagerのルーティングツリーと抑制ルールを書き、速い消費と遅い消費の2つのバーンレートのアラートを作ります。最後に、ランブックの欠落を見つけるCIゲートのスクリプトを自分で書き、正常なファイルは通し、ランブックのないファイルは止めるかを確認します。