JUINTINATION
GitHub Actions를 활용한 CI/CD 배포 본문
어느덧 지금 읽고 있는 책의 마지막 실습이다. CI/CD에 대해서는 지난 글에 간단하게 언급해두었으니 참고하면 될 것 같다.
이전 배포 방식
- 로컬 컴퓨터에서 프로젝트 생성
- 의존성 관리 도구 gradle을 통해 테스트 후 build하여 프로젝트를 jar 파일로 변경
- 실행파일을 AWS에 배포
- EC2 사용: OS 및 Java 설치, 실행 파일 옮기기, 직접 실행
- 엘라스틱빈스톡 사용: 실행 파일 옮기기(이외의 과정 생략 가능)
이때 엘라스틱빈스톡을 사용하여 배포하고 실행했을 때 해당 프로젝트를 테스트했던 환경과 실제로 배포하여 실행하는 환경이 다를 수 있기 때문에 무조건 배포에 성공한다는 보장은 없다.
이번 AWS-V5 배포 구성(CI/CD)
- 로컬 컴퓨터에서 프로젝트 생성
- 테스트와 빌드를 로컬 컴퓨터에서 하지 않고 바로 GitHub으로 배포
- GitHub에 프로젝트가 들어오면 GitHub가 코드의 변경을 감지하여 CI(Continuous Integration; 지속적 통합) 서버를 만든 뒤 해당 서버로 프로젝트 전달
- CI 서버(AWS 환경(리눅스)와 동일한 환경)에서 테스트하고 빌드하여 실행 파일 생성
- CI 서버에서 AWS로 배포한 뒤 실행
이때 CI 서버에서 실행 파일을 생성한 후 직접 AWS에 배포하지 않고 CD(Continuous Delivery; 지속적 배포)를 진행한다.
CD는 GitHub에서 변경 감지를 하여 CI 서버로 배포할 때 1번, CI 서버에서 테스트에 성공하고 빌드한 후 실행 파일이 생성되었을 때 AWS로 배포할 때 1번으로 총 2번 일어난다. 또한 CI 서버는 AWS에 배포할 때 자동으로 CD를 하기 위해서 Access key 역할을 하는 AWS의 IAM이 필요하다.
GitHub 프로젝트 fork 하기
이전처럼 프로젝트를 clone으로 내려받지 않고, 이 프로젝트를 본인의 GitHub 저장소로 fork 할 것이다.
프로젝트의 우측 상단의 Fork 버튼을 누른다.
이후에 Create fork 버튼을 누른다.
그러면 위와 같이 내 레포지토리에 방금 fork한 프로젝트가 나오게 된다. 이러면 기존 저장소에 영향을 주지 않고 프로젝트를 변경할 수 있다.
기존 환경 초기화
먼저 이번 실습을 진행하기 위해 엘라스틱빈스톡 애플리케이션 삭제, RDS 종료, 보안 그룹 삭제 등을 진행해야 한다.
위와 같이 먼저 엘라스틱빈스톡 환경과 애플리케이션을 종료 및 삭제하고 EC2의 인스턴스 탭에서 상태가 종료됨으로 바뀌는 것과 탄력적 IP가 삭제되는 것을 확인한다.
이후 RDS의 데이터베이스 탭에서 기존의 DB를 삭제한다. 그리고 만약에 로드밸런서가 있다면 삭제한다. 지금까지 단일 인스턴스로 엘라스틱빈스톡을 생성했기 때문에 로드밸런서가 없어서 넘어갔지만, 이번 실습에는 생성할 예정이다.
보안 그룹 생성
EC2나 엘라스틱빈스톡을 생성하면 자동으로 보안 그룹이 생성되지만, 보안 그룹의 이름들이 알아보기 힘들고 헷갈리기 때문에 직접 보안 그룹을 생성할 것이다.
EC2의 보안 그룹 탭에서 default를 제외하고 모두 삭제되는 것을 확인한 뒤, 우측 상단의 보안 그룹 생성 버튼을 누른다.
위와 같이 이름은 security-group-aws-v5, 설명은 sg-aws-v5로 설정하고, 인바운드 규칙은 HTTP와 SSH 규칙을 추가하고, 나머지 설정은 따로 건들지 않고 넘어갔다.
RDS 생성
데이터베이스 이름을 aws-v5-mariadb으로, VPC 보안 그룹을 default를 빼고 방금 전에 만든 보안 그룹을 설정한 것을 제외한다면, 지난 AWS 엘라스틱빈스톡과 RDS(MariaDB) 연동하기에서 RDS를 생성할 때 설정한 내용과 동일하게 생성했다.
이후 아까 만든 보안 그룹의 인바운드 규칙에 위와 같이 MYSQL/Aurora로 내 IP와 같은 보안 그룹 규칙을 추가한다.
이후 위와 같이 SQL Tools로 데이터베이스에 접속한다. 마찬가지로 자세한 내용은 지난 AWS 엘라스틱빈스톡과 RDS(MariaDB) 연동하기에서 확인할 수 있다. 이후 다음의 쿼리문을 실행한다.
-- 데이터베이스 생성
CREATE DATABASE metadb;
-- 데이터베이스 선택
USE metadb;
-- 데이터베이스 문자 인코딩 세팅
ALTER DATABASE metadb CHARACTER SET = 'utf8mb4' COLLATE = 'utf8mb4_general_ci';
-- 데이터베이스 문자 인코딩 세팅 확인
SHOW VARIABLES LIKE 'c%';
-- 테이블 생성
CREATE TABLE Book (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(255),
content VARCHAR(255),
author VARCHAR(255)
);
-- 테이블 잘 생성되었는지 확인 및 검증
SELECT * FROM Book;
-- 현재 시간 설정 확인
SELECT @time_zone, NOW();
그러면 TablePlus로 확인했을 때 위와 같이 Book 테이블이 잘 생성된 것을 확인할 수 있다.
그리고 초기 설정이 미국 시간대로 설정되어 있기 때문에 타임존 설정을 위해 다음의 쿼리문을 실행해보자.
SET GLOBAL time_zone='Asia/Seoul';
하지만 권한이 없기 때문에 오류가 발생한다. 원래 DB는 한글 설정과 시간 설정이 가능하지만, RDS는 DB에서 직접적으로 수정할 권한이 없기 때문에 파라미터 그룹으로 한글 설정과 시간 설정을 해야 한다.
RDS의 파라미터 그룹에서 파라미터 우측 상단의그룹 생성 버튼을 누른다.
그룹 이름은 aws-v5-mariadb-group으로 설정하고, 엔진 유형은 MariaDB, 파라미터 그룹 패밀리는 현재 DB 엔진 버전이 10.11.6이기 때문에 mariadb10.11로 설정하여 생성했다. 설명은 안 적고 넘어가려고 했는데 필수라고 해서 그룹 이름을 복붙해서 넣었다.
이후 방금 만든 파라미터 그룹에 들어가 편집 버튼을 누른다.
이후 위와 같이 time_zone 파라미터의 값을 Asia/Seoul로 설정한다.
추가로 한글 입력 시 오류 방지를 위해 위와 같이 모든 character_set을 utf8mb4로 변경한다.
이후 아까 만든 RDS의 추가 구성에서 DB 파라미터 그룹을 위와 같이 수정해준다. 그리고 완료 버튼을 눌렀을 때 즉시 적용과 예약 적용이 있는데 예약 적용을 누르면 더 이상 수정이 불가능하니 즉시 적용을 눌러주자. 알고 싶지 않았다.. RDS 삭제하고 다시 설정중;
RDS 재부팅을 해주지 않으면 파라미터 값을 변경한 이후에도 시간 설정이 안 되어 있기 때문에 재부팅을 해준다.
이후에 확인해보면 현재 시간과 잘 맞는 것을 확인할 수 있다.
엘라스틱빈스톡 생성
애플리케이션 이름은 aws-v5-beanstalk으로 설정했다. 그리고 구성 사전 설정에서 사용자 지정 구성으로 체크하라고 했는데 그냥 그대로 단일 인스턴스로 만들었다. 실습을 하는동안 이것이 문제가 된다면 최대한 빠르게 수정해서 올리도록 하겠다.
용량 부분에서 오토 스케일링 그룹을 밸런싱된 로드로 바꾼 뒤, 인스턴스를 최소 2, 최대 4로 설정했다. 이 설정이 로드 밸런싱을 수행한다는 뜻인데, EC2 두 대가 하나의 RDS를 공유해서 사용하는데, 클라이언트는 EC2 앞에 ALB(Application Load Balancer)에게만 접근한다. 이 로드 밸런서가 부하를 분산하여 둘 중 안 바쁜 EC2 서버에게로 길을 정해준다.
이때 만약 2대의 서버가 모두 바쁘다면 자동으로 Auto Scaling을 하여 서버를 4대로 복제시킬 수 있다. 그러다가 기존의 서버들이 한가해졌을 때 4대로 늘렸던 서버를 정리하고 다시 2대만 가동한다.
로드 밸런서 유형은 애플리케이션 로드 밸런서로 설정했다.
- 리스너: 80 포트로 들어오는 요청을 리스닝한다.
- 프로세스: 80 포트를 통해 상태 검사 경로(/)로 들어오는 요청이 200 코드가 떨어지는지를 계속 보고 있는다.
ALB가 리스닝하다가 어떤 프로세스로 보내줄지 결정하는 것을 라우팅이라고 한다. 여기서는 80 포트로 들어오는 요청만 라우팅한다.
나머지 설정은 지난 AWS 엘라스틱빈스톡과 RDS(MariaDB) 연동하기에서 엘라스틱빈스톡을 생성할 때와 동일하게 설정했다.
생성이 완료되면 EC2의 인스턴스 탭으로 가보면 똑같은 이름의 인스턴스가 2개 생성된 것을 알 수 있다. 프리 티어를 사용중이라면 과금이 발생하기 때문에 실습이 끝나자마자 바로 모두 삭제해줘야 한다는 것을 명심하자.
롤링: 배포 전략
배포 전략을 통해 무중단 배포를 이뤄낼 수 있다. 예를 들어 매주 목요일마다 어떤 서비스가 점검을 한다고 가정했을 때 점검을 위해 서버를 내려서 업데이트 후 가동하게 된다. 이때 서버가 내려간 시간 동안 클라이언트의 요청을 받지 못하게 된다면 많은 문제가 발생할 수 있기 때문에 아예 멈추지 않는 무중단 배포가 필요하다.
- 한 번에 모두
- AWS-V4와 같은 이전 프로젝트에 사용된 방식
- EC2 서버 2개를 가지고 있고, 각각의 서버에 배포되어 있는 프로젝트를 업데이트하기 위해 서버를 잠깐 중단시키면 서비스도 멈추게 된다.
- 업데이트된 프로젝트가 배포되며 가동되기 때문에 무중단 배포가 불가능하다.
- 대신 배포 속도가 빠르다는 장점이 있다.
- 추가 배치
- 새로운 EC2를 생성하여 업데이트된 프로젝트를 배포했을 때 정상 코드가 떨어지면 로드밸런서와 연결한다.
- 연결 가능한 최소 EC2 서버를 2개로 설정했기 때문에 기존에 연결되어 있는 2개의 EC2 중 하나의 EC2 연결을 끊은 다음, 업데이트된 프로젝트를 배포하여 똑같이 정상 코드가 떨어지면 로드밸런서와 연결하고 나머지 하나의 EC2는 연결을 끊어준다.
- 서버를 하나씩 추가로 배치하여 배포하면 무중단 배포가 가능하다.
- 하지만 하나의 서버에는 업데이트도니 프로젝트의 배포가 성공하여 연결되어 있고, 하나의 서버는 아직 업데이트 이전의 프로젝트가 배포되어 있는 상태에서, 연결이 끊어진 상태로 추가 배치되어 있는 서버가 배포를 진행하다가 정상 코드가 아닌 에러가 발생한다면 모든 서버에 업데이트 이전의 프로젝트를 배포하는 롤백이 필요하다.
- 대신 서버를 한두 개씩만 늘리면 되기 때문에 자우너 소모가 적다는 장점이 있다.
- 변경 불가능(블루/그린 배포)
- 로드 밸런서에 기존의 블루 EC2 서버 2개가 연결되어 있다. 업데이트된 프로젝트 배포가 시작되면 새로운 그린 인스턴스 2개가 생성되고, 모두 업데이트된 프로젝트 배포에 정상 코드가 떨어지면 순간적으로 로드밸런서는 그린 서버들에게 연결한 뒤에 블루 서버들과의 연결을 끊어버린다.
- 배포 방식과 롤백이 쉽다는 장점이 있다.
- 인스턴스 자원이 많이 든다는 단점이 있다.
그래서 우리는 변경 불가능으로 배포 방식을 수정할 것이다.
엘라스틱빈스톡의 구성 탭에서 업데이트, 모니터링 및 로깅의 편집 버튼을 눌러 롤링 업데이트 및 배포의 애플리케이션 배포 정책을 변경 불가로 설정한다. 물론 엘라스틱빈스톡을 처음 생성할 때 설정해도 된다.
프로젝트 다운로드 및 GitHub Actions
먼저 프로젝트를 다운로드 해야 한다. 맨 처음에 fork 했던 본인의 레포지토리에서 클론해야 한다.
본인의 레포지토리에서 우측 상단의 Code 버튼을 누르면 링크를 복사할 수 있다.
위와 같이 같이 프로젝트를 클론한 뒤 CI를 위한 deploy.yml 파일을 확인할 것이다. 해당 파일의 내용은 이 링크를 통해 확인할 수 있다.
아래에는 정확한 설명을 위해 책에 있는 코드로 약간의 수정이 들어갈 것이다.
name
name: aws-v5
on:
push:
branches:
- main
이름은 aws-v5이며 main 브랜치에 push가 되면 jobs 이하를 실행한다.
jobs
jobs:
build:
runs-on: ubuntu-18.04
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set up JDK 11
uses: actions/setup-java@v1
with:
java-version: 11
- name: Grant execute pemission for gradlew
run: chmod +x ./gradlew
shell: bash
- name: Build with Gradle
run: ./gradlew clean build
shell: bash
jobs는 하나의 task로, 이름은 임의로 설정이 가능하다. 이 job의 이름은 build이며 최종 목적은 jar 파일을 만들어내는 것이다.
- runs on: ubuntu-latest에서 실행한다. 내부적으로는 도커 기술이 적용된다.
- steps: 하이픈(-)으로 구분되며, 이를 시퀀스라고 한다.
- name: 시퀀스의 이름으로 생략이 가능하다.
- uses: actions는 라이브러리를 사용하기 위한 키워드이며, / 뒤로 라이브러리의 이름을 설정한다. (script의 모임)
- run: 쉘 스크립트를 실행한다.
- shell: run에서 인식하는 명령의 shell 종류를 설정한다.
여기에는 총 4개의 시퀀스가 만들어져 있다.
- Checkoust
- actions/checkout@v2: GitHub 레포지토리의 프로젝트 코드를 CI 서버에 다운로드
- Set up JDK 11
- actions/setup-java@v1: Zulu openJDK 설치
- agt-get install open-jdk 같은 과정 등을 통해 서버에 JDK를 설치한다.
- with.java-version : 11 설정을 해두면 openJDK 11 버전을 설치하며, uses 아래 with로 상세한 설정을 해줄 수 있다.
- Grant execute permission for gradlew
- gradlew에 실행 권한을 부여해준다.
- Build with Gradle
- 빌드로 만들어진 jar 파일의 폴더를 통째로 날린 후 새로 만드는 clean build 명령으로 충돌 걱정 없이 빌드를 한다.
push
먼저 프로젝트의 Actions 탭에서 I understand my workflows, go ahead and enable them 버튼을 눌러 활성화 한다.
이후 기존 프로젝트의 deploy.yml 파일은 위에서 살펴봤던 스크립트를 제외하고 모두 지워준다. 나는 귀찮아서 그냥 파일 자체를 삭제한 뒤 복붙했다.
이렇게 코드의 수정이 일어났으니, GitHub에 push해야 한다. 다음과 같이 main 브랜치로 push하면 CI 서버가 만들어지며 배포된다.
git add .
git commit -m "first commit"
git push origin main
나는 패스키 관련해서 무슨 문제가 있는지.. 자꾸 오류가 뜨길래 github desktop으로 push했다.
이후 Actions 탭으로 다시 가보면 새로운 workflow가 추가된 것을 볼 수 있다.
근데 생각보다 오래 걸일 일이 아닌데 너무 오래 걸려서 위와 같이 build의 runs-on을 ubuntu-latest로 수정했다.
다행히 second commit은 빠르게 실행이 완료됐다. 아마 ubuntu-18.04 버전이 지원을 종료하지 않았을까 하는 합리적인 의심이 든다. 아무튼 여기까지는 크게 의미 없는 CI를 경험해 본 것이다.
글이 너무 길어지니 여기서 끊을까 했지만, 너무 애매해서 바로 AWS로 배포하여 실행하는 것까지 진행하겠다.
엘라스틱빈스톡 배포 첫 번째 도전(실패)
전체 deploy.yml 내용
name: aws-v5
on:
push:
branches:
- main
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set up JDK 11
uses: actions/setup-java@v1
with:
java-version: 11
- name: Grant execute pemission for gradlew
run: chmod +x ./gradlew
shell: bash
- name: Build with Gradle
run: ./gradlew clean build
shell: bash
# UTC가 기준이기 때문에 한국시간으로 맞추려면 +9시간 해야 한다
- name: Get current time
uses: 1466587594/get-current-time@v2
id: current-time
with:
format: YYYY-MM-DDTHH-mm-ss
utcOffset: "+09:00"
- name: Show Current Time
run: echo "CurrentTime=${{steps.current-time.outputs.formattedTime}}"
# EB에 CD 하기 위해 추가 작성
- name: Generate deployment package
run: |
mkdir deploy
cp build/libs/*.jar deploy/application.jar
cp Procfile deploy/Procfile
cp -r .ebextensions deploy/.ebextensions
cd deploy && zip -r deploy.zip .
- name: Deploy to EB
uses: einaregilsson/beanstalk-deploy@v21
with:
aws_access_key: ${{ secrets.AWS_ACCESS_KEY }}
aws_secret_key: ${{ secrets.AWS_SECRET_KEY }}
application_name: aws-v5-beanstalk # 엘리스틱 빈스톡 애플리케이션 이름!
environment_name: Aws-v5-beanstalk-env # 엘리스틱 빈스톡 환경 이름!
version_label: aws-v5-${{steps.current-time.outputs.formattedTime}}
region: us-east-1 # 미국 동부(버지니아), 원래는 서울: ap-northeast-2
deployment_package: deploy/deploy.zip
추가된 각 Steps에 대한 설명
# UTC가 기준이기 때문에 한국시간으로 맞추려면 +9시간 해야 한다
- name: Get current time
uses: 1466587594/get-current-time@v2
id: current-time
with:
format: YYYY-MM-DDTHH-mm-ss
utcOffset: "+09:00"
- name: Show Current Time
run: echo "CurrentTime=${{steps.current-time.outputs.formattedTime}}"
- 현재 시간 가져오기: 1466587594/get-current-time@v2 액션을 사용하여 현재 시간을 가져온다.
- 시간 형식 지정: 날짜와 시간을 'YYYY-MM-DDTHH-mm-ss' 형식으로 지정한다.
- UTC Offset 설정: UTC 기준 시간을 +09:00 (한국 시간)으로 조정한다.
- 현재 시간 출력: 조정된 현재 시간을 출력한다.
# EB에 CD 하기 위해 추가 작성
- name: Generate deployment package
run: |
mkdir deploy
cp build/libs/*.jar deploy/application.jar
cp Procfile deploy/Procfile
cp -r .ebextensions deploy/.ebextensions
cd deploy && zip -r deploy.zip .
- name: Deploy to EB
uses: einaregilsson/beanstalk-deploy@v21
with:
aws_access_key: ${{ secrets.AWS_ACCESS_KEY }}
aws_secret_key: ${{ secrets.AWS_SECRET_KEY }}
application_name: aws-v5-beanstalk # 엘리스틱 빈스톡 애플리케이션 이름!
environment_name: Aws-v5-beanstalk-env # 엘리스틱 빈스톡 환경 이름!
version_label: aws-v5-${{steps.current-time.outputs.formattedTime}}
region: us-east-1 # 미국 동부(버지니아), 원래는 서울: ap-northeast-2
deployment_package: deploy/deploy.zip
- Generate deployment package 단계에서:
- deploy 디렉터리를 생성한 뒤 build/libs 디렉터리에서 모든 .jar 파일을 deploy/application.jar로 복사한다.
- Procfile 파일과 .ebextensions 디렉터리를 deploy 디렉터리로 복사한다.
- deploy 디렉터리로 이동하여 모든 파일을 deploy.zip 파일로 압축한다.
- Deploy to EB 단계에서:
- Elastic Beanstalk에 deploy.zip 파일을 배포하는데 이때 GitHub Secrets에서 AWS 접근 키와 비밀 키를 가져와 사용한다.
- 애플리케이션 이름과 환경 이름을 지정한다.
- 애플리케이션 버전의 이름을 현재 시간을 포함하도록 설정한다.
- 배포할 리전을 us-east-1(미국 동부(버지니아))로 설정한다.
- 초반에 리전을 서울로 설정했어야 했는데 그러지 못했어서 위와 같이 설정했다.
- 서울로 설정이 돼있다면 ap-northeast-2로 설정한다.
- deploy 디렉터리에 있는 deploy.zip을 던진다.
- 이 과정이 지금까지 엘라스틱빈스톡에 직접 jar 파일을 업로드 했던 과정과 동일하다.
jar 배포와 zip 배포의 차이점
jar 파일을 엘라스틱빈스톡에 배포하면 엘라스틱빈스톡의 /var/app/current 폴더 내부에 application.jar라고 이름을 바꿔서 던지고, 동시에 같은 경로에 Procfile을 자동으로 만들어낸다.
하지만 zip 파일을 배포하게 되면 알아서 압축을 풀고 /var/app/current 폴더에 들어간 뒤 배포를 시작할 때 Procfile을 실행하게 된다.
files:
"/sbin/appstart":
mode: "000755"
owner: webapp
group: webapp
content: |
#!/usr/bin/env bash
JAR_PATH=/var/app/current/application.jar
# run app
java -Dspring.profiles.active=prod -Dfile.encoding=UTF-8 -jar $JAR_PATH
- 파일 생성 및 권한 설정:
- /sbin/appstart 파일을 생성한 뒤 파일 권한을 000755로 설정한다.
- 소유자에게는 읽기, 쓰기, 실행 권한을 부여하고, 그룹과 다른 사용자에게는 읽기 및 실행 권한을 부여한다.
- 배포 시에 기본적으로 webapp 사용자로 배포되기 때문에 파일 소유자를 webapp 사용자로 설정하고, 파일 그룹을 webapp 그룹으로 설정한다.
- 파일 내용:
- #!/usr/bin/env bash: 이 파일은 Bash 스크립트임을 나타낸다.
- JAR 파일의 경로를 JAR_PATH로 설정한다.
- run app에서 Java 애플리케이션을 실행한다.
- -Dspring.profiles.active=prod: Spring Boot 애플리케이션을 prod 프로파일로 실행한다.
- -Dfile.encoding=UTF-8: 파일 인코딩을 UTF-8로 설정한다.
- -jar $JAR_PATH: 지정된 JAR 파일을 실행한다.
- 내부적에서 도커가 실행되고 있기 때문에 nohup으로 실행하지 않는다.
이 파일은 이름을 마음대로 지정할 수 있고, .config라고 확장자를 맞춰주면 실행된다.
springapp: appstart
appstart 파일을 실행한다. 리눅스에서 bin, sbin 폴더는 환경 변수가 등록되어 있기 때문에 해당 폴더 내부의 파일은 어느 위치에 있든지 실행이 가능하다.
정리
- deploy.zip 파일을 전송
- 엘라스틱빈스톡에서 압축을 푼 뒤 3개의 파일을 만들어 낸다.
- application.jar
- .ebextensions/00-makefile.config
- Procfile
- 3번의 config 파일이 실행돼서 /sbin 디렉터리에 appstart 파일을 만들어 낸다.
- Procfile이 실행되고 appstart 파일을 실행한다.
- appstart 파일이 실행되면서 application.jar 파일이 실행된다.
그래서 위와 같이 deploy.yml 파일을 수정하고 main 브랜치에 push하고 Actions 탭에 들어가서 확인해보자.
그러면 위와 같이 GitHub Actions에서 AWS의 S3에 접근 권한이 있는 사용자 생성을 하지 않았기 때문에 AWS Access Key에서 오류가 발생하는 것을 확인할 수 있다. 관련 IAM을 생성한 후 다시 배포하면 S3에 deploy.zip 파일이 전송되고, 자동으로 엘라스틱빈스톡에 deploy.zip 파일을 배포한다.
IAM 생성
IAM의 사용자 탭에서 사용자 생성 버튼을 누른다.
사용자 이름은 책과 똑같이 metacoding으로 설정했다.
권한 설정 관련해서 삽질을 좀 오래 했는데, 책에서는 AdministratorAccess-AWSElasticBeanstalk 권한만 추가하면 된다고 했는데 계속해서 오류가 나서 다른 블로그를 찾아보다가 AmazonEC2FullAccess, AmazonS3FullAccess, AWSCodeDeployFullAccess 를 차례대로 검색해 체크하고 넘어갔다.
최종 검토 화면은 위와 같고, 사용자 생성 버튼을 누른다.
이후 방금 만든 사용자로 들어가 보안 자격 증명 탭에서 액세스 키 만들기 버튼을 누른다.
여기서 각자 용도에 맞는 것을 체크하고 넘어가면 된다고 모든 블로그에 그렇게 적혀있어서 정신이 나갈 뻔했다. 아무튼 나는 AWS 외부에서 실행되는 애플리케이션을 설정하고 다음으로 넘어갔다.
태그는 선택 사항이지만 그냥 metacoding을 입력하고 넘어갔다.
이러면 액세스 키와 비밀 액세스 키가 나오는데, 비밀 액세스 키는 다시 확인할 수 없으므로 따로 복사를 하거나 csv 파일로 다운로드 받는 것을 추천한다.
엘라스틱빈스톡 배포 두 번째 도전(성공)
이제 이러한 액세스 키와 시크릿 키를 깃허브 액션이 가져올 수 있도록 설정해야 한다.
위와 같이 Settings의 Secrets and variables의 Actions 탭에서 New repository secret 버튼을 누른다.
이후 위와 같이 AWS_ACCESS_KEY, AWS_SECRET_KEY를 설정한 뒤 다시 Actions를 재실행한다.
그러면 엘라스틱빈스톡이 환경을 업데이트 중이라는 메시지를 확인할 수 있을 것이다.
그리고 EC2의 인스턴스 탭을 가보면 블루/그린 배포 방식을 사용하기 때문에 새로운 인스턴스 2개가 더 생성되어 있는 것을 확인할 수 있는데, 기존의 블루 서버들이 종료되기 전에 로드밸런서는 이미 새로운 그린 서버들에게 연결한 뒤이기 때문에 엘라스틱빈스톡의 환경으로 이동 버튼을 클릭해보면 프로젝트가 잘 실행되는 것을 볼 수 있다.
그리고 GitHub Actions도 보면 정상적으로 오류 없이 잘 실행이 완료된 것을 볼 수 있다.
결론
역대급 삽질의 시간이었던 것 같다. 과금 이슈 때문에 빨리 실습을 끝내고 환경을 종료해야 하는데 뭐가 바뀌어 있고, 정보는 정확히 나와있지도 않고, 코드도 달라졌고 등.. 진짜 정신이 나가는 줄 알았는데 결국엔 끝까지 가서 내가 이겼다. 이러한 경험을 바탕으로 앞으로 진행할 프로젝트도 열심히 박치기해야겠다는 생각이 들었다.
'Amazon Web Services' 카테고리의 다른 글
AWS Ubuntu 22.04 LTS EC2 파이썬 버전 변경하기 (5) | 2024.10.26 |
---|---|
AWS 엘라스틱빈스톡 413 Request Entity Too Large 오류 (0) | 2024.07.29 |
CI/CD(지속적 통합/지속적 배포)란? (1) | 2024.07.19 |
AWS 엘라스틱빈스톡과 RDS(MariaDB) 연동하기 (1) | 2024.07.18 |
AWS 엘라스틱빈스톡 내부 구성 직접 확인하기 (0) | 2024.07.16 |