😺

【AWS SAM】EventBridgeでLambdaを定期実行するテンプレートの書き方

2023/11/29に公開
1

背景

  • EventBridgeを使ってLambdaを定期実行するときに、CloudFormationテンプレートでは主に2つの書き方がありどちらにするか迷ったため、それぞれのメリット・デメリットと記述方法を比較してみました。

比較

1. 組み合わせテンプレートの使用

Lambdaの定義中にEventBridgeRuleの定義を含める方法です。

メリット

  • コードの記述量が少なく、管理するテンプレートも減らせる。
  • YAML では、イベントパターンを定義するだけでよく、AWS SAMが必要なアクセス許可を持つ IAM ロールを自動的に作成してくれる。

デメリット

  • LambdaとEventBridgeのコードが密結合になっているため、別々に管理できずリソース(特にEventBridgeRule)を認識しずらい。
  • IAMロールなど細かい制御ができない。
  • 一つのルールでは一つのLambdaしか指定できない。(ベストプラクティス)

コード例

template.yaml
Resources:
  HelloWorldFunction: # Lambdaの定義
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: hello-world/
      Handler: hello-world
      Runtime: python3.10
      Architectures:
        - x86_64
      Events: # Lambdaの定義内でEventBridgeRuleを定義
        ScheduledFunction:
          Type: ScheduleV2
          Properties:
            ScheduleExpression: cron(0/5 * * * ? *) # 5分毎にトリガー
            ScheduleExpressionTimezone: "Asia/Tokyo" # 日本のタイムゾーンを考慮
            State: ENABLED
	    Name: dev-hoge-hello-schedule-lambda
            Description: hello schedule

2. 分離テンプレート

Lambdaの定義とEventBridgeRuleの定義を分離する方法です。

メリット

  • LambdaとEventBridgeのコードが疎結合になっているため、リソース(EventBridgeRule)の数を把握しやすく、EventBridgeのスタックに統合したりと管理しやすい。
  • 一つのルールから複数のLambdaを指定できる。
    -AWS SAM テンプレートの外部のリソースに接続している場合でも対応できる。

デメリット

  • コードの記述量と管理するテンプレートが増える。
  • 必要なアクセス許可を持つ IAM ロールの定義を自分で行う必要がある。

コード例

template.yaml
Resources:
  HelloWorldFunction: # Lambdaの定義
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: hello-world/
      Handler: hello-world
      Runtime: python3.10
      Architectures:
        - x86_64

  EventBridgeRule: # Lambdaの定義とは別にEventBridgeRuleを定義
    Type: AWS::Events::Rule
    Properties: 
      EventBusName: default
      Name: dev-hoge-hello-schedule-lambda
      Description: hello schedule
      ScheduleExpression: cron(0/5 * * * ? *) # 5分毎にトリガー
      State: ENABLED
      Targets: 
        - Arn: !GetAtt LambdaFunction.Arn # トリガー対象のLambdaのArnを指定
          Id: LambdaFunction #  トリガー対象のLambdaのidを指定

  PermissionForEventsToInvokeLambda: # EventBridgeRuleからLambdaをトリガーするためのPermissionを定義
    Type: AWS::Lambda::Permission
    Properties:
      FunctionName: !Ref HelloWorldFunction
      Action: lambda:InvokeFunction
      Principal: events.amazonaws.com
      SourceArn: !GetAtt 'EventBridgeRule.Arn'

結論

  • 1 つのルールによって 1 つの Lambda 関数が呼び出されるパターンでは、組み合わせテンプレートがお勧め。EventBridgeRuleを一か所でまとめて管理したいという要望がなければこの方法がシンプルで良さそう。
  • 複雑なルーティングロジックがある場合、または AWS SAM テンプレートの外部のリソースに接続している場合には、分離テンプレートの利用が推奨されるようです。

補足

  • 通常は"Events/Properties"には"Schedule"を設定するが、タイムゾーンを考慮する場合は"ScheduleExpression"を設定し、"ScheduleExpressionTimezone"に想定するタイムゾーンを記載する必要がある。

参考

https://docs.aws.amazon.com/ja_jp/eventbridge/latest/userguide/eb-use-sam.html
https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/sam-property-function-eventbridgerule.html
https://docs.aws.amazon.com/ja_jp/eventbridge/latest/userguide/eb-cron-expressions.html
https://docs.aws.amazon.com/ja_jp/eventbridge/latest/userguide/eb-rules-best-practices.html
https://zenn.dev/robon/articles/81f4cf35b3a32c
https://qiita.com/baku2san/items/2514ce485731ff7068c5
https://zenn.dev/nakam_aws/articles/cc37dcd8ab8792

Discussion