AWS CloudFormation (Infrastructure as Code)

#【AWS CloudFormation (Infrastructure as Code)】
今回のSprintでCloudFormationをきっちり理解する！

##CloudFormationとは。
- EC2やELBのなどのAWSリソースの環境構構築を**テンプレート**を元に自動化できるサービス
    - テンプレートを自由に作成できるため、自分好みのシステム構成を自動的に構築可能
    - テンプレートに作成するAWSリソースの定義をYAMLで記述（JSONも可）
        - YAMLはコメントを書くことが可能
    - CloudFormationの利用料は無料
    - (プロビジョニングされたAWSリソース分の料金は当然ながら発生する)
    - GitHub上での管理可能、コードレビューも容易になる

###CloudFormationの基本機能
- 作成
    - テンプレートに定義された構成でスタックを自動作成
    - 並列でリソースを作成
    - 依存関係がある場合は自動的に解決してくれる
- 変更
    - スタックに前回のテンプレートとの差分を適用（**幕等性**）
    - リソース変更時は無停止変更、再起動、再作成のいずれかが発生
    - Change Setを作ることで差分の内容を事前に確認可能
- 削除
    - 依存関係を解決しつつリソースを全て削除
    - データストアはスナップショット取得と保持が可能

（手動でおこなった変更は管理外）

###CloudFormationを使った構成管理の流れ
1. YAMLでテンプレートを記述
1. ローカル環境のファイルをAWSマネジメントコンソールやS3バケット経由でアップロード
1. AWSマネジメントコンソールやAWS CLI、スタックセットを利用してスタック（AWSリソースの集合体）を作成 
1. リソースの作成と管理

※ AWSではリソースはスタック単位で管理される。

###CloudFormation　テンプレート
- AWS CloudFormationの心臓部
- スタックの設計図
- AWSリソースの依存関係は基本的には自動判別してくれる
    - テンプレートに誤りがあれば自動でロールバックをしてくれる。
- ※ DependsOnを利用して手動で依存関係を調整する必要もある。
    - 例えば、NATGatewayやEIPなど。 
    - （EIPを作り、それをNATGatewayにアタッチする順番などは、自動判定されない。）
    - くろかわさんにコメント頂きました！ありがとうございます。

####テンプレートの要素
```yml:AWSTemplateFormat.yml
# AWS CloudFormationテンプレートバージョン
AWSTemplateFormatVersion: "version date"
# テンプレートの説明文
Description:
  String
# テンプレートに関する追加情報
Metadata:
  template metadata
# 実行時(スタック作成、更新)にユーザ入力を求めるパラメータ(キーペア名やDBのユーザ名など)
Parameters:
  set of parameters
# キーと値のマッピング（条件パラメータ値の指定に使用）
Mappings:
  set of mappings
# 条件名と条件判断内容（Resourcesセクションなどでリソース作成時に利用）
Conditions:
  set of conditions
# サーバーレスアプリケーションや定型コンテンツ（挿入等のための、マクロを指定）
Transform:
  set of transforms
# 必須!!
# 起動するリソースのタイプやプロパティを指定（スタックを構成するリソースとプロパティ）
Resources:
  set of resources
# スタック構築後に表示·取得した値や他スタックとの連携のための出力を指定（CloudFormationから出力）
Outputs:
  set of outputs

## その他
## !Refで取得できるのはリソースID、グループIDの取得はできない
## グループIDの取得は、Fn::GetAtt組み込み関数でテンプレートのリソースからの属性を返す
```
- 実務でのメモ　【追記 10/16】
    - Parameters:
        - 値をセット。
        - **画面から入力、デフォルト値を設定しておくことが可能。**
            - テンプレートの使い回しする為、とても大切！！
    - Resources:
        - 必須かつ関数のようなもの。
        - リソース作成に必要なパラメーターを受け取る。
    - Outputs:
        - 作成されたリソースが表示される。

####スタック
- スタック単位でリソースの管理が可能
- 削除を実行すると、スタックに紐づくリソースが削除される
- 使用するリソースおよびリソースの構築順は、テンプレートの依存関係から自動的に決定
- Change Setでスタックの変更内容を事前確認しデプロイ可能
    - 変更を要求した箇所とその変更により影響を受ける箇所を事前確認
    - **変更によってリソースが中断されたり再作成されたりすることに注意**
- StackSets：一回の操作で複数のアカウントやリージョンヘスタックを作成、更新、削除できる

##ライフサイクル別のスタック
```
- フロントエンドリソース：　
    - インスタンス、Auto Scalingグループ
- ステートフルなリソース：　
    - DB、クラスター、キュー
- バックエンドサービス：　
    - API エンドポイント、Lambda関数
- 監視リソース：　
    - アラーム、ダッシュボード
- ネットワーク：　
    - VPC、NATゲートウェイ、VPN、サブネット
- セキュリティ：　
    - IAMユーザー、グループ、ポリシー
```
1. スタックをレイヤーとライフサイクルで分割
1. スタックを環境ごと（dev, stg, prdなど）に再利用 

