본문 바로가기

💻Spring

Jenkins 파이프라인을 이용한 SpringBoot 자동배포 2 (젠킨스 파이프라인 생성 및 깃허브 액션 연결)

반응형

개요

이번 글에서는 저번 글에서 만들어둔 젠킨스에서 파이프라인을 생성하고 깃허브 액션을 연결하도록 하겠다.

우선 나의 프로젝트는 깃허브에 respal이라는 public한 메인 레포지토리가 있고,

application.yml을 관리하는 respal-private이라는 private한 레포지토리가 있고 둘은 깃의 서브모듈로 연결이 되어있다.

따라서 파이프라인에서 메인 레포지토리를 클론하며 서브모듈도 가져오는 작업이 필요했었던 상황이였다.

 

 

Jenkins x Github 연동

SSH 키 생성

젠킨스에서 깃헙 프로젝트로 접근하기 위해서

애플리케이션 서버 인스턴스에 접속하여 SSH키를 생성한다.

ssh-keygen -t rsa

 

이렇게 하면 ~/.ssh 디렉토리 아래에 id_rsa.pub 와 id_rsa 파일이 생긴다.

각각 해당 인스턴스에 접근 할 수 있는 공개키와 비밀키 이다.

비밀키는 해당 인스턴스에 가지고있고, 공개키를 접근을 원하는 곳에 설정하여 접근을 허용하는 것 이다. 

 

Github Deploy Key 등록

위에서 생성해준 키 중 공개키를 깃허브에 등록한다. 사용할 깃헙 프로젝트에서 

Settings > Deploy Keys > Add deploy key 클릭

 

 

Title 은 구분할 수 있는 명칭으로 하고, Key 값에는 퍼블릭키의 값을 넣어준다.

방금 생성한 애플리케이션 인스턴스에서 해당 명령어를 사용하여 얻어온 퍼블릭키 값을 넣어준다.

$ sudo cat ~/.ssh/[설정한 키 명칭].pub

 

Jenkins Credential 등록

젠킨스에서는 생성해준 키의 프라이빗 키를 크리덴셜로 등록해주어야 한다.
Jenkins관리 > Security > Credentials 아래 Domain이 (global) 인 화살표를 눌러 

add credentials 을 눌러 크리덴셜을 추가한다.

위의 Stores scoped to Jenkins 하위의 Domain 컬럼의 global을 누르면 나오는 화면

 

위 크리덴셜 속성에는 

종류는 SSH Username with private key 로 선택,

ID 에는 해당 크리덴셜의 ID라고 생각하고 구분할 수 있도록

그리고, Private Key 부분에 Enter directly를 체크해주면 프라이빗키를 입력할 수 있는 창이 나타난다.

애플리케이션 인스턴스로가서 다음 명령어를 통해 프라이빗 키를 확인하여 입력해준다.

$ sudo cat ~/.ssh/[키 명칭]
-----BEGIN OPENSSH PRIVATE KEY-----
...
... 이와 같은 형태의 key가 private key 
...
-----END OPENSSH PRIVATE KEY-----

키까지 모두 입력하고 OK를 하면 등록이 완료된다.

 

 

위와같은 방법으로 서브모듈 크리덴셜도 생성해준다. 

이 때 서브모듈 크리덴셜의 Kind는 Username and password로 설정하고,

password에는 깃허브 access token을 입력한다.

깃허브 access token은 Github > Settings > Developer Settings에서 Generate new token으로 생성한다.

scopes는 아래와같이 잡아준다.

 

Jenkins x 배포서버 SSH연결

1. Jenkins 서버의 SSH 키 - 쌍 생성

Jenkins 인스턴스에 접근을 하기 위해 PEM 형식의 키를 생성한다.

ssh-keygen -t rsa -C "키명칭" -m PEM -P "" -f /var/lib/jenkins/.ssh/[키명칭]

2. 애플리케이션 서버에 Jenkins 서버의 PublicKey 등록

위에서 생성한 키페어 중 퍼블릭 키를 배포서버인 인스턴스의 .ssh/authorized_keys 파일에 추가한다.

// 젠킨스 서버
$ sudo cat /var/lib/jenkins/.ssh/[키명칭].pub

// 애플리케이션 서버
$ vi .ssh/authorized_keys

3. Publish Over SSH 플러그인 설정

  • Jenkins 관리 > 플러그인 관리 > 설치가능 탭 에서 Publish Over SSH 플러그인을 검색하여 설치하고 젠킨스를 재실행하여 플러그인이 적용 될 수 있도록 한다.

