[忘備録]AWS CloudFormation  基礎!!テンプレートを書くまでの知識

# はじめに

テンプレートを書く時の情報を探すのに時間がかかったので、忘れた時のために知識を残す

（未来の自分への記事）

# 参考

https://blog.serverworks.co.jp/2022/02/09/073000#CloudFormation%E3%83%86%E3%83%B3%E3%83%97%E3%83%AC%E3%83%BC%E3%83%88%E3%81%AE%E4%BD%9C%E6%88%90

https://blog.serverworks.co.jp/2021/12/08/174707#%EF%BC%91-CloudFormation%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9

https://dev.classmethod.jp/articles/cloudformation-beginner01/

https://nopipi.hatenablog.com/entry/2019/04/27/155616

---

# AWS CloudFormation について

AWS CloudFormationはAWS環境をコードから自動で環境を構築するサービス

CFnと略して書かれていることもあるぽい


## 作成の流れ

1. AWS環境の設定値(システム構成)を記載した**テンプレート**を作成
2. AWS マネジメントコンソール or AWS CLI or SDKから CloudFormationを実行する
   → テンプレートファイルを読み込み、**スタック**を作成
3. **スタック**作成と同時に**テンプレート**で指定した環境が構築される

## 用語

### テンプレート

- AWSシステム構成を記載したJSON または YAML 形式のテキストファイル
- JSONだと**コメントアウトが残せない** ので、個人的にはYAML 形式で書きたい！

### スタック

- テンプレートで作成するAWS環境(vpcやec2など)を管理するもの
- CloudFormationで作成した環境はスタックと紐づいている
    - スタックを作成すると、環境が一括で作成される。
    - スタックを編集すると、環境が変更できる。
    編集内容によっては、サーバーの再起動や再構築が発生する
    - スタックを削除すると、作成された環境が一括削除される

---

# テンプレートフォーマット(YAML)

**＜＜ 公式サイト ＞＞**

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/template-anatomy.html#w2ab2c17c15b9


```bash
AWSTemplateFormatVersion: "version date"............(1)

Description:                            ............(2)
  String

Metadata:                               ............(3)
  template metadata

Parameters:                             ............(4)
  set of parameters

Rules:                                  ............(5)
  set of rules

Mappings:                               ............(6)
  set of mappings

Conditions:                             ............(7)
  set of conditions

Transform:                              ............(8)
  set of transforms

Resources:                              ............(9)
  set of resources

Outputs:                                ............(10)
  set of outputs
```

最低限の項目は(1)(2)(9)が書けたらOK！

## ■(1)バージョン「AWSTemplateFormatVersion」

```bash
AWSTemplateFormatVersion: "2010-09-09"
```

テンプレートの形式バージョンの指定する。

バージョンは公式サイトを確認。（2022年11月時点では「`2010-09-09`」が唯一のバージョン)

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/format-version-structure.html

## ■(2)説明「Description」

```bash
Description: "Hoge Hoge"
```

テンプレートに関するコメント。
作成後のスタックの説明欄に設定される。

## ■(4)パラメータ「Parameters」

- テンプレートにPrefix(置換文字)を埋め込みでき、埋め込む文字をパラメータで渡せる。
- 画面からCloudFormationを実行する場合は、パラメータの入力画面で設定する。
- AWS CLIからCloudFormationを実行する場合は、コマンド引数で設定する。

- 使用用途の例
  検証環境と本番環境で設定を変える時パラメータで渡す。
  S3バケット名は世界で一意になるので、検証環境と本番環境で違う名前にしないといけない。 バケット名の一部をPrefixにして、パラメータで「staging」や「production」など文字を渡すとテンプレートでどちらも環境構築できる。
           
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html

<br/>

## ■(7)条件「Conditions」
- 条件名と条件を定義する。
  定義した条件をResourcesで指定するとその条件に一致した時にリソースが作成される。
- 条件は**条件の組み込み関数**を使って定義する。
    - Fn::And
    - Fn::Equals
    - Fn::If
    - Fn::Not
    - Fn::Or
- 検証環境や本番環境で作成する内容が異なる時に使用できる！

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/conditions-section-structure.html

<br/>

## ■(9)リソース「Resources」
(例)
```bash
Resources:
  TestVPC:                                ............①
    Type: AWS::EC2::VPC                   ............②
    Properties:                           ............③
      CidrBlock: ***.***.***.***/**
      Tags:
        - Key: Name
          Value: HogeSystem-VPC
```

### ①リソースのID(論理 ID)

テンプレート内でのリソースのIDになり、テンプレートの他のリソースを参照するために使用する。

- 英数字（A-Za-z0-9）で任意の名前をつけてOK
- テンプレート内で一意にする

### ②リソースタイプ

作成するリソースを指定する。上記の例だとVPCを作成している。

### ③リソースプロパティ

タイプで指定したリソースの設定を記載する。
指定したリソース毎に設定値の記述方法が異なる。

:::note info
💡 
**②リソースタイプ**と**③リソースプロパティ**は公式に定義されているので、それを参照しながら記載！
一覧ページのリソースリンクを押下するとリソースプロパティのページに遷移する。

