【AWS】CloudFormationとは

## CloudFormationとは
AWSリソースをコード化できるマネージドサービスです。
YAML, JSON, XMLなどで書いたコードをCloudFormationに読み込ませることで、AWSサービスを自動作成することができます。
![test.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/838372/3077f190-562c-644b-270c-b677166c1dac.png)

## CloudFormationを使うにはVSCodeがおすすめ
VSCodeには、`CloudFormation`という拡張機能があるのでそちらをダウンロードします。
![スクリーンショット 2021-05-19 9.25.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/838372/e23243bd-0e7b-db13-4301-4feedc5e8f57.png)

### YAMLを使う場合は以下の修正が必要です
Settings.json内に以下の追記をしてください。

```json:Settings.json
"yaml.schemas": {
    "https://d33vqc0rt9ld30.cloudfront.net/latest/gzip/CloudFormationResourceSpecification.json": [
            "*.cf.yaml",
            "*.cf.yml",
            "*.cfn/*.yaml",
            "*.cfn/*.yml",
            "cloud*formation/*.yaml",
            "cloud*formation/*.yml"
        ]
},
"yaml.customTags": [
    "!Ref",
    "!Sub scalar",
    "!Sub sequence",
    "!Join sequence",
    "!FindInMap sequence",
    "!GetAtt scalar",
    "!GetAtt sequence",
    "!Base64 mapping",
    "!GetAZs",
    "!Select scalar",
    "!Select sequence",
    "!Split sequence",
    "!ImportValue",
    "!Condition",
    "!Equals sequence",
    "!And",
    "!If",
    "!Not",
    "!Or"
],
```

## それではVPCを作ってみましょう

### Yamlを作成
「start」+[Tab]でテンプレートが表示されます。

```yaml:test.yml
AWSTemplateFormatVersion: 2010-09-09
Description: ---
Resources:
  myVPC1:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/21
      EnableDnsSupport: true
      Tags:
        - Key: Name
          Value: myVPC-1
```

### CloudFormationを開き設定をする

![スクリーンショット 2021-05-19 9.32.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/838372/66c24491-f176-ecae-f9a8-e7bdcd81889b.png)

![スクリーンショット 2021-05-19 9.34.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/838372/6c8408c7-75aa-7d0d-62d6-2f91b9e86d74.png)

### 作成されているか確認しましょう
![スクリーンショット 2021-05-19 9.36.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/838372/6c23cccf-b8b0-1d9c-bf41-7d8d49709f22.png)

作成されていました！
OKです

## 次にサブネットを作成しましょう
### Yamlを更新する
```yaml:test.yml
AWSTemplateFormatVersion: 2010-09-09
Description: ---
Resources:
  myVPC1:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/21
      EnableDnsSupport: true
      Tags:
        - Key: Name
          Value: myVPC-1
  subnetName:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: 'ap-northeast-1a'
      VpcId: !Ref myVPC1
      CidrBlock: 10.0.0.0/24
      Tags:
        - Key: Name
          Value: Public-1
```

ここで大切なのは、`!Ref`です。
これは組み込み関数と呼ばれるもので、同一テンプレート内で作成されたものの値を返す役割があります。
上記の例で言うと、`VpcId`は、**myVPC1**と同じ値にしてくださいと命令していることになります。

### CloudFormationを更新

![スクリーンショット 2021-05-19 9.45.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/838372/3e46ffc0-1e70-ff1b-4f96-69ba88221684.png)

## 次にセキュリティグループを作成しましょう
### Yamlを更新する
```yaml:test.yml
AWSTemplateFormatVersion: 2010-09-09
Description: ---
Resources:
  myVPC1:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/21
      EnableDnsSupport: true
      Tags:
        - Key: Name
          Value: myVPC-1
  subnetName:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: 'ap-northeast-1a'
      VpcId: !Ref myVPC1
      CidrBlock: 10.0.0.0/24
      Tags:
        - Key: Name
          Value: Public-1
  secGroupName:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: WEB-SG
      GroupDescription: WEB-SG
      VpcId: !Ref myVPC1
      # インバウンド（ポート番号22のすべてからアクセスを受け付ける）
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: 0.0.0.0/0
      Tags:
        - Key: Name
          Value: WEB-SG
```

## 次にSubnet内にEC2を作ろう
ここからは新しいテンプレートファイルを作ります。
新しいテンプレートを作成したテンプレートに紐付ける**クロススタック**に関して学んでいきましょう。

### なぜ分けるべきなのか？
ブラックベルトで紹介されている通り、様々なリソースを1つのファイルにまとめてしまうと可読性が著しく落ちてしまうためレイヤーごとに分けるのがスマートです。

![スクリーンショット 2021-05-19 10.06.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/838372/c8175167-08bd-4b38-17b9-7e9ca7a67c3f.png)


https://youtu.be/Viyqh9fNBjw?t=2598

### Yamlを作成する
```yaml:test.yml
AWSTemplateFormatVersion: 2010-09-09
Description: ---
Resources:
  myVPC1:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/21
      EnableDnsSupport: true
      Tags:
        - Key: Name
          Value: myVPC-1
  subnetName:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: 'ap-northeast-1a'
      VpcId: !Ref myVPC1
      CidrBlock: 10.0.0.0/24
      Tags:
        - Key: Name
          Value: Public-1
  secGroupName:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: WEB-SG
      GroupDescription: WEB-SG
      VpcId: !Ref myVPC1
      # インバウンド（ポート番号22のすべてからアクセスを受け付ける）
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: 0.0.0.0/0
      Tags:
        - Key: Name
          Value: WEB-SG
# 外部でも値を使えるようにする
Outputs:
  Public1: # 適当な名前をつける
    Value: !Ref subnetName # どの値を参照するか
    Export:
      Name: Public-Subnet1 # 外部で呼び出す時の名前
  SG1:
    Value: !Ref secGroupName
    Export:
      Name: WEB-SG1
```

![スクリーンショット 2021-05-19 10.25.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/838372/71fd2b83-3c23-7a07-2eab-ba7f24d19f4e.png)

```yaml:ec2.yml
AWSTemplateFormatVersion: 2010-09-09
Resources:
  myEC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      KeyName: Keypair
      ImageId: ami-0ca38c7440de1749a # インスタンスのID（今回はAmazon Linux 2 AMI (HVM), SSD Volume Type）
      InstanceType: t2.micro
      Monitoring: false
      SecurityGroupIds:
        - !ImportValue WEB-SG1
      SubnetId: !ImportValue Public-Subnet1
      Tags:
        - Key: Name
          Value: Frontend
```

![スクリーンショット 2021-05-19 10.26.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/838372/5c10c676-2977-7a69-d6a2-644f5be8b293.png)

![スクリーンショット 2021-05-19 10.28.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/838372/5ac7e200-2ffa-4405-4203-a0d30fbdfde2.png)