個人的 CloudFormation ベストプラクティスまとめ

# はじめに
最近よく耳にする IaC （Infrastructure as Code）であるCloudFormation を触る機会があったため、使用するにあたりベストプラクティスをまとめました。

# CloudFormation概要
テンプレートを使用してAWSリソースの環境構築を行うサービスです。
テンプレート化しておけば、同じ環境構成を何度も作ることができます。

## スタックとテンプレート
- テンプレート
    - スタックを構成する AWS リソースの定義されたファイルをテンプレートと呼びます。
- スタック
    - テンプレートから作成されたリソースの集合のことをスタックと呼びます。1つのテンプレートから1つのスタックが生成されます。
![スクリーンショット 2022-06-02 22.10.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2612883/b6760f44-c4fb-c4e1-4165-950254ed4401.png)

## IaCのメリットとデメリット
### IaCのメリット

1. 手動オペレーションによる人的ミスの削減
    - 本番環境と同じ環境を手作業で作ると、ヒューマンエラーが起きるがIaCは確実に同じ構築ができる
    - IaCをCl/CD化時に効果を発揮
2. 不要なリソースができない
    - 謎のEIPやSGなど
3. 環境を即構築でき、工数削減
    - 掃除が楽、作り直しが楽
4. インフラ構築の手順書を作る現場だと、コンソール画面のuiは変更頻度が多いため、IaCで手順書を作成する方が手間が少ない

### IaCのデメリット

1. コード化するのに時間がかかる
2. 部分的な修正でもテンプレートからスタックを作成して適用する必要があるため、手動で修正するよりも時間がかかる場合がある
2. 理解が不十分だと意図せずリソースが削除される


# ベストプラクティス
設計時、テンプレート作成時、運用時の観点からAWSのベストプラクティス等を参考にし、まとめます。

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/best-practices.html

## 設計時 


1. ### IaC使い方を設計時に決める
    - 運用もIaCを使い続けるか、IaCを初期構築のみで使用するか
        - **構築のみIaC**：初期構築をIaCで構築し、その後は、プロジェクトごとにコンソールで構築
        - **運用までIaC**：設計だけでなくIaCのデプロイ方法まで考える（**下記の1~3をするには、ハードル高い**）
            1. IaCをgit管理し、プルリク時に複数人でチェックする
            2. IaCにCl/CDを導入し、自動デプロイ
            3. AWS環境をコンソールでリソースに対して、手動操作できないよう、IAMユーザー権限は、ReadOnlyにする。緊急時のみadmin権限使用する。

2. ### ライフサイクルと所有権を考慮し、スタックを整理する
    - 「ライフサイクルが同じ」= 「スタックの作成・削除が同じタイミング」
      - AWSリソースのライフサイクルが同じなら同じスタックにまとめる
        1. ネットワークスタック（vpc,subnet,igw）
        2. セキュリティスタック（sg,IAM）
        3. アプリケーションスタック（cloudfront,elb,fargate,rds）
           -  スタックを細分化しすぎると、１つのスタックを修正しようとしても、他のスタックとの依存関係で修正しにくくなる。
              - スタックをどう分けるかは→ 正解はないよう。。
              <img width="700" alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2612883/4ff37273-4435-e449-ffc2-aa54e113208f.png">


                
    - 誰がそのリソースの変更を担当するのか?（= 所有権）
        - アプリケーションとDBのスタックを担当する部署が別れている場合は、その単位でスタックの分割をすべき
        <img width="700" alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2612883/89f5b7e6-1de5-cee9-77f7-3e808feeda65.png">



## テンプレート作成時



6. ### 命名規則を決めておく
    - スタック内のリソースの命名ルールを最初にちゃんと決めておく
        - `「プロジェクト名 - AWSサービス名 - 環境名」`
            - 環境名は、prod や dev とつける
    
7. ### 複数環境を同じテンプレートで管理する
    - 本番環境、開発環境など複数の環境を使用している場合に、環境ごとに別のテンプレートにせず、同じものを使うようにした方がします。
        1. テンプレートの数を減らして、管理が楽になります
        2. 同じテンプレートを使うことで、必ず同じ構築にすることができます。

