kakakakakku blog

Weekly Tech Blog: Keep on Learning!

AWS CDK で Amazon CloudWatch Alarm の AWS Lambda アクションを設定する

2023年12月のリリースで Amazon CloudWatch Alarm から直接 AWS Lambda 関数を呼び出して,何かしらのアクション(復旧処理など)を実行できるようになった❗️今までは Amazon SNS と組み合わせて実行する必要があって,今までよりもシンプルに統合できるようになった.もちろん Amazon SNS でファンアウトすることによる拡張性も重要なので,個人的には AWS Lambda 関数を呼び出せれば十分というシンプルな場面で使えそうだなーと思っていたりする \( 'ω')/

aws.amazon.com

AWS CDK で試す

AWS CDK では v2.119.0 から Amazon CloudWatch Alarm の Lambda アクションを設定できるようになっていた❗️試してみたサンプルコード (TypeScript) を載せておく.

github.com

docs.aws.amazon.com

👾 sandbox-cdk-cloudwatch-lambda-stack.ts

Amazon SQS キューの ApproximateNumberOfMessagesVisible メトリクスを監視して,メッセージ数が増えたら Amazon CloudWatch Alarm から直接 AWS Lambda 関数を呼び出すようにした(Lambda 関数部分は割愛).今回のポイントは最後の addAlarmAction()aws_cloudwatch_actions.LambdaAction を指定しているところ❗️

import {
    Duration,
    Stack,
    StackProps,
    aws_cloudwatch,
    aws_cloudwatch_actions,
    aws_iam,
    aws_lambda,
    aws_sqs,
} from 'aws-cdk-lib';
import { Construct } from 'constructs';
import path = require('path');

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

        const queue = new aws_sqs.Queue(this, 'SandboxCdkQueue', {
            queueName: 'sandbox-cdk-cloudwatch-lambda-queue',
            visibilityTimeout: Duration.seconds(30),
            receiveMessageWaitTime: Duration.seconds(20),
        });

        const lambdaBasicExecutionRole = new aws_iam.Role(this, 'SandboxCdkLambdaBasicExecutionRole', {
            assumedBy: new aws_iam.ServicePrincipal('lambda.amazonaws.com'),
            managedPolicies: [
                aws_iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSLambdaBasicExecutionRole')
            ]
        });

        const lambda = new aws_lambda.Function(this, 'SandboxCdkLambdaFunction', {
            functionName: 'sandbox-cdk-cloudwatch-lambda-function',
            runtime: aws_lambda.Runtime.PYTHON_3_12,
            code: aws_lambda.Code.fromAsset(path.join(__dirname, '../functions/hello')),
            handler: 'app.lambda_handler',
            role: lambdaBasicExecutionRole,
        });

        const alarm = new aws_cloudwatch.Alarm(this, 'SandboxCdkCloudWatchAlarm', {
            alarmName: 'sandbox-cdk-cloudwatch-lambda-queue-alarm',
            metric: new aws_cloudwatch.Metric({
                namespace: 'AWS/SQS',
                metricName: 'ApproximateNumberOfMessagesVisible',
                dimensionsMap: {
                    QueueName: queue.queueName
                },
                period: Duration.seconds(60),
                statistic: aws_cloudwatch.Stats.SUM,
            }),
            threshold: 5,
            evaluationPeriods: 1,
        });

        alarm.addAlarmAction(new aws_cloudwatch_actions.LambdaAction(lambda));
    }
}

結果

Amazon SQS キューにメッセージを5件以上送信すると(今回は10件)アラーム状態になって AWS Lambda 関数が呼び出された👌

アラーム状態と AWS Lambda アクション設定

注意点

現時点(最新は v2.121.1)では同じ AWS Lambda 関数を複数の Amazon CloudWatch Alarm に紐付けるとエラーになってしまうという問題がある.プルリクエストも出ていて,近々直りそうな気もするけど注意しておくと良いかなーと👀

Error: There is already a Construct with name 'AlarmPermission' in Function [SandboxCdkLambdaFunction]