[アップデート] Amazon CloudWatch のアラームで、実行アクションに Lambda 関数を直接指定出来るようになりました

2023.12.23

いわさです。

Amazon CloudWatch のアラームではアラームの状態変更をトリガーとしたアクションを実行することが出来ます。
これまでは Amazon SNS への通知、Auto Scaling アクション(容量の変更)の実行、EC2 アクション(停止や再起動)、SSM アクション(OpsItem/インシデントの作成)を行うことが出来ていました。

本日のアップデートでこのアクションで新たに Lambda 関数を実行出来るようになりました。

従来はアラート発生時に Lambda によるカスタムアクションを実行したい場合は Amazon SNS トピックを経由して Lambda をサブスクライブさせて間接的に呼び出す必要がありましたが、直接統合出来るようになりました。

設定方法

設定方法は他のアクションを設定する流れと同じで、対象の CloudWatch Alarm のアクション設定画面で設定を行います。

次のように新たに「Lambda アクション」が追加されていることが確認出来ます。
参考までに、2023 年 11 月 21 日時点のアクション設定画面はこちらの記事で確認出来ます。

関数を設定する

適当な関数を作成し、アクションに指定みましょう。
実行されたか確認出来れば良いのでデフォルトで作成します。どういうイベントデータを受信するのか確認したいのでログ出力コードくらいは追加しました。

アクションで設定出来るのは次のような項目です。

従来同様にアラーム状態の何をトリガーにするのかを選択します。
また、この機能は別アカウントの関数呼び出しにも対応しています。権限周りは後述します。
あとは関数を指定し、オプションでバージョンあるいはエイリアスを指定出来ます。ありがたい。

CloudWatch アラームとしての設定はこれで OK です。

Lambda アクションを設定しアラームを発生させてみた

適当な関数をアクションに設定したので早速、次のように AWS CLI 経由で手動でアラーム状態に変更してみました。

アラーム状態に変わりました。

しかし、アラームの履歴画面を確認してみると次のエラーが発生していました。

アクション arn:aws:lambda:ap-northeast-1:123456789023:function:hoge1223lambda の実行に失敗しました。エラーが発生しました: "CloudWatch Alarms is not authorized to perform: lambda:InvokeFunction on the resource because no resource-based policy allows the lambda:InvokeFunction action"

Lambda 側にリソースベースポリシーが必要

そりゃそうかという感じですが Lambda 実行の権限周りを何も指定していませんでした。
アラーム側でサービスロールの指定はないので、Lambda 関数側でリソースベースでのポリシー設定が必要です。

Lambda のアクセス権限機能で次のようにリソースベースポリシーを追加します。
プリンシパルはlambda.alarms.cloudwatch.amazonaws.comになるようなのでこちらを指定しました。

もう一度アラーム状態を変更してみると、次は Lambda 関数のアクションが正常に実行されていることが確認出来ました。

Lambda 側のメトリクスでも実行されていることが確認出来ますね。

イベントログ

CloudWatch アラームから実行されるときのイベントログ内容を確認してみました。
トリガーされた時のアラームの状態だけでなく、変更前の状態も送信されていますね。
アラームで構成されている条件なども確認出来ました。

{
    "source": "aws.cloudwatch",
    "alarmArn": "arn:aws:cloudwatch:ap-northeast-1:123456789012:alarm:hoge1223vcpualarm",
    "accountId": "123456789012",
    "time": "2023-12-22T22:15:48.857+0000",
    "region": "ap-northeast-1",
    "alarmData": {
        "alarmName": "hoge1223vcpualarm",
        "state": {
            "value": "ALARM",
            "reason": "test",
            "timestamp": "2023-12-22T22:15:48.857+0000"
        },
        "previousState": {
            "value": "OK",
            "reason": "Threshold Crossed: 1 out of the last 1 datapoints [0.0 (22/12/23 22:00:00)] was not greater than the threshold (100.0) (minimum 1 datapoint for ALARM -> OK transition).",
            "reasonData": "{\"version\":\"1.0\",\"queryDate\":\"2023-12-22T22:05:15.507+0000\",\"startDate\":\"2023-12-22T22:00:00.000+0000\",\"statistic\":\"Average\",\"period\":300,\"recentDatapoints\":[0.0],\"threshold\":100.0,\"evaluatedDatapoints\":[{\"timestamp\":\"2023-12-22T22:00:00.000+0000\",\"sampleCount\":5.0,\"value\":0.0}]}",
            "timestamp": "2023-12-22T22:05:15.510+0000"
        },
        "configuration": {
            "metrics": [
                {
                    "id": "b2c649c4-bbdd-9e1f-e239-9535e3c67e12",
                    "metricStat": {
                        "metric": {
                            "namespace": "AWS/Usage",
                            "name": "ResourceCount",
                            "dimensions": {
                                "Resource": "vCPU",
                                "Service": "Fargate",
                                "Type": "Resource",
                                "Class": "Standard/OnDemand"
                            }
                        },
                        "period": 300,
                        "stat": "Average"
                    },
                    "returnData": true
                }
            ]
        }
    }
}

さいごに

本日は Amazon CloudWatch のアラームで、実行アクションに Lambda 関数を直接指定出来るようになったので使ってみました。

今までカスタムアクションを実行したい場合は Amazon SNS を経由する必要があったのですが、直接 Lambda を統合出来るようになったので、冗長な SNS トピックを除外出来そうです。リトライなどアクションの要件によっては引き続き SNS を間に挟むケースもありそうですけど。

Lambda のリソースベースポリシーの設定忘れのないように気をつけましょう。