1. ### ParameterやMappingを使用しすぎない
    - 使いすぎると、実際にどのような設定がされているかテンプレートを見てもわからない
    - 使用する判断基準
        1. Gitで管理しなくても運用上問題ない値であること
        2. 複数環境を1つのテンプレートで管理できるか
            - OK：環境名やスペックをパラメータにすることで、本番環境、開発環境を1つのテンプレートで管理できる
                - パラメータ入力値の制限をすると、なおよい。`AllowedValues: [ prod, stg, dev ]`
            - NＧ：RDSのスナップショットやメンテナンス時間は、プロジェクトによって変わることは考えくく、レビュー時に確認できた方がよいので固定値がよい。
            
3. ### テンプレートを開発で役に立つツール
    - VSCodeのプラグイン
        - `cfn-lint` ：CloudFormationの構文チェックツール
            - [使い方は、こちら](https://qiita.com/ita-k/items/31d640d708925c0ae838)
    - Webサービス
        - `former2`：作成済みのリソースからテンプレートが作成できるツール
            - IAMユーザーで認証情報とReadOnlyAccess権限必要
                - former2はAWSで紹介されており、認証情報は、AWS APIのエンドポイント以外の外部サーバーには送信しない設計になっており安心
                    - [使い方は、こちら](https://qiita.com/leomaro7/items/b95880f137c63881f164#former2)
                - [Dockerでローカル環境でも実行可能](https://qiita.com/ka2taka/items/787422050f0b5381d756)


### テンプレート作成時に参考になる記事

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-template-resource-type-ref.html

https://dev.classmethod.jp/articles/list-of-cloudformation-parameters-by-data-type/

https://dev.classmethod.jp/articles/lim-cloudformation-function-1/

https://dev.classmethod.jp/articles/lim-cloudformation-function-2/

https://blog.serverworks.co.jp/2022/02/28/231713

## 運用時

3. ### スタック間のパラメーターの参照は、クロススタック参照を用いる
    - スタックの特定のリソースを別のテンプレートから参照する場合、クロススタック参照を用いることで、動的に参照できる
        - メリット
          1. 値のハードコードを避けることができて、テンプレートが再利用できる
          2. 強い依存関係を作れる
              - 他のスタックに依存されているリソースがある場合、そのリソースを変更したり削除したりできなくなる
              - ただ、スタックが多いと修正しにくいといったデメリットも。
              <img width="700" alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2612883/348d5fd0-aac8-4ac8-36e3-4a1496c2361a.png">
              <img width="700" alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2612883/740f743c-8006-0dda-1bff-ea2db8282ef1.png">

4. ### スタック間で機密情報の受け渡す場合、ダイナミック参照する
    - パラメータを SSMのパラメータストア や Secrets Manager に出力し、スタックは、そこからパラメータを取得する
    - [具体的な方法はこちら](https://dev.classmethod.jp/articles/cfn-dynamic-references-support-latest/)

2. ### スタックの更新は、 変更セット や ドリフト検出 を使用する
    - スタックを修正する場合、変更セットを使用をすることで、変更を反映する前にどのリソースにどのような影響があるかを把握できる
        - リソースが作り直されるか、現状のリソースのままで設定が変わるだけなのか確認できる
    - スタックを手動で修正していた場合、ドリフト検出で差分を検出しましょう
        - Configルールと組み合わせて、通知することも可能です。
        <img width="700" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2612883/98a3809d-fc6d-b0ef-1f15-183713b7c4b1.png">



4. ### 複数の環境に同時にスタックを作成する場合、Stack Setsを活用する
    - 異なるリージョンや異なるAWSアカウントに対して、同時に実行可能
        - AWS Config等をすべてのアカウントに展開ができる
        <img width="700" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2612883/0e5e3d6e-2a2a-c35a-b63e-2a67cd550a27.png">

# 参考

https://www.slideshare.net/AmazonWebServicesJapan/20201006-aws-black-belt-online-seminar-aws-cloudformation-deep-dive

https://www.slideshare.net/AmazonWebServicesJapan/20200826-aws-black-belt-online-seminar-aws-cloudformation-238501102

https://public-cloud-pci-dss.jp/aws/443/

https://dev.classmethod.jp/articles/aws-all-iac/

https://jawsdays2019.jaws-ug.jp/session/2004/

https://qiita.com/uramotot/items/4a55ccad14f44f5006f6

https://qiita.com/hicka04/items/6538f6f31351e6b97f82

https://qiita.com/leomaro7/items/547f8433677ae675d5d8