ネストされたAWS SAM アプリケーションのサンプル その1
概要
AWS SAM を使用して、ネストされたスタックのアプリケーションを構築するサンプルを作成してみましたので紹介します。
本記事では、S3 → EventBridge → Lambda の流れで、S3 にオブジェクトを作成したイベントを使って Lambda をトリガーするという、
シンプルな構成でのCloudFormationのサンプルを解説します。  
新規にS3を作成する場合は、通知先のSQSも同時に作れば簡単に連携できるのですが、既存の S3 にイベントを追加したい場合、
手間が多そうだったので、それも見越して EventBridge を使用してみることにしました。
作ったもの
ソースコード
以下のリポジトリで公開しています。
プロジェクト構造
アプリケーションは、次の 3 つの SAM テンプレートで構成されます。
- template.yaml: 親テンプレート。ネストされたスタックをオーケストレーションするメインテンプレート。
- s3-eventbridge-template.yaml: 子テンプレート1。S3 バケットと EventBridge のカスタムイベントバスを作成し、
 default イベントバスからカスタムイベントバスへの転送ルールを定義。
- lambda-template.yaml: 子テンプレート2。トリガーされる Lambda 関数を定義。
アーキテクチャ
S3, EventBridge, Lambda, および必要な IAM Role となります。
- S3 Bucket を作成します。- S3 には、ファイルアップロード時に S3 イベントを Amazon EventBridge へ送信するよう設定します。
- このイベント通知は Default event busへ送信されます。
 
- Custom event busを作成します。- EventBridge にルールを設定し、 Default event bus から、Custom event busへイベントを転送するようルール設定します。
 
- Lambda 関数を作成します。- Custom event bus にイベントを Lambda 関数へルーティングするようルールを設定します。
 
構成図
 
各テンプレートの説明
親テンプレート (template.yaml)
ネストされたスタックをオーケストレーションするメインテンプレートです。AWS::CloudFormation::Stack を使用して、各子テンプレートを呼び出します。
| 1 | AWSTemplateFormatVersion: '2010-09-09' | 
S3EventBridgeStack
このリソースで S3 と EventBridge の Custom event bus を作成します。
LambdaStack
このリソースで Lambda 関数を作成します。
Custom event bus の名前をパラメータとして渡すのは、トリガーを設定する必要があるためです。
S3 バケット名をパラメータとして渡すのは、Lambda 関数にバケットへのアクセス権を設定するためです。
依存関係があるスタックを DependsOn: S3EventBridgeStack のように関連付けます。
これにより S3EventBridgeStack が生成されてから、 LambdaStack を生成するよう順序付けることができます。
子テンプレート1 (s3-eventbridge-template.yaml)
S3 bucket と Custom event bus および、 Default event bus からの転送するルールを設定するテンプレートです。
| 1 | AWSTemplateFormatVersion: '2010-09-09' | 
MyS3Bucket
S3 から EventBridge へのイベント通知を有効にするため、以下のパラメータを設定します。EventBridgeEnabled: true
これにより、この S3 バケットのイベントが Default event bus へ通知されます。
MyEventBus
Custom event bus を作成します。
ForwardS3PutObjectRule
Default event bus から Custom event bus へ、イベント通知を転送するルールを設定します。EventPattern の source で S3 のイベント通知に限定します。detail-type で Object Created に絞り、detail で今回作成したバケットのイベントのみ転送する設定をします。
ForwardEventRole
Default event bus から Custom event bus へのアクセス許可を設定します。
子テンプレート2 (lambda-template.yaml)
Lambda 関数と Custom event bus へトリガーを設定するテンプレートです。
| 1 | AWSTemplateFormatVersion: '2010-09-09' | 
MyLambdaFunction
Lanbda 関数を作成します。Events でトリガーを今回作成した Custom event bus からの通知に設定しています。
親子間や子子間のパラメータと出力の引き渡し
親テンプレートでは、子テンプレートに情報を渡すために、Parameters を使用します。
子テンプレートでは、生成したリソース名やARNを親テンプレートに渡すために Outputs を使用します。
そして、親テンプレート内で !GetAtt などを使用して子テンプレートの出力を取得し、後続の子テンプレートへパラメータを渡します。
例:
親テンプレートは、子テンプレート1の出力を、子テンプレート2のパラメータとして渡しています。
- 親テンプレートから抜粋 - 1 
 2
 3- Parameters: 
 EventBusName: !GetAtt S3EventBridgeStack.Outputs.EventBusName
 S3BucketName: !GetAtt S3EventBridgeStack.Outputs.S3BucketName
- 子テンプレート1のOutput 
| 1 | Outputs: | 
- 子テンプレート2のParameter
| 1 | Parameters: | 
ネスト構造にすることにより、テンプレートの Outputs を他のテンプレートの Parameters へ簡単に連携できます。
サンプルの使用方法
前提条件
このサンプルを実行するには、以下の権限およびツールが必要です。
- 適切な権限を持つ AWS アカウント
- AWS CLI
- AWS SAM CLI
デプロイ方法
このアプリケーションをデプロイする手順は以下のようになります。
- このリポジトリをクローンします。 - 1 
 2- git clone https://github.com/hiroaki-ma1203/aws-sam-samples.git 
 cd aws-sam-samples/nested-sam-app-1
- SAM アプリケーションをビルドします。 - 1 - sam build 
- SAM アプリケーションをデプロイします。 - 1 - sam deploy --guided - 指示に従ってデプロイメント構成を設定します。 
動作確認
- デプロイ後、作成された S3 バケットにファイルをアップロードしてください。
- 発生した S3 イベントは、EventBridge を介して Lambda 関数をトリガーします。
- AWS コンソールまたは CloudWatch Logs を通じて Lambda 関数の実行結果を確認してください。
カスタマイズ
必要に応じて、テンプレートや Lambda 関数の実装を変更してください。
- template.yaml: ネストされたスタックを追加や変更する場合は、メインのテンプレートを変更。
- s3-eventbridge-template.yaml: S3 バケット設定や EventBridge ルールを変更(例: ファイル削除時にもイベント通知するなど)。
- lambda-template.yaml: Lambda 関数のランタイムや構成を変更。
- src/app.py: Lambda 関数の実装を変更。
環境の削除
このアプリケーションによって作成されたすべてのリソースを削除するには、以下の操作を行ってください。
- S3 バケット内のファイルを削除します。 - 1 
 2
 3
 4- aws cloudformation describe-stacks \ 
 --stack-name nested-sam-app-1 --query "Stacks[0].Outputs[?OutputKey=='S3BucketName'].OutputValue" \
 --output text \
 | xargs -I {} aws s3 rm s3://{} --recursive
- スタックを削除します。 - 1 - sam delete