[Cloud] 8일차 수업 정리

soyeon·2022년 10월 24일
post-thumbnail

Route53

: 높은 가용성과 확장성이 뛰어난 클라우드 DNS 웹 서비스

최종 사용자를 인터넷 애플리케이션으로 라우팅할 수 있는 매우 안정적이고 비용 효율적인 방법을 개발자와 기업에 제공하기 위해 설계하였다.
리전 수준의 장애 조치 서비스를 지원한다.

사용자의 요청을 EC2 인스턴스, ELB, S3 버킷 등 AWs에서 실행되는 인프라에 효과적으로 연결한다.
사용자를 AWS 외부의 인프라로 라우팅하는 데도 Route 53을 사용한다.
트래픽을 정상적인 엔드포인트로 라우팅하거나 애플리케이션 및 해당 엔드포인트의 상태를 개별적으로 모니터링하도록 DNS 상태 확인을 구성할 수 있다.

1) 사용자 입력 → www.example.com
2) ISP가 관리하는 DNS resolver로 라우팅
3) Resolver를 통해 DNS root name server로 전달
4) .com 도메인의 TLD 이름 서버 중 하나에 다시 전달
5) Route 53의 name serve 중 하나로 전달
6) Www.example.com 레코드를 찾아 웹 서버의 IP주소 192.0.2.44 등 연관된 값을 받고 이 IP 주소를DNS resolver로 반환
7) resolver는 이 값을 웹 브라우저로 반환
8) IP 주소로 www.example.com에 대한 요청을 전송
9) 192.0.2.44에 있는 웹 서버 또는 그 밖의 리소스는 www.example.com의 웹 페이지를 웹 브라우저로 반환하고, 웹 브라우저는 이 페이지를 표시

