この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
Lambdaを定期実行する仕組みをよく作ります。
- 1時間に1回起動する
- 1日に1回起動する
これらのLambdaが「起動しなかった場合」に通知が欲しくなったので、CloudWatch Alarmを作ってみました。
実際にLambdaが起動しない事象に遭遇したことは無いですが、このAlarmがあると、「ちゃんと起動しているよね?」というモヤモヤが解消されます。万が一に気づける保険ですね。
おすすめの方
- 定期実行するLambdaが「起動しなかった場合」のCloudWatch Alarmを作りたい方
定期実行するLambdaとCloudWatch Alarmを作成する
sam init
sam init \
--runtime python3.8 \
--name Lambda-No-Start-Alarm-Sample \
--app-template hello-world \
--package-type Zip
SAMテンプレート
CloudWatch Alarmは、Period(期間) * EvaluationPeriods(評価期間)
を1時間または1日にしています。
- 1時間に1回起動するLambda
- Period(期間): 5分
- EvaluationPeriods(評価期間): 12
- Statistic(統計): Sum
- 1日に1回起動するLambda
- Period(期間): 5分
- EvaluationPeriods(評価期間): 288
- Statistic(統計): Sum
これにより、次の条件を満たすとアラーム状態になります。
- 「12データポイント(12個*5分=60分) の Invocationsの合計」が1より小さい
- 「288データポイント(288個*5分=24時間) の Invocationsの合計」が1より小さい
Lambdaが起動しないことを確認したいので、「Invocationsメトリクスが無ければNG」です。 期間を5分から1分にすることも可能ですが、「Invocationsメトリクス」の到着が少し遅れるとすぐにアラーム状態になるため、余裕を見て5分にしています。 期間を60分にした場合も、「Invocationsメトリクス」の到着具合によってアラーム状態にならない可能性があります。
template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Lambda-No-Start-Alarm-Sample
Resources:
HelloWorldFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: hello_world/
Handler: app.lambda_handler
Runtime: python3.8
Timeout: 5
Events:
HelloWorld:
Type: Schedule
Properties:
Schedule: cron(0 */1 * * ? *) # 毎時0分に実行
Enabled: true
HelloWorldFunctionLogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Sub /aws/lambda/${HelloWorldFunction}
HelloWorldFunction2:
Type: AWS::Serverless::Function
Properties:
CodeUri: hello_world/
Handler: app.lambda_handler
Runtime: python3.8
Timeout: 5
Events:
HelloWorld:
Type: Schedule
Properties:
Schedule: cron(0 3 * * ? *) # 毎日12時に実行(JST)
Enabled: true
HelloWorldFunctionLogGroup2:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Sub /aws/lambda/${HelloWorldFunction2}
HelloWorldFunctionInvocationsAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
Namespace: AWS/Lambda
Dimensions:
- Name: FunctionName
Value: !Ref HelloWorldFunction
MetricName: Invocations
ComparisonOperator: LessThanThreshold
Period: 300
EvaluationPeriods: 12
Statistic: Sum
Threshold: 1
TreatMissingData: breaching
# AlarmActions:
# - !Ref any-sns-topic
# OKActions:
# - !Ref any-sns-topic
HelloWorldFunction2InvocationsAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
Namespace: AWS/Lambda
Dimensions:
- Name: FunctionName
Value: !Ref HelloWorldFunction2
MetricName: Invocations
ComparisonOperator: LessThanThreshold
Period: 300
EvaluationPeriods: 288
Statistic: Sum
Threshold: 1
TreatMissingData: breaching
# AlarmActions:
# - !Ref any-sns-topic
# OKActions:
# - !Ref any-sns-topic
Lambdaコード
Lambdaが起動すればOKなので、何もしません。
app.py
def lambda_handler(event, context):
pass
デプロイ
デプロイします。
sam build
sam package \
--output-template-file packaged.yaml \
--s3-bucket cm-fujii.genki-deploy
sam deploy \
--template-file packaged.yaml \
--stack-name Lambda-No-Start-Alarm-Sample-Stack \
--s3-bucket cm-fujii.genki-deploy \
--capabilities CAPABILITY_NAMED_IAM \
--no-fail-on-empty-changeset
デプロイ直後は過去に動いたLambdaが無いので、アラーム発生状態になります。落ち着くまでしばらく待ちます。
1時間に1回起動するLambdaのアラームを確認する
アラーム未発生を確認する
1時間ごとにLambdaが起動しているため、アラーム状態ではありません。
Lambdaの定期実行を無効化して、アラーム発生を確認する
CloudWatch Events(EventBridge)のルールを無効化します。 Lambdaが実行するはずの時刻をすぎると、アラーム状態になりました。
Lambdaの定期実行を有効にして、アラーム解除を確認する
CloudWatch CloudWatch Events(EventBridge)のルールを有効に戻し、Lambdaが動くまで待つと、アラーム状態が解除されました。
履歴の様子は下記です。
1日に1回起動するLambdaのアラームを確認する
アラーム未発生を確認する
1日ごとにLambdaが起動しているため、アラーム状態ではありません。
Lambdaの定期実行を無効化して、アラーム発生を確認する
CloudWatch Events(EventBridge)のルールを無効化します。 Lambdaが実行するはずの時刻をすぎると、アラーム状態になりました。
Lambdaの定期実行を有効にして、アラーム解除を確認する
CloudWatch Events(EventBridge)のルールを有効に戻し、Lambdaが動くまで待つと、アラーム状態が解除されました。
履歴の様子は下記です。
さいごに
定期実行するLambdaが「起動しない場合」のアラームを作ってみました。「ちゃんと起動しているよね?」というモヤモヤが解消されるので、意外と役に立つと思います。