CloudFormationでEC2を立ち上げる

# Cloud Formationとは

コマンドで立ち上げることができる。

1. yml(例えば、`instance.yml`(以下参照))に設定を書く(ymlの書き方については以下で詳しく)

2. 
```bash:起動
aws cloudformation create-stack --template-body file://instance.yml --stack-name instance --parameters ParameterKey=InstanceType,ParameterValue=t2.micro
```
3. 
```bash:取り消し
aws cloudformation delete-stack --stack-name instance
```

# yamlの書き方

## EC2を立ち上げるだけのyaml

```yaml:instance.yml
---
AWSTemplateFormatVersion: '2010-09-09'
Description: 'Template for Kafka Broker'
Parameters:
  KeyName:
    Description: Name of an existing EC2 KeyPair to enable SSH access to the instance
    Type: AWS::EC2::KeyPair::KeyName
    ConstraintDescription: must be the name of an existing EC2 KeyPair.
    Default: test-key
  InstanceType:
    Description: WebServer EC2 instance type
    Type: String
    Default: t2.micro
    AllowedValues:
    - t1.micro
    - t2.nano
    - t2.micro
    - t2.small
    - t2.medium
    - t2.large
    ConstraintDescription: must be a valid EC2 instance type.

Resources:
  EC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      InstanceType:
        Ref: InstanceType

Outputs:
  InstanceId:
    Description: InstanceId of the newly created EC2 instance
    Value:
      Ref: EC2Instance
  AZ:
    Description: Availability Zone of the newly created EC2 instance
    Value:
      Fn::GetAtt:
      - EC2Instance
      - AvailabilityZone
  PublicDNS:
    Description: Public DNSName of the newly created EC2 instance
    Value:
      Fn::GetAtt:
      - EC2Instance
      - PublicDnsName
  PublicIP:
    Description: Public IP address of the newly created EC2 instance
    Value:
      Fn::GetAtt:
      - EC2Instance
      - PublicIp
```

大事なのは、`Resources`だけ。

1. InstanceType
2. key

をParameterであげれるようにする。（もしも決まっている場合には、Parameterを使わずに、直接書き込んでもよい。）


## 既存のSubnet内にEC2を立てる

subnet_idを`SubnetId`に書く

```
Resources:
  EC2Instance:
    ...
    SubnetId: subnet-0000000000000
```


## Public Ip Addressが割り振られないとき

解決方法: subnetのauto-assign IP settingをenableにする

参考: https://dev.classmethod.jp/cloud/aws/auto-assign-public-ip-by-cfn/

## volumeをつける

Instanceの中の`BlockDeviceMappings`の中に、DeviceNameとEbsの設定を書く。以下の設定では、volume typeが`gp2`の10GBのVolumeをつけることになる

```
Resources:
  ...
  EC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      ...
      BlockDeviceMappings:
      -
        DeviceName: /dev/sdf
        Ebs:
          VolumeSize: 10
          VolumeType: gp2
      ...
```

## Elastic IpをEC2につける

### Elastic Ip を作成する場合
`AWS::EC2::EIP`で作成して、`AWS::EC2::EIPAssociation`で付加すればよい

```yaml
...
Resources:
  ElasticIP:
    Type: "AWS::EC2::EIP"
    Properties:
      Domain: vpc

  EC2Instance:
    ...

  IPAssoc:
    Type: AWS::EC2::EIPAssociation
    Properties:
      InstanceId: !Ref EC2Instance
      EIP: !Ref ElasticIP
...
```

### 既存のElastic Ipを付加する場合

```yaml

...
Resources:
  EC2Instance:
    ...

  IPAssoc:
    Type: AWS::EC2::EIPAssociation
    Properties:
      InstanceId: !Ref EC2Instance
      EIP: <existing Elastic IP Address>
```

余談：Elastic IpにもNameのTagをつけたかったがつけられない。

# cloudformationの基本コマンド

## 作ったStackの中身を見る

```
aws cloudformation describe-stacks --stack-name instance
```

## Cloudformationで作ったInstanceIdをゲットする

```bash
aws ec2 describe-instances \
--query "Reservations[*].Instances[*].InstanceId[]" \
--filters "Name=tag-key,Values=aws:cloudformation:stack-name" "Name=tag-value,Values=<stack_name>" \
--output=text
```