CloudFormation 이란?
AWS의 리소스들을 자동으로 생성해주는 IAC(Infrastructure as Code)이다.
즉, AWS의 리소스들을 미리 코드화 하여 배포를 쉽고 빠르게 하는것이다.
이외에도 Terraform을 통하여도 리소스를 자동화 배포가 가능하나
AWS의 서비스인 CloudFromation을 다루도록 하겠다.
CloudFormation 동작 순서
- 템플릿 코드 작성
- 템플릿 업로드
- 스택 생성
- 리소스 생성
템플릿 형싱 : JSON or YAML
해당 과정에서는 VPC를 포함한 전반적인 네트워크 구성을 진행할것이다.
MetaData
해당 섹션에서는 Parameter 항목에서 선언될 항목들을 그룹핑하여 스택 배포시 좀더 보기 쉽게 구분 하도록 한 것이다.
AWSTemplateFormatVersion: "2010-09-09"
Description: VPC Configuration
Metadata: #파라미터들의 그룹들을 Label 작업
AWS::CloudFormation::Interface:
ParameterGroups:
-
Label:
default: "Network Configuration"
Parameters:
- VpcCIDR
- PubCIDR1
- PubCIDR2
- PriCIDR1
- PriCIDR2
-
Label:
default: "Amazon EC2 Configuration"
Parameters:
- InstanceType
- KeyName
- AMI
Mappings
Mappings 항목에서는 인스턴스를 생성시 AMI같은 값이 리전마다 다르기 때문에 각 리전마다의 데이터를 미리 지정해두어 사용자의 환경의 부합 하는 값을 매핑해두는 것이다.
#key: value 쌍으로 이루어지며 각기 다른 리전마다의 값을 지정가능
# 사용자의 환경마다 다르기에 그에 맞는 조건을 매핑해둔것
Mappings:
Regionmap:
ap-northeast-2:
Linux2: ami-0f2c95e9fe3f8f80e
window: ami-0685efd12a23690f5
us-east-1:
HVM64: ami-0ff8a91507f77f867
HVMG2: ami-0a584ac55a7631c0c
Parameter
파라미터 섹션에서는 템플릿 실행 시 사용자가 선택하는 항목을 정의하는 섹션이다.
- 용도에 맞게끔 리소스 구성 시 사용자의 요구 조건에 맞는 선택이 가능하다
- 예를 들어, 동일한 템플릿을 배포하더라도 인스턴스 타입이나 서브넷등이 다를경우 해당 parameter섹션을 통해 리스트 항목들중 선택하여 값을 지정할수도 있어 유용하게 사용한다.
Parameters:
EnvironmentName: #변수값으로 저장하여 리소스들의 공통된 네임 지정
Description: A common name for your resources
Type: String
VpcCIDR:
Description: Please enter the IP range (CIDR notation) for this VPC
Type: String
Default: 10.0.0.0/16
PubCIDR1:
Description: Please enter the IP range (CIDR notation) for the public subnet in the first Availability Zone
Type: String
Default: 10.0.2.0/24
PubCIDR2:
Description: Please enter the IP range (CIDR notation) for the public subnet in the first Availability Zone
Type: String
Default: 10.0.4.0/24
PriCIDR1:
Description: Please enter the IP range (CIDR notation) for the private subnet in the first Availability Zone
Type: String
Default: 10.0.32.0/24
PriCIDR2:
Description: Please enter the IP range (CIDR notation) for the private subnet in the first Availability Zone
Type: String
Default: 10.0.64.0/24
InstanceType: #인스턴스 타입
Description: WebServer EC2 instance type
Type: String
Default: t2.micro
AllowedValues: # 드롭박스 목록으로 해당 타입들을 지정해둔다.
- t2.nano
- t2.micro
- t2.small
- t2.medium
- t2.large
- m4.large
- m4.xlarge
- m4.2xlarge
- m4.4xlarge
- m4.10xlarge
- m3.medium
- m3.large
- m3.xlarge
- m3.2xlarge
- c4.large
- c4.xlarge
- c4.2xlarge
- c4.4xlarge
- c4.8xlarge
- c3.large
- c3.xlarge
- c3.2xlarge
- c3.4xlarge
- c3.8xlarge
- r3.large
- r3.xlarge
AMI:
Description: AMI of EC2
Type: String
Default: Linux2
AllowedValues:
- Linux2
- window
KeyName: #자신의 리전의 있는 keypair 사용하도록 지정
Description: Name of KeyPair
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.
AMI parameter 같은 경우 위에서 mapping 값으로 등록을 해두어 리소스 구성 시 참조 하면 되지만 스택 배포 시 사용자가 Linux or window 등 값들의 항목들을 선택할수 있도록 Allowedvalue 옵션과 함께 default 값은 Linux2로 지정했다.
Resource
실제 스택 배포 시 해당 섹션에 선언 된 구문들로 인하여 리소스가 생성이 되는 부분이다.
VPC 생성
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: !Ref VpcCIDR
EnableDnsSupport: true #해당 VPC의 DNS활성화
EnableDnsHostnames: true #VPC의 DNS호스트네임 활성화
Tags:
- Key: Name
Value: !Sub ${EnvironmentName} VPC #변수값으로 저장된 이름호출
서브넷 생성
#서브넷은 총 az당 public과 private으로 나눈다.
PublicSubnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
AvailabilityZone: !Select [ 0, !GetAZs ]
#GetAZs옵션은 리전의 가용영역을 알파벳 순으로 나열하여 반환한다.
#ex 서울리전의 경우 4개의 az 이므로 a,b,c,d 순으로
# Select 내장함수를 이용해 나열된 abcd의 az를 인덱스값으로 지정
CidrBlock: !Ref PubCIDR1
MapPublicIpOnLaunch: true #해당 서브넷의 퍼블릭 ip 자동활성화 여부
Tags: # Tag 값으로 리소스 식별
- Key: Name
Value: !Sub ${EnvironmentName} Public Subnet 1
#parameter 섹션에 정의된 선언문을 통해 해당 변수명을 참조한다.
PublicSubnet2:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
AvailabilityZone: !Select [ 2, !GetAZs ]
CidrBlock: !Ref PubCIDR2
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: !Sub ${EnvironmentName} Public Subnet 2
PrivateSubnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
AvailabilityZone: !Select [ 0, !GetAZs ]
CidrBlock: !Ref PriCIDR1
MapPublicIpOnLaunch: false
Tags:
- Key: Name
Value: !Sub ${EnvironmentName} Private Subnet 1
PrivateSubnet2:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
AvailabilityZone: !Select [ 2, !GetAZs ]
CidrBlock: !Ref PriCIDR2
MapPublicIpOnLaunch: false
Tags:
- Key: Name
Value: !Sub ${EnvironmentName} Private Subnet2
가용영역은 서울 같은 경우 4개의 az로 이루어져 있으나 a 와 c 가 가장 무난하여 default 로 가져가기 위해 GetAZs 내장 함수를 통해 사용자가 배포하는 리전의 AZ 를 나열 한 후 Select 내장 함수와 함께 인덱스 값으로 선택 하여 지정했다.
PublicSubnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
AvailabilityZone: ap-northeast-2a
or
Parameters:
AZ:
Type: AWS::EC2::AvailabilityZone::Name
Description: Choose your az
이처럼 직접 지정해주는 방식 및 parameter 선언을 통한 방식이 있으니 참고바람
igw 생성 및 연결
InternetGateway:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: !Sub ${EnvironmentName} igw
Attachigw:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
InternetGatewayId: !Ref InternetGateway
VpcId: !Ref VPC
Internet gateway를 생성하기 위해서는 사용될 VPC를 연결 해줘야하므로 참조할 VPC를 Ref 내장함수를 통해 참조한다.
이때, 리소스의 속성 값이 아닌 논리적 ID를 가지고 오는것이다.
NAT 생성 및 EIP
NatGatewayEIP: #NAT gw를 사용하기 위한 EIP 생성
Type: AWS::EC2::EIP
DependsOn: Attachigw # DependsOn 명령을 통해 해당 선언보다 우선시 진행
Properties:
Domain: vpc
NatGateway:
Type: AWS::EC2::NatGateway
Properties:
AllocationId: !GetAtt NatGatewayEIP.AllocationId
SubnetId: !Ref PublicSubnet1
Tags:
- Key: Name
Value: !Sub ${EnvironmentName} NAT
위에서 GetAtt 같은 경우는 Ref 와 달리 가지고 오고자 하는 값의 속성 값을 불러오는 것이다. 해당 선언에서는 NateGateWay의 사용될 ElasticIP의 속성값을 참조하는 것이다.
라우팅 생성
PublicRouteTable: #라우팅 테이블 생성
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${EnvironmentName} PublicRT
PublicRoute: #인터넷과 통신될 퍼블릭 라우팅 테이블 생성
Type: AWS::EC2::Route
DependsOn: Attachigw
Properties:
RouteTableId: !Ref PublicRouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
PublicSubnetRouteTableAssociation: #해당 테이블의 연동될 서브넷 지정
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref PublicRouteTable
SubnetId: !Ref PublicSubnet1
PublicSubnet2RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref PublicRouteTable
SubnetId: !Ref PublicSubnet2
PrivateRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${EnvironmentName} PrivateRT
PrivateRoute:
Type: AWS::EC2::Route
Properties:
RouteTableId: !Ref PrivateRouteTable
DestinationCidrBlock: 0.0.0.0/0
NatGatewayId: !Ref NatGateway
PrivateSubnetRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref PrivateRouteTable
SubnetId: !Ref PrivateSubnet1
PrivateSubnet2RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref PrivateRouteTable
SubnetId: !Ref PrivateSubnet2
보안그룹 생성
sshsecurity: # SSH 접속을 위한 22번포트 활성화
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Test
GroupName: !Sub ${EnvironmentName} ssh-security
VpcId:
!Ref VPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: !Ref SSHLocation
websecurity: #web 접속을 위한 80포트 open
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Test
GroupName: !Sub ${EnvironmentName} web-security
VpcId:
!Ref VPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: 22
ToPort: 22
SourceSecurityGroupId: !Ref sshsecurity
인스턴스 생성
bastion:
Type: AWS::EC2::Instance
Properties:
InstanceType: !Ref InstanceType
ImageId: !FindInMap [Regionmap, !Ref 'AWS::Region', Linux2]
#mapping 된 ami를 findmap함수를 통해 참조 이때 Linux2라고 지정하거나
#parameter에 선언한 ami 리스트를 이용할수도 있다. !Ref AMI
#AWS::Region의 경우는 사용자가 배포할 템플릿의 리전의 값을 자동으로 참조한다.
KeyName: !Ref KeyName
SecurityGroupIds:
- !Ref sshsecurity
SubnetId: !Ref PublicSubnet1
Tags:
-
Key: Name
Value: bastion
webserver:
Type: AWS::EC2::Instance
Properties:
ImageId: !FindInMap [Regionmap, !Ref 'AWS::Region', Linux2]
KeyName: !Ref KeyName
AvailabilityZone: !GetAtt PrivateSubnet1.AvailabilityZone
#GetAtt옵션을 통해서 해당 서브넷의 az속성값을 추출가능
#사실 서브넷의 az가 지정되어 있어 az를 별도로 지정해주지 않아도 되긴한다.
InstanceType: t2.micro
SubnetId: !Ref PublicSubnet1 #테스트를 위해 public지정
SecurityGroupIds:
- !Ref websecurity
UserData:
Fn::Base64:
!Join [ "", [
"#!/bin/bash\n",
"yum install -y httpd \n",
"systemctl enable httpd \n",
"systemctl start httpd \n"] ]
Tags:
- Key: Name
Value: Web Server
기본적으로 bastion 점프 서버와 간단한 webserver를 생성해보았다
확인 테스트
'IAC' 카테고리의 다른 글
cloudformation 정리 (0) | 2021.06.24 |
---|