前置き・概要
計画メンテナンスなど、特定期間だけアラート発報を抑制したい場合があります。
監視ツールには大抵「ダウンタイム」というアラート発報抑制期間を設定する項目があります。
Zabbix の「メンテナンス期間」であれば「毎日xx時からxx時間」「隔週xx曜日」といった柔軟な指定が可能です。
CloudWatchアラームに「ダウンタイム」的な設定項目はありません。
CloudWatch Events + Lambda (or SSM Automation)を利用すれば似たようなことが出来ますが、
アラームアクションを有効化/無効化するタイミングをUTCタイムゾーンのcron形式で表現しなければならず、
前述の監視ツールに比べると分かりやすさ・柔軟性に欠けます。
今回は以下のようなシステムを構築することで、CloudWatchアラームに分かりやすいダウンタイムを設定します。

- Google カレンダーに予定を作成し、説明欄にCloudWatchアラーム名を記載
- 予定が開始される時、CloudWatchアラームアクションを無効化
- 予定が終了する時、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] でアプレットを作成します。

Google Calendar を選択します。


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

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

Webhooks を選択します。


次の画面で、いくつか項目を入力して [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 を開き、


投稿者プロフィール
- 2015年8月入社。弊社はインフラ屋ですが、アプリも作ってみたいです。