CloudWatch AlarmのダウンタイムをLambda+EventBridgeで設定する

2022/03/08に公開

やりたいこと

CloudWatch Alarm Actionを毎日決まった時間に停止/再開したい。(ダウンタイムを設定したい)

検討した方法

CloudWatch Alarm自体にはダウンタイムを設定する機能がありません。
ググって以下の2通りの方法を見つけました。

  1. CloudWatch Metric Math 関数を利用 (参考: CloudWatch アラームのダウンタイム(特定期間の発報抑止)を Metric Math を使用して実現してみた)
  2. Lambda + CloudWatch Eventsを利用 (参考: CloudWatchAlarmにLambdaでダウンタイム設定をいれてみた)

1は余計なリソースを作成しなくてすむ方法ですが、指定時間のメトリクスを欠落させることになるため、今回の私の目的では2を採用しました。
やったことは2の記事とほぼ同じですが、以下の点は新規性ということで一応私の作業ログをインターネットの肥やしにします。先行資料があったらすみません。

  • おそらく2の記事が書かれた頃(2020.10)からコマンドが変わっておりAWSのリファレンスと差異がある
  • CloudWatch Eventsではなく後継であるAmazon EventBridgeを利用した

事前確認

初めにCLIで、無効化/有効化した際のステータス表示を確認しました。
参考: Command Reference

無効化&確認
$ aws cloudwatch disable-alarm-actions --alarm-names "my_alarm_name"
$ aws cloudwatch describe-alarms --alarm-names "my_alarm_name"
{
    "MetricAlarms": [
        {
            "AlarmName": "Smy_alarm_name",
	    :
            "ActionsEnabled": false,
	    :
有効化&確認
$ aws cloudwatch enable-alarm-actions --alarm-names "my_alarm_name"
$ aws cloudwatch describe-alarms --alarm-names "my_alarm_name"
{
    "MetricAlarms": [
        {
            "AlarmName": "Smy_alarm_name",
	    :
            "ActionsEnabled": true,
	    :

Lambda+EventBridgeでスケジューリング

完成図

EventBridgeでダウンタイムの開始(disable)/終了(enable)ルールをそれぞれ作成し、Lambda Functionを実行します。
enableに戻すのに失敗して気づかないままずっとdisableになってしまうとまずいので、失敗時にSNSに通知します。

Lambda Functionの作成

Python 3.8

import boto3

# Create CloudWatch client
cloudwatch = boto3.client('cloudwatch')

def lambda_handler(event, context):
    # define param
    alarm_action = event['alarm_action']
    alarm_name = event['alarm_name']
    
    # Actions
    if alarm_action == 'enable':
        cloudwatch.enable_alarm_actions(
            AlarmNames=[(alarm_name)],
            )
    elif alarm_action == 'disable':
        cloudwatch.disable_alarm_actions(
            AlarmNames=[(alarm_name)],
            )

以下でテストします。

無効化
{
  "alarm_action": "disable",
  "alarm_name": "my_alarm_name"
}

cloudwatch describe-alarmsコマンドと、念のためコンソールでも確認します。

うまくいきました。

有効化
{
  "alarm_action": "enable",
  "alarm_name": "my_alarm_name"
}


こちらも大丈夫そうです。

SNS設定

SNS Topicを作成してチャットに飛ばすようにしました。

IAMロール設定

Lambda実行用のIAMロールを以下のように設定するとともに対象のリソースを絞ります。

  • CloudWatch:
    • DisableAlarmActions
    • EnableAlarmActions
  • CloudWatch Logs:
    • CreateLogGroup
    • CreateLogStream
    • PutLogEvents
  • SNS:
    • Publish

Amazon EventBridge

Amazon EventBridge でルールを作成します。
イベントスケジュールはcronで設定して、jsonでパラメータを入れます。

テスト

実行時間(cronで指定した時間)を適当に変えてイベントを発生させます。

うまくいきました。やったー

(Lambdaのテストパラメータにenable/disable以外の値を入れるなどして失敗させ、失敗時にSNSに通知されることも確認します。)

参考

Discussion