CloudWatch Alarmのステート変更時にEventBridge経由でStep Functionsステートマシンを起動してみた(AWS CDK v2)

2022.05.24

こんにちは、CX事業本部 IoT事業部の若槻です。

AWSで新しい機能が追加されたり、また自分が見つけたりして、同じことを実現するシステムを以前よりシンプル(マネージド)な構成で実現できた時って小躍りしたくなりますよね。

今回は、CloudWatch Alarmのステート変更時にEventBridge経由でStep Functionsステートマシンを起動する構成をAWS CDK v2で作ってみました。

EventBridgeを使うことにより、同じシステムを以前紹介した時の構成よりもシンプルにすることができました。

やってみた

下記のような構成を作成してみます。

CDKコード

AWS CDKのStack定義のコードです。

lib/process-stack.ts

import { Construct } from 'constructs';
import {
  aws_cloudwatch,
  aws_events,
  aws_events_targets,
  aws_stepfunctions,
  Duration,
  Stack,
  StackProps,
} from 'aws-cdk-lib';

export class ProcessStack extends Stack {
  constructor(scope: Construct, id: string, props: StackProps) {
    super(scope, id, props);

    //Step Functions State Machine
    const testStateMachine = new aws_stepfunctions.StateMachine(
      this,
      'testStateMachine',
      {
        stateMachineName: 'testStateMachine',
        definition: new aws_stepfunctions.Choice(this, 'whetherAlarmOrNot')
          .when(
            aws_stepfunctions.Condition.stringEquals(
              '$.detail.state.value',
              'ALARM'
            ),
            new aws_stepfunctions.Pass(this, 'Alarm occurs!')
          )
          .otherwise(new aws_stepfunctions.Pass(this, 'No Alarm.')),
      }
    );

    //CloudWatch Alarm
    const testAlarm = new aws_cloudwatch.Alarm(this, 'testAlarm', {
      alarmName: 'testAlarm',
      metric: new aws_cloudwatch.Metric({
        namespace: 'participants',
        metricName: 'area_01',
        dimensionsMap: { Site: 'A' },
        statistic: aws_cloudwatch.Statistic.MAXIMUM,
        period: Duration.minutes(1),
      }),
      evaluationPeriods: 10,
      threshold: 5,
      comparisonOperator:
        aws_cloudwatch.ComparisonOperator.LESS_THAN_OR_EQUAL_TO_THRESHOLD,
      treatMissingData: aws_cloudwatch.TreatMissingData.MISSING,
    });

    //EventBridge Rule
    new aws_events.Rule(this, 'testAlarmRule', {
      ruleName: 'testAlarmRule',
      eventPattern: {
        source: ['aws.cloudwatch'],
        detailType: ['CloudWatch Alarm State Change'],
        resources: [testAlarm.alarmArn],
      },
      targets: [new aws_events_targets.SfnStateMachine(testStateMachine)],
    });
  }
}
  • ステートマシンは、起動トリガーとなったAlarmの変更先ステートがALARMがそうでないかで分岐するワークフローとしています。
  • EventBridge Ruleのイベントパターンは、CloudWatch Alarmイベントを使用したい場合はアラームのページから指定するべきパターンが確認できます。

CDK Deployしてリソースをデプロイします。

動作確認

アラームのステートをALARMに手動変更します。

$ aws cloudwatch set-alarm-state \
  --alarm-name testAlarm \
  --state-value ALARM \
  --state-reason "test"

CloudWatch AlarmのステートがINSUFFICIENT_DATAからALARMに変更されました。

ステートマシンの実行詳細を見ると、Graph viewはアラーム発生時の分岐となっています。

実行のInputは次のようになります。detailでは今回(state)と前回(previousState)のステートやメトリクスの情報が含まれています。これらの情報を元にステートマシン内で柔軟な処理を行えそうですね。

