Wisdom’s Cloud

[AWS] 26. AWS CloudFormation 본문

AWS/Beginner

[AWS] 26. AWS CloudFormation

지혜로운지혜쓰 2022. 3. 19. 23:47

구분 내용
서비스명 AWS CloudFormation
설명 모든 클라우드 인프라 리소스를 모델링 및 프로비저닝
주요 특징 - 사용자 인프라용 템플릿 생성
- JSON, YAML로 텍스트 모델링 작성
- 인프라 변경 사항에 대해 미리보기 기능 제공
- 코드처럼 버전 관리 / 코드 검토 / 템플릿 업데이트 기능 제공
- 종속성 요구에 기반하여 AWS 리소스 제공
- 개발, CI/CD 및 관리 도구와 통합
- 추가적인 비용 없이 사용할 수 있으며, 리소스 사용 비용만 지불
프리티어(Free Tier) CloudFormation의 사용은 무료이지만, AWS 리소스에 대한 비용은 발생됨

 

 

Cloudformation의 특징
  • 인프라 관리 간소화
  • 신속한 인프라 복제
  • 인프라 변경 사항을 쉽게 제어 및 추적

 

 

Cloudformation의 구성 요소
  • Template: Stack 리소스 프로비저닝 및 구성을 위해 필요한 파일로, JSON 또는 YAML 형식 텍스트 파일로 작성한다. Stack에서 프로비저닝할 리소스를 설명하며, Cloudformation Designer 또는 텍스트 편집기를 사용하여 Template 생성이 가능하다.
  • Cloudformation: Stack을 생성하고, Stack에 대한 변경 사항을 확인 및 업데이트하며, Stack 생성 및 변경 중 에러 감지를 통한 롤백을 지원한다.
  • Stack: 하나의 단위로 관리할 수 있는 AWS 리소스 모음으로, Stack의 생성/수정/삭제를 통해 리소스 모음의 생성/수정/삭제가 가능하다. Stack의 모든 리소스는 Template을 통해 정의되며, Stack을 삭제하면 관련 리소스가 모두 삭제된다.

 

 

Cloudformation Template의 구성 사항
  • AWSTemplateFormationVersion: version date
  • Description: JSON string
  • Metadata: 템플릿에 대한 추가 정보
  • Parameters: 템플릿 실행 시 전달할 파라미터 값
  • Mappings: 템플릿 실행 시 선택하게 되는 값(특정 리전, 인스턴스)
  • Conditions: 특정 자원에 대한 생성 여부를 판단하는 조건
  • Transform: Serverless 애플리케이션용
  • Resources (필수): 생성될 AWS 자원 나열
  • Outputs: 템플릿 실행 후 만들어진 자원 결과 값(자원 ID, IP 등)

 

 

실습: Cloudformation을 활용한 VPC 생성

step 1 Cloudformation을 통해 스택 생성

 

* VPC 생성을 위한 Cloudformation Template 작성을 위해

다음과 같이 코드를 작성한 후, CreateVPC.yaml 파일로 저장한다. *

AWSTemplateFormatVersion: 2010-09-09
Description: Deploy a VPC

Resources:
  ToturialVPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 172.0.0.0/16
      EnableDnsHostnames: true

  InternetGateway:
    Type: AWS::EC2::InternetGateway

  AttachGateway:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref ToturialVPC
      InternetGatewayId: !Ref InternetGateway

  PublicSubnet01:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref ToturialVPC
      CidrBlock: 172.0.0.0/24
      AvailabilityZone: !Select
        - '0'
        - !GetAZs ''

  PrivateSubnet01:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref ToturialVPC
      CidrBlock: 172.0.1.0/24
      AvailabilityZone: !Select
        - '0'
        - !GetAZs ''

  PublicRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref ToturialVPC

  PublicRoute:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref PublicRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway

  PublicSubnetRouteTableAssociation1:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnet01
      RouteTableId: !Ref PublicRouteTable

  PrivateRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref ToturialVPC

  PrivateSubnetRouteTableAssociation1:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PrivateSubnet01
      RouteTableId: !Ref PrivateRouteTable

