IaC 실습 - AWS CloudFormation

jsbak·2023년 5월 16일
0

Cloud

목록 보기
47/59

AWS CloudFormation 실습

  • Azure Resource Manager, GCP Deployment Manager

주요 섹션 설명

1. Resources(생성)

  • Resources
    • Logical ID 는 영숫자(A-Za-z0-9)여야 하며 템플릿 내에서 고유해야 합니다. 논리적 이름을 사용하여 템플릿의 다른 부분에서 리소스를 참조할 수 있다.
    Resources:
      Logical ID:
        Type: Resource type
        Properties:
          Set of properties
  • ❗ AWS 인프라의 실질적인 섹션
    • EC2 인스턴스, S3 버킷, ELB등과 같은 클라우드 포메이션을 이용해 AWS 웹 콘솔에서 실행하는 것으로 거의 모든 리소스 유형을 생성가능 하지만 신규 또는 최첨단의 AWS 리소스는 즉시 제공되지 않는 경우가 존재한다.
    • 리소스에는 기본 반환값이 있다.
    • Ref를 이용해 이 반환값을 얻어올 수 있고 템플릿의 다른 위치에 사용가능
      • 예를 들어 AWS::EC2::VPC 리소스 유형은 기본 반환값을 갖고 있고 이 값은 VPC의 ID 이다.
      • 리소스 ID를 복사해서 지정하지 않아도 쉽게 참조할 수 있는 기능 존재

2. Parameters(입력)

  • Parameters
  • 명령줄 도구에 입력하는 매개변수와 동일하게 스택을 만들거나 업데이트할 때 정의하는 입력값
  • 파라미터는 템플릿의 변경 없이도 스택을 커스터마이즈할 수 있게 해줍니다.
    • 템플릿; 코드를 담고 있는 파일
  • AMI ID, VPC ID, Subnet ID등과 같은 매개변수를 사용가능하다.
    • 도쿄의 AMI ID와 서울의 AMI ID는 다르다.

3. Output(출력)

  • Output
  • 스택이 완료된 후에 결과물을 출력하려고 할때 유용
    • 예를 들어 ELB의 퍼블릭 URL이나 EC2의 퍼블릭 IP를 출력한다.
      • 테스트/접속 할수 있는 엔드포인드

4. Mapping(지정)

  • Mappings
  • 리전의 특화된 템플릿에서 어떠한 요소를 참조할 때 필요
    • 예를 들어 템플릿에 EC2 AMI ID에 대한 매핑을 지정하는 것으로 💦 AMI ID가 리전에 특화된 리소스이기 때문에 유효한 AMI ID를 리전별로 지정하려고 할때 사용한다.

VPC 생성 실습

  • VPC 생성