- 規模が大きくなると単一のテンプレートでの管理は手間と時間がかかる
- 変更時の影響範囲も大きくなるため、スタックを分割しよう

**設計観点**

- 依存関係
    - **VPC→SG+IAM→アプリケーションが基本となる**
        - この上に監視がのる。
        - 監視は、ClouldWatchでログをはかせるだけでは不十分。
- ライフサイクル
    - 更新頻度と寿命
    - 通常VPCやIAMなど依存される側のリソースは更新頻度が少なく寿命が長い
    - アプリケーションは高頻度に更新があり、短命であることが多い
- ステートレス・ステートフル
    - ステートレスなリソースとステートフルなリソースを分割
- 所有権
    - 更新に責任を持っているチーム毎に分割

これらをもとにして、**実装**　→　Cross Stack Reference

###インフラ全体のスタック分割
```
【上：依存する側、短命かつ高頻度　　　下：依存される側、長寿かつ低頻度】

- アプリケーションレイヤー
    - アプリケーションリソース
    - システムが直接利用するリソースを配置
    - アプリケーションだけではなく、共有サービス（Directoryなど）も依存関係上で含まれる
    - リソースの例
        - EC2, RDS, ELB, SQSキュー, Active Directory, CI/CDサーバ
- セキュリティレイヤー
    - ネットワークリソースのうちSGはネットワークの存在を前提とするのでこのレイヤー
    - IAMは事実上依存性のないリソースだが、分類上このレイヤー
    - リソースの例
        - SG, IAMロール, IAMグループ, IAMポリシー
- ネットワークレイヤー
    - ネットワークリソースは最も依存性が低いリソース
    - インフラ環境の「地面」に相当する
    - 外部のリソースの存在を前提としない。
    - （他のテンプレートとVPCやサブネットを連携するためにOutputsで情報出力）
    - リソースの例
        - VPC, サブネット, エンドポイント, ルートテーブル, Route53, IGW, NATGW, VGW
```

####アプリケーションレイヤ内部のスタック分割（インフラ全体の中のうち）
```
【上：依存する側、短命かつ高頻度　　　下：依存される側、長寿かつ低頻度】

- アプリケーション（アプリケーションリソース）
    - アプリケーションコードを直接実行するものを配置
    - またはリクエストをルーティングするものを配置
    - ステートレス
    - リソースの例
        - EC2, ECS, ELB, AutoScaling, API Gateway
- データ
    - DBやキャッシュ、キューなどのアプリケーションのリソースのうちステートフルのリソースを配置
    - リソースの例
        - S3, RDS, Redshift, ElastiCache, SQS, EC2(データを保持するもの)
- シェアードサービス
    - アプリケーションから共通で利用されるサービスを配置
        - Active Directoryのような認証サーバ
        - プロキシサーバー
        - メールリレーサーバー
        - CI/CDサーバー
    - リソースの例
        - Directory Service, EC2(共通サービス), Codeシリーズ, SES, Route53
```

##AWS CLIを使ったスタック操作
- AWS CLIを使ったスタックの基本操作
    - **aws cloudformation deployコマンド**

```
- スタック作成
aws cloudformation deploy --template-file テンプレートファイル名.yml --stack-name スタック名
- スタック作成（パラメーターを指定する場合）
aws cloudformation deploy --template-file テンプレートファイル名.yml --stack-name スタック名 --parameter-overrides パラメーター=指定したいパラメーターの値

- スタック削除
aws cloudformation delete-stack --stack-name スタック名

・　IAMロールを作成する時に、承認するもの。（GUIのオプション）
--capabilities CAPABILITY_NAMED_IAM

・　CFnテンプレートの反映が即時にされずに、一旦作成するリソース、削除するリソースの変更セット、これらの変更に問題が無いことを確認したうえで変更内容を反映できる。（大切なリソースを誤って削除してしまわないように1度確認を挟むことができる。変更セットが表示されて、確認後に実行ができる。）
--no-execute-changeset 
```

####CFnすべきか、しないべきか。
>VPNやDirectConnect周りの設定はcFn化【しない】べきだと考えます。 理由は使い回しが少なく、クリティカルな（設定誤りが許されない）リソースで、かつ一発もののためcFn化をする恩恵があまりないからです。

こちらのコメントは、くろかわさんから頂きました。
自分も使いまわしがなく、一発もののものにはCFn化は不要と考えていました。
しかし、全てCFn前提の話もされることもあります。。
AWS, CFn, IaCに知識がある方にお話をお聞きしたいです。

##今後
新たに追記予定。
実務の中で学んだことを書き足していけたらなと。

##参考
- [【AWS Black Belt Online Seminar】AWS CloudFormation](https://www.youtube.com/watch?v=Viyqh9fNBjw)
- [CloudTech](https://aws-cloud-tech.com)

## おわりに。
この記事はAWS初学者を導く体系的な動画学習サービス
「AWS CloudTech」の課題カリキュラムで作成しました。
https://aws-cloud-tech.com
![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f3436353930362f30303633376536332d353333392d316238332d633363312d3732306539353137346563302e706e67.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/472549/ecaf8e94-37a6-cf4c-fb6d-1c106e0034c1.png)