IaCの汎用化について考えてみる（その１）

# IaCの汎用化について（その１）

Shigeyukiです。

今回は、ブームであるIaCに関してこれからはじめる人向けに、重要となるIaCの汎用化について解説してみたいと思います。

# IaCに関する状況
DX基盤としてIaCの重要性はどんどん高まり、CDKやSAMやAmplifyなど活気となっております。
しかし、IaCの保守性に関した記事は少なく、初心者にとって保守性を意識したIaCを構築するのに障壁があり、少しでもそうした方たちのスキル向上に役立つような情報を発信したいと考えております。
 
# IaCに関する課題
IaCはインフラコードであり、アプリのコード以上に保守性が重要となります。
インフラ部分は一度リリースした後に修正して再リリースするのに、システムダウンや他リソースへの影響などいろいろ考慮する必要があります。
保守性を考える上で、IaCの汎用化は重要なファクタとなってきます。

そこで、AWSサービスの裏で動作している重要なCloudFormationを題材にして、IaCの汎用化について3部構成で解説したいと思います。

:::note info
**コラム構成**
その１）基礎編：テンプレートの抽象化
その２）中級編：テンプレートの分割
その３）上級編：IaCによるインフラ分割
:::

今回は、その１）基礎編として、IaCの汎用化として『テンプレートの抽象化』を解説します。


# テンプレートを抽象化する目的
CloudFormationでテンプレート作成する際に、環境毎に異なる要件を満たすAWSリソースをつくるのに、類似したテンプレートが生成されやすくなり、保守性が下がりやすくなります。
こうした問題を対して、テンプレートを抽象化することで保守性を向上させます。

# テンプレートを汎用化するための検討事項
テンプレートのAWSリソースの作成・設定条件となる情報を外部から受け取り、それを基にAWSリソースの作成・設定を動的に制御する必要があります。

ここでは１つのEC2インスタンスを開発環境用と本番環境用に異なるインタンスタイプを作成し、本番環境だけに専用リソースS3を作成したいとします。
環境に依存した設定値（この場合、インスタンスタイプ）をテンプレートにハードコーディングしたり、環境専用インスタンスをそのまま定義してしまうと、下図のように環境専用のテンプレート化となってしまいます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3744312/ce639858-9e2b-a954-4ccd-709c1678cfc3.png)

:::note warn
問題点
- 環境ごとに類似したテンプレートが量産されてしまう。
- AWSリソースの設定を変更する場合、全テンプレートを修正することになる。
:::

テンプレートの内容が環境依存させない、つまり、汎用化させるためには環境依存値を抽象化する必要があります。
抽象化された値を動的に決定させるための情報をCloudFormationのパラメータファイルにて定義した、CloudFormationを実行する際に指定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3744312/fbba53b5-48e2-abb1-eb37-a3bf0a12441b.png)

AWSリソースの設定値を抽象化するためには、以下のようにいくつかの手段があります。

:::note info
**抽象化手段**
- Parametersセクション（外部から受け取りたい環境依存値）
- Mappingsセクション（リソースの属性値を管理）
- Conditionsセクション（リソースの作成条件）
- パラメータストアの参照（DB接続情報やAPIキーなどを管理）
:::

## 抽象化したテンプレートのイメージ
実際に上記の例に対して抽象化したテンプレート[sample_cfn_template.yml]とパラメータファイル[cfn_param.json]は以下のようになります。
```sample_cfn_template.yml
AWSTemplateFormatVersion: "2010-09-09"

Description: Sample Template

# ------------------------------------------------------------#
# Parametersセクション
# ------------------------------------------------------------# 
Parameters:
  Env:
    Description: "Deploy Target Environment"
    Type: String
    AllowedValues: ["DEV", "PROD"]

# ------------------------------------------------------------#
# Mappingsセクション
# ------------------------------------------------------------# 
Mappings:
  InstanceInfoMap:
    DEV:
      Type : "t2.micro"
    PROD:
      Type : "m5n.xlarge"

# ------------------------------------------------------------#
# Conditionsセクション
# ------------------------------------------------------------# 
Conditions:
  S3CreateFlg: !Equals [!Ref Env, PROD]


# ------------------------------------------------------------#
# Resourcesセクション
# ------------------------------------------------------------# 
Resources:
  EC2Vpc:
    Type: 'AWS::EC2::VPC'
    Properties:
      CidrBlock: "10.0.0.0/16"
      Tags:
        - Key: "Name"
          Value: "cftest_VPC"
  EC2Subnet:
    Type: 'AWS::EC2::Subnet'
    Properties:
      VpcId: !Ref EC2Vpc
      CidrBlock: "10.0.1.0/24"
      Tags:
        - Key: "Name"
          Value: "cftest_Subnet"
  EC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      InstanceType: !FindInMap [InstanceInfoMap, !Ref Env, Type]
      ImageId: 'ami-034c9ca2bdde7b472'
      NetworkInterfaces:
        - AssociatePublicIpAddress: "true"
          SubnetId: !Ref EC2Subnet
          DeviceIndex: 0
  S3Bucket:
    Type: AWS::S3::Bucket
    Condition: S3CreateFlg
    Properties:
      BucketName: "sample-cfn-bucket-123"
              



```


```cfn_param.json
[
  {
    "ParameterKey": "Env",
    "ParameterValue": "PROD"
  }
]
```

実行コマンドがこちらになります。
```cfn_param.json
$ aws cloudformation create-stack --stack-name sample-stack --template-body file://sample_cfn_template.yml  --parameter file://cfn_param.json

```

# まとめ
IaC汎用化について、CloudFormationを例にして解説してみました。
テンプレート作成時に汎用化を意識しないと、無駄なテンプレートが量産されてしまい、保守性の低下が分かりました。保守性を向上させるためにもテンプレートを抽象化することで実現できる例を提示しました。
その２）中級編 では、テンプレートの分割について解説したいと思います。
以下ブログになります。

https://qiita.com/ueno120525/items/db08a218fb79bece3727

本ブログがCloudFormationによるIaCの品質向上につながると幸いです。