Outputs:
  VPC:
    Description: Toturial VPC ID
    Value: !Ref ToturialVPC
  AZ1:
    Description: Availability Zone 1
    Value: !GetAtt
      - PublicSubnet01
      - AvailabilityZone

 

1. 콘솔에 로그인한 후 [서비스] -> [관리 및 거버넌스] 항목에서 [CloudFormation] 메뉴를 클릭한다. [스택] 메뉴를 클릭한 후 [스택 생성] 버튼을 클릭한다.
2. 스택 생성 페이지에서 [준비된 템플릿]을 선택하고 [템플릿 파일 업로드]을 클릭한다. [파일 선택] 버튼을 클릭하여 저장한 CreateVPC.yaml 파일을 선택하고 [다음] 버튼을 클릭한다.
3. 스택 세부 정보 지정 페이지에서 스택 이름에 'Create-VPC'를 입력한 후 [다음] 버튼을 클릭한다.
4. 스택 옵션 구성 페이지에서 [다음] 버튼을 클릭한다.
5. 스택 검토 페이지에서 진행될 내역을 확인한 후 [스택 생성] 버튼을 클릭한다.
6. [스택 세부 정보] 페이지에서 생성된 스택을 확인할 수 있으며, 해당 스택의 생성 결과에 따른 [출력] 섹션에 정의된 정보를 확인할 수 있다.
7. [서비스] -> [네트워킹 및 콘텐츠 전송] -> [VPC]를 클릭한 후 Cloudformation을 통해 생성된 VPC를 확인한다. [태그] 탭에 추가로 등록된 Cloudformation 관련 정보도 확인할 수 있다.

 

step 2 Cloudformation 스택 업데이트

 

* 기존에 작성된 CreateVPC.yaml 파일을 오픈하여 다음과 같이 녹색으로 표기된 내용을

기존 코드에 추가한 후, UpdateVPC.yaml 파일로 저장한다. *

AWSTemplateFormatVersion: 2010-09-09
Description: Make a VPC

Resources:
  ToturialVPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 172.0.0.0/16
      EnableDnsHostnames: true

  InternetGateway:
    Type: AWS::EC2::InternetGateway

  AttachGateway:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref ToturialVPC
      InternetGatewayId: !Ref InternetGateway

  PublicSubnet01:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref ToturialVPC
      CidrBlock: 172.0.0.0/24
      AvailabilityZone: !Select
        - '0'
        - !GetAZs ''

  PrivateSubnet01:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref ToturialVPC
      CidrBlock: 172.0.1.0/24
      AvailabilityZone: !Select
        - '0'
        - !GetAZs ''

  PublicSubnet02:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref ToturialVPC
      CidrBlock: 172.0.2.0/24
      AvailabilityZone: !Select
        - '1'
        - !GetAZs ''

  PrivateSubnet02:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref ToturialVPC
      CidrBlock: 172.0.3.0/24
      AvailabilityZone: !Select
        - '1'
        - !GetAZs ''

  PublicRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref ToturialVPC

  PublicRoute:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref PublicRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway

  PublicSubnetRouteTableAssociation1:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnet01
      RouteTableId: !Ref PublicRouteTable

  PublicSubnetRouteTableAssociation02:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnet02
      RouteTableId: !Ref PublicRouteTable

  PrivateRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref ToturialVPC

  PrivateSubnetRouteTableAssociation1:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PrivateSubnet01
      RouteTableId: !Ref PrivateRouteTable

  PrivateSubnetRouteTableAssociation02:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PrivateSubnet02
      RouteTableId: !Ref PrivateRouteTable

Outputs:
  VPC:
    Description: Toturial VPC ID
    Value: !Ref ToturialVPC
  AZ1:
    Description: Availability Zone 1
    Value: !GetAtt
      - PublicSubnet01
      - AvailabilityZone
  AZ2:
    Description: Availability Zone 2
    Value: !GetAtt
      - PublicSubnet02
      - AvailabilityZone

 

