【AWS】CloudFormation을 통한 웹 서비스 구축①(NW편)

1. 시작
최근에는 인프라 시설 건설도 코드로 진행됐다.
그중의 한 예는 AWS가 제공하는 자원 공급 서비스인'CloudFormation(이하 CFn)'이다.
이번에는 CFn을 사용해 일반적인 2층 웹 서비스를 구축하고 싶습니다.
또 CFn 관련 기사에는 매니저에 구축된 글이 많지만 CFn의 본질이 IaC, 즉 코드 인프라 구축이기 때문에 이 편에서 템플릿 구축은 IDE(Cloud9)에서 AWS CLI를 사용해 이뤄졌다.
글은 3편으로 나눠 공개된다.
①[AWS]CloudFormation을 통한 웹 서비스 구축 ①(NW편)← 본 보도
②[AWS] 클라우드 포메이션을 통한 웹 서비스 구축 ②(EC2편)
③[AWS] 클라우드 포메이션을 통한 웹 서비스 구축 ③(RDS편)
2. 개요
이 글의 개요는 다음과 같다.
2.1 이 글의 목적
CFn을 사용하여 IDE(Cloud9)에서 웹 서버 환경을 구축합니다.
2.2 보도 절차
① NW 환경 및 안전 템플릿 제작→구축
② 서버 템플릿 제작σ구축
③ 데이터베이스 템플릿 만들기→구축
④ 동작 확인
2.3 기능 요건
• 템플릿 형식은 "yaml"
• 템플릿 파일은 각 역할별로 분할되며 크로스 스택 방식 사용
• 제작된 템플릿은 다음과 같다
・“network.yml”
・“security.yml”
・“server.yml”
・“database.yml”
• 명령줄에서 자원 생성부터 구축까지 모두
・IDE Cloud9 사용 ※ VScode 등 좋아하는 IDE 사용
· 완성 요건은 다음과 같은 두 가지이다
· 웹 서버의 테스트 페이지 탐색
· RDS를 통해 제작된 DB 기록을 탐색하는 브라우저
2.4 구조도

3. 사전 준비
사전 준비로 다음과 같은 준비를 하세요.
· IDE (이 편은 Cloud9 사용)
• AWS CLI 사용 가능
· 독립도메인 취득 ※ 기고인은'이름.com'을 통해 도메인 취득
또한 템플릿 파일의 보관 및 구축용 디렉토리를 원하는 위치에 작성하십시오(이하 "작업용 디렉토리").
디렉토리 생성 명령은 다음과 같습니다.
작업 디렉토리 만들기
$ mkdir cfn-dev-dir
$ cd cfn-dev-dir
나중에 제작된 템플릿을 작업용 디렉토리 바로 아래에 모두 저장하십시오.
4.NW 편의 개요
이번'AWS'클라우드 포메이션은 웹 서버 ①(NW 편)를 구축해 웹 환경 주변의 NW 부분에 대한 템플릿을 제작한다.
구체적인 서비스는 다음과 같다.
4.1 "network.yml"에 등장하는 서비스
・Amazon VPC
・Internet Gateway
・VPC Subnet
・VPC RouteTable
4.2'보안.yml'에 등장하는 서비스
・SecurityGroup
4.3 NW 편 구성도
NW 편에서 작성한 템플릿 환경의 구성도는 다음 그림과 같습니다.

5. NW 템플릿 제작
다음은 NW 섹션의 템플릿입니다.
명명 규칙 등 필요하면 자신의 환경에 따라 수정하세요.
수정이 완료되면 작업 디렉토리에 "network.yml"파일 이름으로 저장합니다.
network.yml
AWSTemplateFormatVersion: "2010-09-09"
Description: Web2tier-Network-Template


# ------------------------------------------------------------
# Input Parameters
# ------------------------------------------------------------
Parameters:
### Project Prefix ###
  PJPrefix:
    Type: String
### VPC ###
  VPCCIDR:
    Type: String
    Default: "192.168.0.0/20"
### Public Subnet ###
  PublicSubnetACIDR:
    Type: String
    Default: "192.168.1.0/24"
  PublicSubnetCCIDR:
    Type: String
    Default: "192.168.2.0/24"
