Jenkins를 통해 빌드 결과물을 EC2에 업로드하고 실행하기 (2)

Jang990·2023년 5월 14일
0

Jenkins 시작하기

목록 보기
4/6
post-thumbnail
post-custom-banner

목표

로컬에 Jenkins를 두고,
Github에 특정 레포지토리 Main 브랜치에 push를 하면
EC2에 Push 결과의 jar가 배포되도록 만들 것입니다.

이전 글에서 Github 특정 레포지토리 Main 브랜치에 push를 하면 프로젝트를 빌드하도록 만들었습니다.
이 글에서는 젠킨스를 이용해서 EC2에 빌드한 파일을 올리고 서버를 실행하는 내용을 다루겠습니다.



Publish Over SSH 설치

Jenkins 관리 -> 플러그인 관리

Available plugins로 들어가서 Publish Over SSH 검색

Publish Over SSH를 선택하고 Download now and install after restart를 클릭

젠킨스를 다시 시작하면 됩니다.



젠킨스 설정

Jenkins 관리 -> 시스템 설정


맨 밑으로 쭉 내려보면 Publish over SSH가 있습니다.

다른 것은 신경쓰지말고 Key에 EC2 인스턴스를 생성할 때 받은 키 .pem 파일의 내용을 복사해서 붙혀넣어주면 됩니다.


그리고 하단에 보이는 SSH Server의 추가 버튼을 눌러주면 됩니다.

Name: 임의의 SSH Server의 Name
Hostname: 실제로 접속할 원격 서버 ip
Username: 원격 서버의 user 이름
Remote Directory: 원격서버에서 접속하여 작업을 하게 되는 디렉토리

 참고 입력 예시
Name: ec2-server (마음대로 작성)
Hostname: 1.2.3.4 (ec2 인스턴스의 IP)
Username: ec2-user (ec2를 별도로 설정하지 않았다면 그대로 쓰기)
Remote Directory: /home/ec2-user (ec2를 별도로 설정하지 않았다면 그대로 쓰기)

하단에 Test Configuration 버튼을 누르고 Success라는 문구가 뜬다면 정상적으로 설정이 된 것입니다. 저장하고 나와줍시다.



빌드한 파일을 EC2로 올리기

현재 레포지토리의 main 브랜치에 push가 발생하면 빌드하고 테스트하는 것까지 파이프라인을 구성했습니다.

이제 다음과 같이 EC2에 jar 파일을 올리고 실행해보겠습니다.

  1. EC2에 deploy 폴더로 jar 파일을 올립니다.
  2. EC2에서 이미 실행중인 Spring 서버를 찾습니다.
  3. 이미 실행중인 서버가 있다면 해당 프로세스를 kill합니다.
  4. jar 파일을 실행하여 서버를 실행합니다.


EC2 사전 준비하기

/deploy 폴더를 미리 생성해 놓고 쉘 스크립트 파일을 생성합니다.

mkdir deploy   - deploy 폴더 생성
cd deploy   - depoly 폴더로 이동
touch start-server.sh   - start-server.sh 파일 생성
vim start-server.sh   - start-server.sh 파일 편집

이제 스크립트 파일이 다음 동작을 수행하도록 만들어 줍니다.

  1. EC2에서 이미 실행중인 Spring 서버를 찾습니다.
  2. 이미 실행중인 서버가 있다면 해당 프로세스를 kill합니다.
  3. jar 파일을 실행하여 서버를 실행합니다.(logs 폴더에 api.log 파일을 생성하고 log를 기록합니다.)

위의 명령어를 차례대로 수행한 후 start-server.sh 편집화면에서
다음 쉘 스크립트를 복사해서 붙혀넣어주면 됩니다.

#!/bin/bash

# Spring Boot 애플리케이션을 배포하기 위한 스크립트

echo "Start Spring Boot Application!"
# 현재 실행 중인 프로세스 중 'java'와 'jenkins-0.0.1'를 포함한 프로세스의 PID를 가져옵니다.
CURRENT_PID=$(ps -ef | grep java | grep jenkins-0.0.1 | awk '{print $2}')
echo "$CURRENT_PID"

