びくんびくんしながらコードを書く。

いしきひくい系エンジニアのらくがき帳

AWS CloudFormationで構成管理するときに役立つTips その2

本記事は ディップ with 全部俺 AdventCalendar 6日目の記事です。

昨日の記事に引き続きCloudFormationについてまとめていきます。
今回はテンプレートを分割したときに役立つものを中心に紹介します。

テンプレートの分割

CloudFormationを利用する場合、該当プロダクトの全てのResourcesを1つのテンプレートに集約するバターンと分割したテンプレートを管理するパターンに分かれると思います。

役割ごとのテンプレートに分割することによって1つのテンプレートの行数がヘリ可読性が上がるメリットがある反面、同じデータをMappingsで用意しなければいけないような煩雑さも出てきます。

どちらが良いかはメリット・デメリットを見た上で考えれば良いと思います。

詳細情報の取得 [GetAtt]

組み込み関数の中にはResources内の詳細情報を取得するようなものが存在します。
Resourcesの定義はしているものの、 !Refだと簡易な名前のみの取得になってしまう場合、 !GetAtt を試してみると良いように思います。※公式ドキュメントに利用した場合は何が帰ってくるかの記載がしてありますので、詳しくは公式ドキュメントを見てみてください。

ECSクラスターの定義の場合、まさにその通りで、!Ref だと定義した値のみが取得されます。 本来のArnを取得したい場合は !GetAtt を利用しなければなりません。

Resources:
  batchCluster:
    Type: AWS::ECS::Cluster
    Properties:
      ClusterName: hogehoge-batch-cluster

Outputs:
  BatchClusterArn:
    Description: "HogehogeBatchClusterArn"
    Value: !GetAtt batchCluster.Arn #この場合、フルのArnが返却される
    #Value: !Ref batchCluster       #この場合、hogehoge-batch-clusterが返却される
    Export:
      Name: hogehoge-batch-cluster-arn

Arnを後続のテンプレートに渡したい [Outputs:, Fn::ImportValue]

以前、ECSでCluster作成用のテンプレートを分割したときに、後続のテンプレートでスケジュール起動させるタスクのテンプレートを作成しようとしたときに、スケジュールはクラスターに紐づくようでクラスターのArnが必要になった。

一度クラスター作成用のCloudFormationを動かして出来上がったクラスターのarnをコピペしようかと一瞬思ったが、本番用とステージング用の環境があるのと、クラスターの作り直しのときにめんどくさそうな予感がしたので後続のテンプレートにどうにか渡せないものか調べました。

後続に受け渡すには下記のような記述を行うことで出来ます。

before.yml

Parameters:
  ENV:
    Type: String
    AllowedValues:
      - staging
      - production

Resources:
  batchCluster:
    Type: AWS::ECS::Cluster
    Properties:
      ClusterName: !Sub ${ENV}-hogehoge-batch-cluster

Outputs:
  BatchClusterArn:
    Description: "HogehogeBatchClusterArn"
    Value: !GetAtt batchCluster.Arn
    Export:
      Name: !Sub ${ENV}-hogehoge-batch-cluster-arn

after.yml ※一部抜粋

Resources:
  TaskScheduleEvents:
    Type: AWS::Events::Rule
    Properties:
      Name: !Sub ${ENV}-hogehoge-batch-schedule
      ScheduleExpression: 【ScheduleExpression設定】
      State: ENABLED
      Targets:
        - Id: !Sub ${ENV}-hogehoge-batch-schedule
          RoleArn: 【role arn】
          EcsParameters:
            TaskDefinitionArn: !Ref ECSTaskDefinition
            TaskCount: 1
            LaunchType: FARGATE
            NetworkConfiguration:
              AwsVpcConfiguration:
                AssignPublicIp: DISABLED
                SecurityGroups: 【SecurityGroup設定】
                Subnets: 【subnet設定】
          Arn: {"Fn::ImportValue": {"Fn::Sub": "${ENV}-hogehoge-batch-cluster-arn}}

テンプレートにOutputs項目を入れることでそこに設定された値をスタックから公開することが出来ます。
これを元に、次のテンプレートでは組み込み関数のImportValueを利用し、公開されたNameからValueを取得します。
公開するNameはアカウント内で共通になるようなので、重複するような名前の付け方は避けたほうが良いでしょう。

このようにテンプレートを分割しても値の受け渡しができるの柔軟なテンプレート設計を行えるため、重宝します。

冒頭でも言及した通り、メリデメ含め検討するのが良いでしょう。