> For the complete documentation index, see [llms.txt](https://kde6260.gitbook.io/dev/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://kde6260.gitbook.io/dev/cloud-computing/cloudformation-vpc.md).

# CloudFormation으로 EC2 & ElasticIP 생성하기

#### AWS CloudFormation

CloudFormation은 인프라 리소스를 코드 기반으로 프로비저닝하는 IAC(Infrastructure As Code)를 제공한다. 언어 형식은 `JSON`과 `YAML` 두 가지를 지원한다. `JSON` 또는 `YAML`로 프로비저닝할 리소스를 정의하고 config를 설정한 코드를 **템플릿**이라고 하고 템플릿을 이용하여 AWS 클라우드에 생성되는 리소스들의 묶음 단위를 **스택**이라고 한다. CloudFormation 템플릿을 `YAML`로 작성하여 EC2 인스턴스와 ElasticIP를  생성해보자.

EC2 인스턴스와 ElasticIP를 생성하는 템플릿은 아래와 같이 크게 3가지 속성으로 되어있다.

```yaml
Description:
    ...

Mappings:
    ...

Resources:
    ...
```

| 속성          | 역할                          |
| ----------- | --------------------------- |
| Description | 템플릿 내용이나 작성자에 대한 설명을 기재한다.  |
| Mappings    | 키-값 구조의 데이터를 정의한다.          |
| Resources   | 스택에 생성하고 싶은 AWS 리소스들을 정의한다. |

위 속성들 외에 다른 템플릿 속성을 알고싶다면 [여기](https://docs.aws.amazon.com/en_en/AWSCloudFormation/latest/UserGuide/template-anatomy.html)를 참고하면 된다.&#x20;

#### Resources에 EC2 정의하기

Resources에 EC2 인스턴스를 정의해보자.  아래와 같은 형식으로 리소스를 정의할 수 있다.

```yaml
Resources:
  <ResourceName>:
    Type: AWS::EC2::Instance
    Properties:
      <Key1>: <Value1>
      <Key2>: <Value2>
```

원하는 이름을 `<ResourceName>`에 정의한다. EC2 인스턴스를 생성하므로 리소스 타입은 `AWS::EC2::Instance` 이다. `Properties` 키에는 EC2 인스턴스를 생성하는 데 필요한 설정들을 키-값 형태로 정의한다. 위 형식을 참고하여 리소스 이름과 속성을 정의하면 아래와 같다.&#x20;

```yaml
Resources:
  EC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      AvailabilityZone: !Select [ 0, !GetAZs '']
      ImageId:
        Fn::FindInMap:
          - AmiRegionMap
          - !Ref AWS::Region
          - HVM64
      InstanceType: t2.micro
      KeyName: my-pair-key 
```

| 속성               | 역                                                                                                                                        |
| ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| AvailabilityZone | 인스턴스가 생성될 AZ를 정의한다. 위 코드에서는 `GetAZs` 함수로 가용 AZ들을 조회하여 그 중 첫번째 AZ에 인스턴스를 생성한다. 리전을 기준으로 AZ가 결정되므로 `aws-cli` 명령어에서 지정한 리전이 바뀌면 가용 AZ도 바뀐다. |
| ImageId          | 어떤 AMI(AWS Machine Image)를 사용할 지 정의한다. AMI는 리전과 OS별로 ID가 다르기 때문에 Mappings 에 `리전 - AMIID` 구조로 값을 미리 정의해서 사용했다.                            |
| InstanceType     | 인스턴스의 사양을 설정한다. `t2.micro`가 free-tier로 제공되므로 `t2.micro`로 설정했다.                                                                           |
| KeyName          | 인스턴스에 SSH으로 접속할 때 사용할 키의 이름을 명시한다. 인스턴스가 한 번 스택에 생성되고나면 바꿀 수 없다.                                                                         |

`ImageId`에서 사용하는 `AmiRegionMap`은 아래와 같다. `Ubuntu 18.04 64bit`에 해당하는 AMI만을 사용할 것이기 때문에 리전 당 AMI의 ID는 1개씩 정의했다.&#x20;

```yaml
Mappings:
  AmiRegionMap:
    ap-northeast-2:
      HVM64: ami-00379ec40a3e30f87
    us-east-1:
      HVM64: ami-0ff8a91507f77f867
    us-west-2:
      HVM64: ami-06d51e91cea0dac8d
    ...
```

사용된 내장함수 `Fn::Select`, `Fn::GetAZs`, `Fn::FindInMap`, `Fn::Ref`에 대해 자세히 알고싶다면 [여기](https://docs.aws.amazon.com/ko_kr/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference.html)를 참고한다.

#### ElasticIP 정의하고 EC2에 할당하기

ElasticIP를 `Resources`에 정의하고 스택 생성 시 위에서 정의한 EC2에 ElasticIP가 할당되도록 해보자. ElasticIP를 정의하는 형식도 속성만 다를 뿐 EC2와 동일한 형식을 갖는다.&#x20;

```yaml
EIPforEC2:
  Type: AWS::EC2::EIP
  Properties:
    InstanceId: !Ref EC2Instance
    Tags:
      - Key: Name
        Value: practice CloudFormation
```

| 속          | 역                                                             |
| ---------- | ------------------------------------------------------------- |
| InstanceId | ElasticIP가 퍼블릭 주소로 할당될 인스턴스를 지정한다. 위에서 미리한 EC2 리소스의 이름을 지정했다. |
| Tags       | 리소스를 구분하기 위해 태그를 지정한다.                                        |

#### 템플릿으로 스택 생성하기

위에서 작성한 코드를 종합해보면 아래와 같다.

```yaml
Description:
  Written by DaEun Kim.
  This template deploys an EC2 instance and elastic IP.


Mappings:
  AmiRegionMap:
    ap-northeast-2:
      HVM64: ami-00379ec40a3e30f87
    us-east-1:
      HVM64: ami-0ff8a91507f77f867
    us-west-2:
      HVM64: ami-06d51e91cea0dac8d


Resources:
  EC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      AvailabilityZone: !Select [ 0, !GetAZs '']
      ImageId:
        Fn::FindInMap:
          - AmiRegionMap
          - !Ref AWS::Region
          - HVM64
      InstanceType: t2.micro
      KeyName: my-pair-key

  EIPforEC2:
    Type: AWS::EC2::EIP
    Properties:
      InstanceId: !Ref EC2Instance
      Tags:
        - Key: Name
          Value: practice CloudFormation
```

이 템플릿을 이용하여 AWS 클라우드에 EC2 인스턴스와 ElasticIP를 생성해보자. 스택을 생성하는 aws-cli 명령어는 아래와 같다.

```yaml
aws cloudformation create-stack \n
--stack-name <스택이름> \n
--template-body file://<템플릿 파일이름> \n 
--capabilities CAPABILITY_NAMED_IAM \n
--profile <AWS user profile>
```

| 옵션              | 역                                          |
| --------------- | ------------------------------------------ |
| --stack-name    | 생성할 스택의 이름을 지정한다.                          |
| --template-body | 위에서 만든 템플릿 파일의 이름을 지정한다.                   |
| --capabilities  | 리소스를 생성할 권한이 있는 IAM 유저임을 AWS에 알린다.         |
| --profile       | AWS 유저프로필의 이름. 유저프로필에 정의된 리전에 의해 AZ가 결정된다. |

`create-stack` 뿐만 아니라 `update-stack`으로 기존의 스택을 수정할 수도 있다. (cloudformation 명령어에 대해 자세히 알고싶다면 [여기](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/index.html#cli-aws-cloudformation)를 참고한다.) 위 명령어를 이용하여 스택을 성공정으로 생성하면 아래와 같이 생성된 스택의 ID를 받을 수 있다.

```yaml
$ aws cloudformation create-stack --stack-name test2 --template-body file://launch_instance.yml --capabilities CAPABILITY_NAMED_IAM --profile=my-profile
{
    "StackId": "arn:aws:cloudformation:us-west-2:133143555446:stack/test2/14f91a50-29f4-11ea-b8dd-0a233d312e0a"
}
```

AWS 콘솔에 접속하여 확인해보자.

![](/files/-LxEwU4C33qjfCuj4Dor)

CloudFormation의 `Stacks` 메뉴에서 생성된 스택을 확인할 수 있다. EC2 인스턴스와 Elastic IP가 잘 생성되었다. `Logical ID` 필드에 직접 정의했던 리소스의 이름이 나타난다. `Physical ID` 필드의 값을 클릭하면 EC2 콘솔로 이동하여 생성된 인스턴스와 IP를 확인할 수 있다.
