[무중단 배포 환경 구축하기] - 3. 배포를 위한 서비스 환경 구성

Soover·2021년 8월 4일
0
post-thumbnail

📌들어가기

안녕하세요. soover입니다.
이전 글 [무중단 배포 환경 구축하기] - 2. AWS IAM 설정 에 이어서 배포 대상이 되는 서버를 구축해보겠습니다.

지금부터는 내용이 조금 길어질 수 있습니다..😂
하지만 내용은 그리 어렵지 않으니 차근차근 해나가봅시다 :)






🚀시작하기

우선 우리가 목표로 하는 배포 흐름을 살펴보겠습니다.

운영 중인 서버 a-1, a-2 인스턴스가 있고, 여기에 ELB를 연동하여 사용자의 유입을 각각 a-1a-2로 분배하는 구조가 있다고 가정합시다. 무중단 배포의 시나리오는 다음과 같이 이루어집니다.

  1. 기존 A그룹과 동일한 조건으로 B그룹을 생성합니다. (인스턴스 개수, 서버 환경 동일)

  2. B그룹에 포함된 인스턴스에 변경된 소스를 반영합니다. (CodeDeploy Agent가 작업 수행)

  3. 세팅이 완료된 B그룹ELB에 연결합니다. (이 시점에서는 A그룹과 B그룹이 함께 ELB에 연결되어 있기 때문에 ELB에서 트래픽을 할당하는 인스턴스 개수는 총 4개)

  4. ELB에 연결된 B그룹에 배포 상 문제가 없으면 A그룹의 연결은 해제 및 삭제 처리 됩니다.

  5. 배포 후에는 사용자 유입을 B그룹b-1, b-2 인스턴스가 감당하게 됩니다.

위 시나리오와 같은 배포 방식을 Blue-Green 유형이라고 합니다.
배포 전략에는 다양한 방법들이 존재하고, 주어진 환경과 상황 조건에 따른 장단점을 판단하여 적절한 방법으로 선택하게 됩니다.




AMI 만들기

EC2에 필요한 작업을 먼저 살펴보면,

  1. 배포 대상이 되는 서버(인스턴스)를 생성합니다.

  2. Docker를 통해 Flask로 간단한 API 서버를 구축 및 실행합니다. (for 식별값 확인)

  3. S3와 CodeDeploy에 연동 가능하도록 CodeDeploy Agent를 설치합니다.

  4. Auto Scaling Group을 통해 실제 배포 정책에 사용될 AMI 이미지를 생성합니다.


인스턴스 생성

EC2 서비스 콘솔에서 [인스턴스] - [인스턴스 시작] 버튼을 클릭합니다.

간단한 테스트 서버를 만들 계획이므로 OS는 Ubuntu 20.04 LTS, 인스턴스 유형은 t2.micro로 선택하고, 나머지는 default 값을 선택하여 인스턴스를 하나 생성했습니다.


API 서버 구축

Python의 웹프레임워크 중 Flask를 사용해 간단한 API 서버를 만들겠습니다.

먼저 방금 생성한 EC2로 진입하여 Python 가상환경을 만든 후, Flask 라이브러리를 설치해줍니다.

$ pwd
/home/ubuntu/test

# 가상환경 생성
$ python3 -m venv .venv

# 가상환경 활성화
$ source .venv/bin/active

# pip 최신 버전 업데이트
(.venv) $ python -m pip install --upgrade pip

# Flask 설치
(.venv) $ pip install Flask

그리고 app.py 파일을 만들어 다음 코드를 입력합니다.

### app.py

from flask import Flask, jsonify
import uuid


version = "v1.0"
unique_id = uuid.uuid4()

app = Flask(__name__)


@app.route('/')
def hello():
  return jsonify({"version": version, "id": unique_id}), 200


if __name__ == '__main__':
  app.run(debug=True, host='0.0.0.0', port=5000)

python app.py 명령으로 서버를 실행하여 해당 서버 주소의 5000 포트로 접근을 해보면, 현재 서버가 제공하는 idversion을 확인할 수가 있습니다.
id 값은 식별을 위해 유일한 값을 줄 수 있도록 하였습니다.

여기서 잠깐.. 배포 흐름을 생각해보면 업데이트 된 소스를 S3로 부터 가져와 반영 해야하고, 이때 Flask 서버에 재실행 명령이 필요합니다.
여러가지 방법이 있겠지만 우리는 Docker를 이용해 보도록 하겠습니다. 정말 간단합니다??

  • 개발 환경에 따라 Docker의 사용 유무가 달라집니다.
  • 제약이 없다면 건너뛰셔도 무방합니다 :)
  • Docker 설치의 경우, 공식문서에 자세히 나와있으니 참고 바랍니다.
  • OS 환경에 맞춰 Ubuntu 설치 문서를 참고해주세요.

