본문 바로가기

Back-End/Jenkins

[Jenkins] 젠킨스를 이용한 스프링 부트 CI/CD (feat. EC2)

728x90

스프링 부트 서버를 EC2 서버를 사용하여 구축하고, 서버를 실행시킬 때마다 EC2 인스턴스에 접속하여 명령어를 입력해야 하는 것이 불편해서 젠킨스를 이용해서 스프링 부트 서버의 CI/CD 를 구축하려고 합니다.

이 글은 EC2 서버 구축이 모두 완료된 상태에서 진행합니다. EC2 서버 구축은 아래의 이전 포스팅을 참고해주세요 :)

 

[AWS] AWS EC2 에 스프링 부트 프로젝트 배포하기 (feat. MySQL)

현재 스프링 부트 프로젝트를 하고 있는데, AWS EC2 에 배포하려고 합니다. AWS 에 계정을 만들어놓은 상태이고, 스프링 부트 프로젝트를 AWS 서버에 올려보겠습니다. 1. EC2 인스턴스 생성하기 1) EC2

jeinie-developer.tistory.com

 

1.  젠킨스 설치

현재 사용 중인 EC2 서버에 젠킨스를 설치하도록 하겠습니다.

1) EC2 서버에 접속하여 아래 명령어를 입력하여 yum 업데이트를 합니다.

sudo yum update -y

 

2) 업데이트를 완료하면 아래 명령어를 입력하여 젠킨스 저장소를 가져옵니다.

sudo wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat-stable/jenkins.repo

 

3) 젠킨스 저장소를 가져온 후, 아래 명령어를 입력하여 젠킨스 키를 가져옵니다.

sudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io-2023.key

 

4) 젠킨스 키를 가져왔으면, 아래 명령어를 입력하여 젠킨스를 설치합니다.

sudo yum install jenkins -y

 

5) '/etc/sysconfig/jenkins' 경로로 들어가서 젠킨스 포트를 9090 으로 변경하고, '/usr/lib/systemd/system/jenkins.service' 파일에서도 젠킨스 포트를 9090으로 변경합니다.

해당 포트번호에 대한 인바운드 규칙을 AWS EC2 대시보드에서 추가해줍니다.

 

6) 아래 명령어를 입력하여 젠킨스 서비스를 시작합니다.

sudo service jenkins start

 

2.  젠킨스 접속

1) url 창에 'http://ec2 서버의 ip 주소:9090' 를 입력하여 브라우저로 접속합니다.

2) EC2 서버에서 화면에 나오는 경로에 접속하여 해당 파일을 열어 비밀번호를 복사하여 입력합니다.

3) Install suggested plugins 를 클릭하여 기본 플러그인을 설치합니다.

기본 플러그인 설치

 

4) 계속해서 관리자 계정을 만들고, 최종적인 젠킨스 URL 까지 확인하면 아래와 같이 젠킨스에 접속하게 됩니다.

젠킨스 접속

 

3.  젠킨스 Credentials 설정

젠킨스 파이프라인 구축에 앞서, Credentials 를 먼저 설정하도록 하겠습니다.

1) Jenkins 관리 > 시스템 설정 에 들어갑니다.

젠킨스 관리 > 시스템 설정

 

2) GitHub 탭으로 이동한 후, 아래와 같이 Add GitHub Server 을 클릭합니다.

GitHub > Add GitHub Server

 

3) 이름을 입력하고, 아래와 같이 Add 버튼을 클릭합니다.

Add 버튼 클릭

 

4) 이후 나오는 팝업에서 Kind 는 다음과 같이 Secret text 로 선택해주고, Secret 에 Github 에서 발급받은 access token 을 등록해주면 됩니다.

Add Credentials

 

5) 그럼, Github 에서 토큰을 발급받아보겠습니다. Github 에 접속해 Developer settings > Personal access tokens 로 이동합니다.

Developer settings > Personal access tokens

 

