CloudFormationでループ処理を実装する


はじめに

CloudFormationテンプレートで同じ設定のリソースを複数展開したいとき、ループ処理が使えたらいいなと思うことがありませんか?

CloudFormationにはループ処理を実現する機能は提供されていませんが、マクロ機能を使うことにより、機能を追加することが出来ます。

awslabsにループ処理を実現するCount Macroが公開されているので利用方法を紹介します。

事前準備

CloudFormationテンプレートでCount Macroを利用するために、まずはCount Macroのスタックをデプロイします。

  • CloudFormation用S3バケットの作成

    • <bucket-name>はお好きな名前を付け、これ以降<bucket-name>となっている箇所は置換してください。
    S3バケットを作成します。
    $ aws s3 mb s3://<bucket-name>
    
  • Count Macroのスタックをデプロイ

    • Git HubからCount Macroを展開するCloudFormationテンプレートを取得し、Count Macroを利用するAWSアカウントにスタックをデプロイします。
    gitからクローンします。
    $ git clone https://github.com/awslabs/aws-cloudformation-templates
    
    Count Macroのディレクトリに移動します。
    $ cd aws-cloudformation-templates/aws/services/CloudFormation/MacrosExamples/Count
    
    Count MacroはAWS SAMを利用しているので、LambdaコードをS3にアップロードし、アップロードされたLambdaコードをデプロイするテンプレートに変換します。<bucket-name>は置換してください。
    $ aws cloudformation package \
        --template-file template.yaml \
        --s3-bucket <bucket-name> \
        --output-template-file packaged.yaml
    
    Count-macroという名前でスタックをデプロイします。
    $ aws cloudformation deploy \
      --template-file packaged.yaml \
      --stack-name Count-macro \
      --capabilities CAPABILITY_IAM
    
  • Count Macroのスタックのデプロイ結果確認

    • AWSマネージメントコンソールでCloudFormationを開き、Count-macroスタックが作成されたことを確認します。
    • MacroのLambdaも展開されています。

Count Macroの使い方

サンプルCloudFormationテンプレートを使って複数のS3バケットをデプロイしてみる

では実際にCount Macroを使ってみましょう。GitHubのリポジトリに同梱されていたサンプルファイル(test.yaml)をデプロイしてみます。

  • CloudFormationテンプレート

    • Count Macroを使用するため、テンプレートの初めにTransform: Countが記述されています。
    • S3バケットの定義のプロパティではCount: 3が指定されています。
    • これにより、1つのS3バケット定義で3つのバケットが作成されます。
    test.yaml
    Transform:
      - Count
    Resources:
      Bucket:
        Type: AWS::S3::Bucket
        Count: 3
    
  • CloudFormationテンプレートのデプロイ

    • Count-testというスタック名でデプロイを実行します。
    $ aws cloudformation deploy \
        --stack-name Count-test \
        --template-file test.yaml \
        --capabilities CAPABILITY_IAM
    
  • デプロイ結果の確認

    • 作成されたスタックのリソースタブを開くと、3つのS3バケットが作成されていることを確認できます。
    • 作成されるS3バケット名はCloudFormationテンプレートの論理ID + カウントインデックス + ランダム文字列になります。

応用編 バケット名を個別に指定してみる

バケット名は自分で指定したいので、バケット名を個別に指定しつつ、一つの定義でまとめて作成するテンプレートにしてみます。

  • CloudFormationテンプレート

    • パラメータBucketNameListで作成するバケット名をカンマ区切りで定義します。
    • パラメータBucketNameCountで作成するバケット数を定義します。
    • バケット名は split関数を使いパラメータBucketNameListをカンマで分割しリスト化、select関数を使いリストのインデックス%dを指定してバケット名を取得します。
    • Count Macroはプレースホルダー%dでカウントインデックスが取得できます。
    named_s3_bucket.yaml
    Transform: Count
    Parameters:
      BucketNameList:
        Type: String
        Default: "matu-20211021,take-20211021,ume-20211021"
      BucketNameCount:
        Type: Number
        Default: 3
    Resources:
      NamedS3Bucket:
        Type: AWS::S3::Bucket
        Properties:
          BucketName: !Select [ "%d", !Split [",", !Sub ",${BucketNameList}"] ]
        Count: !Ref BucketNameCount
    
  • CloudFormationテンプレートのデプロイ

    • named-s3-bucketというスタック名でデプロイを実行します。
    $ aws cloudformation deploy \
        --stack-name named-s3-bucket \
        --template-file named_s3_bucket.yaml \
        --capabilities CAPABILITY_IAM
    
  • デプロイ結果の確認

    • パラメータBucketNameListで指定したバケット名でS3バケットが一括作成されました。

最後に

Count Macroを利用することで、CloudFormationでも繰り返し処理を実装することが出来ました。

CloudFormationは宣言的にリソースを定義していくことで読みやすく扱いすい反面、少し複雑な処理をするのが苦手です。

複雑な処理を実装したいときにはTerraformAWS CDKを使った方が楽なので、それぞれのツールのメリットや提供されているテンプレートなど活かしつつ使い分けしたいですね。