vi test-vpc.yaml
----------------------------------------
AWSTemplateFormatVersion: 2010-09-09
Resources:
  VPC: # 리소스의 논리적인 이름, 템플릿 내의 리소스를 참조할 수 있습니다.
    Type: AWS::EC2::VPC # 이렇게 리소스 정의하면 ID를 반환한다.
    Properties:
      CidrBlock: 192.168.0.0/16
      EnableDnsSupport: true # VPC가 Amazon에서 제공하는 DNS 서버를 통해 DNS 확인을 지원하는지 여부를 결정
      EnableDnsHostnames: true # VPC가 퍼블릭 IP 주소가 있는 인스턴스에 퍼블릭 DNS 호스트 이름을 할당하도록 지원할 여부를 결정, 체크가 안된게(false) 디폴트, DNSHostname을 쓰겠다고 설정하는 부분
      InstanceTenancy: default # 인스턴스 테넌시와 자원을 공유하겠다.
      Tags: # 태그 명명
        - Key: Name # Name의 맨앞의 N은 대문자를 써야한다.
          Value: test-vpc 
  PUB2A:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: ap-northeast-2a
      VpcId: !Ref VPC # !Ref, '!' 간소화의 의미가 있다. Ref; 리소스의 논리적 이름을 지정하면 물리적 ID 반환
      CidrBlock: 192.168.0.0/20
      MapPublicIpOnLaunch: true # 기본값(false), 이 서브넷에서 시작된 인스턴스가 퍼블릭 IPv4 주소를 할당 받을지 여부
      Tags:
        - Key: Name
          Value: test-pub-2a
  PUB2B:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: ap-northeast-2b
      VpcId: !Ref VPC
      CidrBlock: 192.168.16.0/20
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: test-pub-2b
  PUB2C:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: ap-northeast-2c
      VpcId: !Ref VPC
      CidrBlock: 192.168.32.0/20
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: test-pub-2c
  PUB2D:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: ap-northeast-2d
      VpcId: !Ref VPC
      CidrBlock: 192.168.48.0/20
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: test-pub-2d
  PVT2A:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: ap-northeast-2a
      VpcId: !Ref VPC
      CidrBlock: 192.168.64.0/20
      MapPublicIpOnLaunch: false # 기본값 false 이니 안 넣어도 되지만 구분하기 위해서 넣음.
      Tags:
        - Key: Name
          Value: test-pvt-2a
  PVT2B:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: ap-northeast-2b
      VpcId: !Ref VPC
      CidrBlock: 192.168.80.0/20
      MapPublicIpOnLaunch: false
      Tags:
        - Key: Name
          Value: test-pvt-2b
  PVT2C:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: ap-northeast-2c
      VpcId: !Ref VPC
      CidrBlock: 192.168.96.0/20
      MapPublicIpOnLaunch: false
      Tags:
        - Key: Name
          Value: test-pvt-2c
  PVT2D:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: ap-northeast-2d
      VpcId: !Ref VPC
      CidrBlock: 192.168.112.0/20
      MapPublicIpOnLaunch: false
      Tags:
        - Key: Name
          Value: test-pvt-2d
  InternetGateway: # 간소화된 인터넷 게이트 만드는 방법은 태그(태그 중 이름만)만 지정하면 된다.
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
        - Key: Name
          Value: test-igw
  VPCGatewayAttachment: # VPCGatewayAttachment; VPC와 IGW 를 Attach 하겠다.
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref VPC
      InternetGatewayId: !Ref InternetGateway
  PUBRTB:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: test-pub-rtb
  PVTRTB: 
    Type: AWS::EC2::RouteTable # 로컬에서만 동작하는 순수한 라우팅 테이블
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: test-pvt-rtb
  InternetRoute: # 경로 정보 지정
    Type: AWS::EC2::Route # 경로 테이블의 경로를 지정
    # DependsOn 속성을 사용하면 특정 리소스 생성이 다른 리소스 다음에 생성되도록 지정할 수 있습니다.
    # 리소스에 DependsOn 속성을 추가하면 해당 리소스는 DependsOn 속성에 지정된 리소스가 생성된 후에만 생성됩니다.
    DependsOn: InternetGateway # 인터넷 게이트웨이가 생성된 이후에 작업이 수행된다.
    Properties:
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway
      RouteTableId: !Ref PUBRTB
  PUB2ARTBAssociation:
    # 서브넷과 라우팅 테이블은 동일한 VPC에 있어야 합니다. 
    Type: AWS::EC2::SubnetRouteTableAssociation # 서브넷을 경로 테이블과 명시적으로 연결합니다. 
    Properties:
      RouteTableId: !Ref PUBRTB
      SubnetId: !Ref PUB2A
  PUB2BRTBAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PUBRTB
      SubnetId: !Ref PUB2B
  PUB2CRTBAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PUBRTB
      SubnetId: !Ref PUB2C
  PUB2DRTBAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PUBRTB
      SubnetId: !Ref PUB2D
  PVT2ARTBAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PVTRTB
      SubnetId: !Ref PVT2A
  PVT2BRTBAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PVTRTB
      SubnetId: !Ref PVT2B
  PVT2CRTBAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PVTRTB
      SubnetId: !Ref PVT2C
  PVT2DRTBAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PVTRTB
      SubnetId: !Ref PVT2D
