Google CloudにおけるAlert Policy作成の試行錯誤

近頃、Google Cloudのログからアラートを設定する方法を検討していました。具体的には、Scheduled Queryのエラーを監視して通知を受け取る方法を模索していました。エラーを通知する方法にはいくつかあるのですが、通知先がSlackであることは決まっていたので、Pub/Subを利用せずに手軽に連携できる方法を探していました。
そこでログベースのアラートとログベースの指標を元にしたアラートを試していたので、その試行錯誤から得られた知見を残しておきます。

参考 blog.g-gen.co.jp

なお言い訳ですが、Google Cloudを利用した経験はこれまでほとんどなく、Cloud Loggingによるアラートの違いについても初めて知ることが多かったため、記事の内容に誤りがあるかもしれません。その際は、ご指摘いただけると幸いです。

やりたかったこと

  • BigQueryで利用しているScheduled Queryがこけた際に気づいて、対応できるようにする
  • 通知先はSlack
  • リソースはTerraform管理

試行した方法

ログベースのアラートまたはログベースの指標を元にしたアラートが手軽でよさそうだったため、それぞれ試してみました。Scheduled Queryの失敗はログをフィルターすれば判別できるので、これを元にアラートを作成する方針で進めました。

参考までに、フィルター条件は例えばこのようになります。

resource.type="bigquery_dts_config" AND severity>="ERROR"

通知先の作成

どちらの手法を選ぶにしても通知先は必要になるので、先に作成します。
Slackについては、Webhookなどを用意しなくてもGoogle Cloudで通知先として設定できます。

Terraformで作成する場合は以下のリソースです。

注意点

Terraformから作成する場合はauth_tokenが必要になります*1。これの取得方法がなんとも分かりにくいです。
ほんまか?Slackの管理者であればSlackのApplicationから取得できるのでは?と思いますが、僕には見つけられませんでした。

stackoverflow.com

ログベースのアラートの作成

ログベースのアラートは、Google Cloud Loggingに対してフィルターとなるクエリを作成し、そのクエリにマッチするログが出力された際にアラートを発生させる仕組みです。コンソール画面であれば、ログエクスプローラーから直接作成できます。

Terraformで作成する場合に作成するリソースは以下の通りです。

Documentationという項目で、アラートの詳細を記載することができます。どのScheduled Queryが失敗したのかを把握する必要があるので以下を含めます。

https://console.cloud.google.com/bigquery/scheduled-queries/locations/$${resource.label.location}/configs/$${resource.label.config_id}/runs?project=$${resource.project}

展開できる変数は以下から確認できます。アラートを作成する側としてはエラーメッセージ(jsonPayload.message)を含めたいのですが、無理そうでした。なぜ...

ユーザー定義のドキュメントで通知にアノテーションを付ける  |  Cloud Monitoring  |  Google Cloud

インシデントの対応

アラートポリシーの作成後、フィルターにマッチするログが出力されるとインシデントになりSlack通知が届きます。

インシデントに対しては、3つの操作ができます

  1. Acknowledge
  2. Snooze
  3. Close

Acknowledgeは、インシデントを認識したことを示す操作です。Acknowledgeをすると、認識した人がインシデント上に表示されるため、対応中であることがわかります。
Snoozeは、インシデントを一時的に無視する操作です。Snoozeをすると、インシデントが一時的に非表示になります。時間は好きに決めることができます。インシデントへの対応中の場合に通知を抑制するために使うようです。ログのフィルター条件によっては、関係ないエラー通知を抑制して検知が漏れる恐れもあるため、慎重に使う必要があります。
Closeは、インシデントを閉じる操作です。インシデントが解決した場合に行います。なお、インシデントが発生してから3分間はCloseができません*2

3分以内に閉じようとしてもエラーになる

ログベースのアラート ポリシーのインシデント  |  Cloud Monitoring  |  Google Cloud

注意点

ログベースのアラートはリマインドができません。後述する指標ベースのアラートでは、閾値を超えている間リマインド*3をすることができますができますが、ログベースのアラートはエラーを拾ったタイミングでただ一度だけ通知されます。

またインシデントをCloseした際、同一のアラートポリシーに紐づくインシデントは全てCloseされます。個人的には結構困るのでやめて欲しいのですが、、、分けたい場合は別のアラートポリシーを作る必要があります。それはそれで、アラートポリシーを増やすことになるので、管理が大変になりそうです。

ログベースの指標に基づいたアラートの作成

ログベースの指標に基づいたアラートは、Google Cloud Loggingに対してフィルターとなるクエリを作成するところまでは同じです。
その後、そのクエリをもとにメトリクスを作成し、そのメトリクスに基づいてアラートを作成します。

Terraformで作成する場合に作成するリソースは以下の通りです。

ログベースのアラートはログに対して直接アラートを作成しますが、こちらではログからメトリクスを作成し、そのメトリクスの閾値に応じてアラートを発火させることになります。
ログベースのアラートとは異なり、閾値を超えている間は設定した間隔でリマインド(renotify)をすることができます。また、メトリクスを作成する際にはグルーピングも可能であるため、スケジュールドクエリ単位でグループ化してアラートを発火させることも可能です。
なおインシデントへの対応は、基本的にログベースのアラートと同じで、Acknowledge, Snooze, Closeをすることになります。

注意点

指標ベースのアラートは、あくまでメトリクスの閾値を基準にアラートを設定することになります。例えば、「X分間に1つ以上のクエリエラー」という条件で設定した場合、X分で1つでもエラーがあればインシデントはCloseできませんし、仮に問題が解決していなくてもX分経過すれば自動的にインシデントがCloseします
土日にも実行されるクエリがある場合、反応できるとは限らないので自動でCloseされたら困ります。一方で監視期間を25時間などにすると*4、仮に問題が解決しても25時間経過しないとインシデントをCloseできません。代替策としてSnoozeをした場合、Snoozeした期間内に別のエラーが発生した場合に通知がきません。
これでは全く意味がないので僕は使えないと判断しました。想定されたユースケースがCPU利用率の監視などのため、その用途では正しいのですが、、、

ちなみにインシデントをCloseした際に同じアラートポリシーに紐づくインシデントが全てCloseされるのはログベースのアラートと同じでした。

指標ベースのアラート ポリシーのインシデント  |  Cloud Monitoring  |  Google Cloud

まとめ

  • ログベースのアラートは手軽に作成できるが、一度通知することしかできないので検知漏れには気をつける必要がある
  • 指標ベースのアラートは、あくまでメトリクスの監視が主目的であり、Scheduled Queryのエラー通知には向いていなさそう
  • 良い感じにインシデントを管理したいのであれば、結局Pub/Subを利用して別のサービスに連携するか、PagerDutyであればSlack同様に連携できそう(?)*5

*1:もちろんトークンのベタ書きはNGなので、別で管理しましょう

*2:連続してアラートが検知されるケースの対策のようですが、個人的には不要な制約だと感じました

*3:厳密にはrenotifyで、リマインドをしているわけではなく通知をし続けてくれる

*4:設定できる期間の最大値が25時間です

*5:試してはいません