いわさです。
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 のリソースベースポリシーの設定忘れのないように気をつけましょう。