CloudFormation IaC Generatorで自動生成されるテンプレートを、人手によるテンプレートと比較してみた

# 1. 概要

[CloudFormation IaC Generator](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/generate-IaC.html)は、CloudFormationで管理されていない既存リソースから、CloudFormationテンプレートを自動生成するツールです。
CloudFormation IaC Generatorで自動生成したテンプレートが、他環境に向けて修正して再利用する用途に向いているかを判断するための参考として、人手で作成したCloud CloudFormationテンプレートと比較してみることにしました。

# 2. 検証構成

広く利用されている構成を例にしたいと思い、[Amazon Elastic Container Service(ECS)](https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/Welcome.html)を用いてWebアプリケーションのコンテナを実行する構成を選びました。

![構成図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3630028/0692826f-02fe-96a7-6e7a-e2a12ed44008.png)

<div style="page-break-after: always;"></div>

上記構成について、CloudFormationテンプレートを4つに分けて作成します。つまり、「人手で作成したテンプレート」と、「CloudFormation IaC Generatorで自動生成したテンプレート」を、それぞれ４つずつ作ります。

| # | テンプレート名 | テンプレート化するリソース|
| - | ---- | ---- |
| 1 | VPC | VPCとそのコンポーネント（サブネット、セキュリティグループ、IGW、NAT-GW、PrivateLink等）  |
| 2 | データベース | RDSとElastiCache |
| 3 | ECSクラスター | ECSクラスター |
| 4 | ECSサービス | ECSサービスとタスク定義、およびロードバランサー |

# 3. 検証手順

下記の手順で、「人手で作成したCloudFormationテンプレート」と、「CloudFormation IaC Generatorで自動生成したCloudFormationテンプレート」を作り、比較を行います。

* ステップ1：CloudFormationテンプレートを人手で作成します。
  * テンプレート内の各リソースに`DeletionPolicy: Retain`属性を付与します。
* ステップ2：人手によるCloudFormationテンプレートを使ってリソースを自動構築します（テンプレートのデバッグも実施します）。
* ステップ3：リソースの自動構築に成功したらCloudFormationスタックを削除します。
  * CloudFormation IaC Generatorは、CloudFormationで既に管理されているリソースからテンプレートを自動生成できません。ただしCloudFormationスタックを削除すれば、リソースをCloudFormationの管理対象外にすることができます。
  * `DeletionPolicy: Retain`属性を付与したリソースについて、スタックが削除されてもリソースは削除されません。
* ステップ4：構築したリソースを対象に、CloudFormation IaC GeneratorでCloudFormationテンプレートを自動生成します。

# 4. テンプレートの比較結果

「人手で作成したCloudFormationテンプレート（生成元のテンプレート）」と、「CloudFormation IaC Generatorで自動生成したCloudFormationテンプレート（自動生成したテンプレート）」を比較した結果を示します。

* テンプレートのセクション
  * 自動生成したテンプレートには、構築するリソースを定義する`Resources`セクションと、テンプレートのIDを示す2行のみの`Metadata`セクションのみが含まれていました。
    * 生成元のテンプレートには他にも`Parameters` 、`Conditions` 、 `Outputs` のセクションが含まれていましたが、自動生成したテンプレートには含まれませんでした。
* リソースのプロパティ：
  * 自動生成したテンプレートには、各リソースの全プロパティが含まれていました。
  * 自動生成したテンプレートでは、ID等のリソース識別子に、生成元リソースの実際のIDが直接記述されていて、パラメータ化はされていませんでした。
