AWS에서는 인프라에 대한 지식이 없어도 배포 환경을 구축할 수 있는 Elastic Beanstalk(EB)를 제공한다. EB에 어플리케이션을 전달하면 EB에서 용량 프로비저닝, 로드 밸런싱, 조정, 어플리케이션 상태 모니터링을 자동으로 처리한다.
다음은 EB가 어떻게 어플리케이션을 관리하는 지 보여주는 워크플로우다.
Elastic Beanstalk 구조
EB는 여러 종류의 환경을 제공할 수 있다. 웹 서버 환경을 중점적으로 살펴보자.
Auto Scaling Group에 여러 EC2 인스턴스들이 존재한다. 이 인스턴스에서 어플리케이션이 실행되는데 여기서 HM(호스트 매니저) 이라는 개념이 있다. HM는 어플리케이션의 로그를 S3에 개시하거나 서버 인스턴스의 상태를 보고하는 역할을 한다.
Auto Scaling Group의 EC2들 앞에는 Elastic Load Balancer가 로드 밸런싱을 한다. EB의 ELB는 CNAME(URL)을 가진다. 그리고 EB 환경도 CNAME을 가진다. 이때 환경의 CNAME은 ELB의 CNAME의 별칭으로 지정된다.
Elastic Beanstalk 직접 구성해보기
EB를 생성할 때 중요한 몇가지 위주로 설명하겠다.
플랫폼 설정하기 및 추가 옵션 구성
AWS EB 콘솔에서 새 어플리케이션 만들기를 선택하면 어플리케이션이 어떤 플랫폼인지 그리고 그 플랫폼을 어떤 운영체제에서 실행할지를 정해야 한다. 필자의 경우는 Spring Boot 어플리케이션이므로 Java 플랫폼에 Linux 2를 설정했다. 즉 EB 환경의 EC2가 Linux 2 기반으로 생성된다는 의미이다.
그리고 이때 중요한 건 바로 애플리케이션 생성을 누르지 말고 무중단 배포를 위해 추가 옵션 구성을 선택한다.
추가 옵션 구성을 클릭하면 여러가지 설정 가능한 옵션이 나온다. 이때 사전 설정에서 사용자 지정 구성으로 우리 상황에 맞도록 구성할 수 있도록 해보자.
인스턴스 보안그룹 설정하기
Auto Scaling Group의 인스턴스들이 적용되는 보안그룹을 반드시 설정해줘야 한다. 그렇지 않으면 외부에서 인스턴스에 SSH로 접근해서 의도하지 않은 작업을 진행할 수 있다.
F12-PROD 보안그룹은 80 포트와 8080 포트를 모든 IP가 접근할 수 있도록 했고, SSH는 개발자 IP만 접근 가능하도록 인바운드 규칙을 적용했다. ec2-rds-1 보안그룹은 mysql 포트인 3306 포트를 아웃바운드 규칙으로 적용되어 있다.
Auto Scaling Group 및 로드 밸런싱 설정하기
먼저 Auto Scaling Group에 어떤 인스턴스를 몇 개나 수용할 지를 정해야 한다. 우리는 프리티어 한도 내에서 인프라를 구축해야 하기 때문에 인스턴스를 한 개만 사용하도록 했다.
다음으로 로드 밸런서를 설정해야 한다. 로드 밸런서는 크게 Classic Load Balancer(ELB)와 Application Load Balancer(ALB)를 선택할 수 있다. ELB가 먼저 출시되어 많은 참고 자료가 존재하지만 갑작스러운 트래픽이 발생할 경우에 대응이 좋지 않다고 한다. 그래서 우리는 ALB를 선택했다.
그리고 추가로 프론트엔드에서 8080포트로 요청하는 상황이라 로드 밸런서의 리스너를 8080포트도 열어줬다.
무중단 배포 설정
이제 EB에서 새 버전을 배포하려고 할 때 무중단 배포가 되도록 설정해야 한다. 롤링 업데이트와 배포 수정에 가서 애플리케이션 배포 방식을 정할 수 있다. 우리는 추가 배치를 사용한 롤링 방식을 선택했다. 만약 새 버전이 배포되면 새 EC2 하나를 만들어서 새 버전을 배포하고 배포가 완료되면 로드 밸런서 설정을 바꾸고 기존의 Auto Scaling은 폐기하는 방식으로 운영된다. 다만 이 방식은 배포가 되고나면 롤백하지 못한다.
EC2 키 페어 설정
EB에서 생성된 EC2 인스턴스에 접근할 수 있는 PEM 키를 설정해 줄 수 있다. 우리는 기존에 만들어놨던 PEM 키를 활용했다.
이제 EB 설정은 어느정도 끝났으니 EB를 생성하면 된다.
EB 어플리케이션 구성
EB 어플리케이션을 실행할 때 인스턴스에서 설정해줘야 하는 것들이 있을 수 있다. 예를 들어 EC2의 타임존 설정이나 리버스 프록시 설정이 필요할 수 있다. 그 설정을 EB에서는 .ebextensions 디렉토리, .platform 디렉토리로 설정해줄 수 있다.
EC2 리버스 프록시 설정하기
로드 밸런서가 보내는 트래픽을 EC2에서 애플리케이션으로 전달 할 때 리버시 프록시를 설정해줄 수 있다. 우리가 사용하는 Linux 2 플랫폼은 Nginx로 리버스 프록시를 구현할 수 있다. 이때 .platform/nginx/nginx.conf 파일을 통해서 EC2의 Nginx의 설정을 오버라이딩 할 수 있다. .platform/nginx/conf.d/{설정파일이름}.conf에 파일을 만들면 기존의 Nginx 설정 파일에 설정을 추가하는 방식으로 구현할 수 있다.
우리는 .platform/nginx/nginx.conf 파일을 프로젝트에 추가해서 Nginx 설정을 오버라이딩 하는 방식으로 구현했다. /로 오는 모든 요청은 로컬의 8080포트로 보내도록 구현했다.
-name:Grantexecutepermissionforgradlew run:chmod+xgradlew -name:ExecuteGradlebuild run:./gradlewbootJar -name:Getcurrenttime# 현재 시각을 기록해둔다. uses:1466587594/get-current-time@v2.0.2 id:current-time with: format:YYYY-MM-DDTHH-mm-ss utcOffset:"+09:00"
-name:Generatedeploymentpackage# JAR 파일과 함께 이전에 만들었던 설정파일을 함께 zip파일로 압축한다. run:| mkdir -p deploy cp build/libs/f12-0.0.1-SNAPSHOT.jar deploy/application.jar cp Procfile deploy/Procfile cp -r .ebextensions deploy/.ebextensions cp -r .platform deploy/.platform cd deploy && zip -r deploy.zip . -name:DeploytoEB uses:einaregilsson/beanstalk-deploy@v21 with: aws_access_key:${{secrets.AWS_ACCESS_KEY_ID}}# IAM aws_secret_key:${{secrets.AWS_SECRET_ACCESS_KEY}}# IAM application_name:f12-prod-backend environment_name:F12prodbackend-env-2 version_label:github-action-${{steps.current-time.outputs.formattedTime}}# 버전명을 아까 기록한 시간을 토대로 구분하게 했다. region:ap-northeast-2 deployment_package:backend/deploy/deploy.zip wait_for_environment_recovery:180# 배포가 Green으로 돌아오는 시간을 고려해 환경 회복 시간을 180초로 하였다.