Jenkins를 이용한 CICD 개요

우리는 백엔드 프로젝트를 진행하면서 서비스 코드를 짜는 일 외에도 필요한 업무 프로세스가 다양하게 존재한다.

서버에 프로젝트를 배포하기 위해서는 빌드가 진행되어야 하고 코드 품질을 높이기 위해 테스트를 수행해야 한다. 또한 코드에서 일어날 수 있는 잠재적인 결함을 미리 예방할 수 있는 방법도 고안해야한다. 배포 과정 중에서도 사용자가 지속적인 서비스 이용이 가능하도록 조취를 해야할 것이다. 또한 서버의 모니터링도 이 과정에 포함된다.

이 모든 과정이 지속적 통합, 지속적 배포, 즉, CI/CD라고 한다.

우리는 Jenkins와 여러 툴을 이용하여 CI/CD를 프로젝트에 적용해 볼 것이다. 한번 자동화를 해 놓으면 지속적으로 코드 품질에 대한 피드백을 받을 수 있고 검증된 코드만 서버에 올라가기 때문에 소스 코드를 짜는 일에만 집중할 수 있어 높은 생산성을 가져갈 수 있다.

환경에 맞는 타협

실제로 서버를 여러대 꾸릴 여력이 된다면 개발 서버, 스테이징 서버, 운영 서버, 배포 서버 등 여러대의 서버를 놓고 진행하면 좋다. 하지만 현재는 여력이 부족하기 때문에 서버의 여러 역할들을 합쳐서 진행할 예정이다.

스테이징 서버를 제거하고, 배포 서버를 로컬에서 Docker Container에 띄워 작업할 예정이다. 하지만 해당 환경을 구성했더라도 CICD과정을 진행하는데 무리가 없게 작성할 것이다.

또한 해당 포스트를 쭉 따라가고 나면 다른 프로젝트에도 적용하는데 무리가 없게 하는데 집중해 포스트를 작성할 예졍이다.

조금 변형된 Git Flow

나는 프로젝트를 진행하며 가장 널리 퍼진 Git Flow를 조금 변형해서 사용할 것이다.

GIt Flow 소개글의 내용을 참조하면 해당 전략에 사용되는 서버의 갯수는 3개이다.

Git Flow는 3가지 서버를 사용한다. develop 브랜치의 내용이 업데이트 되면 개발 서버에 배포가 진행된다. 운영 환경에 배포를 준비하기 위한 release브랜치에 내용이 업데이트 되면 스테이지 서버에 배포가 이루어지고 성능 테스트 등 qc가 이루어진다. 또한 master브랜치에 머지가 되면 실제 운영 서버에 배포가 진행되게 된다.

사이드 프로젝트를 진행하며 qc팀까지 꾸리는데에는 어려움이 따르기 떄문에 스테이지 서버release 브랜치는 사용하지 않을 예정이다.

따라서 개발 서버운영 서버로만 구성할 것이다. 즉, main브랜치와 develop브랜치에 변경이 생겼을 때 각 브랜치에 맞는 서버에 배포 작업이 이루어 지면된다.

서버 구성도

서버 구성에서도 타협을 할 것이다. 예를 들어 Jenkins 서버나 Sonarqube의 서버는 따로 존재하는 것이 좋다. 하지만 서버를 놓을 여력이 부족하기 때문에 local에 Docker Container로 Jenkins와 Sonarqube를 띄우고 실제로 다른 서버에 존재한다고 가정하고 작업을 진행 할 예정이다.

이상적인 서버 구성도는 다음과 같다.

배포 서버에서 배포에 관련한 모든 일을 진행하게 된다.

하지만 타협한 구성도에서는 local에서 Jenkins를 Docker Container로 띄워 작업한다. 만약 협업중인데 나의 local컴퓨터가 켜있지 않다면 배포 과정이 진행되지 않을 것이다.

하지만 이는 CICD 테스트를 하기 위한 것이라면 문제가 생기지 않고, 실제 협업 프로젝트를 진행중이라면 AWS에서 EC2를 띄워 배포 서버로 활용하면 될 것이다. 또한 포스트 작성 시, 개발 서버를 구축한 환경에서도 충분히 적용할 수 있게 작성할 예정이니 따라오면 된다.

Sonarqube 및 Grafana 등은 현재 과정에서 표현하지 않았다. 추후 관련 포스트를 작성할 때 다시 한번 구성도를 업데이트 할 것이다.

전체적인 진행 과정

마지막으로 서버 구성도에도 표현해 놓았던 배포 과정에 대해서 설명하겠다.

가장 먼저

  1. Jenkins 설치하고 실행해보기에서 Jenkins를 Docker Container로 띄우고 실행하는 과정을 소개한다.
  2. GitHub와 Jenkins 연동하기에서 GitHub Repository에 변화가 생기면 Webhook을 Jenkins에 전송해 Jenkins가 빌드 과정을 자동적으로 시작할 수 있게 둘을 연동한다. 여기가 서버 구성도의 3번 까지이다.
  3. Spring 프로젝트 생성에서는 SpringBoot 프로젝트를 생성하고, 환경 별로 설정을 분리한다. 또한 보안에 민감한 정보가 GitHub Repository에 올라가지 않게 설정한다.
  4. Jenkins에서 Build 진행하기에서는 Jenkins에서 GitHub Repository를 checkout하고 Test와 Build까지 진행한다. 여기가 서버 구성도의 5번 까지이다.
  5. Jenkins에서 Docker Image Build & Push하기에서는 Jenkins에서 Build한 jar파일을 가지고 Docker Image로 Build하고 Docker Hub에 Push하는 과정을 거친다. 여기까지가 서버 구성도에서 7번 까지이다.
  6. SSH 접속 및 Docker Container 실행에서는 Jenkins에서 직접 운영/개발 서버에 접속해 Push한 Docker Image를 Pull받고 서버에 Docker Container를 띄우는 것 까지 진행한다. 여기까지가 서버 구성도에서 8번 까지이다. 이 과정에서는 blue-green 배포를 진행하지 않고 직접 커맨드로 Docker Container를 띄우는 과정 까지만 진행한다.
  7. Blue-Green 무중단 배포 적용하기 에서는 배포 shell scriptdeploy.sh를 작성하고, nginx관련 설정 및 설정 파일을 작성한다. 그리고 Jenkins에서 deploy.sh와 관련 파일을 운영/개발 서버에 전송하고 실행한다. deploy.sh를 실행하면 blue-green 무중단 배포가 진행된다. 여기가 서버 구성도에서 10번 까지이다.
  8. (작성 예정) Discord, Slack으로 실시간 배포 과정 전송에서는 Jenkins의 Plugin을 이용해 매 배포 stage마다 성공 또는 실패 결과를 전송받을 수 있게 한다.
  9. [(작성 예정) Sonarqube로 코드 정적분석 피드백 받기]에서는 Sonarqube와 JaCoCo, checkstyle을 이용해 작성해 코드의 잠재적 위험, 버그 등을 피드백받는 방법에 대해 소개할 것이다.
  10. [(작성 예정) Grafana를 이용한 실시간 모니터링 적용]에서는 Grafana를 적용해 모니터링 환경을 구축할 예정이다.

댓글남기기