「AWS無料相談会」をオンラインで開催中

サーバーレスで活用する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
アプリケーションをネストできることに注目されていますが、
ローカルにあるテンプレートをネストすることも可能です。

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

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のバケット名を受け渡しています。

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)

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)

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のオプションを付与する必要があります。

#!/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なサーバーレスシステムに携わりたいエンジニア大募集

MMMのサーバーレスへの取り組みについては以下でご紹介しています。ぜひご覧ください。

サーバーレスアーキテクチャ(AWS Lambda)