6) 토큰의 이름, 유효기간, 필요한 권한을 체크해줍니다. repository 의 접근 권한이 필요하므로 아래와 같이 체크해줍니다.

권한 체크

 

7) 토큰을 생성하면 다시 확인할 수 없기 때문에 토큰 값을 잊어버리면, 토큰을 새로 발급받아야 합니다. 젠킨스로 돌아와서 Password 칸에 해당 토큰값을 복사 + 붙여넣기 해줍니다.

Add Credentials

 

8) 저장 을 클릭한 후, 아래와 같이 Credentials 에 위에서 생성했던 Secret text 를 선택해줍니다. access token 이 정상적으로 동작하는지 확인하기 위해 Test connetion 을 클릭하여 확인합니다.

Test connection 성공

 

9) access token 이 잘 동작하는지 확인한 후, add 를 한 번 더 클릭해 같은 access token 에 대해 유형만 다른 credentials 를 생성해놓겠습니다.
시스템 설정에 있는 GitHub 탭에서는 credentials 에 Secret Text 로 등록한 credentials 만 인식하지만, 이후 프로젝트 CI/CD 구축을 위해 작성할 파이프라인 쉘 스크립트에서는 Username with password 로 생성한 credentials 가 필요하기 때문입니다.

Username 에는 Github 아이디를 입력해주고, ID 칸에는 다른 설정 페이지에서 활용할 이름을 입력해줍니다.

설정 완료

 

3.  젠킨스 CI/CD 구축 (with Pipeline)

[ Github Clone ]

1) 왼쪽에 새로운 Item 을 클릭한 다음, 아이템 이름을 입력하고 Pipeline 을 클릭합니다.

2) Build Triggers 에서 Github 로부터 웹훅을 활용한 빌드를 유발할 수 있도록, 아래와 같이 체크해줍니다.

Build Triggers

 

3) Pipeline syntax 에 들어가서 파이프라인 스크립트 작성을 위한 내용을 만들어보겠습니다. Steps 에서 아래와 같이 설정하고, 아까 Username with password 유형으로 생성한 Credentials 를 추가해줍니다.

pipeline syntax

이렇게 작성한 파이프라인은 다음과 같습니다.

pipeline {
    agent any
    
    stages {
        stage('Github Clone') {
            steps {
                git branch: 'main',
                    credentialsId: 'repo-and-hook-access-token-credentials',
                    url: 'https://github.com/GrapeBongBong/Back-End'
            }
        }
    }
}

 

[ Build ]

1) 이제 빌드를 위한 stage 를 추가하겠습니다. 필자의 경우 스프링부트 프로젝트의 .gradlew 가 소스코드의 루트에 있으므로 / 경로에 위치합니다. 따라서 별다른 디렉토리 명시 없이 작성했습니다.

만약 .gradlew 가 /backend 와 같이 다른 디렉토리에 위치해있다면, dir 스니펫을 활용해 cd backend 명령어를 입력하는 것과 동일하게 작동하도록 해주면 됩니다. 이와 관련된 파이프라인 입력 예시는 아래와 같습니다.

pipeline {
    agent any
    
    stages {
        stage('Github Clone') {
            # 생략
        }
        
        stage('Build') {
            steps {
            	dir('backend') {
                    sh '''
                        echo build start
                        ./gradlew clean bootJar
                    '''
                }
            }
        }
    }
}

 

현재까지의 파이프라인은 다음과 같습니다.

pipeline {
    agent any
    
    stages {
        stage('Github Clone') {
            steps {
                git branch: 'main',
                    credentialsId: 'repo-and-hook-access-token-credentials',
                    url: 'https://github.com/GrapeBongBong/Back-End'
            }
        }
        
        stage('Build') {
            steps {
                sh '''
                    echo build start
                    ./gradlew clean bootJar
                '''
            }
        }
    }
}

 

2) 한 번 테스트를 해보겠습니다. 아래와 같이 지금 빌드 를 클릭해줍니다.

