CloudFormationとKumogata2ざっくりまとめ

# 1. AWS CloudFormation
## 1.1. 概要
**AWSのサーバー・NW・セキュリティといったインフラ周りの環境構築を自動で行うことができる** サービス。
**※一方、アプリケーションソースの自動デプロイには向いていない**


CloudFormationでの環境構築に使われたAWSリソースの集合を「スタック」と呼ぶ。
「スタック」の設定ファイル(JSON or YAML)は「テンプレート」と呼ぶ。


## 1.2. テンプレートの書き方
参考: https://qiita.com/y-ohgi/items/89f07e866713185799f5

テンプレートを書くときにはいくつか第一階層の「セクション」があるが、
以下5つのセクションをだいたい使うらしい。

```
AWSTemplateFormatVersion: '2010-09-09' # CloudFormationのバージョンを指定。2021年時点でもこのバージョンしかないので、もはやおまじない状態
Description: # テンプレート実行時に表示される説明らしい
Parameters: # Resourcesで使える定数を定義する箇所
Resources: # スタックの構成要素であるAWSリソースの設定を記述する箇所
Outputs: # なんか返すらしい
```

### 1.2.1. Resourcesセクション
以下のような構成になっているらしい。

```
Resources:
    <スタック内でAWSリソースに対してつける任意の名前>: # スタック内で一意でないとダメらしい
        Type: <CloudFormationで作成するAWSリソース> # 設定値は、リファレンスを参照
        Properties: # 以下、作成するAWSリソースの設定値. AWSリソースの種類ごとに設定項目は異なる。こちらもリファレンスを参照。
```
[CloudFormationのテンプレートのリファレンス](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-template-resource-type-ref.html) 

## 1.3. AWSマネジメントコンソール(CloudFormation)でのスタックの作り方
参考：https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/cfn-using-console-create-stack-template.html

以下の流れになる模様。

```
①テンプレートをS3にアップロードする
②スタックの作成につかうテンプレート(①のヤツ)を指定し、作成時のパラメータを指定する(任意)
③スタックの作成を実行する
```

**動作イメージ**

![cloudformationの全貌.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59542/4eac92ec-b96f-a867-9d5c-2497dac1598e.jpeg)


# 2. Kumogata2
## 2.1. 概要
クックパッドの人が作成したコマンドラインツール。RubyのGem。
これを使うと、CloudFomationのテンプレートをRubyで書ける(Kumogata2で定義されているルールに沿って)。
Kumogata2を使うことにより、以下の**メリット**が生まれる。

```
 ①テンプレートを分割して書くことができる
 ②Ruby形式のテンプレートから、Kumogata2コマンドを使ってスタックの作成・更新・削除ができる)※
 ③Kumogata2コマンドで、テンプレートのフォーマットをJSONへ変換することもできる※
```

※どちらにせよ、CloudFormation利用にあたっては、
**S3へのJSON or YAMLフォーマットでのテンプレートのアップロードは必要。②の場合はコマンド実行時に変換&アップロードも裏で行われる。**

前提として、 先述の**CloudFormationの使い方をある程度知っていないと、Kumogata2でどう設定すればよいのか、何を実行しているのかイメージがわかないため、先に把握しておくこと。**

## 2.2. テンプレートの書き方のイメージ
素のCloudFormationとkumogata2でテンプレートの書き方を比較すると、具体的には以下のような形になる。

参考：
https://dev.classmethod.jp/articles/sugano-023-kumogata2/
https://github.com/kumogata/kumogata2-plugin-ruby

### 素のCloudFormation
```template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Description: Test Instance
Resources:
  TestInstance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: ami-abcdexxxxxx
      InstanceType: t3.micro
      Tags:
      - Key: Name
        Value: test
      BlockDeviceMappings:
      - DeviceName: "/dev/xvda"
        Ebs:
          VolumeType: gp2
          VolumeSize: '32'
```

### kumogata2
```template.rb
template do
    AWSTemplateFormatVersion "2010-09-09"
    Description (<<-EOS).undent
        Test Instance
    EOS
    Resources do
        # 直で書いたヤツ
        TestInstance do
            Type "AWS::EC2::Instance"
            Properties do
                ImageId 'ami-abcdexxxxxx'
                InstanceType 't3.micro'
                Tags [
                    _{
                        Key "Name"
                        Value "test"
                    }
                ]
                BlockDeviceMappings [
                    _{
                        DeviceName "/dev/xvda"
                        Ebs do
                            VolumeType "gp2"
                            VolumeSize '32'
                        end
                    }
                ]
            end
        end
    end
    # 分割テンプレートを使う場合(インデントは_includeした位置からスタートするので、.rb内では最上位階層のインデントから書けばOK)
    _include 'template_resource.rb'
end
```


```template_resource.rb

TestInstance2 do
    Type "AWS::EC2::Instance"
    Properties do
        ImageId 'ami-abcdexxxxxx'
        InstanceType 't3.micro'
        Tags [
            _{
                Key "Name"
                Value "test"
            }
        ]
        BlockDeviceMappings [
            _{
                DeviceName "/dev/xvda"
                Ebs do
                    VolumeType "gp2"
                    VolumeSize '32'
                end
            }
        ]
    end
end
```

**Kumogata2→YAMLの対応ルール**
(なんか書いてて文章だけだとマジ意味分かんないとおもったので見なくていいかも)

- :: は  __ に変換される
- _path()は パスのキーを持つハッシュを作る
- 半角スペースはハッシュを意味する
- []は配列を意味する
_{ ... } は...の部分が配列の要素となるハッシュであることを意味する
- do 〜 end はハッシュのバリューがハッシュになることを意味する


## 2.3. Kumogata2でのスタック操作
### 2.3.1. 生成
```
# <スタック名>のスタックを<テンプレートファイル(.rb)>を元に生成する
kumogata2 create <テンプレートファイル(.rb)> <スタック名>
```
参考: https://github.com/kumogata/kumogata2

### 2.3.2. 更新
```
# <スタック名>のスタックを<テンプレートファイル(.rb)>を元に更新する
kumogata2 update <テンプレートファイル(.rb)> <スタック名>
```
参考: https://qiita.com/motchi0214/items/77c2d4ba1418d0d77baa

### 2.3.3. 削除
```
# <スタック名>のスタックを削除する
kumogata2 delete <スタック名>
```


# 3. CloudFormation使うときの注意点
## 3.1. CloudFormationで作成したスタック内のリソースを個別に削除するな
cloudformationを使って作成したスタックを構成するAWSリソースを、cloudformationを使わずに個別に削除してしまった場合、
cloudformationからスタックの削除をしようとする(AWSマネジメントコンソール)と失敗する。

これは、スタックの削除処理が、「①スタックを構成する各AWSリソースの削除→②スタックの削除」 という形で進むが、
①ですでに削除済みのAWSリソースを削除しようとしたときに失敗判定となって処理が中断されてしまい、引き続いての「②スタックの削除」に到達しないからのようである。
管理対象のAWSリソースの削除後に自身の削除をしようとして、でもすでに存在しないAWSリソースは削除できず、失敗判定となってスタック自身も削除できなくなる。

## 3.2. やらかした場合のリカバリー
AWSマネジメントコンソールで、個別に削除したAWSリソースの削除をスキップさせる設定を施した上で、スタックの削除を行う必要がある。