はじめに
監視やアラート通知の仕組みを作っていると、「監視基盤自身をどう監視するか」という問題にぶつかります。
たとえば、次のような通知基盤があるとします。
Cloud Monitoring
-> Pub/Sub
-> Worker
-> Slack / メール / 外部通知サービス
Cloud Monitoring のアラートを直接 Slack やメールに送るのではなく、一度 Pub/Sub に流し、Worker が通知文面の整形や通知先の振り分けを行う構成です。
この構成には利点があります。通知処理をコードで管理できるため、アラート種別ごとのルーティング、重複抑制、外部システム向けの変換などを柔軟に実装できます。
一方で、Worker 自身を監視しようとすると、注意が必要な問題があります。
監視基盤自身が止まったとき、その障害を知らせるアラートは誰が通知するのか
この記事では、Pub/Sub backlog 監視を例に、自己監視アラートで見落としやすい通知経路の依存関係について整理します。
前提の構成
ここでは、以下のような構成を考えます。
Cloud Monitoring AlertPolicy
-> Pub/Sub notification channel
-> Pub/Sub topic / subscription
-> 通知処理用 Worker
-> Slack / メール / 外部通知先
Cloud Monitoring のアラートは Pub/Sub に publish されます。
通知処理用 Worker は subscription を購読し、受け取ったアラートを整形して Slack やメールなどに送ります。
この構成では、Cloud Monitoring の notification channel は Pub/Sub です。
最終的な通知先の制御は Worker 側の実装が担います。
本記事では、この通知処理用 Worker が全体としてメッセージを処理できない状態を「完全停止」と呼びます。
プロセス停止だけでなく、クラッシュループ、設定不備、通知処理の例外などで継続的に処理できない状態も含めます。
やりたかったこと
通知処理用 Worker が正常に動いているかを監視するために、Pub/Sub subscription の backlog を見ることにします。
たとえば、次のようなメトリクスを使います。
oldest_unacked_message_age
これは、subscription に残っている未 ack メッセージのうち、最も古いものがどれくらい古いかを見るメトリクスです。
未 ack のメッセージが長時間残っている場合、Worker がメッセージを処理できていない可能性があります。
そのため、一定時間以上 backlog が溜まったらアラートを発火させる、という設計です。
期待する流れは次のようなものです。
Worker が処理できなくなる
-> Pub/Sub に未処理メッセージが溜まる
-> backlog アラートが発火する
-> Slack やメールに通知される
一見すると、自然な自己監視に見えます。
そこで確認すべきこと
ここで確認すべきなのは、backlog アラートの通知経路です。
もし backlog アラートも通常のアラートと同じように、次の経路で通知されるとします。
Cloud Monitoring
-> Pub/Sub
-> Worker
-> Slack / メール
この場合、Worker 自身が完全停止している状態では、backlog アラートも通知されません。
つまり、次のような自己参照的な依存関係になります。
Worker の異常を検知するアラート
-> その通知処理も同じ Worker に依存している
この状態では、Cloud Monitoring 上でアラートポリシーが発火していても、実際の通知は Worker の復旧待ちになります。
この設計で有効に機能するケース
この設計が意味を持たないわけではありません。
いくつかのケースでは十分に有効です。
一時的な停止
Worker が一時的に停止しただけで、しばらくして復旧する場合は、Pub/Sub に残っていたメッセージを復旧後に処理できます。
Worker 停止
-> Pub/Sub にメッセージが滞留
-> Worker 復旧
-> 滞留分を処理
-> 遅延して通知
この場合、通知は遅延しますが、Pub/Sub のメッセージ保持期間内であれば通知できる可能性があります。
一部インスタンスだけの障害
複数インスタンスや複数リージョンで同じ subscription を処理している場合、一部の Worker が停止しても、残りの Worker が処理を継続できます。
この場合、backlog 監視は処理遅延や一部障害の兆候を拾う手段として機能します。
処理が遅いが完全停止ではないケース
Worker が生きていて、処理もできているものの、処理速度が publish 速度に追いついていない場合も backlog 監視は有効です。
この場合は Worker が backlog アラート自体を処理できるため、通常どおり通知できます。
この設計に限界があるケース
一方で、次のようなケースでは注意が必要です。
Worker が全体として継続的に処理不能
通知処理用 Worker が全体として停止している場合、backlog アラートの通知も同じ Worker に依存しているため、通知できません。
Cloud Monitoring で backlog アラート発火
-> Pub/Sub に通知メッセージ publish
-> Worker が停止中
-> 通知されない
Cloud Monitoring の画面ではインシデントが開いていても、Slack やメールには届かない可能性があります。
Pub/Sub にメッセージがない状態で停止した場合
oldest_unacked_message_age は、未 ack のメッセージが存在することを前提にしたメトリクスです。
そのため、subscription が空の状態で Worker が停止した場合、backlog は発生しません。
backlog 監視は「処理すべきメッセージが溜まっていること」の検知です。
「Worker が生きていること」を常に証明するものではありません。
通知ロジック自体に不具合がある場合
Worker のプロセスは起動していても、通知ロジックに不具合がある場合があります。
たとえば、次のようなケースです。
- 特定の payload の parsing に失敗する
- 通知先の解決ロジックで例外が出る
- Slack やメール送信部分だけが失敗している
- 重複抑制や冪等性処理で意図せず通知が止まる
この場合、プロセスの liveness は正常でも、実際の通知は失敗している可能性があります。
アラート発火と通知到達は別
ここで重要なのは、次の点です。
アラートが発火することと、通知が届くことは別
Cloud Monitoring 上で AlertPolicy が正しく定義されていても、その通知経路が止まっていれば、運用者には届きません。
特に自己監視では、アラート条件だけでなく、通知が届くまでの依存関係を見る必要があります。
何を検知するか
どこに通知するか
どの経路で通知するか
その経路は監視対象自身に依存していないか
このあたりを分けて確認しないと、「監視しているつもりだが、肝心な障害時には通知されない」という状態になり得ます。
対応方針
対応方針はいくつかあります。
1. リスクを明示する
まず最低限やるべきなのは、設計書や運用ドキュメントに正しい依存関係を書くことです。
たとえば、次のように明記します。
- backlog アラートは通常の通知経路で処理される
- Worker が全体として継続停止している場合、通知できない
- 一時停止や一部障害では復旧後に処理される可能性がある
- 完全停止の検知には別の仕組みが必要
「自己監視しているから大丈夫」と誤解される状態を避けることが重要です。
2. 重要な自己監視だけ別経路にする
Worker の backlog アラートだけ、通常の Pub/Sub 経由ではなく、Cloud Monitoring から直接 Slack やメールに送る方法もあります。
通常アラート:
Cloud Monitoring
-> Pub/Sub
-> Worker
-> Slack / メール
自己監視アラート:
Cloud Monitoring
-> Slack / メール
この構成なら、Worker が停止していても自己監視アラートだけは届く可能性があります。
ただし、通知経路を例外化することにもなります。
通知先、認証情報の管理、重複通知、運用フローなどを別途設計する必要があります。
3. heartbeat や外形監視を追加する
backlog 監視だけでは、メッセージがない状態の停止を検知できません。
より確実に監視したい場合は、heartbeat や外形監視を検討します。
たとえば、次のような方法です。
- 定期的に監視用メッセージを publish する
- Worker がそのメッセージを処理したことを記録する
- 一定時間処理されなければ別経路でアラートにする
- Worker の health endpoint を外部から監視する
- 起動失敗やクラッシュループを Cloud Logging / Cloud Monitoring で直接検知する
重要なのは、検知したい障害モードに対して、監視方法と通知経路が合っているかです。
まとめ
Pub/Sub backlog 監視は、Worker の処理遅延や一時停止を検知するうえで有効です。
ただし、backlog アラートの通知経路が同じ Worker に依存している場合、Worker が完全に処理不能な状態では、そのアラートも通知できません。
自己監視では、アラート条件だけでなく、通知が届くまでの経路も確認する必要があります。
特に、監視対象自身が通知経路の一部になっている場合、アラートは発火していても通知が届かないことがあります。
監視基盤自身を監視する場合は、次の3つを分けて確認するとよさそうです。
- 何を検知するのか
- どの経路で通知するのか
- その通知経路は監視対象自身に依存していないか
「アラートを定義した」だけではなく、「障害時に運用者まで届く」ことまで確認しておくのが大事です。