### Private Subnet ###
  PrivateSubnetACIDR:
    Type: String
    Default: "192.168.3.0/24"
  PrivateSubnetCCIDR:
    Type: String
    Default: "192.168.4.0/24"


### Resources ###
Resources: 
# ------------------------------------------------------------
# VPC
# ------------------------------------------------------------
  VPC: 
    Type: "AWS::EC2::VPC"
    Properties: 
      CidrBlock: !Ref VPCCIDR
      EnableDnsSupport: "true"
      EnableDnsHostnames: "true"
      InstanceTenancy: default
      Tags: 
        - Key: Name
          Value: !Sub "${PJPrefix}-vpc"


# ------------------------------------------------------------
# InternetGateway:
# ------------------------------------------------------------
  InternetGateway: 
    Type: "AWS::EC2::InternetGateway"
    Properties: 
      Tags: 
        - Key: Name
          Value: !Sub "${PJPrefix}-igw"

  IGWAttachment: 
    Type: "AWS::EC2::VPCGatewayAttachment"
    Properties: 
      InternetGatewayId: !Ref InternetGateway
      VpcId: !Ref VPC


# ------------------------------------------------------------
# NatGateway
# ------------------------------------------------------------
### NAT Gateway ###
  NatGateway:
    Type: AWS::EC2::NatGateway
    Properties:
      AllocationId:
        Fn::GetAtt:
          - NatGatewayEIP
          - AllocationId
      SubnetId: !Ref PublicSubnetA
      Tags:
        - Key: Name
          Value: !Sub "${PJPrefix}-NAT-Gateway"

### NAT Gateway EIP ###
  NatGatewayEIP:
    Type: AWS::EC2::EIP
    Properties:
      Domain: vpc
      Tags:
        - Key: Name
          Value: !Sub "${PJPrefix}-NGW-EIP" 


# ------------------------------------------------------------
# Subnet
# ------------------------------------------------------------
### Public Subnet ###
  PublicSubnetA: 
    Type: "AWS::EC2::Subnet"
    Properties: 
      AvailabilityZone: "ap-northeast-1a"
      CidrBlock: !Ref PublicSubnetACIDR
      VpcId: !Ref VPC 
      Tags: 
        - Key: Name
          Value: !Sub "${PJPrefix}-public-subnet-a"

  PublicSubnetC: 
    Type: "AWS::EC2::Subnet"
    Properties: 
      AvailabilityZone: "ap-northeast-1c"
      CidrBlock: !Ref PublicSubnetCCIDR
      VpcId: !Ref VPC 
      Tags: 
        - Key: Name
          Value: !Sub "${PJPrefix}-public-subnet-c"

### Private Subnet ###
  PrivateSubnetA: 
    Type: "AWS::EC2::Subnet"
    Properties: 
      AvailabilityZone: "ap-northeast-1a"
      CidrBlock: !Ref PrivateSubnetACIDR
      VpcId: !Ref VPC 
      Tags: 
        - Key: Name
          Value: !Sub "${PJPrefix}-private-subnet-a"

  PrivateSubnetC: 
    Type: "AWS::EC2::Subnet"
    Properties: 
      AvailabilityZone: "ap-northeast-1c"
      CidrBlock: !Ref PrivateSubnetCCIDR
      VpcId: !Ref VPC 
      Tags: 
        - Key: Name
          Value: !Sub "${PJPrefix}-private-subnet-c"


# ------------------------------------------------------------
# RouteTable
# ------------------------------------------------------------
### Public Subnet A Routing ###
  PublicARTB: 
    Type: "AWS::EC2::RouteTable"
    Properties: 
      VpcId: !Ref VPC 
      Tags: 
        - Key: Name
          Value: !Sub "${PJPrefix}-public-route-a"

  PublicASubnetRTBAssociation: 
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    Properties: 
      SubnetId: !Ref PublicSubnetA 
      RouteTableId: !Ref PublicARTB

  PublicARoute: 
    Type: "AWS::EC2::Route"
    Properties: 
      RouteTableId: !Ref PublicARTB
      DestinationCidrBlock: "0.0.0.0/0"
      GatewayId: !Ref InternetGateway