DNS record type

  • A(IPv4 address, AAAA(IPv6)
  • CNAME(canonical name)
  • SOA(start of authority)
  • NS(name server)
    route 53은 4개의 네임 서버를 제공한다.

라우팅 정책

  • 단순 라우팅 정책
    : 도메인에 대해 특정 기능을 수행하는 하나의 리소스만 있는 경우(예: example.com 웹 사이트의 콘텐츠를 제공하는 하나의 웹 서버)에 사용합니다.

  • 장애 조치 라우팅 정책
    : 액티브-패시브 장애 조치를 구성하려는 경우에 사용합니다.

  • 지리 위치 라우팅 정책
    : 사용자의 위치에 기반하여 트래픽 라우팅하려는 경우에 사용합니다.

  • 지리 근접 라우팅 정책
    : 리소스의 위치를 기반으로 트래픽을 라우팅하고 필요에 따라 한 위치의 리소스에서 다른 위치의 리소스로 트래픽을 보내려는 경우에 사용합니다.

  • 지연 시간 라우팅 정책
    : 여러 AWS Region에 리소스가 있고 최상의 지연 시간을 제공하는 Region으로 트래픽을 라우팅하려는 경우에 사용합니다.

  • 다중 응답 라우팅 정책
    : Route 53이 DNS 쿼리에 무작위로 선택된 최대 8개의 정상 레코드로 응답하게 하려는 경우에 사용합니다.

  • 가중치 기반 라우팅 정책
    : 사용자가 지정하는 비율에 따라 여러 리소스로 트래픽을 라우팅하려는 경우에 사용합니다.

Microservice & Serverless

Microservice Architecture(MSA)

: 기존의 Server to Application, EC2 to Application 등의 네트워크 연결 방식 대신, Application을 API를 통해 통신하는 독립적 서비스 집합으로 구성하는 것이다.

기존의 방식(Monolithic Application)은 각 서비스 간의 긴밀한 결합을 통해 동작한다. 이는 한 요소에 장애가 발생할 경우 전체 Application에 영향을 줄 수 있다는 의미이다.

  • 전통적 배포 방식 vs 현대적 배포 방식

모든 서비스가 각각의 Application 단위(container of lambda)로 구성되고, API를 통해 통신한다.
-> 유연한 확장성, 디버깅 용이(CI/CD), 서비스 단위 업무 분리
단, 서비스 연결을 위한 API 설계 개발이 복잡할 수 있다.

Container Service

: 컨테이너 애플리케이션을 실행하는데 필요한 인프라 환경 구성이 전혀 없는 독립된 환경
반복 가능하고 배포 가능한 프로세스를 제공하는 것

비관리형 실습

  • Docker 설치
## update
[ec2-user@ip-172-31-2-53 ~]$ sudo yum update -y

## docker 설치
[ec2-user@ip-172-31-2-53 ~]$ sudo amazon-linux-extras install docker -y

## docker service 시작
[ec2-user@ip-172-31-2-53 ~]$ sudo service docker start

## docker에서 sudo 없애기
[ec2-user@ip-172-31-2-53 ~]$ sudo setfacl -m user:ec2-user:rw /var/run/docker.sock

## 잘 설치되었는지 확인
[ec2-user@ip-172-31-2-53 ~]$ docker info
[ec2-user@ip-172-31-2-53 ~]$ docker version
...
Server:
 Engine:
  Version:          20.10.17

## 이미지 pull
[ec2-user@ip-172-31-2-53 ~]$ docker pull nginx:1.23.1-alpine

## run
[ec2-user@ip-172-31-2-53 ~]$ docker run -d --name=myweb -p 8001:80 nginx:1.23.1-alpine

## 접속
[ec2-user@ip-172-31-2-53 ~]$ curl localhost:8001
  • 윈도우에서 3.38.150.76:8001로 접속하면 접속이 되지 않는다. 8001번을 열어주지 않았기 때문이다.
  • 보안 그룹을 추가해준다.
  • 다시 3.38.150.76:8001로 접속하면 접속이 가능하다.

container service 동작

ECS

ECS 구성 workshop

인프라 구성

VPC 생성

  • VPC 생성 클릭
  • VPC 이름과 CIDR 설정
  • 태그 붙이기
  • 생성 완료

서브넷 생성

: 외부 연결이 가능한 2개의 퍼블릭 서브넷과 외부 연결이 차단되는 프라이빗 서브넷을 ecs-vpc에 생성한다.

  • 서브넷 탭으로 이동
  • 서브넷 생성
  • 연결한 VPC 선택
  • public subnet 설정

  • private subnet 설정

  • 서브넷 생성 완료

Internet Gateway 생성

: VPC 내부의 인스턴스가 인터넷과 통신할 수 있도록 인터넷 게이트웨이 생성

  • 인터넷 게이트웨이 탭으로 이동
  • 인터넷 게이트웨이 생성
  • 이름과 태그 설정
  • ecs-vpc에 연결한다.

  • ecs-vpc와 연결되었다.

NAT Gateway 생성

: private 서브넷에 있는 인스턴스가 인터넷과 통신할 수 있도록 NAT Gateway를 생성한다.

  • NAT 게이트웨이 탭으로 이동
  • NAT 게이트웨이 생성
  • 설정
  • 태그
  • 상태가 Available로 변경될 때까지 기다린다.
  • NAT Gateway 생성 완료

route table 생성

: VPC 내부에 있는 인스턴스의 인터넷 연결 요청이 인터넷 게이트웨이와 NAT 게이트웨이로 전달될 수 있도록 라우팅 테이블을 생성한다.
퍼블릿 서브넷은 인터넷 게이트웨이와 프라이빗 서브넷은 NAT 게이트웨이와 연결한다.

  • 라우팅 테이블 탭으로 이동
  • 퍼블릭 라우팅 테이블 생성
  • 라우팅 테이블 이름과 사용할 vpc 선택
  • 태그
  • 생성한 라우팅 테이블의 정보 중 라우팅 항목에서 [라우팅 편집] 클릭
  • 대상 추가
  • 서브넷 연결 항목에서 [서브넷 연결 편집] 클릭
  • 퍼블릭 서브넷 선택
  • 프라이빗 라우팅 테이블 생성
  • 생성한 라우팅 테이블의 정보 중 라우팅 항목에서 [라우팅 편집] 클릭
  • 대상 추가
  • 서브넷 연결 항목에서 [서브넷 연결 편집] 클릭
  • 프라이빗 서브넷 선택
  • 생성 완료

보안 그룹 생성

: VPC 내부의 인스턴스 보안을 위해 보안그룹을 생성한다. 각 보안 그룹에 속한 인스턴스는 인바운드 규칙으로 허용된 트래픽만 접근할 수 있다.

ALB가 외부의 HTTP 요청을 수신하기 위한 보안그룹과 ECS에서 생성한 웹 서비스 인스턴스가 ALB로부터 오는 트래픽은 수신하기 위한 보안 그룹을 생성한다.

  • 보안 그룹 탭으로 이동
  • 보안 그룹 1 생성
  • 보안 그룹 이름과 사용할 vpc 설정
  • 인바운드 규칙 추가
  • 보안 그룹 2 생성
  • 인바운드 규칙 추가 - 보안 그룹 1을 통과한 트래픽만 허용한다.
  • 보안 그룹 생성 완료

애플리케이션 로드 밸런서 생성

: 외부로부터 오는 요청을 분배하고 배포된 웹 서비스에 전달하기 위해 ALB를 생성한다.

  • EC2에서 로드밸런서 탭으로 이동
  • 로드밸런서 생성
  • ALB 선택
  • 구성
  • 부하 분산기는 외부 인터넷 망으로 연결되기 때문에 사전에 구성한 vpc를 선택하면 2개의 가용영역이 제공된다.
  • 외부 연결이 가능한 퍼블릿 서브넷을 선택한다.
  • 앞서 생성한 보안 그룹 선택

다음은 구성한 프로토콜과 포트를 사용하여 연결 요청을 확인하는 과정이다. 리스너가 수신한 트래픽은 대상 그룹으로 라우팅된다.

  • 먼저 대상 그룹을 생성한다.
  • target 유형은 인스턴스로 설정하고, 이름을 입력한다.
  • vpc가 ecs-vpc로 되어있는지 확인
  • 태그 설정
  • 등록 대상과 대상은 아무것도 설정하지 않고 넘어간다.
  • 대상 그룹 생성 완료
  • 다시 로드밸런서 생성 창으로 돌아와서 생성한 대상 그룹을 선택한다.
  • 로드밸런서 생성 완료 - 활성 상태가 될 때까지 기다린다.

AWS Cloud9 도구를 이용한 개발 환경 구성

: 배포될 웹 서비스의 도커 컨테이너 이미지를 빌드하고 업로드하기 위해 AWS에서 제공하는 개발 환경인 Cloud9 환경을 생성한다.

IAM 역할 생성

  • IAM의 역할 탭으로 이동
  • 역할 만들기
  • AWS 서비스와 EC2 선택
  • 권한 정책 연결
  • 이름 설정
  • 태그 추가

Cloud9 환경 생성

: AWS 커맨드 라인 인터페이스 등의 AWS 서비스를 활용하기 위한 환경이 구성되어 있고, IAM 역할을 부여하여 ECR 등의 AWS 서비스에 접근이 용이하다.

  • Cloud9에서 Create environment 클릭
  • 이름 설정
  • 네트워크 설정
  • EC2의 인스턴스 탭으로 이동하고, 만들어진 인스턴스의 IAM 역할 수정 클릭
  • 역할 선택
  • Cloud9에서 임시 자격 증명 제거
  • 기존의 임시 자격 증명 삭제
ec2-user:~/environment $ rm -vf ${HOME}/.aws/credentials
  • 현재 Cloud9 환경이 ecs-workshop-ECRFullAccessRole을 사용하는지 확인
ec2-user:~/environment $ aws sts get-caller-identity --query Arn | grep ecs-workshop
"arn:aws:sts::132520104923:assumed-role/ecs-workshop-ECRFullAccessRole/i-0fbb8a5ad393d2acd"
  • default region을 ap-northeast-2로 설정하고 확인
ec2-user:~/environment $ aws configure set default.region ap-northeast-2
ec2-user:~/environment $ aws configure get default.region
ap-northeast-2

도커 이미지 저장소 ECR 구성

: 컨테이너 이미지를 저장하기 위한 이미지 저장소 ECR을 생성하고, Dockerfile을 빌드한 후에 레포지토리에 컨테이너 이미지를 업로드하는 작업을 수행한다.

저장소 생성

  • Django 저장소 생성
    : 컨테이너 이미지를 저장하기 위한 저장소를 생성한다.
ec2-user:~/environment $ aws ecr create-repository --repository-name "django"
{
    "repository": {
        "repositoryUri": "132520104923.dkr.ecr.ap-northeast-2.amazonaws.com/django", 
        "imageScanningConfiguration": {
            "scanOnPush": false
        }, 
        "encryptionConfiguration": {
            "encryptionType": "AES256"
        }, 
        "registryId": "132520104923", 
        "imageTagMutability": "MUTABLE", 
        "repositoryArn": "arn:aws:ecr:ap-northeast-2:132520104923:repository/django", 
        "repositoryName": "django", 
        "createdAt": 1666578804.0
    }
}
  • Nginx 저장소 생성
ec2-user:~/environment $ aws ecr create-repository --repository-name "nginx"
{
    "repository": {
        "repositoryUri": "132520104923.dkr.ecr.ap-northeast-2.amazonaws.com/nginx", 
        "imageScanningConfiguration": {
            "scanOnPush": false
        }, 
        "encryptionConfiguration": {
            "encryptionType": "AES256"
        }, 
        "registryId": "132520104923", 
        "imageTagMutability": "MUTABLE", 
        "repositoryArn": "arn:aws:ecr:ap-northeast-2:132520104923:repository/nginx", 
        "repositoryName": "nginx", 
        "createdAt": 1666578860.0
    }
}

output의 repositoryUri는 추후에 Dockerfile을 빌드한 후 컨테이너 이미지를 ECR에 업로드할 때 필요하기 때문에 복사해둔다.

  • ECR의 Repositories로 이동
  • 생성된 리포지토리 확인

도커 이미지 빌드

: Dockerfile을 빌드하여 컨테이너 이미지를 생성한다.

  • 소스 코드 clone
  • django 폴더로 이동 후 Dockerfile 확인
## 이동
ec2-user:~/environment $ cd django/

## 확인
ec2-user:~/environment/django $ cat Dockerfile
FROM ubuntu:18.04
RUN apt-get update && \
    apt install -y software-properties-common &&\
    apt-get install --no-install-recommends -y \
    python3.8 python3-pip python3.8-dev &&\
    apt-get install gcc -y
RUN /usr/bin/python3.8 -m pip install --upgrade pip
RUN ln -s /usr/bin/python3.8 /usr/bin/python

RUN pip install -U setuptools
RUN pip install django==3.2 asgiref==3.3.3 gunicorn==20.0.4 setproctitle==1.1.10
RUN pip install django-common-models phonenumbers 

COPY ./app /app
RUN chown -R root:root /app
RUN chmod -R +x /app/bin
RUN chmod -R +x /app/cmd

WORKDIR /app/larva
RUN echo yes | python manage.py collectstatic

WORKDIR /app

VOLUME /app

ENTRYPOINT [ "/app/cmd/start" ]
  • 장고 Dockerfile 빌드
ec2-user:~/environment/django $ docker build -t django .
  • nginx 폴더로 이동 후 Dockerfile 확인
ec2-user:~/environment/django $ cd ..
ec2-user:~/environment $ cd nginx/
ec2-user:~/environment/nginx $ cat Dockerfile 
FROM nginx
WORKDIR /etc/nginx/
RUN rm /etc/nginx/conf.d/default.conf
COPY nginx.conf /etc/nginx/conf.d/
EXPOSE 80
  • nginx Dockerfile 빌드
ec2-user:~/environment/nginx $ docker build -t nginx .
  • 이미지 생성 확인
ec2-user:~/environment/nginx $ docker images
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
nginx        latest    a349fa9cbdf4   12 seconds ago   142MB
django       latest    d3e8a9849905   44 seconds ago   594MB

도커 이미지 업로드

: 생성된 이미지에 tag를 생성한 후 ECR에 업로드 한다.

  • AWS ECR 레지스트리에 대한 Docker client 인증 수행
ec2-user:~/environment $ aws ecr get-login-password --region ap-northeast-2 | docker login --username AWS --password-stdin 132520104923.dkr.ecr.ap-northeast-2.amazonaws.com
  • ECR에 컨테이너 이미지를 push 하기 위해서는 repositoryUri 정보가 필요하다.
    repositoryUri : 132520104923.dkr.ecr.ap-northeast-2.amazonaws.com
  • 장고 이미지에 tag 추가 후 ECR에 업로드
ec2-user:~/environment $ docker tag django:latest 132520104923.dkr.ecr.ap-northeast-2.amazonaws.com/django:latest
ec2-user:~/environment $ docker push 132520104923.dkr.ecr.ap-northeast-2.amazonaws.com/django:latest

  • nginx 이미지에 tag 추가 후 ECR에 업로드
ec2-user:~/environment $ docker tag nginx:latest 132520104923.dkr.ecr.ap-northeast-2.amazonaws.com/nginx:latest                                                                           
ec2-user:~/environment $ docker push 132520104923.dkr.ecr.ap-northeast-2.amazonaws.com/nginx:latest

  • ECR에 업로드된 이미지의 URI를 복사해둔다.
    Django : 132520104923.dkr.ecr.ap-northeast-2.amazonaws.com/django:latest
    nginx : 132520104923.dkr.ecr.ap-northeast-2.amazonaws.com/nginx:latest

ECS 환경 구성

ECS 클러스터 생성

: EC2 인스턴스 기반으로 컨테이너가 서비스 될 수 있도록 클러스터를 구성한다.

  • ECS의 클러스터 탭으로 이동
  • 클러스터 생성
  • 템플릿 선택
  • 클러스터 이름
  • 인스턴스 구성
  • 네트워킹 설정
  • IAM 역할과 태그 설정
  • 클러스터 상태 ACTIVE 확인

ECS 작업 정의 생성

: ECR에 저장된 컨테이너 이미지로 작업 정의를 구성한다.

  • 작업 정의 탭으로 이동
  • 새 작업 정의 생성
  • 시작 유형 선택
  • 작업 이름 설정
  • 볼륨 추가 클릭
  • nginx 컨테이너가 django 컨테이너의 [/app] 폴더 내부에 있는 socket 파일에 접근해야 통신이 가능하므로 두 컨테이너가 공유할 볼륨을 추가한다.
  • 컨테이너 추가 클릭
  • 정보 입력

  • 컨테이너 추가 클릭해서 정보 입력


  • 컨테이너 정의 생성 확인
  • 작업 정의가 생성되었다.

ECS 서비스 생성

: 클러스터에서 구성된 작업 정의로 서비스를 생성한다.

  • 클러스터 탭으로 이동하고, 클러스터 클릭
  • 서비스 탭의 생성 클릭
  • 정보 입력
  • 상태 검사 유예 기간
  • 로드 밸런싱
  • 로드밸런서에 추가 클릭

  • 작업 running 확인

웹 서비스 배포 테스트

  • 로드밸런서의 DNS 이름으로 접속

Virtual server vs Serverless

: 서버를 구성하거나 관리하지 않고 Application과 Service를 구축하고 실행한다.
-> DevOps 환경

Serverless computing

: 서버 구성을 생각하지 않고 애플리케이션과 서비스를 구축하고 실행할 수 있다.

AWS Lambda

: 완전 관리형 컴퓨팅 서비스. 구성이 아닌 애플리케이션에 집중한다.
요청 시에만 컴퓨팅 리소스를 사용하고, 상태 비저장 코드를 실행한다.
비용은 Lambda를 실행한 마이크로서비스에 대해서만 지불한다.

회사에서 중요한 애플리케잉션을 AWS로 마이그레이션하려고 합니다. 애플리케이션의 런타임이 짧습니다. 응용 프로그램은 데이터 변경 또는 시스템 상태 변경에 의해 호출됩니다. 이 회사는 운영 효율성을 극대화하고 애플리케이션 실행 비용을 최소화하는 컴퓨팅 솔루션이 필요합니다. 이러한 요구 사항을 충족하기 위해 회사는 어떤 AWS 솔루션을 사용해야 합니까?

A. Lambda

Lambda를 활용한 웹서비스 구현 실습

Webpage를 보여주는 Lambda

  • Lambda의 함수 탭으로 이동
  • 함수 생성
  • 옵션 선택
  • 함수 이름, 언어 선택
  • 함수 URL 활성화
  • 소스 코드 넣고, Deploy 클릭
import json

def lambda_handler(event, context):
    response = {
        "statusCode": 200,
        "statusDescription": "200 OK",
        "Access-Control-Allow-Origin" : "*",
        "isBase64Encoded": False,
        "headers": {
            "Content-Type": "text/html; charset=utf-8"
        }
    }

    response['body'] = """<html>
    <head>
    <meta charset="utf-8" name="viewport" content="width=device-width, height=device-height, minimum-scale=1.0, maximum-scale=1.0, initial-scale=1.0">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <title>Hello Kakao!</title>
    <style>
        #title {
            font-family: arial; font-size: 2em;color: #eb971a; margin-top:50px;
            text-align: center;
        }
        button {
                background-color: #eb971a;
                border:none;
                color:white;
                border-radius: 5px;
                width:40%;
                height:35px;
                font-size: 13pt;
                margin-top:30px;
                text-align: center;
        }
        #sentence {
                font-size: 17pt;
                margin-top:30px;
                font-weight: bold;
                color: #eb971a;
        }
    </style>
        </head>
        <body>
            <p id="title">Hello Kakao From <b>Lambda</b></p>
            <hr id="lambda-line" width="800px" align="center" color="#eb971a;">
            <center><button onclick="checkEvent();">Who are you?</button></center>
            <center><div id="sentence"></div></center>
        </body>
        <script type="text/javascript">
        
            function checkEvent(){
                $.ajax({ type: "GET", 
                        url: "URL을입력하세요", 
                        dataType:'json',
                        success: function(data){ 
                        document.getElementById('sentence').innerHTML = data.status + "&nbsp;&nbsp;" + data.name
                        }, 
                        error: function (error){
                        alert('ERROR::');
                        console.log(error)
                        }

                });
            }

        </script>
        </html>
            
        """
        
    return response
  • 함수 URL로 접근한다.
  • 홈페이지 확인 - Who are you?를 누르면 데이터베이스가 없어서 error가 뜬다.

Webpage 기능을 보유한 Lambda

  • 함수 옵션 선택
  • 이름 작성, 언어 선택
  • 기본 실행 역할 생성
  • 소스 코드 작성
import json
import boto3
import random
import json

def lambda_handler(event, context):
    
    member_name = ['kevin','soyeon','gibin','yeji','yuri', 'taelim']
    member_status = ['Happy','Sad','Serious','Satisfied','Free', 'Soso']
    
    dynamodb = boto3.resource('dynamodb',endpoint_url='http://dynamodb.ap-northeast-2.amazonaws.com')
    member_table = dynamodb.Table('kakao-member')
    
    name = member_name[random.randint(0,5)]
    status = member_status[random.randint(0, 5)]
    
    member_table.put_item(
       Item={
            'name': name,
            'status': status,
        }
    )
    
    documents = {'name':name,'status':status}
    
    print(documents)
    
    return {
        'statusCode': 200,
        'headers': {'Access-Control-Allow-Origin': '*'},
        'body': json.dumps(documents)
    }
  • Test 클릭해서 작성
  • Deploy 하고, Test 클릭한다.

=> DB쪽에 table이 없기 때문에 error가 발생한다.

Member data를 보유한 DB

  • DynamoDB에서 테이블 생성 클릭
  • 테이블 이름과 키 설정
  • 생성 완료

Webpage 기능을 호출하는 통로 API Gateway

  • API Gateway에서 REST API 구축 클릭
  • 설정
  • 메서드 생성 클릭
  • GET 선택
  • 설정
  • 테스트 클릭
  • 200 확인
  • CORS 활성화
  • 헤더 대체 클릭
  • 확인
  • API 배포 클릭
  • 설정
  • URL 클릭
  • 결과 확인

  • Lambda kakao-webpage로 들어가서 url 붙여넣기

  • Deploy 클릭
  • 함수 URL로 접근
  • 최종 확인

  • DynamoDB에서 표 항목 탐색 클릭
  • 항목 확인 가능


Cloud Infrastructure Automation

CloudFormation

업무 자동화

대규모 컴퓨팅 환경 구축시 고려 사항

  • 고객으로부터의 요구사항을 기반으로 설계 또는 구현 -> 어디에 노력을 투입할 것인가?
  • 수동 구현의 위험은 무엇인가? 사용자 실수
  • 어떻게 프로덕션 서버를 업데이트할 것인가?
  • 어떻게 배포를 여러 지리적 Region에 롤아웃할 것인가?
  • 장애가 발생할 경우 어떻게 롤백을 관리할 것인가?
  • 배포에 대한 디버깅은 어떻게 할 것인가?
  • 어떻게 오류를 발견하고 수정하며 수정을 확인할 것인가?
  • 어떻게 다양한 시스템과 및 하위 시스템에 대한 종속성을 관리할 것인가?
  • 이 모든 작업을 수동으로 할 수 있는가? 보상 없는 위험

CloudFormation Template 인프라 관리의 간소화

CloudFormation은 템플릿을 작성하는 것 하나로 모든 리소스와 해당 속성에 대한 설정을 한번에 할 수 있다.
리소스를 단 한곳에서만 관리하면 되기 때문에 전체적인 흐름도 파악할 수 있게 되고 변경 작업(update → change dataset)도 용이하다.

=> 코드로 인프라를 관리하기 때문에 이 코드만 버전관리한다면 초기부터 인프라
변경 과정을 추적할 수 있다. (IaC 서비스의 특징)

Template(*.yaml)과 Stack(resource list)으로 작업한다.
템플릿을 코드로 취급하고, 원하는 버전 제어 방법으로 이를 관리한다. JSON/YAML 템플릿 파일 내에 전체 애플리케이션 스택을 정의한다.

CloudFormation 구성

스택을 생성할 때마다 CloudFormation이 템플릿에 작성된 리소스를 프로비저닝 수행

  • Stack
    : CloudFormation은 스택 이라는 하나의 단위로 리소스 전체를 관리
    : 스택 단위로 인프라를 만들고(IaC) 지울 수 있다.
    : 스택에서 관리하는 모든 리소스는 CloudFormation의 템플릿으로만 정의

CloudFormation 작동 방식


  • 템플릿 작성: CloudFormation 디자이너에서 작성 가능
  • 템플릿 업로드: 로컬 또는 s3 버킷에 저장
  • 업로드한 템플릿을 이용해 스택 생성
  • 템플릿에 기술된 서비스를 호출해 리소스를 프로비저닝하고 구성
  • 모든 리소스 생성 후 스택 생성 완료 보고

CloudFormation designer

: 템플릿 생성, 보기 및 수정을 위한 그래픽 도구

CloudFormation S3 실습

  • MYCFNBUCKET.yaml 작성
AWSTemplateFormatVersion: 2010-09-09
Resources:
  MYCFNBUCKET:
    Type: AWS::S3::Bucket
    Properties:
      AccessControl: PublicRead
Outputs:
  BucketName:
    Value: MYCFNBUCKET
  • CloudFormatioon의 스택 탭으로 이동
  • 스택 생성
  • 파일 업로드
  • Designer에서 보기로 확인
  • 스택 이름 설정
  • 태그 설정
  • S3에 가서 bucket이 생성된 것을 확인할 수 있다.

CloudFormation EC2 실습

  • yaml 파일 작성
AWSTemplateFormatVersion: '2010-09-09'

Description: EC2 instance Resources LABs.

Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
      - Label:
          default: 'Amazon EC2 Configuration'
        Parameters:
          - InstanceType

    ParameterLabels:
      InstanceType:
        default: 'Type of EC2 Instance'

Parameters:
  InstanceType:
    Type: String
    Default: t2.micro
    AllowedValues:
      - t2.micro
      - t2.small
    Description: 'Enter t2.micro or t2.small. Default is t2.micro.'

Resources:
  WebServerInstance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: ami-09cf633fe86e51bf0    # Seoul Resion의 Amazon Linux AMI-ID
      InstanceType: !Ref InstanceType
  • 스택 생성
  • 파일 업로드
  • Designer로 확인
  • 스택 이름 설정
  • 생성 확인
  • EC2에서 인스턴스가 생성되었다.

CloudFormation EC2 & EBS 실습

  • yaml 코드 작성
AWSTemplateFormatVersion: '2010-09-09'
Description: EC2 instance Resources LAB2.
Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
      - Label:
          default: 'Amazon EC2 Configuration'
        Parameters:
          - InstanceType

    ParameterLabels:
      InstanceType:
        default: 'Type of EC2 Instance'

Parameters:
  InstanceType:
    Type: String
    Default: t2.micro
    AllowedValues:
      - t2.micro
      - t2.small
    Description: 'Enter t2.micro or t2.small. Default is t2.micro.'

Resources:
  WebServerInstance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: ami-09cf633fe86e51bf0    # Seoul Resion의 Amazon Linux AMI-ID
      InstanceType: !Ref InstanceType
      KeyName: kakao-oeckikek
      BlockDeviceMappings:
        -
          DeviceName: /dev/sdm
          Ebs:
            VolumeType: io1
            Iops: 300
            DeleteOnTermination: false
            VolumeSize: 10
  • 스택 생성
  • 업로드
  • 이름 지정

CloudFormation httpd & mariadb 실습

  • yaml 파일 작성
AWSTemplateFormatVersion: "2010-09-09"
Description: EC2 for webserver
Parameters:
  KeyName:
    Description: Name of KeyPair
    Type: AWS::EC2::KeyPair::KeyName
  AMI:
    Description: AMI of EC2
    Type: AWS::EC2::Image::Id
    Default: ami-09cf633fe86e51bf0

  AZpublic:
    Description: AvailabilityZone for public
    Type: AWS::EC2::AvailabilityZone::Name
  AZprivate:
    Description: AvailabilityZone for private
    Type: AWS::EC2::AvailabilityZone::Name

  VPCCidr:
    Description: Cidr Block for VPC
    Type: String
    Default: 10.0.0.0/16
  PublicSubnetCidr:
    Description: Cidr Block for Public Subnet
    Type: String
    Default: 10.0.0.0/24
  PrivateSubnetCidr:
    Description: Cidr Block for Private Subnet
    Type: String
    Default: 10.0.10.0/24

Resources:
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: !Ref VPCCidr
      EnableDnsHostnames: true
      Tags:
        - Key: Name
          Value: soyeonVPC

  PublicSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: !Ref PublicSubnetCidr
      AvailabilityZone: !Ref AZpublic
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: public subnet
  PrivateSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: !Ref PrivateSubnetCidr
      AvailabilityZone: !Ref AZprivate
      Tags:
        - Key: Name
          Value: private subnet

  IGW:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
        - Key: Name
          Value: myigw
  Attachigw:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      InternetGatewayId: !Ref IGW
      VpcId: !Ref VPC

  PublicRT:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: Public RT
  PublicRoute:
    Type: AWS::EC2::Route
    DependsOn: Attachigw
    Properties:
      RouteTableId: !Ref PublicRT
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref IGW
  PublicSubnetRTAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PublicRT
      SubnetId: !Ref PublicSubnet

  SGforWeb:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: allow 22, 80
      GroupName: webaccess
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: 0.0.0.0/0
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: 0.0.0.0/0
      VpcId: !Ref VPC
  SGforDB:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: allow webserver
      GroupName: dbaccess
      SecurityGroupIngress:
        - IpProtocol: -1
          SourceSecurityGroupId : !GetAtt SGforWeb.GroupId
      VpcId: !Ref VPC

  EC2forWeb:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !Ref AMI
      KeyName: !Ref KeyName
      AvailabilityZone: !GetAtt PublicSubnet.AvailabilityZone
      InstanceType: t2.micro
      SubnetId: !Ref PublicSubnet
      SecurityGroupIds:
        - !Ref SGforWeb
      UserData:
        Fn::Base64:
          !Join [ "", [
          "#!/bin/bash\n",
          "#Install APM for Web Server\n",
          "yum install -y mariadb* php httpd php-mysql\n",
          "systemctl enable httpd mariadb\n",
          "systemctl start httpd mariadb\n"] ]
      Tags:
        - Key: Name
          Value: Web Server
  • 스택 생성
  • 업로드
  • Designer로 확인
  • 이름 지정
  • 파라미터 지정

0개의 댓글