* リソースタイプのサポート：
  * CloudFormation IaC Generatorは、[Cloud Control APIでサポートされるリソースタイプ](https://docs.aws.amazon.com/ja_jp/cloudcontrolapi/latest/userguide/supported-resources.html)のみが生成対象となります。そのため、自動生成したテンプレートには取り込まれなかったリソースタイプがありました。取り込まれなかったリソースタイプについては後述の表を参照ください。
* ソースコード行数（LOC）：
  * `Resources` セクションのソースコード行数を比較しました。
    * 生成元のテンプレートについては、全体のソースコード行数も参考として示します。
    * 生成元のテンプレートで省略したプロパティが多い場合に、自動生成したテンプレートには全プロパティが含まれるため、ソースコード行数がより多くなります。
    * サポートされていないリソースタイプがあるため、自動生成したテンプレートは生成元のテンプレートよりもソースコード行数が少なくなる可能性もありましたが、この検証では前述の全プロパティが含まれる影響の方が大きく現れました。

テンプレートのソースコード行数（LOC）を比較した結果と、取り込まれなかったリソースタイプを表に示します。

| # | テンプレート名 | 生成元のテンプレートのLOC(全体) | 生成元のテンプレートのLOC(Resourcesのみ) | 自動生成したテンプレートのLOC(Resourcesのみ) | 取り込まれなかったリソースタイプ |
| - | ---- | ---- | ---- | ---- | ------ |
| 1 | VPC | 563 | 367 | 456 | `AWS::EC2::VPCGatewayAttachment`,<br> `AWS::EC2::VPCGatewayAttachment`,<br> `AWS::EC2::SecurityGroupIngress` |
| 2 | データベース | 258 | 65 | 66 | `AWS::ElastiCache::` `ReplicationGroup`,<br> `AWS::SSM::Parameter` |
| 3 | ECSクラスター | 80 | 46 | 50 | `AWS::ServiceDiscovery::` `PrivateDnsNamespace` |
| 4 | ECSサービス | 255 | 168 | 269 | `AWS::ServiceDiscovery::Service` |

また参考として、テンプレート「ECSサービス」のリソースタイプ`AWS::ECS::Service`について、生成元のテンプレートと自動生成したテンプレートの内容を以下に掲載します。

## 参考：人手作成したCloudFormationテンプレート（生成元のテンプレート）の一部

テンプレート「ECSサービス」のリソースタイプ`AWS::ECS::Service`のみ抜粋。CloudFormationの関数RefとSubなどを用いて、テンプレート内のリソースの値やパラメータを参照しています。

```
  EcsService:
    Type: AWS::ECS::Service
    DeletionPolicy: Retain
    Condition: IsNoLoadBalancer
    Properties:
      ServiceName: !Ref ServiceName
      Cluster:
        Fn::ImportValue: !Sub MyApp-${EnvironmentName}-ECSCluster
      LaunchType: FARGATE
      DeploymentConfiguration:
        MaximumPercent: 200
        MinimumHealthyPercent: 100
      DesiredCount: !Ref DesiredTaskCount
      NetworkConfiguration:
        AwsvpcConfiguration:
          AssignPublicIp: !Ref PublicIp
          SecurityGroups: !Split
            - ","
            - Fn::ImportValue: !Sub MyApp-${EnvironmentName}-Private-SecurityGroup
          Subnets: !Split
            - ","
            - Fn::ImportValue: !Sub MyApp-${EnvironmentName}-PrivateSubnets
      TaskDefinition: !Ref TaskDefinition
      ServiceRegistries:
        - ContainerName: !Ref ServiceName
          RegistryArn: !GetAtt DiscoveryService.Arn
```

## 参考：CloudFormation IaC Generatorで生成したCloudFormationテンプレート（自動生成したテンプレート）

テンプレート「ECSサービス」のリソースタイプ`AWS::ECS::Service`のみ抜粋（ID等をマスクしています）。全てのプロパティを含みますが、パラメータ化はされていません。

```
  ECSService00MyAppCluster********:
    UpdateReplacePolicy: "Delete"
    Type: "AWS::ECS::Service"
    DeletionPolicy: "Delete"
    Properties:
      PlatformVersion: "LATEST"
      HealthCheckGracePeriodSeconds: 120
      EnableECSManagedTags: false
      EnableExecuteCommand: false
      Cluster: "MyApp-Cluster"
      LoadBalancers:
      - TargetGroupArn:
          Ref: "ElasticLoadBalancingV2TargetGroup00targetgroupMyApp******************************"
        ContainerPort: 80
        ContainerName: "MyApp-*****-task"
      DesiredCount: 2
      DeploymentController:
        Type: "ECS"
      ServiceRegistries:
      - RegistryArn: "arn:aws:servicediscovery:ap-northeast-1:************:service/srv-********"
        ContainerName: "myapp-svc"
      LaunchType: "FARGATE"
      Role: "arn:aws:iam::************:role/aws-service-role/ecs.amazonaws.com/AWSServiceRoleForECS"
      SchedulingStrategy: "REPLICA"
      TaskDefinition:
        Ref: "ECSTaskDefinition00taskdefinitionMyApptaskTask*******"
      ServiceName: "myapp-svc"
      NetworkConfiguration:
        AwsvpcConfiguration:
          SecurityGroups:
          - "sg-*****************"
          Subnets:
          - "subnet-*****************"
          - "subnet-*****************"
          AssignPublicIp: "DISABLED"
      DeploymentConfiguration:
        Alarms:
          AlarmNames: []
          Enable: false
          Rollback: false
        DeploymentCircuitBreaker:
          Enable: false
          Rollback: false
        MaximumPercent: 200
        MinimumHealthyPercent: 100
```

# 5. まとめ

人手で作成したCloudFormationテンプレートと、CloudFormation IaC Generatorで自動生成したCloudFormationテンプレートを比較し、テンプレートに含まれるリソースタイプやプロパティ、ソースコード行数（LOC）に違いが出ることを確認しました。
他の環境での再利用を目的としてCloudFormationテンプレートを作成する場合では、CloudFormation IaC Generatorで自動生成したテンプレートをメンテナンスするよりも、（自動生成したテンプレートを参考にして）新しいテンプレートを人手で作成する方が少ない手間ケースがありそうです。