Springboot-Github Action을 이용해서 배포 자동화 : ec2 정보 변경하기

vector13·2022년 10월 21일
0

지난번에 'Springboot 프로젝트 Github Action을 이용해서 배포 자동화하기' 를 했었는데, ec2 정보가 변경되어서 다른 ec2로 옮기는 작업을 해보려고 한다.

이전에 정리해둔 글은
https://velog.io/@vector13/Springboot-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-Github-Action%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%B4%EC%84%9C-%EB%B0%B0%ED%8F%AC-%EC%9E%90%EB%8F%99%ED%99%94%ED%95%98%EA%B8%B0 여기서 보면 된다.

사용하는 s3 bucket은 동일하고, EC2 instance 만
기존의 jenkins-ec2(aka 인스턴스1) 라는 이름에서 chaebbi-backend(aka 인스턴스2) 로 옮기려고 한다.

ec2에 s3 권한 fullaccess

인스턴스 2는 s3 에 대한 fullaccess를 준다
인스턴스 > 작업 > 보안 > IAM 역할 수정에 이전에 만들어둔 s3fullaccess 를 가진 IAM 역할을 부여 (연결)

1 인스턴스2에 CodeDeploy Agent 설치

일단 codeploy가 있어야하므로 인스턴스2에 CodeDeploy Agent 설치 다운받는다
sudo apt update
sudo apt install ruby-full
sudo apt install wget
cd /home/ubuntu
wget https://aws-codedeploy-ap-northeast-2.s3.ap-northeast-2.amazonaws.com/latest/install
chmod +x ./install
sudo ./install auto > /tmp/logfile
sudo service codedeploy-agent status

정상 설치가 되어 active 응답이 온다

2 CodeDeploy 배포 그룹 변경

기존에 만들어둔 배포그룹이 인스턴스1 삭제에 따라 실패가 되어있는 것을 확인 가능 하다

배포그룹 편집을 눌러


환경구성에 인스턴스 1 이 있는것을 변경해준다

이 부분이 어떤 인스턴스에서 동작할 지 선택하는 부분이다
나머지는 그대로 두고 저장하고 나온다.

3 배포 스크립트 수정

기존 인스턴스1에서는 배포스크립트가 실행할 곳이 app/step1이었던 것에서 /var/www/html/spring으로 변경되기 때문에 스크립트도 수정해준다.

기존에 사용하던 배포스크립트

#!/bin/bash

REPOSITORY=/var/www/html/spring
PROJECT_NAME=chaebbiSpring

cd $REPOSITORY/$PROJECT_NAME/

echo "> GIT PULL"

git pull

echo "> 프로젝트 빌드 시즈악"

./gradlew build -x check --parallel

echo ">step1 디렉 이도옹"

cd $REPOSITORY

echo "> Build 파일 복사"

