지난 글에 작성했던 것처럼 코드를 작성하여 master 브랜치에 push 하면 EC2 인스턴스에서 동작하고 있는 스프링 어플리케이션에 반영되도록 만드려고 한다.
자세한 내용들은 아래 블로그에서 친절하게 설명해주고 있어서 여기서는 따라하면서 내가 헷갈렸던 부분을 위주로 언급한다.
https://bcp0109.tistory.com/363
작업 순서
먼저 해야할 작업들은 아래와 같은데,
- Github Actions 에서 AWS 에 배포하는 방법
- AWS EC2 설정 추가
- AWS S3 버킷 생성
- AWS CodeDeploy 앱 생성 및 배포 설정
- Github Actions 에서 사용할 사용자 권한 추가
- AppSpec 파일 작성
- 배포 스크립트 작성
- Github Actions Workflow 작성
- Github 에서 push 로 배포하기
6번부터 조금씩 다른 부분들이 있었다. 나는 EC2 인스턴스에 amazon linux를 설치했었기 때문에 설정들이 조금씩 달랐다. username은 우분투의 ubuntu와 다르게 ec2-user이기 때문에 그에 맞게 수정해주었다. 그리고 프로젝트 별로 디렉터리를 만들고 싶어서 해당 값들을 수정해주었다.
appspec.yml
version: 0.0
os: linux
# 배포 파일 설정
## source: 인스턴스에 복사할 디렉터리 경로
## destination: 인스턴스에서 파일이 복사되는 위치
## overwrite: 복사할 위치에 파일이 있는 경우 대체
files:
- source: /
destination: /home/ec2-user/apps/spring-practice
overwrite: yes
# files 섹션에서 복사한 파일에 대한 권한 설정
## object: 권한이 지정되는 파일 또는 디렉터리
## pattern (optional): 매칭되는 패턴에만 권한 부여
## owner (optional): object 의 소유자
## group (optional): object 의 그룹 이름
permissions:
- object: /
pattern: "**"
owner: ec2-user
group: ec2-user
# 배포 이후에 실행할 일련의 라이프사이클
# 파일을 설치한 후 `AfterInstall` 에서 기존에 실행중이던 애플리케이션을 종료
# `ApplicationStart` 에서 새로운 애플리케이션을 실행
## location: hooks 에서 실행할 스크립트 위치
## timeout (optional): 스크립트 실행에 허용되는 최대 시간이며, 넘으면 배포 실패로 간주됨
## runas (optional): 스크립트를 실행하는 사용자
hooks:
AfterInstall:
- location: scripts/stop.sh
timeout: 60
runas: ec2-user
ApplicationStart:
- location: scripts/start.sh
timeout: 60
runas: ec2-user
start.sh
#!/usr/bin/env bash
PROJECT_ROOT="/home/ec2-user/apps/spring-practice"
JAR_FILE="$PROJECT_ROOT/spring-webapp.jar"
APP_LOG="$PROJECT_ROOT/application.log"
ERROR_LOG="$PROJECT_ROOT/error.log"
DEPLOY_LOG="$PROJECT_ROOT/deploy.log"
TIME_NOW=$(date +%c)
# build 파일 복사
echo "$TIME_NOW > $JAR_FILE 파일 복사" >> $DEPLOY_LOG
cp $PROJECT_ROOT/build/libs/*.jar $JAR_FILE
# jar 파일 실행
echo "$TIME_NOW > $JAR_FILE 파일 실행" >> $DEPLOY_LOG
nohup java -jar $JAR_FILE > $APP_LOG 2> $ERROR_LOG &
CURRENT_PID=$(pgrep -f $JAR_FILE)
echo "$TIME_NOW > 실행된 프로세스 아이디 $CURRENT_PID 입니다." >> $DEPLOY_LOG
stop.sh
#!/usr/bin/env bash
PROJECT_ROOT="/home/ec2-user/apps/spring-practice"
JAR_FILE="$PROJECT_ROOT/spring-webapp.jar"
DEPLOY_LOG="$PROJECT_ROOT/deploy.log"
TIME_NOW=$(date +%c)
# 현재 구동 중인 애플리케이션 pid 확인
CURRENT_PID=$(pgrep -f $JAR_FILE)
# 프로세스가 켜져 있으면 종료
if [ -z $CURRENT_PID ]; then
echo "$TIME_NOW > 현재 실행중인 애플리케이션이 없습니다" >> $DEPLOY_LOG
else
echo "$TIME_NOW > 실행중인 $CURRENT_PID 애플리케이션 종료 " >> $DEPLOY_LOG
kill -15 $CURRENT_PID
fi
security 파일 자동 업데이트
application.properties과 같은 보안과 관련된 파일들은 gitignore에 포함되어 있어 직접 파일 내용을 복사해주거나 할 수 있지만, github action을 사용하여 배포 시 자동으로 업데이트할 수도 있다. IAM 계정의 키값을 등록해준 것처럼, 원하는 보안 파일의 내용을 등록해준다.
그리고 gradle.yml을 다음과 같이 작성한다.
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-gradle
name: Spring Boot & Gradle CI/CD
on:
push:
branches: [ "master" ]
pull_request:
branches: [ master ]
# 해당 코드에서 사용될 변수 설정
env:
AWS_REGION: ap-northeast-2
PROJECT_NAME: spring-practice
S3_BUCKET_NAME: ncookie-github-actions-s3-bucket
CODE_DEPLOY_APP_NAME: codedeploy-app
CODE_DEPLOY_DEPLOYMENT_GROUP_NAME: codedeploy-deployment-group
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set up JDK 11
uses: actions/setup-java@v3
with:
java-version: '11'
distribution: 'temurin'
# create application.properties
- name: make application-aws.properties
if: true # branch가 develop일 때
run: |
# spring의 resources 경로로 이동
cd ./src/main/resources
touch ./application-aws.properties
# GitHub-Actions에서 설정한 값을 application-dev.properties 파일에 쓰기
echo "${{ secrets.PROPERTIES }}" > ./application-aws.properties
shell: bash
# gradlew 파일 실행권한 설정
- name: Grant execute permission for gradlew
run: chmod +x ./gradlew
shell: bash
# Gradle build (Test 제외)
- name: Build with Gradle
uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1
with:
arguments: build
# AWS 인증 (IAM 사용자 Access Key, Secret Key 활용)
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}
# 빌드 결과물을 S3 버킷에 업로드
- name: Upload to AWS S3
run: |
aws deploy push \
--application-name ${{ env.CODE_DEPLOY_APP_NAME }} \
--ignore-hidden-files \
--s3-location s3://$S3_BUCKET_NAME/$GITHUB_SHA.zip \
--source .
# S3 버킷에 있는 파일을 대상으로 CodeDeploy 실행
- name: Deploy to AWS EC2 from S3
run: |
aws deploy create-deployment \
--application-name ${{ env.CODE_DEPLOY_APP_NAME }} \
--deployment-config-name CodeDeployDefault.AllAtOnce \
--deployment-group-name ${{ env.CODE_DEPLOY_DEPLOYMENT_GROUP_NAME }} \
--s3-location bucket=$S3_BUCKET_NAME,key=$GITHUB_SHA.zip,bundleType=zip
참고 링크
https://bcp0109.tistory.com/363
https://geonoo.tistory.com/162
https://docs.aws.amazon.com/ko_kr/codedeploy/latest/userguide/application-revisions-push.html
https://earth-95.tistory.com/132
'AWS' 카테고리의 다른 글
[AWS] EC2에서 스프링 프로젝트 배포 (0) | 2022.10.31 |
---|---|
[AWS] EC2 & RDS 생성 및 연동 (0) | 2022.10.31 |
[AWS] AWS 관리자 및 개발자용 IAM 계정 생성 (0) | 2022.10.29 |