Back-End/Springboot와 AWS로 혼자 구현하는 웹 서비스

Chapter 09. 코드가 푸시되면 자동으로 배포해 보자 - Travis CI 배포 자동화 (4)

yeonx 2022. 5. 1. 22:22
728x90

9.5 배포 자동화 구성

 앞의 과정으로 Travis CI, S3, CodeDeploy연동까지 구현되었다. 이제 이 것을 기반으로 실제 Jar를 배포하여 실행까지 해보겠다.

 

deploy.sh파일 추가

먼저 step2 환경에서 실행될 deploy.sh를 생성한다. .scripts 디렉토리를 생성해서 여기에 스크립트를 생성한다.

deploy.sh 위치

#!/bin/bash

REPOSITORY=/home/ec2-user/app/step2
PROJECT_NAME=springboot-study-webserivce


echo "> Build 파일 복사"
cp $REPOSITORY/$PROJECT_NAME/build/libs/*.jar $REPOSITORY/
echo "> 현재 구동 중인 애플리케이션 pid 확인"
CURRENT_PID=$(pgrep -f ${PROJECT_NAME}.*.jar)
echo "현재 구동 중인 애플리케이션 pid: $CURRENT_PID"
if [ -z "$CURRENT_PID"]; then
        echo ">현재 구동 중인 애플리케이션이 없으므로 종료하지 않습니다."
else
        echo "> kill -15 $CURRENT_PID"
        kill -15 $CURRENT_PID
        sleep 5
fi
echo "> 새 애플리케이션 배포"
JAR_NAME=$(ls -tr $REPOSITORY/ | grep 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=class.path:/application.
        properties,classpath:/application-real.properties./home/ec2-user/app/application-oauth.properties,/home/ec2-user/app/
         application-real-db.properties \
         -Dspring.profiles.active=real \
        &JAR_NAME > $REPOSITORY/nohup.out 2>&1 &
① CURRENT_PID
 - 현재 수행 중인 스프링 부투 애플리케이션의 프로세스 ID를 찾는다.
 - 실행 중이면 종료하기 위해서이다.
 - 스프링 부트 애플리케이션 이름으로 된 다른 프로그램들이 있을 수 있어 springboot-study-webserivce로 된 jar 프로세스를 찾은 뒤 ID를 찾는다

② chmod +x $JAR_NAME
 - jar 파일은 실행 권한이 없는 상태이다.
 - nohup으로 실행할 수 있게 실행 권한을 부여한다.

③ $JAR_NAME>$REPOSITORY/nohup.out 2>&1 !
 - nohup 실행 시 CodeDeploy는 무한 대기이다.
 - 이 이슈를 해결하기 위해 nohup.out 파일을 표준 입출력용으로 별도로 사용
 - 이렇게 하지 않으면 nohup.out파일이 생기지 않고, CodeDeploy 로그에 표준 입출력이 출력된다.
 - nohup이 끝나기 전까지 CodeDeploy도 끝나지 않으니 이렇게 해야함

 

step1에서 작성된 deploy.sh와 크게 다르지 않다. 우선 git pull을 통해 직접 빌드했던 부분을 제거했다. 그리고 Jar를 실행하는 단계에서 몇 가지 코드가 추가되었다.

 

.travis.yml 파일 수정

현재는 프로젝트의 모든 파일을 zip파일로 만드는데, 실제로 필요한 파일들을 Jar, appspec.yml 배포를 우한 스크립트들이다. 이 외 나머지는 배포에 필요하지 않으니 포함하지 않는다. 그래서 .travis.yml 파일의 before_deploy를 수정한다.

before_deploy:
  - mkdir -p defore-deploy
  - cp scripts/*.sh before-deploy/
  - cp appspec.yml before-deploy/
  - cp build/libs/*.jar before-deploy/
  - cd before-deploy && zip -r before-deploy *
  - cd ../ && mkdir -p deploy
  - mv before-deploy/before-deploy.zip deploy/springboot-study-webservice.zip
① Travis CI는 S3로 특정 파일만 업로드가 안된다.
 - 디렉토리 단위로만 업로드할 수 있기 때문에 before-deploy 디렉토리는 항상 생성한다.

② before-deploy에는 zip파일에 포함시킬 파일들을 저장한다.

③ zip -r 명령어를 통해 before-deploy 디렉토리 전체 파일을 압축한다.

 

마지막으로 CodeDeploy의 명령을 담당할 appspec.yml 파일을 수정한다.

 

appspec.yml 파일 수정

appspec.yml 파일에 다음 코드를 추가한다. location, timeout, runas의 들여쓰기를 주의해야 한다. 들여쓰기가 잘못될 경우 배포가 실패한다.

permissions:
  - object : /
    pattern : "**"
    owner : ec2-user
    group : ec2-user
    
hooks:
  ApplicationStart:
    - location : deploy.sh
      timeout : 60
      runas : ec2-user
① permissions
 - CodeDeploy에서 EC2 서버로 넘겨준 파일들을 모두 ec2-user 권한을 갖도록 한다.

② hooks
 - CodeDeploy 배포 단계에서 실행할 명령어를 지정된다.
 - ApplicationStart라는 단계에서 deploy.sh를 ec2-user 권한으로 실행하게 한다.
 - timeout : 60으로 스크립트 실행 60초 이상 수행되는 실패가 된다.

 

모든 설정이 완료되었으니 깃허브로 커밋과 푸시를 한다. Travis CI에서 다음과 같이 성공 메시지를 확인하고 CodeDeploy에서도 배포가 성공한 것을 확인한다 

 

실제 배포 과정 체험

build.gradle에서 프로젝트 버전을 변경한다.

version '1.0.1-SNAPSHOT'

 

신규 버전이 정상적으로 잘 배포 되었다.

 

 

9,6 CodeDeploy 로그 확인

CodeDeploy와 같이 AWS가 지원하는 서비스에는 오류가 발생했을 때 로그 찾는 방법을 모르면 오류를 해결하기가 어렵다. 그래서 배포가 실패하면 어느 로그를 봐야 할지 간단하게 소개하려한다. 

 

CodeDeploy에 관한 대부분 내용은 /opt/codedeploy-agent/deployment-root에 있다. 

 

테스트, 빌드, 배포까지 자동화 도이ㅓㅆ다. 

 

이제는 작업이 끝난 내용을 Master 브랜치에 푸시만 하면 자동으로 EC2에 배포가 된다.

 

 

출처 : 스프링 부트와 AWS로 혼자 구현하는 웹 서비스 [이동욱 지음]