👉지난 게시글에 이어서 레포지토리에
workflow파일
,codedeploy파일
,배포스크립트
이렇게 세가지 파일을 설정해보겠다.
이 구조에서
github actions
는 CI 단계이다.
빌드 및 테스트를 포함하여 EC2에 프로젝트 파일을 압축해제하는 것 까지 수행한다.
code deploy
및 후속 스크립트는 CD단계이다.
서버에 CI된 프로젝트 파일을 실행시킨다.
세부적인 동작은 스크립트 파일을 보면 이해할 수 있다.
sudo dnf install java-17
java -version
설치 후 확인까지 해준다. 버전은 자신의 프로젝트에 맞게
레포지 최상단에서 .github/workflows/user-deploy.yml
파일을 생성한다.
트리거(이벤트)로 동작하기때문에 파일명은 중요하지 않다.
github actions 탭의 new workflow
버튼을 누르면 다양한 서비스(EC2 cluster, java, node, ...) 대한 기본 파일을 제공해주는데 자신의 프로젝트에 맞는 것을 찾아 쓰는 것도 바람직하다.
name: CI
on:
# User브랜치에서 일어난 push/pull request에 작동한다.
push:
branches: [ "User" ]
pull_request:
branches: [ "User" ]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# This workflow contains a single job called "build"
jobs:
build:
# machine which runner would use
runs-on: ubuntu-latest
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v3
- name: JDK 17 설치
uses: actions/setup-java@v4.0.0
with:
java-version: '17'
distribution: 'zulu'
- name: application.yml 생성
shell: bash
run: |
mkdir User/src/main/resources
cd User/src/main/resources
touch ./application.yml
echo "${{ secrets.USER_APPLICATIONYML }}" >> ./application.yml
- name: Grant execute permission for gradlew
run: chmod +x User/gradlew
- name: Build with Gradle
run: |
cd User
./gradlew clean --stacktrace --info build
- name: archive repository #tar 명령어를 이용하여 User폴더 압축
run: tar cvfz ./user.tar.gz User/*
# github secret 이용하여 AWS설정
- name: AWS configure credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.USER_ACCESS }}
aws-secret-access-key: ${{ secrets.USER_SECRET_ACCESS }}
aws-region: ap-northeast-2
# 압축파일 이름, 버켓 이름 설정에 주의
- name: upload to S3
run: aws s3 cp --region ap-northeast-2 ./user.tar.gz s3://scalablemsa-deployarchive/user-service/
# codeDeploy 실행, 다양한 이름 설정에 주의
- name: deploy with AWS codeDeploy
run: aws deploy create-deployment
--application-name codedeploy-user
--deployment-config-name CodeDeployDefault.OneAtATime
--deployment-group-name deploy-group-user
--s3-location bucket=scalablemsa-deployarchive,bundleType=tgz,key=user-service/user.tar.gz
한글 주석 위주로 확인
마지막 설정을 보면 codedeploy를 호출하는데 이로써 github action의 임무는 끝이 난다.
마지막의 code deploy 설정에 대한 설명은 다음과 같다. 옵션줄에 주석이 제한되서 따로 설명한다.
- name: deploy with AWS codeDeploy
run: aws deploy create-deployment
--application-name {Code Deploy 애플리케이션 명}
--deployment-config-name CodeDeployDefault.OneAtATime
--deployment-group-name { Code Deploy 배포그룹 }
--s3-location bucket={버켓이름},bundleType={압축파일 확장자},key={버켓 내 폴더이름}/{압축파일 이름}
❗주의점
다양한 이름 및 경로설정에 주의
cd User
가 있거나 경로명에 User가 명시되어있다. 프로젝트에 맞춰 없애거나 수정한다. - name: MySQL 설정
uses: mirromutth/mysql-action@v1.1
with:
# host port: 3306 # default value is 3306. The port of host
# container port: 3306 # default value is 3306. The port of container
character set server: 'utf8' #default value is 'utf8mb4'
collation server: 'utf8_general_ci' # default value is 'utf8mb4_general_ci'. The '--collation-server' option for mysqld
mysql version: '8.0.33' # 프로젝트에 맞게 입력, Optional, default value is "latest". The version of the MySQL
# mysql database: 'some_test' # Optional, default value is "test". The specified database which will be create
mysql root password: ${{ secrets.RDS_USER_PASSWORD }} # 이 항목을 작성하거나 아래 두 항목을 작성해야한다.
# mysql user: admin
# mysql password: ${{ secrets.ROOT_PASSWORD }}
version: 0.0
os: linux
files:
- source: /
destination: /home/ec2-user/Playground/User
permissions:
- object: /home/ec2-user/Playground/User
owner: ec2-user
group: ec2-user
mode: 755
hooks:
AfterInstall:
- location: deploy-user.sh
timeout: 60
runas: root
CodeDeploy
에서 이용하는 appspec.yml이다.
User 폴더안에 넣어두었다.
이 파일에선 폴더명과 파일명에만 주의한다. 자신의 프로젝트에 맞게..
appspec.yml에 명시한 deploy-user.sh 파일을 생성한다.
오류 시 확인할 로그파일 출력을 그대로 놔두었으니 참고한다.
#!/usr/bin/env bash
REPOSITORY=/home/ec2-user/Playground/User
LOG_FILE=$REPOSITORY/log.txt
echo "deploy-user.sh 시작" | sudo tee -a $LOG_FILE
cd $REPOSITORY || echo "repository 없음 $REPOSITORY" | sudo tee -a $LOG_FILE
echo "현재 디렉토리: $REPOSITORY" | sudo tee -a $LOG_FILE
APP_NAME=ScalableMSA-User
JAR_NAME=$(ls $REPOSITORY/build/libs/ | grep '.jar' | tail -n 1)
JAR_PATH=$REPOSITORY/build/libs/$JAR_NAME
CURRENT_PID=$(pgrep -f $APP_NAME)
if [ -z "$CURRENT_PID" ]
then
echo "실행중인 user서비스 없음." | sudo tee -a $LOG_FILE
else
echo "kill -9 $CURRENT_PID" | sudo tee -a $LOG_FILE
kill -9 "$CURRENT_PID"
sleep 5
fi
# 실행 및 로그 저장
nohup java -jar -Dspring.profiles.active=prod -Dapp.name=$APP_NAME "$JAR_PATH" > jarExecute.log 2>&1 < /dev/null &
# 실행된 프로세스ID 확인
RUNNING_PROCESS=$(ps aux | grep java | grep "$JAR_NAME")
if [ -z "$RUNNING_PROCESS" ]
then
echo "어플리케이션 프로세스가 실행되고 있지 않습니다." | sudo tee -a $LOG_FILE
else
echo "어플리케이션 프로세스 확인: $RUNNING_PROCESS" | sudo tee -a $LOG_FILE
fi
변경사항을 push/merge하고 실행결과를 확인한다.
workflow(deploy-user.yml) 성공
codedeploy(appspec.yml) 성공
서비스도 잘 실행중이고 jarExecute.log
, log.txt
파일의 결과도 정상적이다.
스프링에 찍어둔 로그파일(runtime.log)도 잘 나온다.
log.txt
는 deploy.sh 스크립트의 로그이다.
jarExecute.log
는 deploy.sh가 실행한 빌드타임 로그이다
runtime.log
는 자바프로그램의 실행 로그이다.
오류가 난다면 해당하는 단계의 로그를 확인하면 되고 jarExecute.log의 경우 빌드 문제가 없다면 생성되지 않게 하는 것이 좋다.
마지막으로 결과 확인에 도움이 될만한 명령어들을 소개하고 마무리하겠다.
tail -f runtime.log # 로그파일 실시간으로 확인. 줄 제한 옵션은 -tail 100
sudo netstat -tulpn # 전체 시스템의 포트확인.
ps aux | grep java # 실행중인 프로세스 확인. grep으로 java가 포함된 라인만 찾음
find . -type f -name "runtime.log" # 현재위치에서 특정파일 찾기