----------------------------------------

CloudFormation

  • CloudFormation용 저장소 ❌
    • 이미 가지고 있는 S3 또는 템플릿 파일 업로드를 이용(버킷이 생성된다.)
  • 스택 생성 클릭
  • 템플릿 지정 - 템플릿 파일 업로드
  • 스택 세부 정보 지정 - 이름 지정
  • 스택 옵션 구성 (기본값)

  • 검토 - 전송 클릭
  • 생성 결과
    • VPC 가서 확인시 정상적으로 생성된 것 확인 가능


EC2 생성 실습

  • EC2 생성 템플릿
vi test-ec2.yaml
----------------------------------------
AWSTemplateFormatVersion: 2010-09-09
# Mappings 섹션(선택 사항)은 키를 해당하는 명명된 값 세트와 맞춥니다.
# 예를 들어 리전에 따라 값을 설정하려면 리전 이름을 키로 사용하고 각각의 특정 리전에 대해 지정할 값을 포함하는 매핑을 생성할 수 있습니다. 
Mappings:
  RegionMap:
    ap-northeast-2:
      AMIID: ami-035da6a0773842f64 # 서울리전에서는 해당 AMI ID를 활용해서 이용한다.
    ap-northeast-1:
      AMIID: ami-08928044842b396f0
# 선택 사항인 Parameters 단원을 사용하여 템플릿을 사용자 지정합니다. 
# 파라미터를 통해 스택을 생성하거나 업데이트 할 때마다 템플릿에 사용자 지정 값을 입력할 수 있습니다.
Parameters:
  InstanceType:
    Type: String
    Default: t2.micro
    Description: Enter instance size. Default is t2.micro
  VPC: # 사용할 VPC 세팅, aws ec2 describe-vpcs
    Type: String
    Default: vpc-0b32d7c21fcd12399
    Description: VPC ID.
  Subnet: # aws ec2 describe-subnets --filters "Name=vpc-id,Values=vpc-0b32d7c21fcd12399" --query 'Subnets[*].{ID:SubnetId,TAGS:Tags[0].Value}'
    Type: String
    # test-pub-2a
    Default: subnet-05afb35cfbc919437
    Description: Subnet ID.
  AMI:
    Type: String
    Default: AMIID
    Description: The Linux AMI to use.
  Key:
    Type: String
    Default: test-key
    Description: The key used to access the instance.
Resources:
  InstanceSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: "test-sg-web" # 보안 그룹의 이름
      GroupDescription: "test-sg-web" # 보안 그룹에 대한 설명
      VpcId: !Ref VPC #  Parameter 에서 지정한 VPC의 vpc-id를 가져온다.
      SecurityGroupIngress: # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-security-group-ingress.html
        - IpProtocol: tcp # IP 프로토콜 이름
          FromPort: '80'
          ToPort: '80'
          CidrIp: 0.0.0.0/0
        - IpProtocol: tcp
          FromPort: '22'
          ToPort: '22'
          CidrIp: 106.253.56.124/32
        - IpProtocol: icmp
          FromPort: '-1'
          ToPort: '-1'
          CidrIp: 0.0.0.0/0
      SecurityGroupEgress:
        - IpProtocol: -1
          CidrIp: 0.0.0.0/0
  EC2Insteance:
    Type: AWS::EC2::Instance
    Properties:
      SubnetId: !Ref Subnet
