Java/Spring

[Spring] Github Action 적용하기 (+ properties 추가)

태감새 2023. 4. 23. 17:41

준비물

  1. EC2 서버 하나
  2. IAM 역할 추가 (S3FullAccess, CodeDeployRole) 각각 하나씩
  3. S3 버킷 하나
  4. CodeDeploy 애플리케이션, 배포 그룹 하나씩
  5. IAM 사용자 하나 (DeployFullAccess, S3FullAccess)

IAM 역할 추가

  • AmazonS3FullAccess 역할 추가
  • AWSCodeDeployRole 역할 추가

EC2 서버 설정

  1. 태그 추가
    작업 -> 인스턴스 설정 -> 태그 관리 -> 태그 하나 추가 (이름은 본인 마음대로)
  2. EC2 역할 부여
    보안 -> IAM 역할 수정 -> AmazonS3FullAccess역할 선택

S3 버킷 생성

버킷 하나 만들면 됨

CodeDeploy

  1. ubuntu에 설치
    기본 메뉴얼
$ 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
  1. 애플리케이션 생성
  • EC2/온프레미스로 생성
  1. 배포 그룹 생성
  • 서비스 역할 IAM 역할(AWSCodeDeployRole) 선택
  • EC2 인스턴스의 key값은 [EC2 서버 설정]에서 설정한 key값 선택

GithubAction에서 사용할 IAM 사용자 추가

  • AWSCodeDeployFullAccess
  • AmazonS3FullAccess

Access key, Secret Key
Github Action secret key로 등록하기

 

파일 작성

  1. AppSpec.yml
  2. stop.sh
  3. start.sh
  4. build.gradle 수정

AppSpec.yml

전문
CodeDeploy에서 배포를 위해 참조할 파일 -> EC2 배포 설정
루트 디렉토리에 위치해야 한다.

version: 0.0
os: linux

# file section 
# 인스턴스에서 파일이 복사되는 위치
# 파일이 있는 경우 대체 여부
files:
  - source:  /
    destination: /home/ubuntu/app
    overwrite: yes

# pattern 매칭되는 패턴에만 권한 부여
permissions:
  - object: /
    pattern: "**"
    owner: ubuntu
    group: ubuntu

# 배포 이후 수행할 스크립트 지정  
# AfterInstall : scripts/stop.sh 실행 (기존에 실행중이던 애플리케이션 종료)
# ApplicationStart : scripts/start.sh 실행 (새로운 애플리케이션 실행)
# timeout = 스크립트 실행 허용 시간
hooks:
  AfterInstall:
    - location: scripts/stop.sh
      timeout: 60
      runas: ubuntu
  ApplicationStart:
    - location: scripts/start.sh
      timeout: 60
      runas: ubuntu

stop.sh

현재 설정에는 scripts 디렉토리에 위치해야함

#!/usr/bin/env bash 

PROJECT_ROOT="/home/ubuntu/app" 
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

start.sh

현재 설정에는 scripts 디렉토리에 위치해야함

#!/usr/bin/env bash 

PROJECT_ROOT="/home/ubuntu/app" 
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

build.gradle 수정

build시 jar 파일이 두 개가 생성된다. (~.jar, ~-plaij.jar)
두 개가 만들어지면 *.jar 복사가 안되므로 -plain.jar 파일이 안만들어지도록 설정해야 한다.

// plugin 밑에 위치해야함

jar {
    enabled = false
}

 

workflow 작성

name: Deploy to Amazon EC2  

# 현재 main에 pull-request하면 아래 과정(빌드 테스트 후 자동배포) 실행
on:  
  pull_request:  
    branches:  
      - main  

# 본인이 설정한 값을 여기서 채워넣습니다.  
# 리전, 버킷 이름, CodeDeploy 앱 이름, CodeDeploy 배포 그룹 이름  
env:  
  AWS_REGION: ap-northeast-2  
  S3_BUCKET_NAME: action-test-bucket  
  CODE_DEPLOY_APPLICATION_NAME: my-codeDeploy-app  
  CODE_DEPLOY_DEPLOYMENT_GROUP_NAME: my-codeDeploy-app-group  

permissions:  
  contents: read  

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

    steps:  
    # (1) 기본 체크아웃  
    - name: Checkout  
      uses: actions/checkout@v3  

    # (2) application.properties 추가  
    - run: touch ./src/main/resources/application.properties  
    - run: echo "${{ secrets.APPLICATION }}" > ./src/main/resources/application.properties  
    - run: cat ./src/main/resources/application.properties  

    # (3) JDK 11 세팅  
    - name: Set up JDK 11  
      uses: actions/setup-java@v3  
      with:  
        distribution: 'temurin'  
        java-version: '11'  

    # (4) Gradle build (Test 제외)  
    - name: Build with Gradle  
      uses: gradle/gradle-build-action@0d13054264b0bb894ded474f08ebb30921341cee  
      with:  
        arguments: clean build -x test  

    # (5) 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 }}  

    # (6) 빌드 결과물을 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 . 

    # (7) 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

(2) application.properties 추가

현재 우리 프로젝트에는 application.properties가 ignore에 등록되어 있어서 github에는 존재하지 않음
그래서 따로 배포시 작성하는 과정이 필요함

  • Action의 secret에서 APPLICATION(이름은 자유)이란 이름으로 application.properties을 내용으로 가지는 키를 하나 생성한다.

(2)의 과정

# resource 루트에 application.properties 생성
- run: touch ./src/main/resources/application.properties  
# 생성된 application.properties에 등록한 secret 키 입력
- run: echo "${{ secrets.APPLICATION }}" > ./src/main/resources/application.properties  
# 열어보기
- run: cat ./src/main/resources/application.properties 

참고 자료

전반적인 진행 과정
application.properties ignore시 적용법

'Java > Spring' 카테고리의 다른 글

JPA 간단정리  (0) 2023.04.25
[Spring] QueryString 객체로 받기  (0) 2023.04.23
SpringMVC (2) - Servlet Container와 Spring Container  (0) 2023.04.20
SpringMVC (1) - WAS와 WebServer  (0) 2023.04.19
스프링 배치 이해하기  (0) 2023.04.18