cp $REPOSITORY/$PROJECT_NAME/build/libs/*.jar $REPOSITORY/

echo "> 현재 구동중인 애플리케이션 pid 확인"
CURRENT_PID=$(pgrep -f ${PROJECT_NAME}-0.0.1-SNAPSHOT.jar)

echo "현재 구동중인 어플리케이션 pid: $CURRENT_PID"

if [ -z "$CURRENT_PID" ]; then
    echo "> 현재 구동중인 애플리케이션이 없으므로 종료하지 않습니다."
else
    echo "> kill -9 $CURRENT_PID"
    kill -9 $CURRENT_PID
    sleep 5
fi

echo "> 새 어플리케이션 배포"

#JAR_NAME=$(ls -tr $REPOSITORY/ | grep *.jar | tail -n 1)
JAR_NAME=$(ls -tr $REPOSITORY/*.jar | tail -n 1)

echo "> JAR Name: $JAR_NAME"

echo "> $JAR_NAME 에 실행권한 추가"

chmod +x $JAR_NAME

echo "> $JAR_NAME 실행"

nohup java -jar \
    -Dspring.config.location=/var/www/html/spring/application-real-db.properties,/var/www/html/spring/application.yml \
    -Dspring.profiles.active=real \
    $JAR_NAME 2>&1 &

처럼
AppSpec Hooks 에서 실행할 스크립트 stop.sh 와 start.sh 를 설정해주기

start.sh

#!/usr/bin/env bash

PROJECT_ROOT="/var/www/html/spring"
JAR_FILE="$PROJECT_ROOT/chaebbiSpring.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="/var/www/html/spring"
JAR_FILE="$PROJECT_ROOT/chaebbiSpring.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 -9 $CURRENT_PID
fi

github repository에 scripts 폴더 생성해서 저 두 스크립트 넣어주고 commit 해보면

듀근두근

완료 되었다!


인스턴스 2에서 app log를 보기위해서 application.log를 vim으로 열었지만 내용이 없었고

error.log를 여니까

jar 에 실행권한이 없었다. 그리고 jar 파일이 있는 파일의 위치도 /var/www/html/sprinng/build/libs 안에 있는 곳으로 변경해주었고, plain 과 snapshot 중 하나의 jar 만 지정해주기

일단 appspec.yml에 destination이 잘못되어있는 것 (home/ubuntu/app으로 되어있는 부분)을 수정

있어야할 /var/www/html에는 scripts가 안생기고
home/ubuntu/app에 생겨있음

그러니까 deploy 과정에서 에러가 난다


--> 아직 이전 작업이 안끝난 상태에서 급하게 돌려서 그럼 다시 re do 해보니까 된다


우하하 됐다!
그렇지만 에러가 있었다
기존에 ec2에 있는 applicaiton.properties 파일과 application.yml 파일을 못읽어서 sql에러와 s3에러가 나는 것이었다.

github action에는 설정 파일을 어떻게 주는 걸까 ?

4 secret 에 properties 파일 (application.properties & application.yml)

프로젝트 서비스 실행에 필요한 설정파일이 두개다
application.properties & application.yml
이 둘을 github action이 알아들을 수 있게 해보겠다

application.properties


properties 같은 경우는 저렇게 새 비밀을 해서 다 넣어버리면 되고
gradle.yml에 application.properties를 만드는부분을 넣어준다


    # (+++) application.properties 생성 
    - name:  make application.properties
      run:
        mkdir ./src/main/resources | 
        touch ./src/main/resources/application.properties 
      shell: bash
    - name: deliver application.properties
      run: echo "${{ secrets.PROPERTIES }}" > ./src/main/resources/application.properties
      shell: bash


ec2에도 잘 생겼는지 파악해보겠다.

생겼다!

application.yml

yml도 secret에 생성해주고


gradle.yml을 수정해줌

github action 과정에서 수행되는것 확인

ec2에도 생겼다


⚾ 결과적으로.. 단계별 적용되는 파일

그러므로 결과적으로 맨 위의 그림에서 단계별로 적용되는 파일의 그림은 다음과 같다.


자 이제 적용된 최종적인 파일을 봐보자!

(🎃 급하다면 여기로) 최종 파일

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://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle

name: Spring Boot & Gradle CI/CD 

on:
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]

env:
  AWS_REGION: ap-northeast-2
  S3_BUCKET_NAME: chaebbi-deploy-bucket
  CODE_DEPLOY_APPLICATION_NAME: chaebbi-codedeploy-app
  CODE_DEPLOY_DEPLOYMENT_GROUP_NAME: chaebbi-codedeploy-deployment-group

permissions:
  contents: read

jobs:
  deploy:
    name: Deploy
    runs-on: ubuntu-latest

    steps:
    # (1) 기본 체크아웃
    - name: Checkout
      uses: actions/checkout@v3
    # (2) JDK 11 세팅
    - name: Set up JDK 11
      uses: actions/setup-java@v3
      with:
        java-version: '11'
        distribution: 'temurin'
    
    # (+++) application.properties 생성 
    - name:  make application.properties
      run:
        mkdir ./src/main/resources | 
        touch ./src/main/resources/application.properties 
      shell: bash
    - name: deliver application.properties
      run: echo "${{ secrets.PROPERTIES }}" > ./src/main/resources/application.properties
      shell: bash
    # (+++) application.yml 생성 
    - name:  make application.yml
      run: touch ./src/main/resources/application.yml
      shell: bash
    - name: deliver application.yml
      run: echo "${{ secrets.APPLICATION }}" > ./src/main/resources/application.yml
      shell: bash 
    # (++++) 
    - uses: actions/upload-artifact@v2
      with:
        name: application.properties
        path: ./src/main/resources/application.properties
      
    # (3) gradlew 실행 권한부여
    - name: Grant execute permission for gradlew
      run: chmod +x gradlew
      # (3) Gradle build (Test 제외)    
    - name: Build with Gradle
      uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1
      with:
        arguments: clean build -x test
      #run : ./gradlew clean build --exclude-task test
    
    # (4) 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 }}

    # (5) 빌드 결과물을 S3 버킷에 업로드
    - name: Upload to AWS S3
      run: |
        aws deploy push \
          --application-name ${{ env.CODE_DEPLOY_APPLICATION_NAME }} \
          --ignore-hidden-files \
          --s3-location s3://$S3_BUCKET_NAME/$GITHUB_SHA.zip \
          --source .

    # (6) S3 버킷에 있는 파일을 대상으로 CodeDeploy 실행
    - name: Deploy to AWS EC2 from S3
      run: |
        aws deploy create-deployment \
          --application-name ${{ env.CODE_DEPLOY_APPLICATION_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

scripts/start.sh

#!/usr/bin/env bash

PROJECT_ROOT="/var/www/html/spring"
PROJECT_NAME="chaebbiSpring"
JAR_FILE="$PROJECT_ROOT/${PROJECT_NAME}-0.0.1-SNAPSHOT.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 "> $JAR_FILE 에 실행권한 추가"
chmod +x $JAR_FILE

# jar 파일 실행
echo "$TIME_NOW > $JAR_FILE 파일 실행" >> $DEPLOY_LOG
nohup java -jar \
    -Dspring.config.location=/var/www/html/spring/src/main/resources/application.properties,/var/www/html/spring/src/main/resources/application.yml \
    -Dspring.profiles.active=real \
    $JAR_FILE > $APP_LOG 2> $ERROR_LOG &

CURRENT_PID=$(pgrep -f $JAR_FILE)
echo "$TIME_NOW > 실행된 프로세스 아이디 $CURRENT_PID 입니다." >> $DEPLOY_LOG

여기서 nohup java -jar 에서 뒤에 설정파일 저장된 경로를 지정해주어야 설정파일이 적용되어서 파일이 실행된다!

scripts/stop.sh

 #!/usr/bin/env bash

PROJECT_ROOT="/var/www/html/spring"
JAR_FILE="$PROJECT_ROOT/${PROJECT_NAME}-0.0.1-SNAPSHOT.jar"
PROJECT_NAME="chaebbiSpring"

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 -9 $CURRENT_PID
fi

github

적용된 폴더와 코드들은 아래 깃허브에서 확인 가능 !
https://github.com/Chaebbi/chaebbiSpring

profile
HelloWorld! 같은 실수를 반복하지 말기위해 적어두자..

0개의 댓글