#      ImageId: !Ref AMI
      # 두개 이상의 값중에서 골라야하기 때문에 FindInMap 이라는 함수는 사용
      # !FindInMap [ MapName, TopLevelKey, SecondLevelKey ]
      # SecondLevelKey에 해당하는 값을 가져온다. ; RegionMap 에서 리전에 맞는 이미지 값을 반환
      # https://docs.aws.amazon.com/ko_kr/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-findinmap.html
      ImageId: !FindInMap [ RegionMap, !Ref "AWS::Region", !Ref AMI ]
      # InstanceType: !Ref: InstanceType 로도 표현 가능
      InstanceType:
        Ref: InstanceType
      KeyName: !Ref Key
      SecurityGroupIds: # 여러개를 표현 할때는 - 뒤에 작성표현
        - Ref: InstanceSecurityGroup
      BlockDeviceMappings: # 여러개를 표시한 예시, 루트 볼륨과 추가 볼륨 나열
        - DeviceName: /dev/xvda
          Ebs:
            VolumeSize: 8
        - DeviceName: /dev/xvdb
          Ebs:
            VolumeSize: 8
      Tags:
        - Key: Name
          Value: test-ec2

      # Fn::Base64 내장 함수는 입력 문자열의 Base64 표시를 반환, 일반적으로 UserData 속성을 통해 인코딩된 데이터를 Amazon EC2 인스턴스에 전달하는 데 사용
      # '|' 파이프 문자 -> 다음행에 있는 것들을 개행을 하겠다라는 의미
      # 아래 개행으로 나열된 것들이 개행인 것을 인지 하겠다라는 의미
      UserData:
        Fn::Base64: |
          #cloud-boothook
          #!/bin/bash
          yum install -y httpd
          systemctl enable --now httpd
          echo "Hello World!" > /var/www/html/index.html
Outputs:  
  PublicIp:    
    Description: PublicIp Output    
    # https://docs.aws.amazon.com/ko_kr/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-getatt.html
    # Fn::GetAtt 내장 함수는 템플릿의 리소스에서 속성 값을 반환
    # Fn::GetAtt: [ logicalNameOfResource, attributeName ]
    # logicalNameOfResource 의 attributeName 에 해당하는 attributeValue 를 반환
    Value: {"Fn::GetAtt": ["EC2Insteance","PublicIp"]}

CloudFormation 수행

  • S3 업로드
  • S3 URL
  • 스택 생성
  • 스택 세부 정보; yaml에 지정한 내용이 들어가 있다.
  • 스택 결과



도쿄 리전에서 수행

  • VPC 스택
  • VPC 리소스 생성 확인
  • 도쿄리전 키페어 생성
    aws ec2 create-key-pair --region ap-northeast-1 --key-name tokyo-key --query 'KeyMaterial' --output text > tokyo-key.pem
  • EC2 스택; 파라미터 직접 입력 가능 (리소스 ID 복사후 입력)

  • EC2 리소스 생성 확인


  • test-vpc-tokyo
AWSTemplateFormatVersion: 2010-09-09
Resources:
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 192.168.0.0/16
      EnableDnsSupport: true
      EnableDnsHostnames: true
      InstanceTenancy: default
      Tags:
        - Key: Name
          Value: test-vpc
  PUB1A:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: ap-northeast-1a
      VpcId: !Ref VPC
      CidrBlock: 192.168.0.0/20
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: test-pub-1a
  PUB1C:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: ap-northeast-1c
      VpcId: !Ref VPC
      CidrBlock: 192.168.16.0/20
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: test-pub-1c
  PUB1D:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: ap-northeast-1d
      VpcId: !Ref VPC
      CidrBlock: 192.168.32.0/20
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: test-pub-1d
  PVT1A:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: ap-northeast-1a
      VpcId: !Ref VPC
      CidrBlock: 192.168.48.0/20
      MapPublicIpOnLaunch: false
      Tags:
        - Key: Name
          Value: test-pvt-1a
  PVT1C:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: ap-northeast-1c
      VpcId: !Ref VPC
      CidrBlock: 192.168.64.0/20
      MapPublicIpOnLaunch: false
      Tags:
        - Key: Name
          Value: test-pvt-1c
  PVT1D:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: ap-northeast-1d
      VpcId: !Ref VPC
      CidrBlock: 192.168.80.0/20
      MapPublicIpOnLaunch: false
      Tags:
        - Key: Name
          Value: test-pvt-1d
  InternetGateway:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
        - Key: Name
          Value: test-igw
  VPCGatewayAttachment:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref VPC
      InternetGatewayId: !Ref InternetGateway
  PUBRTB:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: test-pub-rtb
  PVTRTB:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: test-pvt-rtb
  InternetRoute:
    Type: AWS::EC2::Route
    DependsOn: InternetGateway
    Properties:
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway
      RouteTableId: !Ref PUBRTB
  PUB1ARTBAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PUBRTB
      SubnetId: !Ref PUB1A
  PUB1CRTBAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PUBRTB
      SubnetId: !Ref PUB1C
  PUB1DRTBAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PUBRTB
      SubnetId: !Ref PUB1D
  PVT1ARTBAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PVTRTB
      SubnetId: !Ref PVT1A
  PVT1CRTBAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PVTRTB
      SubnetId: !Ref PVT1C
  PVT1DRTBAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PVTRTB
      SubnetId: !Ref PVT1D
  • test-ec2-tokyo