{
  "version": "0",
  "id": "148399e2-88ac-c35a-3648-d2cc2e8b06b1",
  "detail-type": "CloudWatch Alarm State Change",
  "source": "aws.cloudwatch",
  "account": "XXXXXXXXXXXX",
  "time": "2022-05-24T14:25:01Z",
  "region": "ap-northeast-1",
  "resources": [
    "arn:aws:cloudwatch:ap-northeast-1:XXXXXXXXXXXX:alarm:testAlarm"
  ],
  "detail": {
    "alarmName": "testAlarm",
    "state": {
      "value": "ALARM",
      "reason": "test",
      "timestamp": "2022-05-24T14:25:01.829+0000"
    },
    "previousState": {
      "value": "INSUFFICIENT_DATA",
      "reason": "Insufficient Data: 10 datapoints were unknown.",
      "reasonData": "{\"version\":\"1.0\",\"queryDate\":\"2022-05-24T14:13:19.816+0000\",\"statistic\":\"Maximum\",\"period\":60,\"recentDatapoints\":[],\"threshold\":5.0,\"evaluatedDatapoints\":[{\"timestamp\":\"2022-05-24T14:12:00.000+0000\"},{\"timestamp\":\"2022-05-24T14:11:00.000+0000\"},{\"timestamp\":\"2022-05-24T14:10:00.000+0000\"},{\"timestamp\":\"2022-05-24T14:09:00.000+0000\"},{\"timestamp\":\"2022-05-24T14:08:00.000+0000\"},{\"timestamp\":\"2022-05-24T14:07:00.000+0000\"},{\"timestamp\":\"2022-05-24T14:06:00.000+0000\"},{\"timestamp\":\"2022-05-24T14:05:00.000+0000\"},{\"timestamp\":\"2022-05-24T14:04:00.000+0000\"},{\"timestamp\":\"2022-05-24T14:03:00.000+0000\"}]}",
      "timestamp": "2022-05-24T14:13:19.820+0000"
    },
    "configuration": {
      "metrics": [
        {
          "id": "96c07b31-ffe0-59ae-6609-f8e608d124f7",
          "metricStat": {
            "metric": {
              "namespace": "participants",
              "name": "area_01",
              "dimensions": {
                "Site": "A"
              }
            },
            "period": 60,
            "stat": "Maximum"
          },
          "returnData": true
        }
      ]
    }
  }
}

また、ステートがALARMからINSUFFICIENT_DATAへ戻った際にもEventBridge Ruleは発行されます。

それにより起動された実行の詳細は次のようになります。Graph viewはアラームでない時の分岐となっています。

実行のInputでは先程と同様な情報を取得できます。

{
  "version": "0",
  "id": "20f3f515-0f1d-e497-4f94-11a6d77a98e0",
  "detail-type": "CloudWatch Alarm State Change",
  "source": "aws.cloudwatch",
  "account": "XXXXXXXXXXXX",
  "time": "2022-05-24T14:25:19Z",
  "region": "ap-northeast-1",
  "resources": [
    "arn:aws:cloudwatch:ap-northeast-1:XXXXXXXXXXXXs:alarm:testAlarm"
  ],
  "detail": {
    "alarmName": "testAlarm",
    "state": {
      "value": "INSUFFICIENT_DATA",
      "reason": "Insufficient Data: 10 datapoints were unknown.",
      "reasonData": "{\"version\":\"1.0\",\"queryDate\":\"2022-05-24T14:25:19.816+0000\",\"statistic\":\"Maximum\",\"period\":60,\"recentDatapoints\":[],\"threshold\":5.0,\"evaluatedDatapoints\":[{\"timestamp\":\"2022-05-24T14:24:00.000+0000\"},{\"timestamp\":\"2022-05-24T14:23:00.000+0000\"},{\"timestamp\":\"2022-05-24T14:22:00.000+0000\"},{\"timestamp\":\"2022-05-24T14:21:00.000+0000\"},{\"timestamp\":\"2022-05-24T14:20:00.000+0000\"},{\"timestamp\":\"2022-05-24T14:19:00.000+0000\"},{\"timestamp\":\"2022-05-24T14:18:00.000+0000\"},{\"timestamp\":\"2022-05-24T14:17:00.000+0000\"},{\"timestamp\":\"2022-05-24T14:16:00.000+0000\"},{\"timestamp\":\"2022-05-24T14:15:00.000+0000\"}]}",
      "timestamp": "2022-05-24T14:25:19.821+0000"
    },
    "previousState": {
      "value": "ALARM",
      "reason": "test",
      "timestamp": "2022-05-24T14:25:01.829+0000"
    },
    "configuration": {
      "metrics": [
        {
          "id": "96c07b31-ffe0-59ae-6609-f8e608d124f7",
          "metricStat": {
            "metric": {
              "namespace": "participants",
              "name": "area_01",
              "dimensions": {
                "Site": "A"
              }
            },
            "period": 60,
            "stat": "Maximum"
          },
          "returnData": true
        }
      ]
    }
  }
}

おわりに

CloudWatch Alarmのステート変更時にEventBridge経由でStep Functionsステートマシンを起動する構成をAWS CDK v2で作ってみました。

EventBridgeのことを分かっているつもりでまだまだ全然活用できていませんでした。同じことをするのにLambda関数が1つ不要になるってすごく嬉しいですね。

参考

以上