1. 기존에 생성된 스택으로 이동하여 [업데이트] 버튼을 클릭한다.
2. 스택 업데이트 페이지에서 [현재 템플릿 교체]을 선택하고 [템플릿 파일 업로드]을 클릭한다. [파일 선택] 버튼을 클릭하여 저장한 UpdateVPC.yaml 파일을 선택하고 [다음] 버튼을 클릭한다.
3. 스택 세부 정보 지정 페이지에서 [다음] 버튼을 클릭한다.
4. 스택 옵션 구성 페이지에서 [다음] 버튼을 클릭한다.
5. 스택 검토 페이지에서 검토 결과를 확인하고 [변경 세트 보기] 버튼을 클릭한다.
6. 변경 세트 미리보기 항목에서 추가로 등록한 프라이빗 서브넷과 퍼블릭 서브넷의 정보를 확인하고 [실행] 버튼을 클릭한다.
7. [스택 세부 정보] 페이지에서 스택이 정상적으로 업데이트 되었음을 확인한다.
8. [서비스] -> [네트워크 및 콘텐츠] -> [VPC]로 이동한 후 [서브넷] 메뉴에서 Private Subnet2와 Public Subnet2가 정상적으로 등록되었음을 확인한다.

 

step 3 Cloudformation Designer에서 보기와 스택 삭제

1. [스택 세부 정보] 페이지에서 템플릿 섹션의 [Designer에서 보기] 버튼을 클릭한다.
2. Cloudformation Designer 항목에서 비주얼하게 리소스와 템플릿의 개별 속성 및 정보를 확인할 수 있다.
3. [스택 세부 정보] 페이지로 이동한 후 [삭제] 버튼을 클릭한다.
4. 스택 삭제 확인 팝업에서 [스택 삭제] 버튼을 클릭한다.
5. [스택 세부 정보] 페이지에서 스택이 모두 삭제됨을 확인할 수 있다.
6. [서비스] -> [네트워크 및 콘텐츠] -> [VPC]를 클릭한 후 Cloudformation으로 생성된 VPC와 Subnet, Route table이 정상적으로 삭제되었음을 확인한다.

 

 

실습: Cloudformation으로 웹 애플리케이션 배포 및 관리

step 1 Cloudformation을 이용하여 웹 애플리케이션 배포

 

* 해당 실습을 통해 Apache Web Server에 호스팅되며

Amazon Linux AMI를 통한 단일 인스턴스 PHP 웹 애플리케이션을 배포하게 된다.

Apache Web Service, PHP는 기본적으로 Amazon Linux AMI에 설치되어 있는

AWS Cloudformation Helper Script를 통해 설치된다.

Cloudformation Helper Script는 스택을 통해 생성된 EC2에 소프트웨어를 설치하고

서비스를 시작하는데 사용할 수 있는 Python 기반의 Helper Script다.

이후 템플릿 섹션에서는 설치할 패키지와 파일을 설명하는 Metadata를 출력하며,

Apache Web Server가 실행 중인지를 확인하는 코드도 포함하고 있다.

또한 Amazon EC2 인스턴스 정의의 Properties 섹션에서 UserData 속성에는

cfn-init를 호출하여 패키지 및 파일을 설치하는 CloudInit 스크립트가 들어 있으며,

스택의 실행 결과로 'AWS CloudFormation Sample PHP application'을 출력한다.

 

Cloudformation Template 작성을 위해 다음과 같이 코드를 작성한 후,

WebApplication.JSON 파일로 저장한다. *