AWSTemplateFormatVersion: 2010-09-09
Mappings:
  RegionMap:
    ap-northeast-2:
      AMIID: ami-035da6a0773842f64
    ap-northeast-1:
      AMIID: ami-08928044842b396f0
Parameters:
  InstanceType:
    Type: String
    Default: t2.micro
    Description: Enter instance size. Default is t2.micro
  VPC:
    Type: String
    Default: vpc-0b32d7c21fcd12399
    Description: VPC ID.
  Subnet:
    Type: String
    Default: subnet-05afb35cfbc919437
    Description: Subnet ID.
  AMI:
    Type: String
    Default: AMIID
    Description: The Linux AMI to use.
  Key:
    Type: String
    Default: tokyo-key
    Description: The key used to access the instance.
Resources:
  InstanceSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: "test-sg-web"
      GroupDescription: "test-sg-web"
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: '80'
          ToPort: '80'
          CidrIp: 0.0.0.0/0
        - IpProtocol: tcp
          FromPort: '22'
          ToPort: '22'
          CidrIp: 106.253.56.124/32
        - IpProtocol: icmp
          FromPort: '-1'
          ToPort: '-1'
          CidrIp: 0.0.0.0/0
      SecurityGroupEgress:
        - IpProtocol: -1
          CidrIp: 0.0.0.0/0
  EC2Insteance:
    Type: AWS::EC2::Instance
    Properties:
      SubnetId: !Ref Subnet
#      ImageId: !Ref AMI
      ImageId: !FindInMap [ RegionMap, !Ref "AWS::Region", !Ref AMI ]
      InstanceType:
        Ref: InstanceType
      KeyName: !Ref Key
      SecurityGroupIds:
        - Ref: InstanceSecurityGroup
      BlockDeviceMappings:
        - DeviceName: /dev/xvda
          Ebs:
            VolumeSize: 8
        - DeviceName: /dev/xvdb
          Ebs:
            VolumeSize: 8
      Tags:
        - Key: Name
          Value: test-ec2

      UserData:
        Fn::Base64: |
          #cloud-boothook
          #!/bin/bash
          yum install -y httpd
          systemctl enable --now httpd
          echo "Hello World! Tokyo!" > /var/www/html/index.html
Outputs:  
  PublicIp:    
    Description: PublicIp Output    
    Value: {"Fn::GetAtt": ["EC2Insteance","PublicIp"]}

리소스 제거

  • 사용된 스택 제거

기타

  • CLI 환경에서 내가 있는 곳의 IP 확인
    curl ipconfig.io
  • 💥 최종 프로젝트에서는 CloudFormation을 이용하지 않음
profile
끄적끄적 쓰는곳

0개의 댓글