Available plugins 에서 publish over ssh 검색

 

Jenkins 관리 > 시스템 설정 아래 Publish Over SSH 영역의 고급 버튼을 눌러 확장하여 설정한다.

  • Path to Key 는 위에서 생성해준 (젠킨스 서버의) private key의 경로를 넣는다.
    • /var/lib/jenkins/.ssh/{private key 명}
  • Key 는 Private key 파일안의 내용을 복사 붙여넣기 해준다.
  • Name 는 접속할 ssh 서버의 이름을 작성한다.
  • Hostname 는 접속할 (배포할 애플리케이션)인스턴스의 주소를 넣는다.
  • Username 는 접속할 (배포할 애플리케이션) 인스턴스의 유저명을 넣는다.

입력을 마친 후 Test Configuration 버튼을 눌러 정상적으로 연결이 되는지 확인까지 한다.

 

4. 파이프라인 작성

Test Configuration이 정상적으로 이루어지면 애플리케이션 서버의 인스턴스에 접속해서

/home/ubuntu/{서비스명}/script 디렉토리를 만들어주고 해당 디렉토리에 다음과 같은 init_server.sh 파일을 만들어준다.

        echo "> respal pid 확인"
        CURRENT_PID=$(ps -ef | grep java | grep respal | grep -v nohup | awk '{print $2}')
        echo "$CURRENT_PID"
        if [ -z ${CURRENT_PID} ] ;then
        echo "> 현재 구동중인 애플리케이션이 없으므로 종료하지 않습니다."
        else
        echo "> sudo kill -9 $CURRENT_PID"
        sudo kill -9 $CURRENT_PID
        sleep 10
        fi
        echo "> 서버 배포"
        JAR_PATH=$(ls -t /home/ubuntu/{서버명}/deploy/*.jar | head -1)
        sudo nohup java -jar -DServer.port=80 ${JAR_PATH} >> /home/ubuntu/{{서버명}}/logs/{서버명}.log 2>&1 &

        echo "Deploy Success"

init_server.sh 파일 설정

 

sh 파일을 생성했으면 이제 다시 웹 젠킨스로 돌아가서

대시보드 > 새로운 Item을 들어간 후 

item name을 작성하여 Pipeline을 선택 후 OK를 클릭해준다.

 

 

프로젝트가 생성되면 스크립트 작성을 하여 수동 배포를 먼저 확인한 이후 Github와 연동하는 설정을 하도록 하겠다 !

4 - 1 파이프라인 스크립트 작성

젠킨스에서는 파이프라인 스크립트를 2가지로 제공하고 있다.

  • Pipeline script
    • 젠킨스 웹 내에서 스크립트를 작성하여 관리 (default)
  • Pipeline script from SCM 
    • 프로젝트 내에서 Jenkinsfile에 스크립트를 작성하여 관리

우리는 default 방법인 Pipeline script를 활용해서 작성해보도록 하겠다.

 

Pipeline Script는 2가지 타입으로 작성이 가능하다. 두 방법 모두 Groovy문법 기반이며 둘의 차이는 아래와 같다.

  • Declarative Pipeline : 쉽게 작성이 가능하며 Groovy 문법 기반이지만 해당 문법을 몰라도 작성 가능하다고 한다. (최상단에 pipeline 이라고 되어 있으면 declarative 문법으로 작성된 것이다.)
  • Scripted Pipeline : Groovy 문법 기반이며 Declarative 보다 효과적이고 많은 기능으로 포함해서 작성 가능한데 어렵다. (최상단에 node 지시어가 있으면 scripted 문법으로 작성된 것이다.)

두 문법을 혼합해서 사용할 수는 없으며 상세한 내용은 공식 문서에서 참고가 가능하다.

Pipeline Syntax (jenkins.io)

 

Pipeline Syntax

Scripted Pipeline, like Declarative Pipeline, is built on top of the underlying Pipeline sub-system. Unlike Declarative, Scripted Pipeline is effectively a general-purpose DSL built with Groovy. Most functionality provided by the Groovy language is made av

www.jenkins.io

 

이 중 우리는 Declarative Pipeline  문법을 사용하여 스크립트를 작성하도록 하겠다.

 

pipeline {
    agent any
    
    
    stages {
        stage('Git Clone') {
            steps {
                checkout scmGit(branches: [[name: '*/master']], 
                extensions: [submodule(parentCredentials: true, reference: '', trackingSubmodules: true)], 
                userRemoteConfigs: [[credentialsId: '{Credential에서 설정한 서브모듈 토큰의 이름}', url: '배포 서버의 깃 레포지토리']])
            }
        }
    
    
        stage('build'){
            steps{
                sh'''
                echo build start
                ./gradlew clean bootJar
                '''
                }
            }
        stage('publish on ssh'){
            steps{
                sshPublisher(
                    publishers: 
                        [
                            sshPublisherDesc(
                                configName: '{위에서 설정한 SSH Server의 name을 입력}',
                                transfers: 
                                    [
                                        sshTransfer(
                                            cleanRemote: false, 
                                            excludes: '', 
                                            execCommand: 'sh /home/ubuntu/respal/script/init_server.sh', 
                                            execTimeout: 0, 
                                            flatten: false, 
                                            makeEmptyDirs: false, 
                                            noDefaultExcludes: false, 
                                            patternSeparator: '[, ]+',
                                            remoteDirectory: '/respal/deploy', 
                                            remoteDirectorySDF: false, 
                                            removePrefix: 'build/libs',
                                            sourceFiles: 'build/libs/*.jar'
                                        )
                                    ], 
                                usePromotionTimestamp: false, 
                                useWorkspaceInPromotion: false, 
                                verbose: true
                        )
                    ]
                )
            }
        }
        
    }
}

