[CI/CD] Github Action으로 EC2 + RDS 배포하기(2) - 스크립트 생성

데프·2024년 1월 10일
0

CI/CD - Github Action

목록 보기
2/2

👉지난 게시글에 이어서 레포지토리에 workflow파일, codedeploy파일, 배포스크립트 이렇게 세가지 파일을 설정해보겠다.

이 구조에서

  • github actions는 CI 단계이다.
    빌드 및 테스트를 포함하여 EC2에 프로젝트 파일을 압축해제하는 것 까지 수행한다.

  • code deploy 및 후속 스크립트는 CD단계이다.
    서버에 CI된 프로젝트 파일을 실행시킨다.

세부적인 동작은 스크립트 파일을 보면 이해할 수 있다.

#1. [EC2] Java설치

👉 MobaXterm을 이용한 EC2 콘솔 접속 방법

sudo dnf install java-17
java -version

설치 후 확인까지 해준다. 버전은 자신의 프로젝트에 맞게

#2. [Github] workflow파일 생성

레포지 최상단에서 .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={버켓 내 폴더이름}/{압축파일 이름}

주의점

다양한 이름 및 경로설정에 주의

  • 본 프로젝트는 아래 사진처럼 레포지토리 최상단에서 폴더를 한번 더 들어가야 자바 프로젝트 폴더가 나온다. 그래서 위의 yml파일에서 대부분 cd User가 있거나 경로명에 User가 명시되어있다. 프로젝트에 맞춰 없애거나 수정한다.
  • RDS를 쓰지 않고 EC2에서 MySQL을 실행시킬거라면 다음과 같은 설정도 넣는다.
      - 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 }}

#3. appspec.yml 생성

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 폴더안에 넣어두었다.
이 파일에선 폴더명과 파일명에만 주의한다. 자신의 프로젝트에 맞게..

#4. deploy-user.sh 생성

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" # 현재위치에서 특정파일 찾기

profile
정보의 홍수를 기록하는 데프의 로그

0개의 댓글