CloudFormation テンプレートが肥大化したので分割したいです。方法を教えてください

2021.10.06

困っていた内容

CloudFormation でインフラ環境を構築していますが、テンプレートが非常に大きくなりました。可読性を高めるためにテンプレートファイルを分割したいのですが、分割する方法を教えてください。 なお、単純にファイルを分割するのではなく、一回の実行で複数のテンプレートがリリースされるようにしたいです。

どう対応すればいいの?

ネスト機能をお使いください。

ネストされたスタックの操作 - AWS CloudFormation

CloudFormation のネスト機能を使用することで、複数のテンプレートを一度に実行できます。具体的には、テンプレート内でAWS::CloudFormation::Stackタイプのリソースとして別のテンプレート(S3 URL)を定義すると、実行時に指定したテンプレートも実行されます。

# 例
Resources:
  networkStack:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: <呼び出すテンプレートURL>

やってみた

先日使用した ECS タスクの停止理由を CloudWatch Logs に保管するテンプレートを使用します。

テンプレートでは、 EventBridge と CloudWatch Logs を作成しますが、EventBridge 部分を別ファイルに分割します。

  • メインテンプレート(CloudWatch Logs):ecs-stopped-tasks-cwlogs.yml
  • サブテンプレート(EventBridge):ecs-stopped-tasks-cwlogs_eventrule.yml

元ファイル

AWSTemplateFormatVersion: 2010-09-09
Description: Deploys the resources needed to store events of Amazon ECS stopped tasks in CloudWatch Logs

Parameters:
  CWLogGroupName:
    Type: String
    Description: The CloudWatch log group name to store the events
    Default: /aws/events/ECSStoppedTasksEvent
  CWLogGroupRetention:
    Type: Number
    Description: The number of days to retain the events in the log group
    Default: 30

Resources:
  EventRule:
    Type: AWS::Events::Rule
    Properties:
      Name: ECSStoppedTasksEvent
      Description: Triggered when an Amazon ECS Task is stopped
      EventPattern:
        source:
          - aws.ecs
        detail-type:
          - ECS Task State Change
        detail:
          desiredStatus:
            - STOPPED
          lastStatus:
            - STOPPED
      State: ENABLED
      Targets:
        - Arn: !GetAtt LogGroup.Arn
          Id: ECSStoppedTasks

  LogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: !Ref CWLogGroupName
      RetentionInDays: !Ref CWLogGroupRetention

分割後

メインテンプレート

AWSTemplateFormatVersion: 2010-09-09
Description: Deploys the resources needed to store events of Amazon ECS stopped tasks in CloudWatch Logs

Parameters:
  CWLogGroupName:
    Type: String
    Description: The CloudWatch log group name to store the events
    Default: /aws/events/ECSStoppedTasksEvent
  CWLogGroupRetention:
    Type: Number
    Description: The number of days to retain the events in the log group
    Default: 30
  EventRuleTemplateURL:
    Type: String
    Description: Template URL for EventRule

Resources:
  EventRule:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: !Ref EventRuleTemplateURL
      Parameters:
        CWLogGroupARN: !GetAtt LogGroup.Arn

  LogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: !Ref CWLogGroupName
      RetentionInDays: !Ref CWLogGroupRetention

サブテンプレート

AWSTemplateFormatVersion: 2010-09-09
Description: Deploys the resources needed to store events of Amazon ECS stopped tasks in CloudWatch Logs

Parameters:
  CWLogGroupARN:
    Type: String

Resources:
  EventRule:
    Type: AWS::Events::Rule
    Properties:
      Name: ECSStoppedTasksEvent
      Description: Triggered when an Amazon ECS Task is stopped
      EventPattern:
        source:
          - aws.ecs
        detail-type:
          - ECS Task State Change
        detail:
          desiredStatus:
            - STOPPED
          lastStatus:
            - STOPPED
      State: ENABLED
      Targets:
        - Arn: !Ref CWLogGroupARN
          Id: ECSStoppedTasks

TemplateURLについて

分割したテンプレートは、あらかじめ S3 にアップロードしておく必要があり、アップロード先のURLを元テンプレートに記載する必要があります。
今回はテンプレート内ではなく、スタック作成時にパラメーターとしてテンプレートURLを指定します。

テンプレートアップロードとデプロイ

テンプレートファイルを S3 にアップロードします。

アップロードしたテンプレート(メイン・サブ)のURLをメモします。

AWS CloudFormation コンソールを開き、「スタックの作成」をクリックします。

「Amazon S3 URL」を選択し、「Amazon S3 URL」にメインテンプレートのURL(https://XXX.s3.ap-northeast-1.amazonaws.com/cf-templates/ecs-stopped-tasks-cwlogs.yml)を入力。「次へ」をクリックします。

任意の名前を入力し、「EventRuleTemplateURL」にサブテンプレートのURL(https://XXX.s3.ap-northeast-1.amazonaws.com/cf-templates/ecs-stopped-tasks-cwlogs_eventrule.yml)を指定します。
必要に応じてログの保管先(CloudWatch Logs のロググループ名)と保持期間(単位:日)を変更します。

次の項目にチェックを入れ、「スタックの作成」をクリックします。

  • AWS CloudFormation によって IAM リソースがカスタム名で作成される場合があることを承認します。
  • AWS CloudFormation によって、次の機能が要求される場合があることを承認します: CAPABILITY_AUTO_EXPAND

ステータスが「CREATE_COMPLETE」なったことを確認します。

ネスト関係のスタック表記

サブテンプレートには「ネストされた」と表記されます。 また「概要」欄にメインテンプレートが記載されます。

ネスト関係のスタック削除

ネストを使用したスタックを削除する場合はメインテンプレート側から削除を実行してください。

サブテンプレートだけも削除されますが、非推奨となります。(削除時に警告が表示されます)

参考資料