AWS CloudFormationを使ってみた

# はじめに
* AWS CloudFormationとは、VPC, Subnet, EC2Instance等のリソースを一括で構築したいときに、yamlファイルに設定を記述して、構築をオートメーション化するサービスである。つまりVPC, Subnet, SecurityGroup, ...などと、何回もマネージメントコンソール上でポチポチする必要がない。
* yamlじゃなくてjsonでもOK

このCloudFormationによるインフラ構築をAWS CLIを用いて行ってみました。


## 前提知識
* VPC, EC2, SecurityGroup, etc.
* S3
* AWS CLI
* 
但し、それほど深い知識は必要ない。

## Key pairの作成
AWSのkey pairを事前に作成しておく。すでにある場合は問題ない。

## yaml fileの作成
[aws_cf.yaml](https://github.com/oga-a/aws_cloudformation/blob/master/aws_cf.yaml)（ファイル名は任意）でVPC, Subnet, EC2Instance等のリソースの設定を記述。
自分が作成したものを[GitHub](https://github.com/oga-a/aws_cloudformation)にpushしているので、その内容を簡単に解説する。（ほぼしていないが）

### これは最初に必ず書く
```yaml
AWSTemplateFormatVersion: '2010-09-09'
Resources:
```

### VPC
```yaml
  VPC1:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/16
      Tags:
      - Key: Name
        Value: VPC1
```

### InternetGateway
```yaml
  InternetGateway:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
      - Key: Name
        Value: VPC1-IGW
  AttachGateway:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref VPC1
      InternetGatewayId: !Ref InternetGateway
```

### RouteTable
```yaml
  FrontendRouteTable:
    Type: AWS::EC2::RouteTable
    DependsOn: AttachGateway
    Properties:
      VpcId: !Ref VPC1
      Tags:
      - Key: Name
        Value: VPC1-FrontendRoute
  FrontendRoute:
    Type: AWS::EC2::Route
    DependsOn: AttachGateway
    Properties:
      RouteTableId: !Ref FrontendRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway
```

### Subnet
```yaml


  FrontendSubnet:
    Type: AWS::EC2::Subnet
    DependsOn: AttachGateway
    Properties:
      CidrBlock: 10.0.1.0/24
      AvailabilityZone: us-west-2a
      MapPublicIpOnLaunch: 'true'
      VpcId: !Ref VPC1
      Tags:
      - Key: Name
        Value: VPC1-FrontendSubnet
  FrontendSubnetRouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref FrontendSubnet
      RouteTableId: !Ref FrontendRouteTable
```

### SecurityGroup
```yaml
  SecurityGroup1:
    Type: AWS::EC2::SecurityGroup
    Properties:
      VpcId: !Ref VPC1
      GroupDescription: Enable some access via user defined port
      SecurityGroupIngress:
      - IpProtocol: tcp
        FromPort: 22
        ToPort: 22
        CidrIp: 0.0.0.0/0
      - IpProtocol: tcp
        FromPort: 80
        ToPort: 80
        CidrIp: 0.0.0.0/0
      - IpProtocol: tcp
        FromPort: 8000
        ToPort: 8000
        CidrIp: 0.0.0.0/0
      - IpProtocol: tcp
        FromPort: 8888
        ToPort: 8888
        CidrIp: 0.0.0.0/0
      SecurityGroupEgress:
      - IpProtocol: -1
        FromPort : 0
        ToPort : 65535
        CidrIp: 0.0.0.0/0
      Tags:
      - Key: Name
        Value: Template-SecurityGroup
```

### Interface of EC2
```yaml
  EC2Interface:
    Type: AWS::EC2::NetworkInterface
    Properties:
      SubnetId: !Ref FrontendSubnet
      GroupSet:
        - !Ref SecurityGroup1
      SourceDestCheck: true
```

### EC2
KeyNameの所は、AWSに登録した公開鍵のKey pairの名前

```yaml
  EC2Instance1:
    Type: AWS::EC2::Instance
    Properties:
      InstanceType: t2.micro
      ImageId: ami-09dd2e08d601bff67
      KeyName: id_rsa_oga
      NetworkInterfaces:
        - NetworkInterfaceId: !Ref EC2Interface
          DeviceIndex: 0
      BlockDeviceMappings:
        - DeviceName: "/dev/sda1"
          Ebs:
            VolumeSize: 15
            VolumeType: gp2
      Tags:
        - Key: Name
          Value: Template-Instance
```

### Elastic IP of EC2
```yaml
  EC2ControlPortAddress:
    Type: AWS::EC2::EIP
    Properties:
      Domain: vpc
  EC2AssociateControlPort:
    Type: AWS::EC2::EIPAssociation
    Properties:
      AllocationId: !GetAtt EC2ControlPortAddress.AllocationId
      NetworkInterfaceId: !Ref EC2Interface
```

## AWS CLIを用いたstack作成
stackとはざっくり言うと、上記で解説した[aws_cf.yaml](https://github.com/oga-a/aws_cloudformation/blob/master/aws_cf.yaml)に記述しているVPC, EC2などのリソースの集合のこと。
これをAWS CLIを用いて立ち上げ、その後破棄する。

```bash
# S3上にyamlファイルを転送
aws s3 mb s3://cf-templates-oga
aws s3 cp ./aws_cf.yaml s3://cf-templates-oga/aws_cf.yaml

# cf-oga1という名前でstack作成
aws cloudformation create-stack --stack-name cf-oga1 --template-url https://cf-templates-oga.s3-us-west-2.amazonaws.com/aws_cf.yaml

# stackを破棄、これを実行するとstackに紐づいているVPC, EC2などのリソースもすべて消える。
aws cloudformation delete-stack --stack-name cf-oga1
```
もちろんマネージメントコンソールからでもできるが、command line上からやりたかった。

## その他
SSH接続するために、Elastic IPのIP addressをcommand lineを通して確認する。

```bash
# IP addressを含むEC2の一覧を表示する
aws ec2 describe-addresses
```

#参考文献
* CloudFormation
    * https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/Welcome.html
    * https://dev.classmethod.jp/articles/cloudformation-beginner01/
    * https://qiita.com/namoshika/items/528d8a50f399b998b14b
    * https://qiita.com/yasuhiroki/items/8463eed1c78123313a6f