도커 설치하기

Docker 설치 후, User 모드에서 docker 명령어에 대한 권한이 부여되지 않아 실행에 문제가 생길 수 있습니다.
그럴땐 아래 명령으로 해당 사용자에게 docker 명령어 권한을 부여해줍니다.

$ sudo usermod -a -G docker $USER

앞서 만든 코드를 컨테이너로 실해하기 위해선 먼저 Dockerfile로 이미지를 만들어주어야 합니다.
아래와 같이 파일을 작성해봅시다.

### Dockerfile

# pull official base image
FROM python:3.8-alpine

# set work directory
WORKDIR /usr/src/app

# set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

# install dependencies
RUN python3 -m pip install --upgrade pip
RUN pip install Flask

# copy app.py
COPY app.py /usr/src/app/

CMD python3 app.py

공식 python 이미지를 가져와 필요한 환경 세팅을 하고, 소스를 복사하여 서버를 실행한다는 내용입니다.
본 시리즈에서는 Docker와 관련된 자세한 내용은 주제에 벗어나므로 생략하겠습니다.

Dockerfile을 이미지로 빌드하면 다음 화면을 볼 수 있습니다.

$ ls -al
total 20
drwxrwxr-x 3 ubuntu ubuntu 4096 Jul 21 09:10 .
drwxr-xr-x 5 ubuntu ubuntu 4096 Jul 21 09:10 ..
drwxrwxr-x 6 ubuntu ubuntu 4096 Jul 20 10:45 .venv
-rw-rw-r-- 1 ubuntu ubuntu  323 Jul 21 08:50 Dockerfile
-rw-rw-r-- 1 ubuntu ubuntu  282 Jul 20 11:20 app.py

# 이미지 빌드
$ docker build --tag deploy-test .

# 이미지 확인
$ docker images
REPOSITORY    TAG          IMAGE ID       CREATED         SIZE
deploy-test   latest       094abde73094   3 minutes ago   47.9MB
python        3.8-alpine   5e8816ee5207   3 weeks ago     43.3MB

그리고 빌드한 이미지로 컨테이너를 올리면, 이전에 python 명령으로 실행한 것과 같은 결과를 얻을 수 있습니다.

# 컨테이너 실행
$ docker run -d -p 5000:5000 --restart always --name deploy-test deploy-test

# 컨테이너 상태 확인
$ docker ps -a
CONTAINER ID   IMAGE         COMMAND                  CREATED         STATUS         PORTS                                       NAMES
acf3496afbbe   deploy-test   "/bin/sh -c 'python3…"   8 seconds ago   Up 7 seconds   0.0.0.0:5000->5000/tcp, :::5000->5000/tcp   deploy-test

당연히 새로운 형태의 서버를 실행했기 때문에 id값은 달라지겠죠?

추가로 docker run 명령을 실행할 때 사용한 옵션을 설명드리면,
컨테이너는 격리된 공간에 생성된 녀석이기 때문에 해당 인스턴스의 IP 주소로 컨테이너에 접근 하기 위해선 포트포워딩이 필요합니다. 그렇기 때문에 -p 5000:5000으로 포트포워딩을 설정하였습니다.
또한, ASG을 통해 인스턴스 생성 시에 컨테이너 구동이 가능하도록 --restart always옵션을 주고, --name deploy-test로 컨테이너 명을, 마지막 입력값으로 앞서 만들어 놓은 이미지 명을 주었습니다.


CodeDeploy Agent 설치

CodeDeploy에 의해 작업을 부여받기 위해선 CodeDeploy Agent가 있어야 합니다.

AWS 공식 문석를 참고하면 금방 설치가 가능합니다!
CodeDeploy Agent 설치하기


이미지 생성

모든 세팅이 완료 되었으니 Auto Scaling Group에서 사용 가능하도록 AMI 이미지를 만들어야 합니다.

EC2 콘솔창에서 인스턴스를 우클릭하여 [이미지 및 템플릿] - [이미지 생성] 을 선택합니다.

그리고 '이미지 생성' 화면으로 전환되면 이미지 이름 을 입력 후, [이미지 생성] 버튼을 클릭합니다.

서버 세팅이 완료된 AMI 이미지가 만들어 졌습니다!




ELB 만들기

ELB 생성은 AMI를 만드는 과정보다 더 쉽습니다.

콘솔창에서 [로드밸런서] - [Load Balancer 생성] 을 선택하고, Classic Load Balancer로 시작합니다.