{
  "AWSTemplateFormatVersion" : "2010-09-09",

  "Description" : "AWS CloudFormation Sample Template: Sample template that can be used to test EC2 updates. **WARNING** This template creates an Amazon Ec2 Instance. You will be billed for the AWS resources used if you create a stack from this template.",

  "Parameters" : {
    "InstanceType" : {
      "Description" : "WebServer EC2 instance type",
      "Type" : "String",
      "Default" : "t2.nano",
      "AllowedValues" : [
         "t1.micro",
         "t2.nano",
         "t2.micro",
         "t2.small"
      ],
      "ConstraintDescription" : "must be a valid EC2 instance type."
    }
  },

  "Mappings" : {
    "AWSInstanceType2Arch" : {
      "t1.micro"    : { "Arch" : "HVM64"  },
      "t2.nano"     : { "Arch" : "HVM64"  },
      "t2.micro"    : { "Arch" : "HVM64"  },
      "t2.small"    : { "Arch" : "HVM64"  }
    },
    "AWSRegionArch2AMI" : {
      "us-east-1"        : {"HVM64" : "ami-0ff8a91507f77f867", "HVMG2" : "ami-0a584ac55a7631c0c"},
      "us-west-2"        : {"HVM64" : "ami-a0cfeed8", "HVMG2" : "ami-0e09505bc235aa82d"},
      "us-west-1"        : {"HVM64" : "ami-0bdb828fd58c52235", "HVMG2" : "ami-066ee5fd4a9ef77f1"},
      "eu-west-1"        : {"HVM64" : "ami-047bb4163c506cd98", "HVMG2" : "ami-0a7c483d527806435"},
      "eu-west-2"        : {"HVM64" : "ami-f976839e", "HVMG2" : "NOT_SUPPORTED"},
      "eu-west-3"        : {"HVM64" : "ami-0ebc281c20e89ba4b", "HVMG2" : "NOT_SUPPORTED"},
      "eu-central-1"     : {"HVM64" : "ami-0233214e13e500f77", "HVMG2" : "ami-06223d46a6d0661c7"},
      "ap-northeast-1"   : {"HVM64" : "ami-06cd52961ce9f0d85", "HVMG2" : "ami-053cdd503598e4a9d"},
      "ap-northeast-2"   : {"HVM64" : "ami-0a10b2721688ce9d2", "HVMG2" : "NOT_SUPPORTED"},
      "ap-northeast-3"   : {"HVM64" : "ami-0d98120a9fb693f07", "HVMG2" : "NOT_SUPPORTED"},
      "ap-southeast-1"   : {"HVM64" : "ami-08569b978cc4dfa10", "HVMG2" : "ami-0be9df32ae9f92309"},
      "ap-southeast-2"   : {"HVM64" : "ami-09b42976632b27e9b", "HVMG2" : "ami-0a9ce9fecc3d1daf8"},
      "ap-south-1"       : {"HVM64" : "ami-0912f71e06545ad88", "HVMG2" : "ami-097b15e89dbdcfcf4"},
      "us-east-2"        : {"HVM64" : "ami-0b59bfac6be064b78", "HVMG2" : "NOT_SUPPORTED"},
      "ca-central-1"     : {"HVM64" : "ami-0b18956f", "HVMG2" : "NOT_SUPPORTED"},
      "sa-east-1"        : {"HVM64" : "ami-07b14488da8ea02a0", "HVMG2" : "NOT_SUPPORTED"},
      "cn-north-1"       : {"HVM64" : "ami-0a4eaf6c4454eda75", "HVMG2" : "NOT_SUPPORTED"},
      "cn-northwest-1"   : {"HVM64" : "ami-6b6a7d09", "HVMG2" : "NOT_SUPPORTED"}
    }
  },

  "Resources" : {
    "WebServerInstance": {
      "Type" : "AWS::EC2::Instance",
      "Metadata" : {
        "Comment" : "Install a simple PHP application",
        "AWS::CloudFormation::Init" : {
          "config" : {
            "packages" : {
              "yum" : {
                "httpd"             : [],
                "php"               : []
              }
            },
            "files" : {
              "/var/www/html/index.php" : {
                "content" : { "Fn::Join" : ["", [
                  "<?php\n",
                  "echo '<h1>AWS CloudFormation sample PHP application</h1>';\n",
                  "?>\n"
                ]]},
                "mode"    : "000644",
                "owner"   : "apache",
                "group"   : "apache"
              },
              "/etc/cfn/cfn-hup.conf" : {
                "content" : { "Fn::Join" : ["", [
                  "[main]\n",
                  "stack=", { "Ref" : "AWS::StackId" }, "\n",
                  "region=", { "Ref" : "AWS::Region" }, "\n"
                ]]},
                "mode"    : "000400",
                "owner"   : "root",
                "group"   : "root"
              },
              "/etc/cfn/hooks.d/cfn-auto-reloader.conf" : {
                "content": { "Fn::Join" : ["", [
                  "[cfn-auto-reloader-hook]\n",
                  "triggers=post.update\n",
                  "path=Resources.WebServerInstance.Metadata.AWS::CloudFormation::Init\n",
                  "action=/opt/aws/bin/cfn-init -s ", { "Ref" : "AWS::StackId" }, " -r WebServerInstance ",
                                                   " --region     ", { "Ref" : "AWS::Region" }, "\n",
                  "runas=root\n"
                ]]}
              }
            },
            "services" : {
              "sysvinit" : {
                "httpd"   : { "enabled" : "true", "ensureRunning" : "true" },
                "cfn-hup" : { "enabled" : "true", "ensureRunning" : "true",
                    "files" : ["/etc/cfn/cfn-hup.conf", "/etc/cfn/hooks.d/cfn-auto-reloader.conf"]}
              }
            }
          }
        }
      },
      "Properties": {
        "ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" },
                          { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] },
        "InstanceType"   : { "Ref" : "InstanceType" },
        "SecurityGroups" : [ {"Ref" : "WebServerSecurityGroup"} ],
        "UserData"       : { "Fn::Base64" : { "Fn::Join" : ["", [
             "#!/bin/bash -xe\n",
             "yum install -y aws-cfn-bootstrap\n",
             "# Install the files and packages from the metadata\n",
             "/opt/aws/bin/cfn-init -v ",
             "         --stack ", { "Ref" : "AWS::StackName" },
             "         --resource WebServerInstance ",
             "         --region ", { "Ref" : "AWS::Region" }, "\n",
             "# Start up the cfn-hup daemon to listen for changes to the Web Server metadata\n",
             "/opt/aws/bin/cfn-hup || error_exit 'Failed to start cfn-hup'\n",
              "# Signal the status from cfn-init\n",
             "/opt/aws/bin/cfn-signal -e $? ",
             "         --stack ", { "Ref" : "AWS::StackName" },
             "         --resource WebServerInstance ",
             "         --region ", { "Ref" : "AWS::Region" }, "\n"
        ]]}}
      },
      "CreationPolicy" : {
        "ResourceSignal" : {
          "Timeout" : "PT5M"
        }
      }
    },
    "WebServerSecurityGroup" : {
      "Type" : "AWS::EC2::SecurityGroup",
      "Properties" : {
        "GroupDescription" : "Enable HTTP access via port 80",
        "SecurityGroupIngress" : [
          {"IpProtocol" : "tcp", "FromPort" : "80", "ToPort" : "80", "CidrIp" : "0.0.0.0/0"}
        ]
      }
    }
  },

  "Outputs" : {
    "WebsiteURL" : {
      "Description" : "Application URL",
      "Value" : { "Fn::Join" : ["", ["http://", { "Fn::GetAtt" : [ "WebServerInstance", "PublicDnsName" ]}]] }
    }
  }
}

 

