特定時刻だけ CloudWatch アラームを抑制する、Amazon EventBridge Scheduler で。

AWS の標準機能だけで CloudWatch アラームの特定期間の抑止ができ(ると言っていいのではないかと思い)ます!

特定の時間だけは CloudWatch アラームによる通知を止めたい

コンバンハ、千葉(幸)です。

CloudWatch アラームによるモニタリングを行っている環境で、特定の時間だけは発報してほしくないということがあるかと思います。

夜間帯は対応できる人がいないとか、特定の定期バッチで負荷が上がる(そしてシステム稼働には影響がでない)ことがわかっているのでそれは抑止したいとか、定常作業中はステータス監視を止めたい、といったシチュエーションを想定しています。

スクリプトを組んで定期的に CloudWatch アラームを無効化/有効化したり、CloudWatch アラーム→ SNS トピック→ Lambda 関数→ SNS トピックという構成にして時間判定を行う処理を挟んだりというやり方が思いつきますが、作り込みをせずに済ませたいことが多いでしょう。

CloudWatch メトリクスの Metric Math を利用してダウンタイムを設ける方式を考えたこともありますが、こちらも関数の条件式を記述するのがお世辞にもお手軽とは言えません。

そんな中 Amazon EventBridge Scheduler という可能性溢れる新機能が発表されました。単純な API 実行を柔軟にスケジューリングできる優れもので、いろんな活用例が見出されています。

Amazon EventBridge Scheduler の対応 API に CloudWatch アラームの無効化/有効化が含まれていたので、これを活用してみることにしました。

今回試してみる構成

このようなイメージです。

CloudWatch Alarm

Amazon EventBridge Scheduler では「スケジュール」というリソースを作成してスケジュリーングを定義します。今回は以下2種類のスケジュールを用意します。

  • 特定の時間に CloudWatch アラームを無効化するスケジュール
  • 特定の時間に CloudWatch アラームを有効化するスケジュール

それぞれのスケジュールで複数の CloudWatch アラームを対象にできます。スケジュールでは JST で指定できるのも嬉しいところです。

Amazon EventBridge Scheduler による CloudWatch のダウンタイム設定をやってみた

やっていきます。

CloudWatch アラームの準備

ふたつの CloudWatch アラームを準備しました。

  • Test-Alarm
  • Test-Alarm2

適当なメトリクスを指定し、アクションとして SNS トピックへの通知を設定しています。

EventBridge_CloudWatch_Management_Console

Amazon EventBridge Scheduler 用 IAM ロールの作成

このあと設定する「スケジュール」が API を実行するため、その権限を持たせるための IAM ロールが必要です。スケジュールの作成に合わせて自動で作成してくれたりはしないので、あらかじめ準備しておく必要があります。

詳細は以下手順に詳しいです。

ポイントは 2 つです。

  • 信頼ポリシーでscheduler.amazonaws.comからの AssumeRole を許可していること
  • アイデンティティポリシーで API 実行に必要な許可が与えられていること

今回は 2 種類のスケジュールを作成するのですが、両者で共通の IAM ロールを使用することにします。もちろん別々のものを用意しても大丈夫です。

今回は AWS CLI で IAM ロールを作成します。

% trustpolicy=$(cat <<EOM
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "scheduler.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}
EOM
)

% aws iam create-role\
 --role-name SchedulerExecutionRole\
 --assume-role-policy-document "$trustpolicy"
{
    "Role": {
        "Path": "/",
        "RoleName": "SchedulerExecutionRole",
        "RoleId": "AROAQ3BIIH73RDM6MXHZQ",
        "Arn": "arn:aws:iam::012345678910:role/SchedulerExecutionRole",
        "CreateDate": "2022-11-25T13:53:33+00:00",
        "AssumeRolePolicyDocument": {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Principal": {
                        "Service": "scheduler.amazonaws.com"
                    },
                    "Action": "sts:AssumeRole"
                }
            ]
        }
    }
}

作成したロールにインラインポリシーをアタッチします。(インラインにした理由は単に管理ポリシーを作成する手間を省きたかっただけです。)

% policy=$(cat <<EOM
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "cloudwatch:EnableAlarmActions",
                "cloudwatch:DisableAlarmActions"
            ],
            "Resource": "*"
        }
    ]
}
EOM
)

% aws iam put-role-policy\
 --role-name SchedulerExecutionRole\
 --policy-name SwitchAlarmActions\
 --policy-document "$policy"
%

準備ができました。

CloudWatch アラームアクションを無効化するスケジュールの作成

EventBridge コンソールからスケジュールの作成を試みます。

今回は cron ベースで適当な時間を設定しました。タイムゾーンを指定できるのが嬉しいですね。

EventBridge_Scheduler_create

ターゲットの指定を行います。まずはサービスを選択することになりますのでCloudWatchを検索し指定します。その後、CloudWatch の中で API を指定します。まずはアラームアクションを無効化する API DisableAlarmActionsを選択しました。

EventBridge_Schedular_create_schedule

↑「入力」としてターゲットの API を実行する対象の CloudWatch アラームを指定します。複数の CloudWatch アラーム名を指定可能です。

{
  "AlarmNames": [
    "Test-Alarm",
    "Test-Alarm2"
  ]
}

次の画面で各種詳細を設定します。ここでは末尾で先ほど作成した IAM ロールを選択する以外は特にいじらず次に進みました。

EvnetBridge_Scheduler_atach_role

次のステップの確認を行い、作成を実行すればスケジュールの完成です。

CloudWatch アラームのアクションステータスを確認する

作成したスケジュールで指定した時間になったら CloudWatch アラームのアクションステータスを覗きにいきます。想定通り無効になっていました。

EventBridge_schedulaer_disabled_CloudWatch_Management_Console

アラームの履歴から「設定の更新」を確認すると、cron で指定した時刻から 25 秒ほど遅れて更新された記録が残っていました。流石に多少のバッファのタイムは見込んでおいた方が良さそうです。

片方の CloudWatch アラームの対象のメトリクスを発行してアラーム状態にしても、アクションが無効なため SNS トピックへの通知アクションは行われません。

% aws cloudwatch put-metric-data\
 --namespace Sample\
 --metric-name TestMetric\
 --value 1

EventBridge_alarm_no_action_CloudWatch_Management_Console

CloudWatch アラームアクションを有効化するスケジュールの作成

先ほどと同様の手順で、APIEnableAlarmActionsをターゲットとするスケジュールを作成します。(詳細は割愛します。)

こちらも指定した時刻になったら CloudWatch アラームのアクションステータスを確認します。きちんと有効になっていました。

EventBridge_enable_actions_CloudWatch_Management_Console

なお、14:27 にスケジュールが実行されるように設定しましたが、今回は 19 秒ほどズレがありました。

EventBridge_history_CloudWatch_Management_Console

一通りの確認ができました。無効化、有効化のスケジュールを組み合わせれば特定期間の CloudWatch アラーム抑止が実現できそうですね。

終わりに

Amazon EventBridge Scheduler のスケジュールを作成して CloudWatch アラームのアクションを無効化/有効化してみました。

特にスクリプトや Lambda 関数などを用意しなくても自動で実行できるのは助かります。スケジュールでは万が一失敗した際の再試行ポリシーも指定できますし、デッドレターキューも指定できます。かなりお任せできる仕組みと言えるのではないでしょうか。

CloudWatch アラームにダウンタイムを設けたい、という方は導入をご検討ください。

以上、 チバユキ (@batchicchi) がお送りしました。

参考