Load Balancer 이름 을 입력하고, 앞서 EC2에서 설정한 웹서버 포트에 맞추어 5000 포트로 들어오는 트래픽을 그대로 EC2의 5000 포트로 보내주도록 리스너를 설정합니다.

그리고 로드밸런서에서 5000포트로 접근할 수 있도록 포트를 열어주어 ELB를 생성합니다.

ELB 준비 끝..!




Auto Scaling 구현하기

이제 마지막 단계입니다.
준비된 AMI와 ELB를 ASG에 연동하여 서버를 생성해봅시다.


Launch Configurations

ASG(Auto Scaling Group) 기능을 활성화하기 위해선 ASG의 작업명세서 역할을 하는 시작 구성(Launch Configurations) 파트를 먼저 작성해주어야 합니다.

콘솔창의 Auto Scaling 영역에서 [시작 구성] - [시작 구성 생성] 버튼을 클릭하면,
아래와 같은 양식의 화면이 나오게 됩니다.

  • 시작 구성 이름 : 시작 구성의 이름을 입력합니다. deploy-test-lc
  • AMI : 배포 환경에 적용하기 위해 생성했던 AMI를 선택합니다. deploy-test-ami
  • 인스턴스 유형 : 배포될 인스턴스 유형을 선택합니다. 여기에서는 t2.micro를 사용하겠습니다.
  • IAM 인스턴스 프로파일 : S3 및 CodeDeploy와 통신하기 위해 만들었던 IAM 역할을 선택합니다. ec2-deploy-test-role
  • EBS 볼륨 : 생성될 인스턴스에 의해 만들어질 EBS입니다. 기본 값(8GiB)으로 선택하겠습니다.
  • 보안 그룹 : 생성될 인스턴스으 보안 그룹 설정 내용입니다. ELB와 5000 포트로 연결되어야 하므로 앞서 생성했던 보안그룹을 연결해줍니다. deploy-test-sg
  • 키 페어 : 인스턴스에 접근하기 위한 키 페어를 생성할 수 있습니다. (선택)

위와 같은 구성으로 [시작 구성 생성] 버튼을 클릭하여 완료합니다.


Auto Scaling Group

생성된 시작 구성을 가지고 이제 진짜 마지막으로 오토스케일링 기능을 활성화 하도록 합시다.

먼저 [Auto Scaling Groups] - [Auto Scaling 그룹 생성] 으로 이동합니다.

1단계 - 시작 템플릿 또는 구성 선택 에서 오토스케일링 이름(deploy-test-asg)을 입력하고, 앞서 만들었던 시작 구성(deploy-test-lc)을 선택합니다.

2단계 - 설정 구성 에서는 사용될 VPCSubnet 을 선택해줍니다.

3단계 - 고급 옵션 구성 에서 ASG로부터 생성되는 EC2 인스턴스를 ELB에 연결할지 결정합니다. 생성해 둔 ELB가 있으므로 기존 로드 밸런서에 연결 을 선택하고, ELB 유형에 따라 Classic Load Balancer에서 선택 을 선택하여 이전에 생성한 ELB를 찾아 지정해줍니다. deploy-test-lb

4단계 - 그룹 크기 및 조정 정책 구성 에서는 그룹 크기(개수)를 지정할 수 있습니다. 원하는 용량최소 용량을 2, 최대 용량을 4로 구성하겠습니다.
조정 정책 부분은 오토스케일링의 핵심 기능이긴 하지만, 본 시리즈에서는 다루지 않겠습니다.

나머지 단계들은 기본 값으로 설정하여 완료하면,
아래와 같이 오토스케일링이 생성된 걸을 확인할 수 있습니다.

그리고 오토스케일링이 생성됨과 동시에 연결된 EC2 인스턴스 2개가 생성되었습니다.

ELB를 확인해보면 오토스케일링에 의해 생성된 EC2 인스턴스가 ELB에도 연결된 것을 확인할 수가 있습니다.

그말인즉슨, 각 EC2 인스턴스에 API 서버가 구현되어서 ELB의 5000번 포트로 접근을 하면 idversion 정보를 나타내주겠죠?

(와~!) 실제로 ELB의 5000 포트로 접근하니 각 인스턴스 마다 정보를 보내주는 것을 확인할 수 있습니다.






👏마무리

지금까지 서비스 환경을 구축하는 내용을 알아보았습니다.
어려운 내용은 없어기에 금방 세팅 하셨으리라 생각합니다.

다음 글에서는 [무중단 배포 환경 구축하기] - 4. Jenkins 설정 및 Gitlab 연동 을 다루면서 배포 설정을 시작해보도록 하겠습니다.


감사합니다.

profile
자동화가 우리를 자유케 하리라

0개의 댓글