1. 콘솔에서 [CloudFormation]에 접속한 후 [스택] 메뉴에서 [스택 생성] 버튼을 클릭한다.
2. 스택 생성 페이지에서 [준비된 템플릿]을 선택하고 [템플릿 파일 업로드]를 클릭한다. [파일 선택]을 클릭하여 저장한 WebApplication.JSON 파일을 선택하고 [다음] 버튼을 클릭한다.
3. 스택 세부 정보 지정 페이지에서 스택 이름에 'WebApplication'을 입력하고 파라미터 항목에서 [t2.nano]를 선택한 후 [다음] 버튼을 클릭한다.
4. 스택 옵션 구성 페이지에서 [다음] 버튼을 클릭한다.
5. 스택 검토 페이지에서 최종으로 생성할 스택 정보를 확인하고 [스택 생성] 버튼을 클릭한다.
6. [스택 세부 정보] 페이지에서 스택을 확인하고 출력 탭에서 WebsiteURL을 확인한 후 해당 주소를 클릭한다.
7. 설정 완료된 PHP 웹 사이트에 접속할 수 있다.

 

step 2 EC2 인스턴스 유형 업데이트

 

* Cloudformation을 통해 생성된 EC2 인스턴스에 접속하기 위한 Key Pair를 부여하고,

