- AWS CloudFormation 템플릿을 빌드하여 간단한 인프라 프로비저닝하고 CreateStack 작업 수행
- Detect drift 명령을 사용하여 AWS CloudFormation 스택에서 드리프트 감지
- AWS CloudFormation Change Set 생성 및 실행
AWS CloudFormation은 코드형 자동 인프라 프로비저닝 서비스입니다. 줄여서 IaC(Infrastructure as Code)라고도 부르기도 합니다,
인프라를 코드(IaC)로 작성할 경우 다음과 같은 이점이 있습니다.
- 애플리케이션 코드처럼 버전 지정 및 관리가 가능하다.
- 반복적으로 그리고 안정적으로 생성, 종료 및 재생성 가능
- 애플리케이션의 최신 버전 테스트 필요성에 따라 생성 가능
- 여러 환경의 생성 가능
- 여러 고객에 대한 동일한 환경 생성 가능
아래의 아키텍처는 HTTP 접속이 가능한 아파치 웹서버입니다. 전용 VPC, 단일 공용 서브넷 및 소규모 Amazon Elastic Compute Cloud 인스턴스로 구성되었습니다. 필요한 인프라를 CloudFormation을 통해 구성해 봅시다.
AWS Cloud9 접속합니다.
AWS CloudFormation에서는 클라우드 환경에서 리소스를 모델링하고 프로비저닝할 수 있도록 공용 언어를 제공합니다. CloudFormation 템플릿 언어를 사용하여 yaml 또는 json 형식으로 인프라를 코딩합니다.
simple-infrastructure.yaml
을 통해 CloudFormation 템플릿을 구성합니다.
AWSTemplateFormatVersion: 2010-09-09
Description: >-
AWS CloudFormation Simple Infrastructure Template
VPC_Single_Instance_In_Subnet: This template will show how to create a VPC and
add an EC2 instance with an Elastic IP address and a security group.
Parameters:
VPCCIDR:
Description: CIDR Block for VPC
Type: String
Default: 10.199.0.0/16
AllowedValues:
- 10.199.0.0/16
PUBSUBNET1:
InstanceType:
Description: WebServer EC2 instance type
Type: String
Default: t2.nano
AllowedValues:
- t2.nano
- t2.micro
- t2.small
ConstraintDescription: must be a valid EC2 instance type.
KeyName:
Description: Keyname for the keypair that Qwiklab will use to launch EC2 instances
Type: 'AWS::EC2::KeyPair::KeyName'
ConstraintDescription: must be the name of the provided existing EC2 KeyPair.
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.
LatestAmiId:
Description: Find the current AMI ID using System Manager Parameter Store
Type: 'AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>'
Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2
QwiklabLocale:
Default: en
Description: >-
The locale of the student will be passed in to this parameter via the
Qwiklab platform (via the student's browser)
Type: String
Resources:
VPC:
Type: 'AWS::EC2::VPC'
Properties:
CidrBlock: !Ref VPCCIDR
EnableDnsSupport: 'true'
EnableDnsHostnames: 'true'
Tags:
- Key: Application
Value: !Ref 'AWS::StackId'
- Key: Name
Value: CF lab environment
Subnet:
Type: 'AWS::EC2::Subnet'
DependsOn: VPC
Properties:
VpcId: !Ref VPC
CidrBlock: !Ref PUBSUBNET1
MapPublicIpOnLaunch: 'true'
AvailabilityZone: !Select
- '0'
- !GetAZs ''
Tags:
- Key: Application
Value: !Ref 'AWS::StackId'
- Key: Name
Value: Public Subnet
InternetGateway:
Type: 'AWS::EC2::InternetGateway'
DependsOn: VPC
Properties:
Tags:
- Key: Application
Value: !Ref 'AWS::StackId'
AttachGateway:
Type: 'AWS::EC2::VPCGatewayAttachment'
DependsOn: VPC
Properties:
VpcId: !Ref VPC
InternetGatewayId: !Ref InternetGateway
RouteTable:
Type: 'AWS::EC2::RouteTable'
DependsOn: VPC
Properties:
VpcId: !Ref VPC
Tags:
- Key: Application
Value: !Ref 'AWS::StackId'
Route:
SubnetRouteTableAssociation:
NetworkAcl:
Type: 'AWS::EC2::NetworkAcl'
DependsOn:
- VPC
- InternetGateway
Properties:
VpcId: !Ref VPC
Tags:
- Key: Application
Value: !Ref 'AWS::StackId'
InboundHTTPNetworkAclEntry:
Type: 'AWS::EC2::NetworkAclEntry'
DependsOn:
- VPC
- InternetGateway
Properties:
NetworkAclId: !Ref NetworkAcl
RuleNumber: '100'
Protocol: '6'
RuleAction: allow
Egress: 'false'
CidrBlock: 0.0.0.0/0
PortRange:
From: '80'
To: '80'
InboundSSHNetworkAclEntry:
Type: 'AWS::EC2::NetworkAclEntry'
DependsOn:
- VPC
- InternetGateway
Properties:
NetworkAclId: !Ref NetworkAcl
RuleNumber: '101'
Protocol: '6'
RuleAction: allow
Egress: 'false'
CidrBlock: 0.0.0.0/0
PortRange:
From: '22'
To: '22'
InboundResponsePortsNetworkAclEntry:
Type: 'AWS::EC2::NetworkAclEntry'
DependsOn:
- VPC
- InternetGateway
Properties:
NetworkAclId: !Ref NetworkAcl
RuleNumber: '102'
Protocol: '6'
RuleAction: allow
Egress: 'false'
CidrBlock: 0.0.0.0/0
PortRange:
From: '1024'
To: '65535'
OutBoundHTTPNetworkAclEntry:
Type: 'AWS::EC2::NetworkAclEntry'
DependsOn:
- VPC
- InternetGateway
Properties:
NetworkAclId: !Ref NetworkAcl
RuleNumber: '100'
Protocol: '6'
RuleAction: allow
Egress: 'true'
CidrBlock: 0.0.0.0/0
PortRange:
From: '80'
To: '80'
OutBoundHTTPSNetworkAclEntry:
Type: 'AWS::EC2::NetworkAclEntry'
DependsOn:
- VPC
- InternetGateway
Properties:
NetworkAclId: !Ref NetworkAcl
RuleNumber: '101'
Protocol: '6'
RuleAction: allow
Egress: 'true'
CidrBlock: 0.0.0.0/0
PortRange:
From: '443'
To: '443'
OutBoundResponsePortsNetworkAclEntry:
Type: 'AWS::EC2::NetworkAclEntry'
DependsOn:
- VPC
- InternetGateway
Properties:
NetworkAclId: !Ref NetworkAcl
RuleNumber: '102'
Protocol: '6'
RuleAction: allow
Egress: 'true'
CidrBlock: 0.0.0.0/0
PortRange:
From: '1024'
To: '65535'
SubnetNetworkAclAssociation:
Type: 'AWS::EC2::SubnetNetworkAclAssociation'
Properties:
SubnetId: !Ref Subnet
NetworkAclId: !Ref NetworkAcl
IPAddress:
Type: 'AWS::EC2::EIP'
DependsOn: AttachGateway
Properties:
Domain: vpc
InstanceId: !Ref WebServerInstance
InstanceSecurityGroup:
Type: 'AWS::EC2::SecurityGroup'
Properties:
VpcId: !Ref VPC
GroupDescription: Enable SSH access via port 22 and HTTP 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
WebServerInstance:
Type: 'AWS::EC2::Instance'
DependsOn: AttachGateway
Metadata:
Comment: Install a simple application
'AWS::CloudFormation::Init':
config:
packages:
yum:
httpd: []
files:
/var/www/html/index.html:
content: !Join
- |+
- - >-
<h1>Congratulations, you have successfully deployed a simple
infrastructure using AWS CloudFormation.</h1>
mode: '000644'
owner: root
group: root
/etc/cfn/cfn-hup.conf:
content: !Join
- ''
- - |
[main]
- stack=
- !Ref 'AWS::StackId'
- |+
- region=
- !Ref 'AWS::Region'
- |+
mode: '000400'
owner: root
group: root
/etc/cfn/hooks.d/cfn-auto-reloader.conf:
content: !Join
- ''
- - |
[cfn-auto-reloader-hook]
- |
triggers=post.update
- >
path=Resources.WebServerInstance.Metadata.AWS::CloudFormation::Init
- 'action=/opt/aws/bin/cfn-init -v '
- ' --stack '
- !Ref 'AWS::StackName'
- ' --resource WebServerInstance '
- ' --region '
- !Ref 'AWS::Region'
- |+
- |
runas=root
mode: '000400'
owner: root
group: root
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:
InstanceType: !Ref InstanceType
ImageId: !Ref LatestAmiId
KeyName: !Ref KeyName
Tags:
- Key: Application
Value: !Ref 'AWS::StackId'
- Key: Name
Value: Lab Host
NetworkInterfaces:
- GroupSet:
- !Ref InstanceSecurityGroup
AssociatePublicIpAddress: 'true'
DeviceIndex: '0'
DeleteOnTermination: 'true'
SubnetId: !Ref Subnet
UserData: !Base64
'Fn::Join':
- ''
- - |
#!/bin/bash -xe
- |
yum update -y aws-cfn-bootstrap
- '/opt/aws/bin/cfn-init -v '
- ' --stack '
- !Ref 'AWS::StackName'
- ' --resource WebServerInstance '
- ' --region '
- !Ref 'AWS::Region'
- |+
- '/opt/aws/bin/cfn-signal -e $? '
- ' --stack '
- !Ref 'AWS::StackName'
- ' --resource WebServerInstance '
- ' --region '
- !Ref 'AWS::Region'
- |+
CreationPolicy:
ResourceSignal:
Timeout: PT15M
Outputs:
URL:
Value: !Join
- ''
- - 'http://'
- !GetAtt
- WebServerInstance
- PublicIp
Description: Newly created application URL
템플릿에 포함된 섹션은 다음과 같은 목적으로 사용됩니다.
AWS Cloud9 terminal에서 키 페어 이름을 검색하고 이를 이용해 환경 변수를 생성합니다.
keyPair=$(aws ec2 describe-key-pairs --output text --query KeyPairs[*].KeyName)
cd ~/environment/templates
터미널에 다음 명령을 실행하여 스택 생성 프로세스를 시작합니다.
aws cloudformation create-stack --stack-name AWSStudent-Lab1 \
--parameters ParameterKey=KeyName,ParameterValue=$keyPair \
ParameterKey=InstanceType,ParameterValue=t2.micro \
--template-body file://simple-infrastructure.yaml
create-stack을 성공적으로 실행하면 명령줄에 StackId
가 반환됩니다.
describe-stacks 명령은 터미널에 많은 양의 정보를 반환합니다. 템플릿에서 정의한 모든 리소스, 빌드 프로세스의 현재 상태, describe-stacks를 실행할 때 사용할 수 있는 리소스의 특정 속성에 대한 정보를 제공합니다. AWS CloudFormation 대시보드에는 동일한 정보가 표시되지만 더 익숙한 형식으로 표시됩니다.
CloudFormation - Stacks(스택) - Status(상태)에서 생성한 스택 이름을 클릭합니다.
각 스택의 스택 정보, 출력, 이벤트를 확인할 수 있으며 출력의 url로 접속합니다.
Create Stack 작업의 상태가 CREATE_COMPLETE
일 경우, Output 탭에서 표시된 URL을 웹 브라우저에서 확인 가능합니다.
AWS CloudFormation을 통해 간단한 인프라를 구축했습니다. 다음 편에서는 외부의 변경을 감지하는 Drift Detection(드리프트 감지)에 대해 실습합니다.