들어가며
프로젝트를 진행할 때 개발한 애플리케이션을 배포해본 경험이 있을 것이다. 배포를 진행할 때 서버에 접속하여 수동으로 할 수도 있지만 매번 이렇게 하기에는 너무 번거롭다.
그렇다면 이러한 수동 배포 방식 말고, 자동으로 배포가 진행되도록 할 수는 없을까?
예를 들어 Github에서 push, merge와 같은 이벤트가 발생했을 때 자동으로 배포가 이루어질 수 있다면 매우 편리할 것이다.
이번 포스트에서는 Jenkins를 활용하여, Github에 어떤 이벤트가 발생했을 때 자동으로 배포가 이루어지도록 하는 자동 배포 방법에 대해 소개하려고 한다.
이번 포스트에서는 서버 프레임워크로 스프링 부트를 사용한다.
Jenkins 설치
Jenkins 설치는 도커를 이용하는 것이 가장 간편하다. 다음 명령어를 통해 Jenkins를 설치하도록 하자.
$ docker run -d -p 8080:8080 -v [호스트의 공유 디렉토리]:/var/jenkins_home --name jenkins jenkins/jenkins:jdk11
이후, 서버의 공인 IP:8080로 접근하면 다음과 같이 Jenkins를 사용할 수 있게 된다.
Jenkins를 처음 설치하게 되면 가장 먼저 관리자 비밀번호를 입력하여 Jenkins를 unlock 해주어야 하는데, 해당 비밀번호는 Jenkins 컨테이너의 로그를 통해 확인할 수 있다.
$ docker logs jenkins
...
Please use the following password to proceed to installation:
// 여기에 비밀번호가 나타난다.
This may also be found at: /var/jenkins_home/secrets/initialAdminPassword
...
비밀번호를 복사하여 Jenkins를 unlock 시키고, 다음과 같이 suggested 플러그인들을 설치해주도록 한다.
플러그인 설치를 완료하고 계정을 등록하면, Jenkins 설치가 완료된다.
Credentials 등록
Jenkins를 사용하는 목적은 배포이고, 배포를 하기 위해서는 Github에서 소스 코드를 가져와야 한다. 따라서 Jenkins와 Github를 연동해줄 필요가 있는데, 이를 위해서는 Github에 대한 접근 권한이 필요하다. 이번에는 Github 접근 권한을 위해 Credential을 등록하는 과정을 진행해보도록 하자.
가장 먼저 Github에서 access token를 발급받는 과정이 필요하다. 계정 - Settings - Developers settings - Personal access token - Generate new token의 과정을 거쳐 토큰을 발급받도록 하자.
이때 해당 토큰에 권한을 부여해주어야 하는데, 아래와 같이 repo에 대한 권한과 admin:repo_hook에 대한 권한이 필요하다.
이제 이렇게 발급받은 토큰을 Jenkins에 등록해주어 Jenkins와 Github을 연동해주도록 하자.
먼저, Jenkins로 돌아와서 Jenkins 관리 - Manage credentials를 클릭한다.
이후 다음과 같이 global을 클릭한 뒤, Add Credentials를 통해 global credential을 등록해주도록 하자.
여기서 Username은 자신의 Github 계정, Password에는 앞서 발급받은 access token을 입력하도록 한다.
그러면 새로운 credential이 생성될 것이고, 여기까지가 Jenkins와 Github 연동을 위한 Github 접근 권한을 설정해주는 과정이다.
Pipeline 생성
이번에는 실질적인 배포 과정을 작성해볼 차례이다. 간단한 Job을 수행한다면 freestyle을 고려해볼 수 있지만, Job들의 순차적인 수행이 필요하다면 pipeline을 사용하는 것이 좋다. 따라서 여기서는 pipeline을 생성하여 배포를 진행해보도록 하자.
1. 좌측 상단의 새로운 Item을 클릭한다.
2. Item의 이름을 입력하고 pipeline을 선택한다.
3. pipeline 설정에서 Github project에 배포하고자 하는 프로젝트의 url을 입력한다.
4. Github에 push 혹은 merge 등의 이벤트가 발생했을 때 자동 배포가 시작되도록 하기 위해서 아래 Build Triggers 옵션을 선택해주어야 한다.
5. 다음은 pipeline에서 가장 중요한 부분으로, 수행할 Job들을 선언하는 pipeline script을 작성해주어야 한다.
여기서 잠시 배포 과정에 대해 생각해보도록 하자. 배포를 할 때 보통 아래와 같은 과정을 거치게 된다.
- 배포할 브랜치에서 git clone
- Build
- Test
- Deploy
따라서 위 과정을 pipeline script로 작성하여 순차적으로 수행되도록 하면 될 것이다.
그전에 pipeline script를 어떻게 작성해야 하는지 감이 잘 오지 않을 수 있는데, 이때는 pipeline 구성 하단 pipeline script를 작성하는 부분에서 오른쪽 상단의 드롭다운을 통해 pipeline script의 예시를 확인하면 도움이 된다.
위 pipeline script를 분석해보자면, 다음과 같다.
- agent는 pipeline을 실행할 실행자를 설정하는 부분으로, any로 설정하면 가용한 agent 중 어떠한 것으로도 pipeline을 실행할 수 있다는 것이 된다. (Execute the Pipeline, or stage, on any available agent.)
- stages는 실행할 stage들의 집합이다.
- stage는 각 단계의 Job을 의미한다. 즉, 해당 단계에서 어떠한 작업을 수행할지 선언하는 곳이다.
- steps는 각 단계의 Job이 수행될 때 실제로 실행되는 코드가 선언되는 곳이다.
이제 이러한 pipeline script에 배포의 각 단계를 작성해보도록 하자.
배포할 브랜치에서의 git clone
먼저 배포할 브랜치에서의 git clone이다.
pipeline에서는 git clone 과정에 대한 pipeline script를 생성해주는 기능을 제공해준다. 다음과 같이 pipeline을 클릭한 후, 좌측에 pipeline syntax를 클릭하도록 하자.
그 후 Sample Step에서는 Git을 선택하고, Repository URL, 배포할 브랜치, 앞서 등록한 credential을 입력하고 Generate Pipeline Script를 클릭하면, git clone에 대한 pipeline script를 자동으로 생성해준다.
이렇게 생성한 script를 pipeline script의 첫 번째 단계로 작성해주도록 하자.
Build & Test
다음은 Build, Test 두 단계를 작성해보도록 하자.
이 단계는 애플리케이션을 Build & Test 하는 명령어를 그대로 작성해주면 된다. 이때 작성한 명령어는 쉘에서 수행되기 때문에 sh ''' '''로 감싸주어야 한다.
그리고 steps 내부에 dir이라는 키워드가 보이는데, dir은 작성한 명령어를 실행할 디렉토리를 의미한다. 즉, gradlew가 위치한 디렉토리를 작성해주면 된다.
Deploy
마지막으로 Deploy 단계를 작성해보도록 하자.
이 단계에서는 실제 운영용 서버로 빌드한 파일을 전달해주어야 한다. 이때 젠킨스의 Publish Over SSH 플러그인을 활용하면 수월하게 진행할 수 있다.
물론 scp를 이용해도 된다.
1. Jenkins 관리로 들어가 플러그인 관리를 클릭한다.
2. Publish Over SSH를 검색하고 설치한다.
3. 빌드한 파일을 전달할 운영용 서버를 등록해주어야 한다.
아래와 같이 Jenkins 관리 - 시스템 설정으로 들어오면 앞서 설치한 Publish Over SSH 플러그인과 관련된 부분을 찾을 수 있을 것이다.
그리고 Publish Over SSH 부분에 운영용 서버에 접속하기 위한 정보들을 입력해주어야 한다.
위에서 체크한 부분에 다음과 같은 내용들을 입력해주면 된다.
- Passphrase - 운영 서버의 비밀번호
- Name - SSH Server에 대한 설정을 식별할 수 있는 이름
- Hostname - 운영 서버 접속용 IP
- Username - 운영 서버 username
- Remote Directory - 빌드 파일을 전달 받고 싶은 루트 디렉토리
서버 접속 포트가 22번이 아니라면 고급 버튼을 클릭하여 Port를 수정해주도록 하자.
설정한 정보들을 바탕으로 운영 서버에 정상적으로 접속할 수 있는지 Test Configuration을 통해 테스트 해볼 수 있다.
Success가 나온다면 저장 버튼을 클릭하여 빌드한 파일을 전달할 운영용 서버 등록을 완료하도록 한다.
4. 빌드 파일을 전달할 운영용 서버 등록까지 완료하였으니, 실제 운영 서버로 빌드 파일을 전달하는 스크립트를 작성해주어야 한다. 이때도 해당 과정에 대한 pipeline script를 생성해주는 pipeline syntax를 이용하도록 하자.
먼저, 대시보드에서 생성한 pipeline - pipeline syntax로 들어가서 Sample Step 드롭다운에서 sshPublisher: Send build artifacts over SSH를 선택한다.
그러면 앞서 등록한 운영 서버가 자동으로 SSH Server에 등록되어 있을 것이다. 따라서 Transfers 부분만 작성해주면 되는데, 작성해야 할 부분은 다음과 같다.
- Source files에는 전달할 빌드 파일의 경로를 작성해주면 된다. gradlew의 빌드 파일 경로는 build/libs에 위치하므로 위와 같이 작성해주었다.
- Remove prefix에는 Source files에 붙은 경로 중 제거하고 싶은 부분을 작성해주면 된다. 위 예시에서는 backend/build/libs/*.jar 에서 backend/build/libs 를 제거하였으므로 경로 없이 *.jar 파일만 전달되게 된다.
- Remote directory에는 빌드 파일을 전달 받고 싶은 디렉토리를 작성해주면 된다.
- Exec command에는 빌드 파일 전달을 마치고 실행할 명령어를 작성해주면 된다.
이제 아래의 Generate Pipeline Script를 클릭하여 실제 운영용 서버로 앞서 빌드한 파일을 전달해주는 과정에 대한 script를 생성하도록 한다.
그리고 생성한 스크립트를 앞서 Build & Test 단계에서 작성한 스크립트에 붙혀넣도록 하자. 그러면 여기까지 작성한 pipeline script는 다음과 같을 것이다.
여기까지 왔다면 pipeline에서 Build now를 클릭하여 git clone, build, test, deploy의 단계를 거쳐 운영 서버에 빌드 파일이 제대로 전달되는지 확인해보도록 하자.
운영 서버로 빌드 파일이 잘 전달되는 것을 확인할 수 있다.
그런데 Build now를 클릭하여 배포하는 것은 자동 배포가 아니라 수동 배포이다. 우리가 원하는 것은 수동 배포가 아니라 Github에서 push나 merge와 같은 이벤트가 발생했을 때 자동으로 배포가 진행되는 것이다. 따라서 Github에서 어떤 이벤트가 발생하면 자동으로 pipeline이 실행되도록 설정해줄 필요가 있다.
Github Webhook 설정 Ver1
Github에서 어떤 이벤트가 발생했을 때 Jenkins가 자동으로 pipeline을 실행하기 위해서는 Github Webhook을 설정해주어야 한다.
Webhook은 어떤 이벤트가 발생했을 때 발생한 이벤트에 대한 정보를 외부 서비스(Jenkins)에게 보내주는 기능을 한다.
1. 배포하려는 프로젝트의 레포지토리에서 Settings - Webhooks에서 Add webhook을 클릭한다.
2. 이벤트에 대한 정보를 보내고자 하는 URL을 입력하고, select individual events를 클릭하여 원하는 이벤트를 설정한다.
위 예시에서는 push와 pull request 이벤트에 대해서 자동 배포가 이루어지도록 하였다. 그리고 Add webhook을 통해 Webhook을 생성하면, 이제 push와 pull request 이벤트가 발생할 때 pipeline이 실행되면서 배포가 이루어질 것이다.
하지만 팀 프로젝트를 진행할 때 보통 배포가 진행되는 시점은 PR을 날리고 merge하여 코드를 병합했을 때 일 것이다. 즉, 위에서 볼 수 있는 pull request 이벤트가 발생하는 많은 경우는 사실 불필요하다. 따라서 오직 PR이 merge되는 시점에만 자동 배포가 이루어지도록 보다 세밀한 설정이 필요하다.
Github Webhook 설정 Ver2
이번에는 앞서 설정한 Webhook 방식과는 달리 push와 merge 이벤트가 발생했을 때만 자동 배포가 이루어지도록 해보자.
1. 가장 먼저, Jenkis에서 Generic Webhook Trigger 플러그인을 설치해주어야 한다. Jenkins 관리 - 플러그인 관리에서 설치해주도록 하자.
2. pipeline 구성으로 들어가서 이전에 설정한 Github hook trigger for GITScm polling 방식에서 Generic Webhook Trigger 방식으로 변경해준다.
여기서 잠시 Generic Webhook Trigger의 기능에 대해 간단히 소개하자면, 다음과 같다.
- Github Webhook 을 통해 Github 이벤트에 대한 정보 받을 수 있다.
- JSON 데이터에서 값을 추출할 수 있다.
- 추출한 값을 사용해서 빌드를 트리거할 수 있다.
우리는 Github Webhook이 보내주는 Github 이벤트에 대한 정보에서 값을 추출해서 merge된 경우라면 빌드가 진행되도록 할 것이다.
3. Generic Webhook Tigger에서 Token을 설정해주어야 한다.
이 토큰은 Github Webhook을 설정할 때 이벤트에 대한 정보를 보내고자 하는 URL에서 사용할 토큰으로, Github Webhook URL에 설정한 토큰이 함께 제공되어야만 해당 pipeline이 실행될 수 있다. URL에 입력하는 것은 뒤에서 Github Webhook을 설정할 때 진행해주도록 하겠다.
4. 다음은 Post content parameters를 설정해주어야 한다.
이 부분은 Webhook을 통해 전달 받은 JSON 데이터에서 원하는 값을 추출하는 부분이다. 우리는 PR이 merge되었는지에 대해 관심이 있기 때문에 이와 관련된 값을 추출하면 될 것이다.
여기서는 JSON 데이터에서 PR이 merge되었는지 여부를 IF_MERGED라는 변수에 담아두었다. 이제 이 변수의 값이 true일 때 배포가 진행되도록 설정해주면 된다.
5. 마지막으로 Optional filter를 설정해주어야 한다. IF_MERGED라는 변수에 담긴 merge 여부가 true인지 필터링을 하도록 설정하는 부분이다.
위 예제에서는 간단하게 true인지를 확인해주었는데, 만약 여러 개의 값을 추출하여 필터링한다면 보다 세밀한 정규표현식을 통해 필터링할 수도 있다.
이제 해당 내용을 저장하여 Generic Webhook Trigger에 대한 설정을 마치도록 하자.
6. 기존의 Github hook trigger for GITScm polling 방식에서 Generic Webhook Trigger 방식으로 변경되었기 때문에 Github Webhook 설정에서 URL을 변경해주어야 한다.
URL은 http://JENKINS_URL/generic-webhook-trigger/invoke?token={TOKEN} 으로 설정해주면 되고, 여기서 {TOKEN} 부분에 앞서 3번째 단계에서 설정한 Token을 입력해주면 된다. 그리고 Github 이벤트에 대한 설정은 그대로 push와 pull request 이벤트를 선택해주면 된다.
여기까지 설정을 마친 뒤, PR을 날리고 merge하여 자동 배포가 정상적으로 이루어지는지 확인해보도록 하자. 배포가 이루어진다면 우리의 목표인 Github 이벤트에 따른 자동 배포 구축에 성공한 것이다.
Reference
'DevOps' 카테고리의 다른 글
인덱스 컨디션 푸시다운(index_condition_pushdown) (0) | 2022.02.19 |
---|---|
어댑티브 해시 인덱스(Adaptive Hash Index) (0) | 2022.02.02 |
도커 스웜(Docker Swarm) 알아보기 (0) | 2021.12.26 |
Docker란 무엇인가 (0) | 2021.12.20 |