레넌의 개발 일기

Jenkins Pipeline 구축하기 - 백엔드편 본문

DevOps

Jenkins Pipeline 구축하기 - 백엔드편

brorae 2022. 8. 11. 01:20

젠킨스를 통해 CI/CD 파이프라인을 구축해보자.

 

Jenkins의 Item

FreeStyle vs Pipeline

FreeStyle 방식은 진입 장벽이 낮고 기존 사용 사례가 많아서 참고할 자료가 풍부하다는 장점이 있다. 하지만 젠킨스 플러그인을 이용한 커스터마이징이 제한적이고, 테스트 혹은 빌드 등의 작업에서 병렬처리를 미지원한다는 점과 다수의 형상관리 Repository와 연계하여 사용할 수 없다는 단점이 있다. Pipeline 방식은 FreeStyle 방식에 비해 진입장벽이 비교적 높고 기존 사용 사례가 적어 참고할 자료가 많이 없다는 단점이 있다. 하지만 커스터마이징의 폭이 넓고 테스트 혹은 빌드 등의 작업에서 병렬 처리를 지원하다는 점과 다수의 형상관리 Repository와 연계하여 사용할 수 있다는 장점이 있다.

 

이전에 FreeStyle로 Jenkins를 사용해본 경험이 있기 때문에, 비교적 어렵지만 커스터마이징하기 용이한 Pipeline 방식을 사용하기로 했다.

이제 본격적으로 파이프라인을 구축해보자. 

 

1. Github Access Token 발급

여기서 발급 받는 토큰을 활용하여 레포지토리에 대한 권한을 얻어온다.

 

Github Settings - Developer Settings - Personal Access Token에 들어간다.

Generate new token 버튼을 클릭하여 새로운 Access Token을 만든다.

repo와 admin:repo_hook 을 체크하고 토큰을 만들어준다.

repo는 깃허브 레포지토리에 대한 권한을 부여하는 것이고 admin:repo_hook은 레포지토리의 훅에 대한 권한을 부여하는 것이다.

키를 생성하게 된다면 위와 같은 화면이 나올 것이다. 해당 키는 창을 벗어나게 되면 다시 볼 수 없으므로 별도로 저장해야한다.

 

2. Credential 등록

Dashboard - Jenkins관리 - Manage Credentials - Add Credentials

 

Kind 부분을 Username with password를 선택해준 후, Username, Password, ID를 작성해준다.

Username은 Github ID, Password는 위에서 발급 받은 Token, ID에는 Credentials ID를 작성해주면 된다.

 

3. Github Web Hook 설정

webhook이란?

- webhook이란 원격 저장소의 소스에 push, commit 등의 이벤트가 발생하면 Jenkins와 같은 CI 서버에 해당 이벤트를 전달하는 기능이다.

 

프로젝트를 진행하고 있는 Repository에서 Settings - Webhooks 에 들어가서 'Add webhook' 버튼을 누르면 다음과 같은 화면을 볼 수 있다.

Payload URL - Web hook을 보낼 URL뒤에 '/github-webhook/'을 붙여준다.

Content type - 전송될 타입을 지정해준다.

Just the push event를 선택한 후 webhook을 만들어준다.

 

4. EC2의 Pem Key를 Credential로 등록

Jenkins에서 접근할 EC2의 Pem 키를 Credential로 등록해주어야한다. Jenkins 서버에서 특정서버로(여기선 백엔드 서버로) 파일을 전달한다거나 쉘 스크립트를 실행해야할 일이 있는데, 이 때 Credential이 필요하다.

 

Dashboard - Jenkins관리 - Manage Credentials - Add Credentials

 

SSH Username with private key를 선택한다.

ID에는 해당 credential을 식별할 ID를 적어주면 된다.

Username에는 해당 EC2 인스턴스의 Username을 적어주면 된다. Default인 ubuntu를 작성해주었다.

그 후 아래에 보이는 Enter directly를 클릭하면 아래와 같이 pem key를 입력할 수 있는 창이 나오는데 이 곳에 pem key를 입력해주면 된다. cat {key 이름}.key 를 통해 나오는 키 값을 -----BEGIN RSA PRIVATE KEY----- 부터 -----END RSA PRIVATE KEY-----까지 모두 복사해 입력하면 된다.

