サーバーレスで活用するCloudFormationのNested Applications

弊社のサーバレス開発事例にて利用している
Nested Applications についてご紹介いたします。

CloudFormationのリソース数の制限

AWS CloudFormation には制限があることをご存知でしょうか。
制限のほとんどは、上限解放することができない制限となっております。

重要な制限として、リソース数の制限があります。
リソースは一つのテンプレートに最大で200までしか作成することができません。

「テンプレートに記載したリソース数 = リソース数」
ではない

例えば、シンプルなAWS Lambdaをテンプレートに定義した場合、
下記2つのリソースが作成されます。

  • AWS::Lambda::Function
  • AWS::IAM::Role

テンプレートに記載したリソース数は
最終的に出力されるリソース数とは合致しません。
リソース数はテンプレートへの記載を増やす毎に、膨らんでいきます。
特にサーバーレスの場合はAWS Lambdaに対してのイベントソースとして
複数のAPIエンドポイントを紐づけるケースがあり、
すぐにリソース数がいっぱいになってしまうこともあります。

具体的なリソース数は、マネージメントコンソールから確認することができます

では、どのようにすればよいのでしょうか。
解決策を記載します。

Nested Applicationsを利用してネストされたスタックを作成する

AWS Serverless Application Model(SAM)は拡張されたフォーマットのため、
AWS::CloudFormation::Stack 定義を利用することができません。

代替手段として、 Nested Applicationsの
AWS::Serverless::Application が利用可能です。
Nested Applicationsを利用することで 最大で40,000
リソースを作成することが可能になります。
また、ネストされるテンプレートは自動的にS3にアップロードされます。

Nested Applicationsは Serverless Application Repository
アプリケーションをネストできることに注目されていますが、
ローカルにあるテンプレートをネストすることも可能です。

ローカルにあるテンプレートをネストする場合の記述例:

1
2
3
4
5
6
7
Transform: AWS::Serverless-2016-10-31

Resources:
applicationaliasname:
Type: AWS::Serverless::Application
Properties:
Location: ../my-other-app/template.yaml

Nested Applicationsを利用して、サーバーレスのスタックを作成

それでは、実際にやってみましょう。
サンプルは下図のフォルダ構成となります。

筆者本人のGitHubアカウントにてリポジトリも公開しておりますので、
よろしければご参照下さい。

テンプレートファイル(template.yml)

テンプレートファイルは AWS::Serverless::Application のリソースを定義し
ネストされたスタックを構築します。パラメータを受け渡すことも可能です。
下記の記述例では、 Parameters に定義された変数とS3のバケット名を受け渡しています。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31

Parameters:
Stage:
Type: String
Default: test

Resources:
app1:
Type: AWS::Serverless::Application
Properties:
Location: ./template_app1.yml
app2:
Type: AWS::Serverless::Application
Properties:
Location: ./template_app2.yml
Parameters:
Stage: !Ref Stage
BucketTest: !Ref S3Bucket

S3Bucket:
Type: AWS::S3::Bucket
Properties:
BucketName: aws-sam-nested-application-test-bucket-0-001

ネストされたテンプレートファイル

サンプルでは、ネストされたテンプレートファイルのそれぞれに AWS::Serverless::Function のリソースを定義しました。
親のテンプレートファイルから受け渡されたパラメータも参照しています。

テンプレート1(template_app1.yml)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
AWSTemplateFormatVersion: 2010-09-09
Transform: AWS::Serverless-2016-10-31

Resources:
App1Function:
Type: AWS::Serverless::Function
Properties:
FunctionName: app1
CodeUri: handlers/app1
Handler: app1
Runtime: go1.x

S3Bucket001:
Type: AWS::S3::Bucket
Properties:
BucketName: aws-sam-nested-application-test-bucket-1-001

テンプレート2(template_app2.yml)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
AWSTemplateFormatVersion: 2010-09-09
Transform: AWS::Serverless-2016-10-31

Parameters:
Stage:
Type: String
Default: dev
BucketTest:
Type: String

Globals:
Function:
Runtime: go1.x
Timeout: 900
Environment:
Variables:
STAGE: !Ref Stage

Resources:
App2Function:
Type: AWS::Serverless::Function
Properties:
FunctionName: app2
CodeUri: handlers/app2
Handler: app2

S3Bucket2001:
Type: AWS::S3::Bucket
Properties:
BucketName: aws-sam-nested-application-test-bucket-2-001

デプロイ

デプロイは sam deploy の実行時にCAPABILITY_AUTO_EXPANDのオプションを付与する必要があります。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/bin/sh

# Create Package
sam package \
--template-file ./template.yml \
--output-template-file ./template-output.yml \
--s3-bucket aws-sam-nested-application-packages \
--profile temp_profile

# Deploy
sam deploy \
--template-file ./template-output.yml \
--stack-name aws-sam-nested-application \
--capabilities CAPABILITY_IAM CAPABILITY_AUTO_EXPAND \
--profile temp_profile

実行結果

Nested Applicationsの作成に成功していることが確認できました!

テンプレートの分割は計画的に

サーバレス開発の場合、気づいたらリソース数が逼迫しているということも
珍しくないと思います。中・大規模のサーバレス開発なら尚更です。
リソースの整理に伴う再作成が余儀なくされる前に、計画的にテンプレートを分割することをオススメいたします。

弊社ではGoとAWS SAMを活用したサーバレスアプリケーション開発実績があります

少しでもご興味を持ちましたら、弊社にエントリーしていただければ幸いです。
一緒に楽しく成長しあえる仲間を募集しています。

リモートワークでAWSなサーバーレスシステムに携わりたいエンジニア大募集

このエントリーをはてなブックマークに追加