Introduction

  • 저번 포스트에서 CD 부분까지를 마치고 테스트를 진행했다. 이번에는 지금까지 우리가 구성한 CI/CD의 전체적인 구조를 한 번 보고, github push와 같은 특정 명령어를 실행했을 때 자동으로 빌드를 할 수 있게끔 자동화하는 것을 볼 것이다.

 

 

구조 확인하기

  • 지금까지 우리가 구축한 그림이다. 플로우를 보면 다음과 같다.
  • 사용자 PC(우리)에서 Jenkins instance에 접속하여 Jenkins에게 빌드해라는 지시를 내린다. Jenkins는 해당 Job에 정의된 Jenkins Pipeline 스크립트를 따라가며 먼저 github repository에서 소스 코드를 가져오는 것 부터 시작한다.
  • github에서 코드를 가져온다. 그러면 적절한 처리를 수행한 후 maven 또는 gradle를 통해 빌드를 수행한다.
    • 여기서 적절한 처리란 github에서 다운받지 못한 여러 민감한 설정 파일이나 데이터들을 Jenkins에서 직접 집어넣어 주는 것을 의미한다.
    • 해당 maven build 과정에서 테스트를 진행할 수도 있다.
  • 해당 과정에서 산출되는 것은 빌드가 완료된 .jar 파일이다. 이 파일을 이제 각 서버 인스턴스에게 전달해야 한다.
    • 우리는 서버 인스턴스가 하나인 것을 가정하고 구축했지만 현업이나 큰 프로젝트에서는 여러 개의 서버에 서버 빌드파일을 전달해야할 수도 있다.
  • 이런 전달의 과정은 SSH 통신 프로토콜을 사용하여 수행했다. SSH 통신을 사용하기 위해 ssh-keygen과 같이 비대칭 키를 사용하여 통신을 수행했다.
  • CI/CD 파이프라인의 구조는 대략적으로 위와 비슷할 것이며 만약 추가적으로 수행해야 하는 일들이 존재한다면 Jenkins Pipeline Script에서 추가적으로 step을 추가하는 등의 동작으로 해결할 수 있을 것이다.

 

개선된 구조

문제점과 개선 구조

  • 위의 구조는 좋아 보이지만 결국 사용자가 jenkins instance에 접속하여 deploy 명령을 내려야 한다. 물론 배포를 하기 위해 수행해야 하는 여러 작업들을 버튼 한 번으로 해결하는 것은 좋지만 접속하는 것조차 귀찮을 때가 있다.
  • 결국 문제는 자동화가 되어 있지 않다는 것이다. 그래서 자동화를 해 보도록 하자. 새로운 구조는 다음과 같다.

  • 새로운 구조에서 우리는 다이렉트로 젠킨스에 deploy 해달라고 명령하지 않는다. 우리가 github에 push를 하면 github web hook에서 Jenkins instance로 deploy를 해달라고 요청을 보낸다.
  • 그럼 Jenkins에서 이전과 같이 deploy 과정을 수행할 것이다. 이를 통해 우리는 github repository에 변경 내용을 commit하고 push하면 변경된 내용이 자동으로 Server 인스턴스에 배포된다. 즉 우리가 다이렉트로 Jenkins 인스턴스에 접속할 필요가 사라진다.
  • 이제 github web hook을 사용하여 젠킨스로 요청을 보내는 부분을 구현해 보도록 하자.

 

 

Github Web Hook을 사용한 CI/CD 자동화

Github Token 발급

  • Github Web Hook을 사용하기 위해서는 먼저 토큰을 발급받아야 한다. github으로 들어가 보자.

  • Github Setting에 들어가 Developer Settings를 들어간다.

  • 아래의 토큰을 클릭한다.

  • 여기서 내가 만들어 놓은 토큰들을 확인할 수 있다. 대신 토큰 값이 무엇인지는 알 수 없다. 새로 생성하기 위해 Generate New Token(Classic)을 클릭한다.

  • Note에는 해당 토큰의 이름을 지정하는 텍스트를 넣어주면 된다.
  • Expiration은 해당 토큰의 유효 기간을 설정할 수 있다. 만약 여러분들이 단순 배포 및 공부를 위해 생성하는 것이라면 30일 정도로 설정해두는 것을 추천한다.
  • 만약 그렇지 않고 프로젝트 배포를 위해 사용하는 목적이라면 No Expiration으로 만료 기간이 없이 설정할 수 있다. 만료 일자는 여러분이 처한 보안적 상황에 맞게 지정해 주도록 하자.
  • 아래 select scopes는 이 토큰으로 할 수 있는 동작들을 선택할 수 있다. 우리가 jenkins에 deploy 명령을 web hook으로 하기 위해서는 admin:repo_hook 이라고 하는 곳을 체크해주면 되며 나머지는 필요하지 않다.

만약 여러분들의 프로젝트 저장소가 private 하거나, private으로 전환할 계획이 있다면 맨 위의 repo도 같이 선택해야 한다. repo를 선택하지 않을 시 저장소가 private 한 상태에서 jenkins가 해당 저장소의 소스 코드를 가져오지 못할 가능성이 있기 때문이다.

