이번 내용은 필자가 프로젝트를 진행하면서 처음으로 DevOps를 맡으면서 꼭 공유 하겠다고 마음 먹고 작성하였다.
CI/CD란?
CI(Continuous Integration)
지속적인 통합을 의미한다. 이는 개발자를 위한 자동화 프로세스 중 하나이며 어플리케이션을 변경할 때 자동으로 빌드 및 테스트되어 Github 공유 레포지토리에 병합된다. 그렇기에 협업 시 발생할 수 있는 충돌문제를 해결할 수 있다.CD(Continuous Deployment)
지속적인 배포를 의미한다. 어플리케이션 변경 사항이 반영된 공유 레포지토리에서 사용자가 사용 가능한 환경까지 자동으로 배포하는 것을 말한다. 이를 통해 어플리케이션을 원활히 그리고 더 빠르게 제공하므로써 사용자의 피드백을 빠르게 반영할 수 있다.
아래는 필자가 맡은 프로젝트의 전체 시스템 구조이면서 동시에, CI/CD 과정을 볼 수 있다.
전체 시스템 구조
대부분 Travis CI, AWS, Docker, NGINX를 사용하여 CI/CD 무중단 배포를 구축한다는 점에서 비교하여 보아도 좋을 것이다.
선택의 순간들
AWS가 아닌 NAVER CLOUD 선택
AWS와 NAVER Cloud Platform을 사용해 보면서 느낀 것은 확실히 AWS의 기능이 훨씬 많고 유용하다.
그럼에도 NAVER Cloud Platform을 사용한 것은 40만 크레딧(지원 받았다.)이 제일 컸다.
AWS에는 무중단 배포까지 지원하는 서비스인 Blue-Green Deployment가 있는데 반해 NAVER Cloud는 없다…
그럼 굳이 왜 AWS를 선택하지 않았냐고 할 수 있는데 내가 직접 설정해서 구축하고 싶었기 때문이다. (사서 고생한다는 얘기)
Travis가 아닌 Jenkins 선택
Travis reference만 보아도 AWS랑 얼마나 죽이 잘 맞는지를 알 수 있다. (AWS말고도 Google Cloud, Azure도 지원한다.) 이미 NAVER Cloud를 선택한 이상 Travis는 더 어려운 방법으로 가는 길이라 생각했다. 오히려 설정할 수 있는 범위가 넓은 Jenkins를 택하는 것이 쉽다고 판단하였다. 처음에 AWS와 Travis로 자동화 배포 환경 구축을 연습했었는데, 개인적인 입장으로는 Jenkins가 좀 더 쉬운 것 같다.
40만 크레딧의 위엄으로 Jenkins를 도커가 아닌 Naver Cloud로 서버를 따로 구축했다. 지금 생각해보면 자원 낭비인 셈이지만 안정성 측면에서는 따로 서버를 두는 것이 좋다.
환경 구축하기
NAVER Cloud 사용 설명서는 무척 잘 되어 있고 AWS의 EC2나 S3와 같은 개념과 똑같기에 같은 방식으로 설정하면 된다.
- NAVER Cloud의 Server = AWS의 EC2
- NAVER Cloud의 Object Storage = AWS의 S3
아래와 같이 SourcePipeline 서비스를 이용하면 Github에서 push한 것을 자동으로 빌드하고 배포할 수 있는데, 아래 사진 우측 상단에 보이는 파이프라인 실행하기를 매번 클릭해줘야 한다…내가 원한건 push만 해도 자동화 빌드 및 배포이다. 결국 이걸 접고 Jenkins와 NAVER Cloud의 Server만 사용하기로 결정했다.
1. Jenkins 설정하기
Docker로 Jenkins 서버를 운영해도 되지만 NAVER Cloud에서 다음과 같이 지원하기에 사용하였다.
다만 수동으로 최신 업데이트 하는 것을 권장한다.
1-1. Jenkins 보안 설정
Jenkins는 기본적으로 보안 설정이 되어있지 않다.
Jenkins 관리 > Configure Global Security에서 설정할 수 있다.
- 처음에 사용자의 가입을 허용하여 admin 계정을 생성한다. 팀원과 함께 작업한다면 팀원 각각 계정 생성하도록 둔다.
- 계정 생성을 끝냈으면 ‘Matrix-based security’를 적절히 설정한다. (없다면 Matrix Authorization Strategy Plugin를 설치하자.)
필자는 익명에게 읽기 권한 중 Job(Jenkins 작업 단위) 부분만 볼 수 있게 하였다. 이는 나중에 설정할 Github의 build status를 보여주기 위함이다.
그리고 혼자 환경 구축을 담당 하였기에 팀원 계정 역시 익명과 같은 권한을 주었다.
1-2. 플러그인 설치하기
Jenkins 관리 > 플러그인 관리
- Github plugin: Jenkins와 Github 통합
- Global Slack Notifier Plugin: Slack 연동(Job 알림 설정)
- Publish Over SSH: ssh로 빌드 파일 보내기
- Embeddable Build Status Plugin: Github 레포지토리에 빌드 상태바 생성
- Managed Scripts: Node.js 기반의 서버를 배포하기 위한 스크립트
1-3. Jenkins Global 설정하기
Jenkins 관리 > 시스템 설정 > GitHub Servers에서 다음과 같이 설정한다.
Credentials 설정을 위해 자신의 Github > Settings > Developer settings > Personal access tokens에서 다음과 같이 토큰을 생성한다.
생성 후 화면에 보이는 secret 문자열을 아래의 Secret에 입력한다.
1-4. 프로젝트 생성 및 설정하기
새로운 Item을 클릭하고 프로젝트 이름을 입력, Freestyle을 누른다.
- 다음과 같이 프로젝트 url을 입력하고 Credentials를 설정한다.
이 작업은 Github을 연동하는 것인데, ID와 PW로 연동하면 보안에 취약하기에 ssh키로 연동하였다.
ssh 키 생성하기
- ssh로 Jenkins 서버에 원격 접속하여 다음을 입력한다.
1
ssh-keygen -t rsa -f id_rsa
id_rsa
, id_rsa.pub
를 포함해 총 4개의 키가 생성된다.
- 아래 Add 표시를 눌러
cat ~/.ssh/id_rsa
입력 후 나오는 private key를 넣어준다
BEGIN ~부터 모두 복사하여 입력한다.
- Github에 공개 키 등록하기.
cat ~/.ssh/id_rsa.pub
를 입력하면 나오는 공개 키를 프로젝트 레포지토리의 Setting > Deploy keys에 등록한다.
이제 Jenkins과 Github을 연동시켰기에, Jenkins에 코드를 가져올 수 있게 되었다.
- 다음으로는 push했을 때 Jenkins가 push 이벤트를 받을 수 있도록 설정 해보자.
마찬가지로 레포지토리의 setting > webhooks 에서 빨간색 네모박스에 Jenkins ip 주소를 입력하고 나머지는 그대로 입력한다.
- Github에서의 설정은 끝났고 Jenkins 프로젝트에서 다음을 체크함으로써 이벤트 설정은 끝이 났다.
이젠 push만 하면 Jenkins 해당 프로젝트에서 빌드가 시작됨을 볼 수 있다.
빌드 기록을 통해 소스 코드가 빌드 중인지 빌드 완료 되었는지를 확인할 수 있다.
이것으로 Jenkins로 CI 환경 구축은 끝이 났다. 2편에서는 CD 환경 구축과 무중단 배포를 구축해보겠다.