### Public Subnet C Routing ###
  PublicCRTB: 
    Type: "AWS::EC2::RouteTable"
    Properties: 
      VpcId: !Ref VPC 
      Tags: 
        - Key: Name
          Value: !Sub "${PJPrefix}-public-route-c"

  PublicCSubnetRTBAssociation: 
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    Properties: 
      SubnetId: !Ref PublicSubnetC
      RouteTableId: !Ref PublicCRTB

  PublicCRoute: 
    Type: "AWS::EC2::Route"
    Properties: 
      RouteTableId: !Ref PublicCRTB
      DestinationCidrBlock: "0.0.0.0/0"
      GatewayId: !Ref InternetGateway 

### Private Subnet A Routing ###
  PrivateARTB: 
    Type: "AWS::EC2::RouteTable"
    Properties: 
      VpcId: !Ref VPC 
      Tags: 
        - Key: Name
          Value: !Sub "${PJPrefix}-private-route-a"

  PrivateSubnetRTBAAssociation: 
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    Properties: 
      SubnetId: !Ref PrivateSubnetA
      RouteTableId: !Ref PrivateARTB

  PrivateRouteA01: 
    Type: "AWS::EC2::Route"
    Properties: 
      RouteTableId: !Ref PrivateARTB
      DestinationCidrBlock: "0.0.0.0/0"
      NatGatewayId: !Ref NatGateway

### Private Subnet C Routing ###
  PrivateCRTB: 
    Type: "AWS::EC2::RouteTable"
    Properties: 
      VpcId: !Ref VPC 
      Tags: 
        - Key: Name
          Value: !Sub "${PJPrefix}-private-route-c"

  PrivateSubnetRTBCAssociation: 
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    Properties: 
      SubnetId: !Ref PrivateSubnetC
      RouteTableId: !Ref PrivateCRTB

  PrivateRouteC01: 
    Type: "AWS::EC2::Route"
    Properties: 
      RouteTableId: !Ref PrivateCRTB
      DestinationCidrBlock: "0.0.0.0/0"
      NatGatewayId: !Ref NatGateway


# ------------------------------------------------------------
# Output Parameter
# ------------------------------------------------------------
Outputs:
### VPC ###
  VPC:
    Value: !Ref VPC
    Export:
      Name: !Sub "${PJPrefix}-vpc"

### Subnet ###
## Public Subnet A ##
  PublicSubnetA:
    Value: !Ref PublicSubnetA
    Export:
      Name: !Sub "${PJPrefix}-public-subnet-a"
## Public Subnet C ##
  PublicSubnetC:
    Value: !Ref PublicSubnetC
    Export:
      Name: !Sub "${PJPrefix}-public-subnet-c"
## Private Subnet A ##
  PrivateSubnetA:
    Value: !Ref PrivateSubnetA
    Export:
      Name: !Sub "${PJPrefix}-private-subnet-a"
## Private Subnet C ##
  PrivateSubnetC:
    Value: !Ref PrivateSubnetC
    Export:
      Name: !Sub "${PJPrefix}-private-subnet-c"
5.1 NW 템플릿 구축
구문을 생성합니다.
구축은 AWS CLI 명령을 사용하여 수행됩니다.
투고자가 클라우드 9를 사용하기 때문에 클라우드 9에서 베이스를 열고 그곳에서 구축합니다.
AWS CLI를 사용하여 CFn 템플릿을 구성하는 방법은 하나의 쓰기로 간단합니다.
다음 명령을 실행하십시오.
※ 스택 이름, 접두사, 또는 추가로 지정하려는 매개 변수 등이 있으면 자신의 환경에 따라 수정하십시오.
NW 템플릿 구성 명령
$ aws cloudformation create-stack \
--stack-name web2tier-Network-stack \
--template-body file://./network.yml \
--parameters ParameterKey=PJPrefix,ParameterValue=web2tier
↓ 문법 오류가 없으면 다음 결과를 출력합니다.
실행 결과
{
    "StackId": "arn:aws:cloudformation:ap-northeast-1:xxxxxxx:stack/<スタックネーム>/<メタ番号>"
}
6. 안전 템플릿 제작
다음은 Security 섹션의 템플릿입니다.
여기에도 명명 규칙 등이 있으니 필요하면 자신의 환경에 따라 수정하세요.
수정이 완료되면 작업 디렉터리에 '보안.yml' 파일 이름으로 저장하십시오.
security.yml
AWSTemplateFormatVersion: "2010-09-09"
Description: Web2tier-Security-Template


