欠けた計測と遅れて鳴るアラート
一言でいうと
値が0であること、今選べるサンプルがないこと、新しいサンプルが届いていないことは、それぞれ異なります。アラートが条件を初めて満たしたpending状態と、実際のfiring状態も、区別する必要があります。このラボは、その違いがアラートの待機時間をどう変えるかを、仮想時間の実際のルールテストで検証します。アラートがfiringだという事実を、通知メールが届いたという主張にまで広げることはしません。
なぜ必要なのか
「データがなければ0で埋めればグラフがきれいになる」という修正は、レポートを見やすくできますが、消えた測定を、実際のリクエストなしと言い換えてしまう危険もあります。決済サービスにリクエストがなかったことと、エクスポーターが決済のcounterを提供しなくなったことは、対応の方法から違います。前者では需要を分析し、後者では計装と収集経路を確認する必要があります。
アラートも、数字を1つ比較するだけでは終わりません。条件が一瞬満たされてから消えたのに、以前の待機時間を合算し続けると、早く鳴りすぎることがあります。逆に、データを抜いたテストで、条件が消えたと仮定したのに、実際のエンジンが以前のサンプルを選んだ場合は、予想と違って、アラートの待機が続くことがあります。時間軸が入る動作は、説明を読むだけで確信せず、イベントを前後に配置したテストで確認する必要があります。
どう動くのか
このラボには、routeごとに2つの入力時系列がなければならない、という限定した約束があります。基本のrateルールに、現在選ばれる時系列数が2のrouteだけを残す保護条件を付けます。すべてのサービスで、インスタンスを必ず2つだけにするという推奨ではありません。このラボでは、現在の時系列数とサンプルの存在を比較する、小さな仕掛けとして使います。
明示的なstale記録を入れたシナリオでは、/checkoutのbが、現在の選択結果から消えます。6分の時点のcountは1です。保護条件を外すと、古い範囲サンプルで計算したリクエスト率が出続けることがありますが、保護したrateには/checkoutのサンプルがありません。/statusの2つのインスタンスと、値2は、そのまま残ります。これは全体の空のベクトルではなく、1つのrouteの情報不足です。
一方、実際のリクエストなしの事例では、aとbのcounterが0として観測され続けます。現在の時系列数は2で、保護したリクエスト率は0です。期待サンプルを空のリストにすると、この正常な状態を誤って拒否してしまいます。テストで「ない」ことを検査するときは、該当するラベルの集合が結果にないことを、0を検査するときは、該当するラベルの集合が存在して値が0であることを、それぞれ書く必要があります。
欠けたサンプルとstale記録は同じ入力ではない
テストのvaluesで_は、その位置にサンプルがないという表示で、staleは、時系列が古くなったことを明示する記録です。実験でbの6分のサンプルだけを_にすると、エンジンは5分の直前のサンプルを選びました。6分のサンプルの経過時間は60秒、現在の時系列数は相変わらず2、保護したrateは11です。同じ位置をstaleに変えると、保護した/checkoutの結果が消えます。
この違いは、最新値の選択が、評価時刻ごとに必ず新しいサンプルを要求するわけではないために生じます。lookback内の直前のサンプルが選ばれることがあります。したがって、countが2だという事実は、2つの入力の現在の鮮度が十分であることや、実際のscrapeがたった今成功したことの保証ではありません。インスタンスの身元も、countだけでは確認できません。本番の判定であれば、期待するターゲットの一覧と、収集の状態、サンプルの経過時間についての、別の約束を設計する必要があります。この単元は、その約束まで実装したとは主張せず、単純なcountの保護条件の限界を、学習者に報告させます。
また、実際のHTTP scrapeの失敗が、常に単体テストの_と同じように処理されると一般化してはいけません。実際のコレクターは、状況に応じてstale記録を生成し、ターゲットの削除やタイムスタンプの設定にも、別の意味があります。ここでは、すでに用意した時系列を、ルールエンジンに入れます。実際のネットワーク収集の検証は、前の単元の独立したPrometheusの実験と区別します。
アラートの待機時間を前後から検査する
アラートPcaHighRequestRateは、保護したrateが10.5より大きい状態が、for: 2mのあいだ続くとfiringになるように設計します。評価間隔は1分です。正常な入力の実際の結果は、5分がpending、6分がpending、7分がfiringです。しきい値を最初に超えた時刻と、発火時刻を、一緒に検査してこそ、forを消したルールも見つけられます。7分のfiringだけを検査すると、もっと早く鳴るルールも、その時刻にはfiringなので、誤った実装を通してしまうことがあります。
アラートの待機の途中の6分にstaleを入れると、条件が消えます。7分に入力が復帰しても、すぐにはfiringにならず、またpendingが始まります。8分もpendingで、9分にfiringです。逆に、6分にサンプルを1つだけ欠かした事例は、直前のサンプルが選ばれて、条件が維持され続け、7分にfiringです。学習者のテストには、2つのシナリオがどちらも必要です。
alert_rule_testは、指定した時刻のfiringのアラートを比較します。firingがないという期待だけでは、pendingと完全な非アクティブ状態を区別できません。そのため、promql_expr_testで、ALERTSのalertstateラベルも一緒に検査します。6分のstaleの事例はALERTSのサンプルがなく、単純なサンプル欠落の事例はpendingのサンプルがあります。「まだ鳴っていない」という一言よりも、はるかに強い、時間軸の契約になります。
現場での姿
アラートのレビューでは、発火後の一場面だけをキャプチャしません。しきい値を超える直前、最初に超えたとき、待機中、発火の境界、データの欠損と復帰を、別々にテストします。forを1分に縮めたり、3分に延ばしたりした変異も、それぞれ早すぎる発火と、遅すぎる発火として検出される必要があります。アラートがうるさすぎるからと、やみくもに待機時間を延ばす変更も、要件を変える決定です。どんな障害を、どれだけ遅れて知ってもよいかは、チームの対応バジェットとあわせて議論する必要があります。
最後に、firingの意味を狭く正確に報告します。今回のテストで確認するのは、ルールエンジンが生成した状態です。Alertmanagerのグループ化・サイレンス・ルーティングや、メールの送信は、別の段階であり、このVMの実験では外部への通知を送りません。確認していない配信まで「通知は正常」と書かない習慣は、テストの品質と同じくらい重要な、運用の技術です。
次のラボですること
coverage-rules.ymlで、ない値を0で埋める誤った処理をなくし、実際の0は保存します。 coverage-tests.ymlで、欠けたrouteに対する誤った期待サンプルを直します。そのあと、alert-rules.ymlの待機時間を設定し、alert-tests.ymlで、復帰の直後に発火を期待した誤答を修正します。 観測には、実際のエンジンの出力が残ります。最後のレポートには、countの鮮度の限界と、このテストが確認していない外部への配信の範囲を明記します。