# $CURRENT_PID가 비었는지 확인합니다.
if [ -z $CURRENT_PID ]; then
    echo ">현재 구동중인 어플리케이션이 없으므로 종료하지 않습니다."
else
    echo "> kill -15 $CURRENT_PID"
    
    # PID를 사용하여 해당 프로세스를 종료시킵니다.
    kill -15 $CURRENT_PID
    
    # 정상적으로 종료할 수 있도록 10초 대기합니다.
    sleep 10
fi

echo ">어플리케이션 배포 진행!"
# JAR 파일을 실행하고 실행 결과를 로그 파일에 리다이렉트하여 백그라운드에서 실행합니다.
nohup java -jar ~/deploy/jenkins-0.0.1-SNAPSHOT.jar >> ~/deploy/logs/api.log &
# 주의 "~/deploy/{젠킨스 빌드 결과 파일}."

마지막으로 log를 기록할 logs 폴더를 mkdir logs 명령어를 통해 만들어줍니다.


명령어 모음

- EC2 접속
mkdir deploy
cd deploy
touch start-server.sh
vim start-server.sh
- i버튼 눌러서 입력 모드로 전환
- 쉘 스크립트 내용 복붙
- ESC를 누르고 :wq 로 밖으로 나오기
mkdir logs

FIX: 젠킨스 배포단계에서 타임아웃 문제

마지막 스크립트문을 다음과 같이 변경해주자.

nohup java -jar ~/deploy/jenkins-0.0.1-SNAPSHOT.jar >> ~/deploy/logs/api.log 2>&1 &

2>&1이 추가됐다. 표준 에러 출력을 표준 출력에 함께 출력한다는 의미이다.
이 부분을 추가해주면 타임아웃이 발생하지 않는다.



젠킨스 파이프라인 설정하기

현재 빌드한 파일은 다음과 같이 /workspace/{젠킨스 프로젝트 이름}/build/lib/xxx.jar에 있습니다.

구성으로 다시 들어가 줍니다.


쭉 내려서 제일 하단에 보이는 Pipeline Syntax를 클릭해줍니다.


Steps에 sshPublisher: Send build artifacts over SSH를 클릭해줍니다.


다음과 같은 화면이 나올 것입니다.

Name: 앞서 설정한 SSH Server의 Name
Source files: 내가 전송할 파일의 위치
Remove prefix: 파일 전송 시 source files 에서 제거할 prefix
Remote directory: 파일을 전송할 원격 서버(EC2)의 디렉토리
Exec command: 파일 전송 후 실행할 명령어

설정 예시 코드
Name: 설정한 그대로 두기
Source files: build/libs/*.jar  = 빌드 결과물로 설정
Remove prefix: build/libs  = 이 부분 제거
Remote directory: /deploy  = ec2에 준비해둔 deploy 폴더로 전송(서버 폴더 설정을 `/home/ec2-user`로 했기 때문에 알아서 /deploy로 갈 수 있다.)
Exec command: 
cd /home/ec2-user/deploy
sh start-server.sh  = /home/ec2-user/deploy 폴더로 이동해서 스크립트 실행 

설정을 마치고 하단에 Generate Pipeline Script 버튼 누르고, 결과물 복사합니다.


다시 구성으로 들어가서 파이프라인 Deploy에 복사한 파이프라인 코드 붙혀넣고 저장합니다.



성공!

index 페이지를 생성하고 레포지토리에 커밋을 해서 페이지가 정상적으로 화면에 출력되는지 확인해보겠습니다.

젠킨스가 정상적으로 동작하면서 파일이 EC2에 업로드되고 정상적으로 페이지가 출력된 것을 확인할 수 있습니다.

출처

https://velog.io/@sa1341/Jenkins%EC%97%90%EC%84%9C-EC2%EB%A1%9C-%EB%B0%B0%ED%8F%AC%ED%95%98%EA%B8%B0#%EB%B9%8C%EB%93%9C-%ED%9B%84-%EC%A1%B0%EC%B9%98
https://thalals.tistory.com/430

profile
공부한 내용을 적지 말고 이해한 내용을 설명하자
post-custom-banner

0개의 댓글