CloudFormation으로 EC2 인스턴스 구축해 보기

CloudFormation으로 EC2 인스턴스를 구축해 보는 과정을 정리해 봤습니다.
2022.02.03

안녕하세요 클래스메소드 김재욱(Kim Jaewook) 입니다. 이번에는 CloudFormation으로 EC2 인스턴스를 구축해 보는 과정을 정리해 봤습니다.

EC2를 구축하기에 앞서, VPC, 서브넷과 같은 네트워크가 구성 되어 있어야 합니다. CloudFormation으로 네트워크를 구성하는 방법은 아래 블로그를 참고해 주세요.

CloudFormation Output

이번에는 하나의 CloudFormation 스택에서 모든 작업 처리 하는 것이 아니기 때문에 다른 스택으로 값을 넘겨줄 필요가 있습니다. 값을 넘겨주기 위해서는「Outputs:」를 사용합니다.

#-------------------------------------------------------------------
#OutPut
#-------------------------------------------------------------------
Outputs:
# VPC
  VPC:
    Value: !Ref VPC
    Export:
      Name: !Sub "test-vpc"

  VPCCIDR:
    Value: !Ref VPCCIDR
    Export:
      Name: !Sub "test-vpc-cidr"
# Subnet
  PublicSubnetA:
    Value: !Ref PublicSubnetA
    Export:
      Name: !Sub "test-front-subnet-1a"

  PublicSubnetACIDR:
    Value: !Ref PublicSubnetACIDR
    Export:
      Name: !Sub "test-front-subnet-1a-cidr"

  PublicSubnetC:
    Value: !Ref PublicSubnetC
    Export:
      Name: !Sub "test-front-subnet-1c"

  PublicSubnetCCIDR:
    Value: !Ref PublicSubnetCCIDR
    Export:
      Name: !Sub "test-front-subnet-1c-cidr"

  PrivateSubnetA:
    Value: !Ref PrivateSubnetA
    Export:
      Name: !Sub "test-application-subnet-1a"

  PrivateSubnetACIDR:
    Value: !Ref PrivateSubnetACIDR
    Export:
      Name: !Sub "test-application-subnet-1a-cidr"

  PrivateSubnetC:
    Value: !Ref PrivateSubnetC
    Export:
      Name: !Sub "test-application-subnet-1c"

  PrivateSubnetCCIDR:
    Value: !Ref PrivateSubnetCCIDR
    Export:
      Name: !Sub "test-application-subnet-1c-cidr"

# Route
  FRONTRTB:
    Value: !Ref FRONTRTB
    Export:
      Name: !Sub "test-front-rtb"

  APPRTB1A:
    Value: !Ref APPRTB1A
    Export:
      Name: !Sub "test-application-rtb-1a"

  APPRTB1C:
    Value: !Ref APPRTB1C
    Export:
      Name: !Sub "test-application-rtb-1c"

먼저 파라미터에는 EC2에 접속하기 위한 키 페어 값을 입력합니다.

CloudFormation 내에서 키 페어를 생성할 수는 없기 때문에 콘솔 환경으로 들어가서 2개의 키 페어를 생성합니다. 편의상 키 페어 이름을 파라미터의 디폴트 값과 동일하게 적었지만 실제로 사용할 때는 디폴트 이름과 다른 이름을 사용할 필요가 있습니다.

파라미터 생성

AWSTemplateFormatVersion: "2010-09-09"
Description:
  Create EC2, RDS

Metadata:
  "AWS::CloudFormation::Interface":
    ParameterGroups:
      - Label:
          default: "EC2 Configuration"
        Parameters:
          - BastionEC2KeyPair
          - AppEC2KeyPair

    ParameterLabels: 
      BastionEC2KeyPair: 
        default: "BastionEC2KeyPair"
      AppEC2KeyPair: 
        default: "AppEC2KeyPair"