[AWS リソースおよびプロパティタイプのリファレンス](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-template-resource-type-ref.html)

※VPCは[Amazon EC2](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/AWS_EC2.html)の中に定義されている。
リソースによってはネストされていて、一覧から辿っていくものもある。

[AWS::EC2::VPC](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpc.html)

:::

## ■(10)Outputs「Outputs」

- 規模が大きくなってくるとテンプレートを複数ファイルに分けて記述することがあり（＝スタックを分ける）、この項目には他のスタックに渡す値を記述する。
- アクセスURLや、作成したIAMユーザ名などスタック構築後に取得した情報を定義する！


<br/>

## サンプルYAML


```bash
AWSTemplateFormatVersion: 2010-09-09

Description: "hoge system template"

Resources:
  # ===================
  # NWの作成
  # ===================
  # VPC作成
  HogeVpc:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: xxx.xxx.0.0/16
      Tags:
        - Key: Name
          Value: Hoge-System-VPC

  # Publicサブネット1つ
  PublicSubNet1:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: ap-northeast-1a
      VpcId: !Ref HogeVpc # ←リソースIDを参照
      CidrBlock: xxx.xxx.xxx.0/24
      Tags:
        - Key: Name
          Value: Hoge-System-PublicSubNet1


  # ===================
  # IGWの設定
  # ===================
  # InternetGateway作成
  HogeIGW:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
        - Key: Name
          Value: Hoge-System-IGW

  # InternetGatewayをVPC にアタッチ
  AttachmentIGW:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      InternetGatewayId: !Ref HogeIGW # IGWを指定
      VpcId: !Ref HogeVpc             # VPCを指定

```

カスタムルートテーブルを作って、サブネットを関連設定させるなど細かい設定もできる〜

---

# CloudFormation実行コマンド(AWS CLI)

## AWS CLIからスタックを検証
    
```bash
aws cloudformation validate-template --template-body [テンプレのパス]
```
    
### 例
    
```bash
$ aws cloudformation validate-template --template-body file://./cloudformation/test.yml --profile hoge-system_dev
{
    "Parameters": [],
    "Description": "test template"
}
```
    
- 結果で「ValidationErrorエラー」が発生しなければOKぽい
- ローカル環境上でのテンプレートファイルは--template-bodyに「**file://**」で指定する
- AWSアカウント情報はプロファイルに保存しているので「--profile」オプションで指定する

https://qiita.com/marumeru/items/ee61e90ac5d790679e27
    
## AWS CLIからスタックを作成

```bash
aws cloudformation create-stack --stack-name [スタック名] --template-body [テンプレのパス] --parameters [パラメーター]
```
    
### 例

```bash
$ aws cloudformation create-stack --stack-name hoge-stack --template-body file://./cloudformation/test.yml --profile hoge-system_dev
{
    "StackId": "arn:aws:cloudformation:xxxxxxxxx"
}
```
    
- 結果で「StackId」が表示されたら作成された
  コンソールで確認すると作成始まってる。
        

- 構築したスタックのステータスを確認
    
    ```bash
    $ aws cloudformation describe-stacks --stack-name hoge-stack --profile hoge-system_dev
    {
        "Stacks": [
            {
                "StackId": "arn:aws:cloudformation:xxxxxxx:xxxxxxx",
                "StackName": "hoge-stack",
                }
            }
    ```
        
    
## AWS CLIからスタックを削除

```bash
aws cloudformation delete-stack --stack-name [スタック名]
```


## AWS CLIからスタックを更新

```bash
aws cloudformation update-stack --stack-name [スタック名] --template-body [テンプレのパス]
```

※上記コマンドだとスタックの直接更新になるため、以下のような機能が用意されている。

#### ■テンプレート変更前ー差分チェック（ドリフト検出）

- スタック作成後にリソースを直接変更された場合、スタック作成した時点と差分が出てしまう。
- テンプレート修正前に、テンプレートと現在のリソースの差分（ドリフト）を検出をして確認することができる。


#### ■スタック更新前ー変更内容の確認　(変更セット)

- 変更セット(ChangeSet)を使えば、更新前に変更内容や影響範囲を確認できる。
- 詳細は[変更セットを使用したスタックの更新](#1-変更セットを使用したスタックの更新)に記載

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-changesets.html
     
      
:::note  info
**★スタック更新時の流れは以下のようになる★**
1. ドリフト検出
1. テンプレート修正
1. 変更セットの作成・確認
1. スタック更新
:::

<br/>

---

# 変更セットを使用したスタックの更新

- 変更セットを使用すると、スタックの更新の前に、変更内容と変更によって影響を受けるリソースを確認できる。
- 変更セットは、AWSマネジメントコンソールのCloudFormation コンソール、AWS CLI、または CloudFormation API を使用して作成および管理できる

    1. 変更セットの作成
    変更したスタックのテンプレートまたは入力パラメータ値を指定して変更セットを作成する。(現在のスタックと変更内容が比較され、変更セットが生成される)
    2. 変更セットの確認
    変更されるスタック設定やリソースを確認する。
    3. 変更セットの実行
    変更内容が問題なければ変更セットを実行する。CloudFormation によって、これらの変更を使用してスタックが更新される。