Skip to content

[INFRA] 2. 백엔드 CI CD 구축

Hanuel Lee edited this page Jul 28, 2023 · 4 revisions

0. intro

image

앞서 구축한 infra 서버를 바탕으로 본격적으로 ci/cd 구축을 시작하자.

Jenkins에서 하나의 ci/cd를 구축하기 위해서는 하나의 아이템(item)을 생성해야 한다.

하나의 jenkins 서버에는 여러개의 item을 만들 수 있고, 각각의 item은 설정에 따라 다르게 동작한다.

펀잇은 jenkins의 item을 만들기 위해 Pipeline방식을 사용했다.

pipeline : script파일에 코드를 작성해 item을 관리할 수 있다.

1. item 생성

jenkins에 접속해 '새로운 item'을 클릭한다.

image

item 이름을 지정해주고 pipeline 방식을 선택한다.

image

item을 생성하면 자동으로 설정 페이지로 이동한다.

스크롤을 쭉 내려서 pipeline 파트를 보자.

2. script 작성

image

이곳에서 pipeline의 script를 작성할 수 있다.

일단 전체 ci/cd script는 다음과 같다.

pipeline {
    agent any
    tools {
        gradle 'gradle'
    }
    stages {
        stage('Git Clone') {
            steps {
                git branch: 'develop', url: {git url}
            }
        }
        stage('Build') {
            steps {
                dir("./backend") {
                    sh "./gradlew clean build"
                }
            }
        }
        stage('Deploy') {
            steps {
                sshagent(credentials: ['aws-key']) {
                    sh '''
                        ls
                        pwd
                        ssh -o StrictHostKeyChecking=no ubuntu@{개발서버ip} uptime
                        scp /var/jenkins_home/workspace/{item이름}/backend/build/libs/funeat-0.0.1-SNAPSHOT.jar ubuntu@{개발서버ip}:/home/ubuntu/funeat
                        ssh -t ubuntu@{개발서버ip} ./deploy.sh
                    '''
                }
            }
        }
    }
}

각 stage 별로 살펴보자.

1) Git Clone

        stage('Git Clone') {
            steps {
                git branch: 'develop', url: {git url}
            }
        }

Git에 올라가있는 프로젝트의 develop 브랜치를 clone한다.

2) Build

        stage('Build') {
            steps {
                dir("./backend") {
                    sh "./gradlew clean build"
                }
            }
        }

clone한 프로젝트의 backend 디렉터리로 이동 후 프로젝트를 빌드한다.

여기까지 하면 CI 구축은 끝이난다 👏

마지막 스테이지인 Deploy를 위해서는 몇가지 설정이 필요하다 ⚠️

설정 후에 다시 Deploy 스테이지를 살펴보도록 하겠다.

3. AWS 접속 설정

1) ssh plugin 설치

Jenkins가 설치된 infra 서버에서 스프링 어플리케이션이 실행될 develop 서버에 접속하기 위해서는 다양한 SSH plugin을 사용할 수 있다.

펀잇은 그중 SSH Agent라는 플러그인을 사용했다.

☁️ Jenkins 관리 → Plugins → Available plugins에서 SSH Agent를 검색해서 설치할 수 있다.

image

2) pem 키 설정

우리가 개인 pc에서 ec2에 접속할 때 ssh -i {pem키} ubuntu@{ec2의ip}로 접근했던 것처럼,

infra서버(Jenkins)에서 develop서버로 접속하기 위해서도 pem 키가 필요하다.

☁️ Jenkins관리 → Credentials

image

☁️ Stores scoped to Jenkins → System

image

☁️ Global credentials (unrestricted) → Add Credentials

image image
  • kind : SSH Username with private key
  • scope : global
  • id : 해당 crendential의 id
  • private key : cat {pem키}를 통해 나오는 값을 BEGIN~END까지 모두 입력

4. Deploy

다시 script로 돌아와 Deploy 스테이지를 살펴보자.

  • Deploy
        stage('Deploy') {
            steps {
                sshagent(credentials: ['aws-key']) {
                    sh '''
                        ls
                        pwd
                        ssh -o StrictHostKeyChecking=no ubuntu@{개발서버ip} uptime
                        scp /var/jenkins_home/workspace/{item이름}/backend/build/libs/funeat-0.0.1-SNAPSHOT.jar ubuntu@{개발서버ip}:/home/ubuntu/funeat
                        ssh -t ubuntu@{개발서버ip} ./deploy.sh
                    '''
                }
            }
        }

develop 서버로 배포하기 위해 sshagent 플러그인을 사용한다.

우리가 jenkins에 설정해둔 credentials중 'aws-key'라는 키를 사용해 접근한다.

infra 서버에서 develop 서버에 접근할 수 있도록 StrictHostKeyChecking을 no로 설정한다.

그리고 scp명령어를 통해 infra 서버에 빌드된 jar파일을 develop서버에 전송한다.

scp란?

  • ssh를 이용하여 네트워크로 연결된 호스트간에 파일을 주고받는 명령어
  • 원격지에 있는 파일과 디렉터리를 보내거나 가져올 때 사용하는 파일 전송 프로토콜

마지막으로 develop 서버에 있는 deploy.sh 파일을 작동해 빌드된 jar 파일을 실행시킨다.

참고로 우리팀의 deploy.sh 파일은 다음과 같다.

#!/bin/bash
pid=$(pgrep -f funeat)
if [ -n "${pid}" ]
then
        kill -15 ${pid}
        echo kill process ${pid}
else
        echo no process
fi
chmod +x ./funeat/funeat-0.0.1-SNAPSHOT.jar
nohup java -jar ./funeat/funeat-0.0.1-SNAPSHOT.jar >> application.log 2> /dev/null &

여기까지 하면 CD도 완료!! 👏

5. Github Webhook 연동

Jenkins를 이용한 CI/CD pipeline 만들기는 끝이 났다!

하지만 지금 상태에서는 사용자가 직접 jenkins 웹에 접속하여 지금 빌드를 눌러야만 해당 pipeline이 실행된다..

이제 정말 마지막으로

Github의 Webhook 기능을 이용하여 develop branch에 뭔가가 merge되었을 때 자동으로 pipeline이 실행되도록 설정해보자.

1) Github에서 webhook 만들기

☁️ 프로젝트 repository → Settings → Webhooks

image

Add Webhook을 클릭한다.

image
  • Payload URL : https://{젠킨스 url}/github-webhook/
  • Content type : application/json

또한 Which events would you like to trigger this webhook?는

펀잇의 경우 develop브랜치에 push(merge)되었을 경우에만 pipeline을 발동시킬 것이기 때문에

Just the push event로 설정했다.

2) Jenkins에 Git hook 설정

☁️ Configuration → General → Build Triggers

image

GitHub hook trigger for GITScm polling을 체크한다.

해당 옵션을 통해 github에서 webhook이 왔을 때 자동으로 pipeline이 실행된다.

6. End

이제 펀잇팀의 작업은 pr이 merge될 때마다 테스트, 빌드를 거쳐 배포까지 자동으로 진행된다 😋

또한 jenkins 웹에 접속하여 밑의 이미지처럼 한눈에 pipeline 진행상황을 확인할 수 있다!

image

이 글은 펀잇팀 오잉이 작성하였습니다.

🔐 공통

🔑 프론트엔드

🔒 백엔드

📝 회의록

🤩 데모데이

Clone this wiki locally