지금 빌드

 

아래와 같이 빌드가 정상적으로 되었음을 확인할 수 있습니다. (이미 빌드를 몇 번 한 후라 시간이 짧게 나왔네요..ㅎ)

빌드 성공

 

[ Deploy ]

빌드까지 잘 확인이 되었으면, 이제 배포를 해보겠습니다.

1) 배포 과정에서 EC2 서버에 있는 쉘 스크립트를 실행하도록 합니다. 쉘 스크립트의 순서는 다음과 같습니다.

  • CURRENT_PID=$(ps -ef | grep java | grep capstone | grep -v nohup | awk '{print $2}')
    >> 현재 스프링부트 애플리케이션의 PID 를 확인합니다.

  • if / else 문
    >> 현재 실행 중인 스프링부트 애플리케이션이 있다면 해당 프로세스를 종료합니다.

  • sudo cp /home/ec2-user/server/Back-End/build/libs/*.jar /home/ec2-user/server/deploy
    >>  '/home/ec2-user/server/Back-End/build/libs/*.jar' 경로에 생긴 최신 버전의 스프링부트 애플리케이션을, '/home/ec2-user/server/deploy' 경로에 복사해옵니다.

  • nohup java -jar /home/ec2-user/server/deploy/capstone-0.0.1-SNAPSHOT.jar > /dev/null 2>&1 &
    >> 복사해온 jar 파일을 실행시켜, 최신 버전의 서버를 구동시킵니다.
    >> nohup : no hang up 의미로, 터미널 세션이 끊어진 후에도 프로세스가 백그라운드에서 계속 실행되도록 합니다.
    >> '> /dev/null' : 표준 출력을 /dev/null 로 리디렉션합니다. 즉, 모든 출력을 무시하고 버리는 역할을 합니다.
                                 (이 명령어가 없으면 젠킨스에서 계속 실행하다가 timeout 에러가 나게 됩니다.)
    >> 2>$1 : 표준 에러를 표준 출력으로 리디렉션합니다. 즉, 표준 에러도 표준 출력으로 함께 /dev/null 로 리디렉션합니다.
    >> & : 명령어를 백그라운드에서 실행하므로, 명령어 실행 후 즉시 프롬프트를 사용할 수 있습니다.

다음은 init_server.sh 내용입니다.

#!/bin/sh
echo "> GrapeBongBong pid 확인"
CURRENT_PID=$(ps -ef | grep java | grep capstone | grep -v nohup | awk '{print $2}')
echo "$CURRENT_PID"

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

echo "> 스프링부트 애플리케이션 배포"

sudo cp /home/ec2-user/server/Back-End/build/libs/*.jar /home/ec2-user/server/deploy

nohup java -jar /home/ec2-user/server/deploy/capstone-0.0.1-SNAPSHOT.jar > /dev/null 2>&1 &

 

현재까지의 파이프라인은 아래와 같습니다.

pipeline {
    agent any
    
    stages {
        stage('Github Clone') {
            steps {
                git branch: 'main',
                    credentialsId: 'repo-and-hook-access-token-credentials',
                    url: 'https://github.com/GrapeBongBong/Back-End'
            }
        }
        
        stage('Build') {
            steps {
                sh '''
                    echo build start
                    ./gradlew clean bootJar
                '''
            }
        }
        
        stage('Deploy') {
            steps {
                sh "sudo -u ec2-user /home/ec2-user/server/script/init_server.sh"
            }
        }
    }
}

 

2) 이제 파이프라인을 이용해 지금 빌드 를 클릭해서 최신 버전의 서버가 잘 구동되는지 확인해보겠습니다.

배포까지 성공

이제는 EC2 서버에서 jar 파일을 실행시키는 명령어를 입력하지 않고도, 젠킨스에서 '지금 빌드'를 클릭하면 최신 버전의 서버를 백그라운드에서 실행시킬 수 있습니다. 이로써 CI/CD 구축을 완료했습니다.

728x90