물론 repo를 체크만 한다고 jenkins가 바로 가져오진 못하며 jenkins에도 별도의 설정을 해주어야 한다. 이것에 대해서는 아래에서 확인해볼 수 있다.

 

  • 이후 generate token을 누르면 토큰의 값이 생성된다. 이때 반드시 토큰의 값을 기록해둬야 한다!! 토큰의 값은 현재 페이지에서만 확인이 가능하며 페이지를 이동하면 그 즉시 숨겨져 다시 확인할 수 없다는 것을 유의하라
  • 이후 여러분의 프로젝트 레포지토리로 이동하자.

  • 여러분들의 repository에서 Settings - Webhooks로 들어가자.
  • 들어가면 Web Hook을 추가할 수 있는 관리 페이지로 들어가지는데 Add webhook 버튼을 눌러 추가하자.

 

  • Payload URL은 어디로 request를 보낼 것인지를 지정하는 URL이다. 우리는 Jenkins로 보낼 것이기 때문에 Jenkins 인스턴스 IP로 보내주어야 할 것이다.
  • 또한 Jenkins의 포트가 8080인 것도 유의하자. 그 뒤에는 고정적으로 /github-webhook/ 이라는 주소가 추가적으로 들어간다. 따라서 전체적인 주소는 아래와 같다.
    • http://{repository-ip:8080}/github-webhook/
    • 만약 Jenkins의 포트를 8080으로 열어두지 않고 다른 특정 포트를 사용했다면 해당 포트 번호를 입력해주면 된다.
  • Content-Type은 어떤 형식으로 보낼 것인지인데 일반적으로 application/json을 사용한다.
  • Secret은 아까 여러분이 발급받은 github access token값을 넣어주면 된다.
  • 이후 어떤 이벤트에 대해서 webhook을 동작시킬 것인지를 선택할 수 있다.
    • Just the push event는 push하는 경우에 대해서만 webhook request가 전송된다.
    • everything은 모든 동작에 대해 webhook request가 전송된다.
    • select individual events는 어떤 이벤트에 대해 webhook을 동작시킬 것인지를 커스터마이징해 선택할 수 있다. 예를 들어 pull request나 merge등을 할 때를 설정해볼 수 있을 것이다.
  • 이후 Add webhook을 누르면 정상적으로 등록되는 것을 확인할 수 있다.
  • web hook을 등록했으면 GitHub에서의 일은 끝났다.

 

Jenkins 설정

  • Jenkins에 접속하여 Jenkins 관리 - Credentials로 들어간다. 여기서 새로운 credentials를 생성할 것이다.

  • Username with password로 진행하며 이때 username은 여러분의 github 이메일(또는 닉네임)을 넣어야 한다.
  • password는 방금 전 여러분이 발급받은 github access token을 넣어주면 된다.
  • ID는 Jenkins Pipeline에 해당 ID로 credentials 값을 가져오기 위한 alias로 아무렇게나 지정해주면 된다. Description은 해당 credentials가 어떤 것인지를 설명하는 것이므로 넣어도 되고 넣지 않아도 상관없다.
  • 이후 create를 눌러 추가되었는지 확인한다.

 

  • 이후 Dashboard - 내 작업 - 구성으로 들어간다.

  • 원래는 GitHub project가 체크가 되어 있지 않을 것이다. 해당 부분을 체크한 뒤 여러분이 배포할 레포지토리 주소를 입력하면 된다.
  • 이후 아래의 Build Triggers에서 GitHub hook trigger for GITScm polling을 체크한다.

  • 이러면 Jenkins가 GitHub Hook에 반응해 deploy를 시작하게 설정할 수 있다.

 

private repository인 경우

  • 프로젝트 repository를 private으로 바꿔야 할 경우 Jenkins Pipeline script에서 Checkout Stage를 다음과 같이 살짝 수정해주어야 한다.
pipeline {
    agent any

    tools {
        maven "M3" // Jenkins에서 설정한 Maven의 이름
    }

    stages {
        stage('Checkout') {
            steps {
                git url: 'your project repository', branch: 'main', credentialsId: 'GITHUB_WEBHOOK_TOKEN'
            }
        }
        
        ...
    }
    
    post {
        success {
            echo 'Deployment was successful.'
        }
        failure {
            echo 'Deployment failed.'
        }
    }
}
  • credentialsId를 추가하여 아까 Jenkins Credentials에서 추가했던 Web Hook Token을 넣어주면 된다.

 

테스트

  • 정상적으로 모든 설정을 마쳤다면 여러분의 프로젝트를 수정한 뒤 push해보도록 하자. 이후 jenkins dashboard를 확인해보면 자동으로 deploy가 진행되고 있는 것을 확인할 수 있다.

  • History에서 자동으로 Deploy가 진행되는 것을 확인할 수 있다.

  • 우측에 commit 하나가 반영되었다고 적혀 있는 것을 확인할 수 있다.

 

 

마치며

  • 이번에는 Github Web Hook과 연동하여 push를 수행할 시 자동으로 서버 인스턴스에 배포하도록 구성해 보았다. 즉 우리는 이제 CI/CD 자동화를 구축한 것이다.
  • 하지만 아직 끝나지 않았다. CI/CD 자동화는 구축했지만 배포하는 동안 서비스가 내려가 있는 시간이 있기 때문이다. 다음 파트에서는 이런 서비스 다운타임을 최대한 줄이기 위한 방법 중 하나로 무중단 배포에 대해 알아보도록 한다.
  • 아래는 Jenkins Pipeline으로 배포한 서버 인스턴스의 Swagger API Document 사진이다.

 

복사했습니다!