TT Lab
はじめる
学ぶ 学習パス コース

PCA — Prometheus認定アソシエイト

ルーティングツリーとバーンレートのアラート

TT Labで続きを見る

目標

Alertmanagerの設定を、ルーティングツリーから抑制ルールまで自分で書き、SLOから逆算したバーンレートのアラートを2つ作り、ランブックの欠落をビルドで止めるゲートを作成します。

なぜ重要なのか

アラートの成功基準は、「問題を検知したか」ではなく、人が今、何かをしなければならないかです。この基準を通らないアラートは、正確でも有害です。正確なアラート400個がオンコールの反応速度を壊してしまえば、正確さにはまったく意味がありません。そのため、順序が決まります。ユーザーの症状でSLOを定義し、バジェットからしきい値を逆算し、長いウィンドウと短いウィンドウをANDでつないで感度と誤検知を同時に押さえ、グルーピングと抑制でアラートの件数を人が読めるレベルまで減らし、ページにはランブックを必須にします。しきい値を「過去の最大値の1.2倍」のような方法で決めると、なぜその値なのかを説明できず、説明できないしきい値は、事故が起きるたびに少しずつ上がっていきます。

ステップ

  1. /root/pca-alerting/alertmanager.ymlを作成し、ルートのrouteを書きます。receiver: ticket-queue、group_by: ['alertname', 'cluster', 'slo']、group_wait: 30s、group_interval: 5m、repeat_interval: 4hを設定します。
  2. ルートのroutesの最初の項目に、子ルートを入れます。matchers: ['severity="page"']、receiver: oncall-pager、group_wait: 10s、repeat_interval: 1hを設定します。
  3. receiversに、2つの受信先を定義します。ticket-queueとoncall-pagerのそれぞれにwebhook_configsを置き、urlは、http://で始まる内部アドレスであれば何でもかまいません。
  4. inhibit_rulesの最初の項目を書きます。source_matchers: ['alertname="ClusterDown"', 'severity="page"']、target_matchers: ['severity=~"page|ticket"']、equal: ['cluster']を設定します。
  5. /root/pca-alerting/burnrate.ymlを作成し、グループの下にアラートCheckoutErrorBudgetBurnFastを書きます。exprは、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でつないだもの、for: 2m、labelsにはseverity: pageとslo: checkout-availability、annotationsにはsummaryとrunbook_urlを入れます。
  6. 同じファイルに、アラートCheckoutErrorBudgetBurnSlowを追加します。exprは、job:slo_errors:ratio_rate6h{job="checkout-api"} > (6 * 0.001)と、job:slo_errors:ratio_rate30m{job="checkout-api"} > (6 * 0.001)をandでつないだもの、for: 15m、labelsにはseverity: ticketとslo: checkout-availabilityを入れます。
  7. /root/pca-alerting/runbook-gate.shを作成します。1つ目の引数でルールファイルのパスを受け取り、labels.severityがpageなのにannotations.runbook_urlがないアラートが1つでもあれば、その名前を出力して0以外のコードで終了し、1つもなければ0で終了します。

参考

ルートレベルのrouteを書く

/root/pca-alerting/alertmanager.ymlを作成し、ルートのrouteを書きます。receiver: ticket-queue、group_by: ['alertname', 'cluster', 'slo']、group_wait: 30s、group_interval: 5m、repeat_interval: 4hを設定します。

ルートのreceiverは、マッチする子がないときの既定値です。group_byに何を入れるかがアラートの件数を決める、という点を思い出してください。3つのタイマーは、それぞれ最初の送信の待機、グループの更新間隔、変化がないときの繰り返し間隔です。

重大度別の子ルート

ルートのroutesの最初の項目に、子ルートを入れます。matchers: ['severity="page"']、receiver: oncall-pager、group_wait: 10s、repeat_interval: 1hを設定します。

routesはルートの下のリストで、上から下へマッチします。continueを有効にしなければ、最初のマッチで止まります。子は親の設定を継承し、明示した値だけを上書きします。

受信先の定義

receiversに、2つの受信先を定義します。ticket-queueとoncall-pagerのそれぞれにwebhook_configsを置き、urlは、http://で始まる内部アドレスであれば何でもかまいません。

ルートで名前で参照した受信先がreceiversの一覧になければ、設定が読み込まれません。このラボ環境には実際の送信先がないので、WebhookのURLで形だけ整えます。

抑制ルール

inhibit_rulesの最初の項目を書きます。source_matchers: ['alertname="ClusterDown"', 'severity="page"']、target_matchers: ['severity=~"page|ticket"']、equal: ['cluster']を設定します。

抑制は、原因のアラートが生きているときに、下位の症状のアラートを止めます。equalに書いたラベルの値が両側で同じであるときに成立するので、このラベルを抜かすと、別のクラスターのアラートまで抑制されます。

速い消費のアラート

/root/pca-alerting/burnrate.ymlを作成し、グループの下にアラートCheckoutErrorBudgetBurnFastを書きます。exprは、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でつないだもの、for: 2m、labelsにはseverity: pageとslo: checkout-availability、annotationsにはsummaryとrunbook_urlを入れます。

長いウィンドウは消費の速度を、短いウィンドウは今も進行中かどうかを判定します。ここに最小トラフィックのゲートを加えて、3つの項をANDでつなぎます。長いウィンドウをすでに使っているので、forは欠落の吸収用に短くかけます。

遅い消費のアラート

同じファイルに、アラートCheckoutErrorBudgetBurnSlowを追加します。exprは、job:slo_errors:ratio_rate6h{job="checkout-api"} > (6 * 0.001)と、job:slo_errors:ratio_rate30m{job="checkout-api"} > (6 * 0.001)をandでつないだもの、for: 15m、labelsにはseverity: ticketとslo: checkout-availabilityを入れます。

バジェットが漏れてはいるが速度が遅い場合は、人を起こす事柄ではなくチケットです。短いウィンドウは長いウィンドウの12分の1にする慣例に従い、severityはページであってはいけません。

ランブックのCIゲートスクリプト

/root/pca-alerting/runbook-gate.shを作成します。1つ目の引数でルールファイルのパスを受け取り、labels.severityがpageなのにannotations.runbook_urlがないアラートが1つでもあれば、その名前を出力して0以外のコードで終了し、1つもなければ0で終了します。

スクリプトは、1つ目の引数でルールファイルのパスを受け取ります。yqで、severityがpageのルールのうちrunbook_urlのアノテーションがないものを取り出し、1つでもあれば名前を出力して失敗で終わらせれば十分です。チケット等級まで止めてはいけません。