파이프라인은 3개의 stage로 분리가 되어있다.

  • 1번 스테이지('Git Clone')에서는 Git에서 프로젝트를 클론해오고
    • 우리는 이번 포스트에서 언급했듯 서브모듈도 같이 클론해와야 하기 때문에 extensions를 추가하여 submodule도 같이 클론해온다. 
  • 2번 스테이지('build')에서는 클론해온 프로젝트를 빌드 한 다음
  • 3번 스테이지('publish on ssh')에서는 아까 작성해둔 쉘 스크립트를 실행한다. 

스크립트를 작성하고 저장을 한 다음 대시보드에 가서 만들어둔 파이프라인을 클릭 후에 

지금 빌드 버튼을 누르면 ( 한 번만 눌러야 함.. 여러번 누르면 에러나니 주의 ! )

하기와 같은 Stage별 Status가 나오는 Stage View에서 정상적으로 동작하는것을 확인 할 수 있다.

 

이렇게 모든 단계가 초록색으로 되면 배포가 된 것을 확인 할 수있다.

이제 깃허브와 연동을해서 해당 프로젝트를 푸쉬를 하면 자동으로 배포가 되도록 설정을 하도록 하겠다.

5. Github Webhook 연동

5-1 Github 프로젝트에 Webhook 생성

Github의 배포를 원하는 프로젝트의 레포지토리를 들어가 Setting > Webhook > Add Webhook을 클릭한다.

해당 Webhook 세팅에서 

  • Payload URL
    • {Jenkins 인스턴스 주소}/github-webhook/
      • 해당 Jenkins는 8080포트를 이용하기 때문에 포트를 적어줬다. 
  • Content type
    • application/json

을 설정 후 Update webhook을 눌러 Github 설정을 해준다. 

 

5-2 Jenkins 파이프라인에 Github Webhook 연동

아까 작성해둔 파이프라인 프로젝트의 구성 탭으로 들어가서 다음과 같이 설정을 해준다.

  • Github project
    • Project url : 방금 webhook을 설정한 깃허브 레포지토리 주소 
  • Github hook trigger for GITScm.polling

해당 설정들을 체크해주고 저장 버튼을 누르면 연동이 모두 완료된다. 

 

 

출처 

- [AWS] Jenkins를 활용한 Docker x SpringBoot CI/CD 구축 (velog.io)

 

[AWS] Jenkins를 활용한 Docker x SpringBoot CI/CD 구축

AWS EC2 인스턴스 2개를 구축서버와 배포서버로 활용하여 CI/CD 구축

velog.io

- [DevOps] Jenkins를 통한 CI/CD 구축기 4편 (Backend DB 구축) | Seongwon.dev 

 

[DevOps] Jenkins를 통한 CI/CD 구축기 4편 (Backend DB 구축)

🔗 연관 게시글 CI/CD란? [DevOps] Jenkins를 통한 CI/CD 구축기 1편 (Jenkins 설치) [DevOps] Jenkins를 통한 CI/CD 구축기 2편 (Backend CI/CD 구축) [DevOps] Jenkins를 통한 CI/CD 구축기 3편 (Frontend CI/CD 구축) [DevOps] Jenkins

seongwon.dev

 

반응형