GoogleカレンダーでCloudWatchアラームにダウンタイムを設定する

前置き・概要

計画メンテナンスなど、特定期間だけアラート発報を抑制したい場合があります。

監視ツールには大抵「ダウンタイム」というアラート発報抑制期間を設定する項目があります。
Zabbix の「メンテナンス期間」であれば「毎日xx時からxx時間」「隔週xx曜日」といった柔軟な指定が可能です。

CloudWatchアラームに「ダウンタイム」的な設定項目はありません。
CloudWatch Events + Lambda (or SSM Automation)を利用すれば似たようなことが出来ますが、
アラームアクションを有効化/無効化するタイミングをUTCタイムゾーンのcron形式で表現しなければならず、
前述の監視ツールに比べると分かりやすさ・柔軟性に欠けます。

今回は以下のようなシステムを構築することで、CloudWatchアラームに分かりやすいダウンタイムを設定します。

  1. Google カレンダーに予定を作成し、説明欄にCloudWatchアラーム名を記載
  2. 予定が開始される時、CloudWatchアラームアクションを無効化
  3. 予定が終了する時、CloudWatchアラームアクションを有効化・アラームステータスをOKに変更

ダウンタイム中にALARM状態に変化した場合、その後でアラームアクションを有効化してもSNSへの通知は行われません。
そこで、アラームアクション有効化後、アラームステータスを一旦「OK」の状態にします。
すると、再度ALARM状態に変化した際にSNSへの通知が行われることになります。

前準備

IFTTT サインアップ

ifttt.com にアクセスし、サインアップしておきます。

IFTTT(イフト)はサービス自動連係ツールです。
今回利用するGoogleカレンダー以外にも、Slack や Facebook も利用可能です。

CloudWatchアラーム 作成

ON/OFF の対象となるCloudWatchアラームを作成しておきましょう。

ちなみに、今回実施するのは「アラームの有効/無効化」ではなく「アラームアクションの有効/無効化」です。
アクションの有効/無効が分かるように項目を表示しておきましょう。
※画像は編集を加えています。

以下のように、有効かどうかが確認できます。

ダウンタイム設定システム 構築

AWS

SSMパラメータ

IFTTT の webhook で API Gateway にPOSTする際、HTTP BODYにAPIキー(的なもの)を含めます。
そのキーとSSMパラメータの値が一致すればCloudWatchアラームアクション無効化/有効化を行います。

認証に使う文字列なので、Secure String (安全な文字列) として作成し、暗号化します。
Secure String は CFn をサポートしていないので手動で作成します。

Lambda 周り

Lambda 関数やIAMロールなど、以下の CFnテンプレートで作成可能です。

API Gateway

API Gateway (HTTP API)を作成します。
HTTP API は CFn をサポートしていないので手動作成します。Lambda のコンソールから作成可能です。

API Gateway のエンドポイントを控えておきましょう。

Google カレンダー

新しいカレンダーを作成します。このカレンダーに作成した予定の期間内、CloudWatchアラームアクションが無効化されます。

IFTTT

Googleカレンダー イベント開始時

[Create] でアプレットを作成します。

[This] でトリガー(Google カレンダー)を設定します。

Google Calendar を選択します。

[Any event starts] (=カレンダーで予定が開始された時)を選択します。

先ほど作成したカレンダーを選択し [Create Trigger] します。

次に [That] でアクション(Webhook)を作成します。

Webhooks を選択します。

[Make a web request] を選択します。

次の画面で、いくつか項目を入力して [Create action] を選択します。

URL https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/default/set-alarm-downtime
Method POST
Content Type application/json
Body { “ApiKey”: “xxxxxxxxxx”, “EventType”: “start”, “Alarms”: “{{Description}}” }
  • URL は、API Gateway のURLです。
  • Body の xxxxxxxxxx はAPIキー(的なもの)です。先ほど作成したSSMパラメータの値を入力します。
  • Body の {{Description}} はそのままで大丈夫です。IFTTT で扱える変数で、Google カレンダーの予定の説明欄の内容を表します。

最後にアプレットに名前を付けて完了です。

これで、Google カレンダーで予定が開始された時に API Gateway に HTTP POST されます。
その BODY には json 形式で以下が含まれています。

APIキー(的なもの) この文字列をSSMパラメータの値と比較し、一致しない場合 Lambda はそこで止まります。
イベントタイプ 予定の「開始」または「終了」を表します。
開始の場合、対象のCloudWatchアラームアクションを無効化します。
終了の場合、アラームアクションを有効化しアラームの状態を「OK」に更新します。
予定の説明 Googleカレンダーの予定の説明欄に記載されている文字列です。
今回はここに、有効化/無効化するCloudWatchアラーム名を記載します。

 

Googleカレンダー イベント終了時

イベント開始時と同じ流れで IFTTT のアプレットを作成します。先ほどと異なるのは以下2点です。

  • トリガーとして [Any event ends] (=カレンダーで予定が終了した時) を選択する
  • Webhooks の Body は以下のようにする

ダウンタイム設定システムを試す

試す

Googleカレンダーで、以下のような予定を作成します。設定した期間内、アラームが無効化されます。

それまで有効だったアラームアクションが…

カレンダーの予定開始時間になると、無効化されました。

予定終了時間になるとアクションが有効化され、復旧(OK)状態になります。
(実際に復旧したわけではなく、Lambda の set_alarm_state で一時的に状態を変更しています)

しばらくすると、アラームの状態が本来のものになります。
こうすることで、ダウンタイム期間が終了して尚 継続しているアラートも通知されるようになっています。

「ダウンタイム開始前からNG状態だったアラームが、ダウンタイム終了後に通知されてしまう」
というのが難点、というか、通常の監視ツールで利用できるダウンタイムとの違いです。

アラームアクションがなかなか有効化/無効化されない時

Googleカレンダーの予定が開始/終了されてから Webhooks がトリガーされるまで時間がかかる場合があります。
そんな時はアプレットの Settings を開き、

[Check now] を押すと即時 Webhooks がトリガーされます。

AWS CloudWatchとは?