# ------------------------------------------------------------#
# Input Parameters
# ------------------------------------------------------------# 
Parameters:
  BastionEC2KeyPair:
    Type: String
    Default: "BastionEC2KeyPair"
  AppEC2KeyPair:
    Type: String
    Default: "AppEC2KeyPair"

보안 그룹 생성

# ------------------------------------------------------------#
#  Create Security Groups
# ------------------------------------------------------------#
Resources:
  FrontBastionSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: "test-front-bastion-sg"
      GroupName: test-front-bastion-sg
      SecurityGroupIngress:
              IpProtocol: tcp
              FromPort : 22
              ToPort : 22
              CidrIp: 0.0.0.0
      VpcId: { "Fn::ImportValue": !Sub "test-vpc" }
      Tags: 
        - Key: "Name"
          Value: test-front-bastion-sg
  APPSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: "test-app-sg"
      GroupName: test-app-sg
      SecurityGroupIngress:
            -
              IpProtocol: tcp
              FromPort : 22
              ToPort : 22
              SourceSecurityGroupId: !GetAtt FrontBastionSecurityGroup.GroupId
      VpcId: { "Fn::ImportValue": !Sub "test-vpc" }
      Tags: 
        - Key: "Name"
          Value: test-app-sg

테스트용이기 때문에 test-front-bastion-sg에서 0.0.0.0으로 아이피를 뚫어놨지만, 실제 사용할 때는 파라미터에서 자신의 아이피를 입력 받아서 넣는 편이 좋습니다.

EC2 인스턴스 생성

# ------------------------------------------------------------#
#  Create EC2 Instance
# ------------------------------------------------------------#
# Bastion EC2
  BastionEC2:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: ami-0f66bf23ed74d9284
      InstanceType: t3.micro
      KeyName: !Ref BastionEC2KeyPair
      DisableApiTermination: true
      BlockDeviceMappings: 
      - DeviceName: "/dev/xvda"
        Ebs: 
          VolumeType: "gp2"
          DeleteOnTermination: "true"
          VolumeSize: "8"
      SecurityGroupIds:
        - !Ref FrontBastionSecurityGroup
      SubnetId: { "Fn::ImportValue": !Sub "test-front-subnet-1a" }
      Tags: 
        - Key: "Name"
          Value: test-front-bastion
# test-app-1a
  AppEC2:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: ami-0f66bf23ed74d9284
      InstanceType: t3.micro
      KeyName: !Ref AppEC2KeyPair
      DisableApiTermination: true
      BlockDeviceMappings: 
      - DeviceName: "/dev/xvda"
        Ebs: 
          VolumeType: "gp2"
          DeleteOnTermination: "true"
          VolumeSize: "50"
      SecurityGroupIds:
        - !Ref APPSecurityGroup
      SubnetId: { "Fn::ImportValue": !Sub "test-application-subnet-1a" }
      Tags: 
        - Key: "Name"
          Value: test-app-1a

Public Subnet에서 발판 서버를 만들고, Private Subnet에는 외부에서 접속이 불가능한 EC2 서버 한대를 구축 했습니다.

접속 테스트

  • ssh -i "BastionEC2KeyPair.pem" ec2-user@ec2-13-124-243-180.ap-northeast-2.compute.amazonaws.com

해당 명령어로 접속해 보면 정상적으로 발판 서버에 접속한 것을 확인할 수 있습니다.

  • scp -i /BastionEC2KeyPair.pem /AppEC2KeyPair.pem ec2-user@13.124.243.180:~
  • ssh -i "AppEC2KeyPair.pem" ec2-user@10.0.181.212

이어서 scp 명령어를 사용해서 발판 서버로 키 페어를 업로드 하고 ssh로 접속해 보면 프라이빗 EC2에도 문제 없이 접속 되는 것을 확인할 수 있습니다.

콘솔 환경에서 EC2 환경에 들어가보면 CloudFormation으로 생성한 EC2 인스턴스를 확인할 수 있습니다.

참고