SSH 접속을 위해 Security 그룹을 변경하는 리소스를 추가하고,

Application을 변경하는 코드를 추가하여 기존 스택을 업데이트한다.

 

기존에 작성된 WebApplication.JSON 파일을 오픈하여 다음과 같이 녹색으로 표기된 내용을

기존 코드에 추가한 후, WebApplicationUpdate.JSON 파일로 저장한다. *

 

{
  "AWSTemplateFormatVersion" : "2010-09-09",

  "Description" : "AWS CloudFormation Sample Template: Sample template that can be used to test EC2 updates. **WARNING** This template creates an Amazon Ec2 Instance. You will be billed for the AWS resources used if you create a stack from this template.",

  "Parameters" : {
    "InstanceType" : {
      "Description" : "WebServer EC2 instance type",
      "Type" : "String",
      "Default" : "t2.nano",
      "AllowedValues" : [
         "t1.micro",
         "t2.nano",
         "t2.micro",
         "t2.small"
      ],
      "ConstraintDescription" : "must be a valid EC2 instance type."
    },

    "KeyName" : {
      "Description" : "Name of an existing Amazon EC2 key pair for SSH access",
      "Type": "AWS::EC2::KeyPair::KeyName"
    },
    "SSHLocation" : {
      "Description" : " The IP address range that can be used to SSH to the EC2 instances",
      "Type": "String",
      "MinLength": "9",
      "MaxLength": "18",
      "Default": "0.0.0.0/0",
      "AllowedPattern": "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})",
      "ConstraintDescription": "must be a valid IP CIDR range of the form x.x.x.x/x."
    }
  },

  "Mappings" : {
    "AWSInstanceType2Arch" : {
      "t1.micro"    : { "Arch" : "HVM64"  },
      "t2.nano"     : { "Arch" : "HVM64"  },
      "t2.micro"    : { "Arch" : "HVM64"  },
      "t2.small"    : { "Arch" : "HVM64"  }
    },
    "AWSRegionArch2AMI" : {
      "us-east-1"        : {"HVM64" : "ami-0ff8a91507f77f867", "HVMG2" : "ami-0a584ac55a7631c0c"},
      "us-west-2"        : {"HVM64" : "ami-a0cfeed8", "HVMG2" : "ami-0e09505bc235aa82d"},
      "us-west-1"        : {"HVM64" : "ami-0bdb828fd58c52235", "HVMG2" : "ami-066ee5fd4a9ef77f1"},
      "eu-west-1"        : {"HVM64" : "ami-047bb4163c506cd98", "HVMG2" : "ami-0a7c483d527806435"},
      "eu-west-2"        : {"HVM64" : "ami-f976839e", "HVMG2" : "NOT_SUPPORTED"},
      "eu-west-3"        : {"HVM64" : "ami-0ebc281c20e89ba4b", "HVMG2" : "NOT_SUPPORTED"},
      "eu-central-1"     : {"HVM64" : "ami-0233214e13e500f77", "HVMG2" : "ami-06223d46a6d0661c7"},
      "ap-northeast-1"   : {"HVM64" : "ami-06cd52961ce9f0d85", "HVMG2" : "ami-053cdd503598e4a9d"},
      "ap-northeast-2"   : {"HVM64" : "ami-0a10b2721688ce9d2", "HVMG2" : "NOT_SUPPORTED"},
      "ap-northeast-3"   : {"HVM64" : "ami-0d98120a9fb693f07", "HVMG2" : "NOT_SUPPORTED"},
      "ap-southeast-1"   : {"HVM64" : "ami-08569b978cc4dfa10", "HVMG2" : "ami-0be9df32ae9f92309"},
      "ap-southeast-2"   : {"HVM64" : "ami-09b42976632b27e9b", "HVMG2" : "ami-0a9ce9fecc3d1daf8"},
      "ap-south-1"       : {"HVM64" : "ami-0912f71e06545ad88", "HVMG2" : "ami-097b15e89dbdcfcf4"},
      "us-east-2"        : {"HVM64" : "ami-0b59bfac6be064b78", "HVMG2" : "NOT_SUPPORTED"},
      "ca-central-1"     : {"HVM64" : "ami-0b18956f", "HVMG2" : "NOT_SUPPORTED"},
      "sa-east-1"        : {"HVM64" : "ami-07b14488da8ea02a0", "HVMG2" : "NOT_SUPPORTED"},
      "cn-north-1"       : {"HVM64" : "ami-0a4eaf6c4454eda75", "HVMG2" : "NOT_SUPPORTED"},
      "cn-northwest-1"   : {"HVM64" : "ami-6b6a7d09", "HVMG2" : "NOT_SUPPORTED"}
    }
  },

  "Resources" : {
    "WebServerInstance": {
      "Type" : "AWS::EC2::Instance",
      "Metadata" : {
        "Comment" : "Install a simple PHP application",
        "AWS::CloudFormation::Init" : {
          "config" : {
            "packages" : {
              "yum" : {
                "httpd"             : [],
                "php"               : []
              }
            },
            "files" : {
              "/var/www/html/index.php" : {
                "content" : { "Fn::Join" : ["", [
                  "<?php\n",
                  "echo '<h1>AWS CloudFormation sample PHP application</h1>';\n",
                  "echo 'Updated version via UpdateStack';\n ",
                  "?>\n"
                ]]},
                "mode"    : "000644",
                "owner"   : "apache",
                "group"   : "apache"
              },
              "/etc/cfn/cfn-hup.conf" : {
                "content" : { "Fn::Join" : ["", [
                  "[main]\n",
                  "stack=", { "Ref" : "AWS::StackId" }, "\n",
                  "region=", { "Ref" : "AWS::Region" }, "\n"
                ]]},
                "mode"    : "000400",
                "owner"   : "root",
                "group"   : "root"
              },
              "/etc/cfn/hooks.d/cfn-auto-reloader.conf" : {
                "content": { "Fn::Join" : ["", [
                  "[cfn-auto-reloader-hook]\n",
                  "triggers=post.update\n",
                  "path=Resources.WebServerInstance.Metadata.AWS::CloudFormation::Init\n",
                  "action=/opt/aws/bin/cfn-init -s ", { "Ref" : "AWS::StackId" }, " -r WebServerInstance ",
                                                   " --region     ", { "Ref" : "AWS::Region" }, "\n",
                  "runas=root\n"
                ]]}
              }
            },
            "services" : {
              "sysvinit" : {
                "httpd"   : { "enabled" : "true", "ensureRunning" : "true" },
                "cfn-hup" : { "enabled" : "true", "ensureRunning" : "true",
                    "files" : ["/etc/cfn/cfn-hup.conf", "/etc/cfn/hooks.d/cfn-auto-reloader.conf"]}
              }
            }
          }
        }
      },
      "Properties": {
        "ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" },
                          { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] },
        "InstanceType"   : { "Ref" : "InstanceType" },
        "KeyName" : { "Ref" : "KeyName" },
        "SecurityGroups" : [ {"Ref" : "WebServerSecurityGroup"} ],
        "UserData"       : { "Fn::Base64" : { "Fn::Join" : ["", [
             "#!/bin/bash -xe\n",
             "yum install -y aws-cfn-bootstrap\n",
             "# Install the files and packages from the metadata\n",
             "/opt/aws/bin/cfn-init -v ",
             "         --stack ", { "Ref" : "AWS::StackName" },
             "         --resource WebServerInstance ",
             "         --region ", { "Ref" : "AWS::Region" }, "\n",
             "# Start up the cfn-hup daemon to listen for changes to the Web Server metadata\n",
             "/opt/aws/bin/cfn-hup || error_exit 'Failed to start cfn-hup'\n",
              "# Signal the status from cfn-init\n",
             "/opt/aws/bin/cfn-signal -e $? ",
             "         --stack ", { "Ref" : "AWS::StackName" },
             "         --resource WebServerInstance ",
             "         --region ", { "Ref" : "AWS::Region" }, "\n"
        ]]}}
      },
      "CreationPolicy" : {
        "ResourceSignal" : {
          "Timeout" : "PT5M"
        }
      }
    },
    "WebServerSecurityGroup" : {
      "Type" : "AWS::EC2::SecurityGroup",
      "Properties" : {
        "GroupDescription" : "Enable HTTP access via port 80",
        "SecurityGroupIngress" : [
          {"IpProtocol" : "tcp", "FromPort" : "22", "ToPort" : "22", "CidrIp" : { "Ref" : "SSHLocation"}},
          {"IpProtocol" : "tcp", "FromPort" : "80", "ToPort" : "80", "CidrIp" : "0.0.0.0/0"}
        ]
      }
    }
  },

  "Outputs" : {
    "WebsiteURL" : {
      "Description" : "Application URL",
      "Value" : { "Fn::Join" : ["", ["http://", { "Fn::GetAtt" : [ "WebServerInstance", "PublicDnsName" ]}]] }
    }
  }
}

 

