앞 게시글을 보면 나의 배포 일기를 확인할 수 있다.
https://yooooooni.tistory.com/132
하지만 위 해결 방안은 jar을 직접 실행하는 방식이었기 때문에 자동화를 적용하지 못했다.
당시 상황은 EC2 우분투 환경으로 들어가 git ssh 클론을 받아 직접 jar을 실행했다. 나는 CodeDeploy를 이용하여 nohup 명령어를 통해 백그라운드 자동화 배포를 하고 싶었다.
그럼 S3에 업로드하고 CodeDeploy에서 배포하면 되잖아! 라고 생각하실 수도 있다.
하지만 나는 이미 Github Action workflow 스크립트를 통해 S3에 업로드하고, CodeDeploy 배포까지 성공한 상태였다.
터미널에서 nohup 명령어로 jar을 직접 실행하면 잘 돌아가는데 왜 자동으로 배포하면 안 돌아가는 걸까? 곰곰이 생각을 하다가 내가 CodeDeploy를 사용하고 있으면서 제일 중요한 걸 놓치고 있었다는 것을 깨달았다.
바로 appspec.yml 파일과 이 파일이 호출하는 scripts/deploy.sh 파일이다. 즉, CodeDeploy가 자바 파일을 배포하기 위해서는 deploy.sh에 명령어를 제대로 작성해야 한다. 바로 쎄함을 느끼고 파일을 확인했는데, 역시나 명령어를 제대로 입력하지 않았다.
우선 appspec.yml 파일과 scripts 폴더의 위치이다.
우리는 안드로이드와 백엔드가 나누어지지 않고 하나의 모노레포 안에 폴더로 구분되어 있기 때문에 아래와 같이 배치했다. 처음에는 다른 블로그에서 appspec.yml 파일을 프로젝트 최상단에 두라고 했지만, 모노레포인 우리 프로젝트는 위와 같이 배치했다.
내가 처음에 작성한 deploy.sh이다. 언뜻 보면 제대로 작성한 것처럼 보인다. 하지만 제일 중요한 경로(*JAR_NAME)를 틀렸다.
앞서 말했듯이 나는 backend 레포지토리를 업로드하기 때문에 backend 폴더는 생략하고 그 내부 폴더들이 /home/ubuntu/app에 위치한다. 이렇게 잘못 작성한 이유는, 자동화 배포에 처음이었기 때문에 다른 분의 deploy.sh을 참고했고, 그 과정에서 정확한 경로를 작성하지 못한 것 같다.
REPOSITORY=/home/ubuntu/howabouttrip
cd $REPOSITORY
JAR_NAME=$(ls $REPOSITORY/build/libs/ | grep 'SNAPSHOT.jar' | tail -n 1)
JAR_PATH=$REPOSITORY/build/libs/$JAR_NAME
CURRENT_PID=$(pgrep -fl 'java -jar backend-0.0.1-SNAPSHOT.jar')
if [ -z $CURRENT_PID ]
then
echo "> 종료할 애플리케이션이 없습니다."
else
echo "> kill -9 $CURRENT_PID"
kill -15 $CURRENT_PID
sleep 5
fi
echo "> Deploy - $JAR_PATH "
nohup java -jar $JAR_PATH > $REPOSITORY/build/libs/nohup.out 2>&1 &
내가 최종적으로 작성한 deploy.sh이다.
JAR_NAME=$(ls $REPOSITORY/build/libs/ | grep 'SNAPSHOT.jar' | tail -n 1)
처음에는 jar 파일이 존재하는 build/libs 에서 .jar을 grep 했지만, 그렇게 되면 SNAPSHOT-plain.jar이 호출되는 경우도 있어 no main manifest attribute in 문제가 발생했다. 해당 문제는 JVM이 MANIFEST.MF 파일에서 메인 메서드를 찾지 못하는 문제인데, SNAPSHOT-plain.jar에 메인 메서드가 올라가지 않기 때문에 발생하는 것이다. 이 문제를 해결하기 위해서 메인 메서드를 갖는 SNAPSHOT.jar 파일을 grep 해주었고, 바로 해결되었다.
CURRENT_PID=$(pgrep -fl action | grep java | awk '{print $1}')
if [ -z $CURRENT_PID ]
then
echo "> 종료할 애플리케이션이 없습니다."
else
echo "> kill -9 $CURRENT_PID"
kill -15 $CURRENT_PID
sleep 5
fi
돌아가는 java 프로세스가 있는지 확인하기 위해 CURRENT_PID를 선언했다. 이후 조건문을 거쳐 이미 실행 중인 java 프로세스가 있으면 종료하도록 작성했다.
nohup java -jar $JAR_PATH > /dev/null 2> /dev/null < /dev/null &
마지막으로 네 번째 줄에 작성한 JAR_PATH(*SNAPSHOT.jar 파일 경로)를 호출하여 jar 파일을 실행시키는 명령어이다. 처음에는 해당 명령어를 실행하고, 해당 위치(/build/libs)에 nohup.out 파일에 로그를 넣도록 구현했다. 하지만 내 EC2에서는 권한 문제가 발생했고, 쓰기 권한을 줘도 해결이 되지 않았다. 차선책으로 /dev/null 방식을 사용하여 백그라운드에서 잘 동작하도록 구현할 수 있었다. (/dev/null은 데이터를 버리는 특수 파일로, 여기에 출력된 내용은 모두 사라진다. 따라서 이 부분은 프로세스의 표준 출력을 무시한다.)
이렇게 작성하면 코드가 수정될 때마다 Github Action으로 스크립트가 돌아가고, S3에 업로드된 후, CodeDeploy가 자동으로 배포한다.
+) 만약 자동화배포 후 로그를 확인하고 싶으면 마지막 jar 실행 명령문을 아래와 같이 작성하면 된다.
nohup java -jar $JAR_PATH > $REPOSITORY/build/libs/nohup.out 2>&1 &
'Dev > AWS' 카테고리의 다른 글
[AWS] EC2 + CodeDeploy + S3 + GithubActions 조합으로 자동화배포 구축하기 - (2) CodeDeploy 및 S3 세팅 (0) | 2024.04.15 |
---|---|
[AWS] EC2 + CodeDeploy + S3 + GithubActions 조합으로 자동화배포 구축하기 - (1) EC2 인스턴스 생성 및 세팅 (0) | 2024.04.12 |
[AWS] io.awspring 라이브러리를 활용하여 SpringBoot & Amazon S3 연동하기 (0) | 2024.03.12 |
[AWS] EC2 배포 일주일 삽질 스토리 (feat. 환경변수) (1) | 2024.01.27 |
[AWS] CPU 사용률 급증으로 인한 EC2 무한 로딩 해결 (1) | 2024.01.27 |