# ------------------------------------------------------------
# Input Parameters
# ------------------------------------------------------------
Parameters:
### Project Prefix ###
  PJPrefix:
    Type: String


### Resources ###
Resources:
# ------------------------------------------------------------
# SecurityGroup
# ------------------------------------------------------------
### ALB Server Security Group ###
    ALBSG:
        Type: "AWS::EC2::SecurityGroup"
        Properties:
            GroupDescription: "https"
            GroupName: cfn-dev-alb-sg
            VpcId: { "Fn::ImportValue": !Sub "${PJPrefix}-vpc" }
            Tags: 
                - Key: Name
                  Value: !Sub "${PJPrefix}-alb-sg"
            SecurityGroupIngress:
                IpProtocol: tcp
                FromPort : 443
                ToPort : 443
                CidrIp: 0.0.0.0/0

### Web Server Security Group ###
    WebSG:
        Type: "AWS::EC2::SecurityGroup"
        Properties:
            GroupDescription: "http"
            GroupName: cfn-dev-web-sg
            VpcId: { "Fn::ImportValue": !Sub "${PJPrefix}-vpc" }
            Tags: 
                - Key: Name
                  Value: !Sub "${PJPrefix}-web-sg"
            SecurityGroupIngress:
                IpProtocol: tcp
                FromPort : 80
                ToPort : 80
                SourceSecurityGroupId: !Ref ALBSG

### RDS Security Group ###            
    RDSSG:
        Type: "AWS::EC2::SecurityGroup"
        Properties:
            GroupDescription: "mysql"
            GroupName: cfn-dev-rds-sg
            VpcId: { "Fn::ImportValue": !Sub "${PJPrefix}-vpc" }
            Tags: 
                - Key: Name
                  Value: !Sub "${PJPrefix}-RDS-sg"
            SecurityGroupIngress:
                IpProtocol: tcp
                FromPort : 3306
                ToPort : 3306
                SourceSecurityGroupId: !Ref WebSG


# ------------------------------------------------------------
# Output Parameter
# ------------------------------------------------------------
Outputs:
### SecurityGroup ###
    ALBSG:
        Value: !Ref ALBSG
        Export:
            Name: !Sub "${PJPrefix}-alb-sg"
    WebSG:
        Value: !Ref WebSG
        Export:
            Name: !Sub "${PJPrefix}-web-sg"
    RDSSG:
        Value: !Ref RDSSG
        Export:
            Name: !Sub "${PJPrefix}-rds-sg"

6.1 NW 템플릿 구축
를 참고하십시오.
다음 명령을 실행하십시오.
※ 스택 이름, 접두사, 또는 추가로 지정하려는 매개 변수 등이 있으면 자신의 환경에 따라 수정하십시오.
보안 템플릿 구성 명령
$ aws cloudformation create-stack \
--stack-name web2tier-Security-stack \
--template-body file://./security.yml \
--parameters ParameterKey=PJPrefix,ParameterValue=web2tier
↓ 문법 오류가 없으면 다음 결과를 출력합니다.
실행 결과
{
    "StackId": "arn:aws:cloudformation:ap-northeast-1:xxxxxxx:stack/<スタックネーム>/<メタ番号>"
}
7. 요약
이상은 본 보도입니다.
다음은 서버 부분의 템플릿 제작 [AWS] 클라우드 포메이션 구축 웹 서버 ②(EC2편)입니다.
GUI는 CUI보다 직관적이고 알기 쉬우며 오류 없는 조작도 간단하다. 익숙해지면 CUI는 인프라를 간단하게 구축할 수 있다.
또한 인코딩을 통해 GiitHub 등 버전 관리 시스템에서 코드 관리를 할 수 있어 대규모 인프라 구축의 가시성을 높이고 신속하게 제공할 수 있다.
이 기사를 발판으로 이 시점에서 IaC에 꼭 도전해보고 싶다.
- 기사 목록 -
①[AWS] 클라우드 포메이션을 통한 웹 서비스 구축 ①(NW편)
②[AWS] 클라우드 포메이션을 통한 웹 서비스 구축 ②(EC2편)
③[AWS] 클라우드 포메이션을 통한 웹 서비스 구축 ③(RDS편)

좋은 웹페이지 즐겨찾기