1. EC2에 부여할 키 페어 생성을 위해 [서비스] -> [컴퓨팅] -> [EC2]로 이동한 후 [네트워크 및 보안] 메뉴에서 [키 페어]를 선택하고 [키 페어 생성] 버튼을 클릭한다.
2. 키 페어 생성 페이지에서 이름에 'Keypair-CF'를 입력한 후 파일 형식에서 [.ppk]를 선택하고 [키 페어 생성] 버튼을 클릭한다. 키 페어 생성과 동시에 다운로드된 Keypair-CF.ppk 파일을 잘 보관한다.
3. [스택 세부 정보] 페이지에서 기존에 생성된 스택을 선택하고 [업데이트] 버튼을 클릭한다.
4. 스택 업데이트 페이지에서 [현재 템플릿 교체]를 선택한 후 [템플릿 파일 업로드]를 선택한다. [파일 선택]을 클릭하여 저장한 WebApplicationUpdate.JSON 파일을 선택하고 [다음] 버튼을 클릭한다.
5. 스택 세부 정보 지정 페이지에서 다음과 같이 파라미터를 선택한 후 [다음] 버튼을 클릭한다.
6. 스택 옵션 구성 페이지에서 [다음] 버튼을 클릭한다.
7. 스택 검토 페이지에서 최종 검토 결과를 확인한 후 [스택 업데이트] 버튼을 클릭한다.
8. 스택의 업데이트가 완료된 것을 확인하고, 출력 탭에서 WebsiteURL 값을 클릭하여 웹 페이지가 수정되었는지 확인한다.
9. 웹 페이지가 정상적으로 업데이트되었음을 확인한다.
10. [서비스] -> [컴퓨팅] -> [EC2] -> [인스턴스]에서 기존 인스턴스(t2.nano)가 삭제되고, 신규 인스턴스(t2.micro)가 정상적으로 생성됨을 확인한다.
11. 신규로 생성된 인스턴스의 퍼블릭 IP를 확인한 후 Putty를 실행하여 [Session] 항목의 [Host Name]에 확인된 퍼블릭 IP를 입력한다. 이후 키 페어 등록을 위해 [Connection] -> [SSH] -> [Auth]에 이전에 생성한 키 페어를 선택하고 [Oepn] 버튼을 클릭한다.
12. Putty를 통해 터미널에 접속한 후 'ec2-user'를 입력하여 서버에 로그인한다.

'AWS > Beginner' 카테고리의 다른 글

[AWS] 28. AWS Lambda  (0) 2022.03.22
[AWS] 27. AWS OpsWorks  (0) 2022.03.21
[AWS] 25. 클라우드 용어 정리(11)  (0) 2022.03.19
[AWS] 24. Amazon Lightsail  (0) 2021.03.12
[AWS] 23. 클라우드 용어 정리(10)  (0) 2021.03.12