Spring Boot 배포 자동화(CI/CD) : Github Actions와 AWS CodeDeploy
먼저 AWS Cloud 환경에서 필요한 선행 작업을 안내하고, Github Actions와 AWS CodeDeploy에서 사용할 스크립트에 대해 설명하겠다.
👉 AWS 사전 구성하기
1. IAM 사용자 생성
- 디플로이용 계정을 만들어 아래 정책을 연결
AmazonS3FullAccess
AWSCodeDeployFullAccess
- 이 사용자는 Github Actions에서 S3, CodeDeploy에 접근하기 위해 사용하는 IAM 계정이다.
- 액세스키와 시크릿키를 잘 저장해두자. Github Secret에 저장할거다.
- 참고 : 아래 EC2, CodeDeploy에서 생성하는 IAM 서비스역할과 사용자는 다르다.
- Github Secret에 등록
DEV_AWS_ACCESS_KEY_DEPLOY
: 액세스키 등록DEV_AWS_SECRET_KEY_DEPLOY
: 시크릿키 등록
2. EC2
- EC2 생성
- EC2에서 사용할 서비스 역할 생성
AmazonEC2RoleforAWSCodeDeploy
정책 부여- EC2의 IAM 역할에 생성한 서비스역할을 연결
- EC2 내 Java와 CodeDeploy 클라이언트 설치
- 코드디플로이 생성 시 에이전트 설치/업데이트 옵션이 있기 때문에 CodeDeploy 클라이언트 설치는 옵셔널로 보임 (본 포스팅를 작성하면서 EC2에 미리 설치해둠)
- 참고 : AWS 오토스케일링을 위해 서버 의존성을 자동화할 필요가 있으나, 이 포스팅에서는 안내하지 않음
3. S3
- 버킷 생성 : 빌드된 파일을 업로드할 버킷이 필요함
4. CodeDeploy
- CodeDeploy 어플리케이션 생성
- CodeDeploy 서비스역할 생성
AWSCodeDeployRole
정책 부여
- 배포그룹 생성
- 생성해둔 EC2 연결
- 로드밸런서 활성화 옵션은 off
- 참고 : 이번 포스팅에서 무중단 배포 설정은 안내하지 않음
👉 CodeDeploy 스크립트 작성
프로젝트 최상단에 appspec.yml
를 생성한다. CodeDeploy가 제일 먼저 호출할 설정파일이다. 루트에 있는 deploy.sh
라는 파일을 수행하게 해두었다.
version: 0.0
os: linux
files:
- source: /
destination: /home/ubuntu
permissions:
- object: /
pattern: "**"
owner: ubuntu
group: ubuntu
mode: 755
hooks:
AfterInstall:
- location: deploy.sh
timeout: 60
runas: root
deploy.sh
파일을 생성한다. 위치와 명칭은 자유롭게 바꿔도 되는데, Github Actions 스크립트에도 동일하게 반영해주어야 한다. 본 포스팅에서는 script/deploy.sh
로 명명함.
해당 스크립트는 기존에 실행중이던 jar 프로세스를 종료하고, 새로운 jar를 실행시키는 작업을 수행한다.
#!/usr/bin/env bash
REPOSITORY=/home/ubuntu
cd $REPOSITORY
JAR_NAME=$(ls $REPOSITORY/ | grep '.jar' | tail -n 1)
JAR_PATH=$REPOSITORY/$JAR_NAME
CURRENT_PID=$(pgrep -f *.jar)
if [ -z $CURRENT_PID ]
then
echo "> Nothing to end."
else
echo "> kill -9 $CURRENT_PID"
kill -15 $CURRENT_PID
sleep 5
fi
echo "> $JAR_PATH deploy"
nohup java -jar $JAR_PATH --spring.profiles.active=dev > /dev/null 2> /dev/null < /dev/null &
👉 Github Actions 스크립트 작성
프로젝트 최상단에 .github/workflows
폴더를 만들고 deploy-dev.yml
를 생성한다.
dev 브랜치에 push 혹은 pull request가 발생했을 때 Github Actions이 수행되도록 하였다.
한글로 작성해둔 부분은 프로젝트 명칭에 알맞게 수정하도록 하자.
(참고로 deploy.sh 는 script 내에 있지만, 압축을 해제하고 나면 최상위 디렉토리에 위치하게 된다)
name: Deploy dev
on:
push:
branches: [ dev ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK 11
uses: actions/setup-java@v2
with:
java-version: '11'
distribution: 'adopt'
cache: maven
# Caching dependencies
- name: Cache Maven packages
uses: actions/cache@v2
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
restore-keys: ${{ runner.os }}-m2
# Build
- name: Build with Maven
run: mvn -Dmaven.test.skip=true -B package --file pom.xml
# 전송할 파일을 담을 디렉토리 생성
- name: Make Directory for deliver
run: mkdir deploy && cp target/*.jar deploy/ && cp appspec.yml deploy/ && cp script/deploy.sh deploy/
# 압축
- name: Make zip file
run: zip -r -qq -j 압축파일.zip deploy
# AWS 인증
- name: AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.DEV_AWS_ACCESS_KEY_DEPLOY }}
aws-secret-access-key: ${{ secrets.DEV_AWS_SECRET_KEY_DEPLOY }}
aws-region: ap-northeast-2
# S3에 빌드된 파일 업로드
- name: Upload to AWS S3
run: aws s3 cp --region ap-northeast-2 압축파일.zip s3://S3버킷명/폴더위치/압축파일.zip
# Deploy
- name: Code Deploy
run: aws deploy create-deployment --application-name 어플리케이션명 --deployment-config-name CodeDeployDefault.AllAtOnce --deployment-group-name 배포그룹명 --s3-location bucket=S3버킷명,bundleType=zip,key=폴더위치/압축파일.zip
dev 브랜치에 push 이벤트가 발생하면 위 스크립트에서 정의해놓은 Github Actions 가 트리거 된다. 아래처럼 수행되는 것을 확인할 수 있다.
👉 오류 케이스
- CodeDeploy 배포 이벤트가
blockTraffic
에서 멈췄다면?
로드밸런서 활성화 옵션을 확인하라. 이 옵션은 배포대상 인스턴스에 연결된 로드밸런서가 받는 트래픽을 차단하고, 인스턴스 배포 성공 이후 로드밸런서에 다시 인스턴스를 붙여서 트래픽을 허용하는 작업이다. 별도의 설정없이 사용하면 트래픽 차단하는 부분에서 무한로딩되는 현상이 있다. 본 포스팅에서는 이 옵션을 비활성화해두었다.
- 정상 배포가 안되었다면? 코드디플로이 확인하기 (설정문제)
AWS CodeDeploy에 직접 들어가서 배포 단계를 확인해보자. 특정 배포 단계에서 멈추었거나 오류가 난 것을 확인할 수 있다.
- 정상 배포가 안되었다면? EC2내 로그 확인하기 (권한문제)
코드디플로이 작업은 정상적으로 완료되었는데, 배포가 정상적으로 되지 않았다면 EC2 내에 있는 코드 디플로이 로그를 확인해보자.
로그 위치는 /var/log/aws/codedeploy-agent
이다.
나같은 경우 EC2에 권한이 없어 아래와 같은 오류가 발생했다.
2021-10-08 12:20:11 INFO [codedeploy-agent(1368)]: Version file found in /opt/codedeploy-agent/.version with agent version OFFICIAL_1.3.2-1902_deb.
2021-10-08 12:20:11 ERROR [codedeploy-agent(1368)]: InstanceAgent::Plugins::CodeDeployPlugin::CommandPoller: Missing credentials - please check if this instance was started with an IAM instance profile
참고하면 좋은 글
'엔지니어링 > DevOps' 카테고리의 다른 글
CodeDeploy에서 저장하는 배포본의 수 변경하기 (용량 줄이기) (0) | 2022.02.19 |
---|---|
AWS 계정들간의 ACM 인증서 공유하기 (0) | 2021.08.10 |
Connection Pool이 없는 언어(PHP, Ruby)의 DB Connection 관리 (0) | 2021.07.16 |
[Firebase] Firebase Authentication (0) | 2021.03.16 |
[Firebase] Cloud Firestore (0) | 2021.03.11 |
댓글
이 글 공유하기
다른 글
-
CodeDeploy에서 저장하는 배포본의 수 변경하기 (용량 줄이기)
CodeDeploy에서 저장하는 배포본의 수 변경하기 (용량 줄이기)
2022.02.19 -
AWS 계정들간의 ACM 인증서 공유하기
AWS 계정들간의 ACM 인증서 공유하기
2021.08.10 -
Connection Pool이 없는 언어(PHP, Ruby)의 DB Connection 관리
Connection Pool이 없는 언어(PHP, Ruby)의 DB Connection 관리
2021.07.16 -
[Firebase] Firebase Authentication
[Firebase] Firebase Authentication
2021.03.16