모두 등록이 완료되었다면 아래와 같이 Credential이 등록된 것을 볼 수 있다. (EC2마다 pem 키를 두어서 등록된 키가 많다..)

 

5.  파이프라인 생성

DashBoard의 Add Item을 눌러 Pipeline을 선택하여 Pipeline을 생성해준다.

프로젝트 url에 CI/CD를 설정할 Github Project url을 작성해준다.

GitHub hook trigger for GITscm polling을 체크해준다.

파이프라인 문법을 활용하여 파이프라인을 작성한다.

스크립트 작성 방법에 대해 다루게 된다면 글이 너무 길어지기에 이번 포스트에서 다루지 않겠다.

자세한 내용은 공식문서를 활용하기 바란다.

자세한 파이프라인은 아래와 같다.

pipeline {
    agent any
    
    options {
        timeout(time: 5, unit: 'MINUTES')   // timeout on whole pipeline job
    }
    
    stages {
        stage('Checkout SCM') {
            steps {
                checkout([$class: 'GitSCM', branches: [[name: '*/develop']], extensions: [[$class: 'SubmoduleOption', disableSubmodules: false, parentCredentials: true, recursiveSubmodules: true, reference: '', trackingSubmodules: true]], userRemoteConfigs: [[credentialsId: 'github_token', url: 'https://github.com/woowacourse-teams/2022-gong-seek.git']]])
            }
        }

        stage('Build and Test') {
            steps {
                dir('backend') {
                    sh '''
                        ./gradlew clean bootjar
                    '''
                }
            }
        }

        stage('Deploy') {
            steps {
                dir('backend/build/libs') {
                    sshagent(['gongseek-backend-dev']) {
                        sh 'scp -o StrictHostKeyChecking=no gongseek-0.0.1-SNAPSHOT.jar ubuntu@${backend_dev_ip}:/home/ubuntu/'
                        sh 'ssh -o StrictHostKeyChecking=no ubuntu@${backend_dev_ip} "sh deploy.sh" &'
                    }
                }
            }
        }
    }
    
    post {
        success {
            slackSend (channel: 'jenkins', color: '#00FF00', message: "SUCCESSFUL: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]' (${env.BUILD_URL})")
        }
        failure {
            slackSend (channel: 'jenkins', color: '#FF0000', message: "FAILED: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]' (${env.BUILD_URL})")
        }
        aborted {
            slackSend (channel: 'jenkins', color: '#000000', message: "ABORTED: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]' (${env.BUILD_URL})")
        }
    }
}

options - timeout

파이프라인이 5분 내로 끝나지 않으면 해당 파이프라인은 ABORT 시키는 옵션이다.

 

CheckOut SCM

develop 브랜치로 checkout 한 후 서브모듈을 포함한 코드들을 가져온다.

 

Build and Test

가져온 코드들에서 backend 경로로 이동하여 ./gradlew clean bootjar를 실행해준다.

 

Deploy

빌드 결과로 나온 jar 파일을 백엔드 서버로 이동시켜준 후, 해당 서버 안에 있는 쉘 스크립트를 실행한다.

백엔드 서버 안에 있는 deploy.sh 파일의 쉘 스크립트는 아래와 같다.

fuser -k 8080/tcp
nohup java -jar -Dspring.profiles.active=dev gongseek-0.0.1-SNAPSHOT.jar > nohup.out 2>&1 &

기존에 8080포트로 서버가 떠있을 경우를 대비하여 8080포트를 먼저 죽인후 jar 파일을 실행시켜준다.

 

post

파이프라인 결과에 따라 슬랙 알림을 보낸다.

 

'Deploy' stage의 sshagent를 사용하기 위해서는 별도의 sshagent Plugin을 설치해주어야한다.

해당 파이프라인을 실행해보면 정상적으로 작동하는 것을 확인할 수 있다.

 

 

참고

https://l-sanghyeup.medium.com/jenkins%EC%97%90%EC%84%9C-ci-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EB%A5%BC-%EC%A0%95%EC%9D%98%ED%95%98%EB%8A%94-2%EA%B0%80%EC%A7%80-%EB%B0%A9%EB%B2%95-22bf0fb1e608