본 글은 NHN Injeinc 공식 기술 블로그에 기고 된 글입니다.
안녕하세요. 저는 NHN Injeinc의 DevOps Tech팀에서 SRE/DevOps Engineer로 근무중인 라모스라고 합니다.
이전까진, 기술지원팀에서 Backend Developer로 줄곧 NHN Cloud 전사 기술지원업무를 담당하여 다양한 프로젝트에서 서버 개발을 담당했습니다. 이를 통해 NHN 전사 개발 환경의 노하우와 기술 표준 준수의 중요성을 몸소 체감할 수 있었습니다.
오늘은 제가 그동안 백엔드 리드 및 개발을 담당했고 곧 출시를 앞둔 Veritas Backup(BaaS) 상품의 CI/CD Pipeline 구축 과정에서 겪은 시행착오와, 이를 극복하며 마련한 NHN 전사 표준 가이드를 공유하고자 합니다.
저희 서비스의 배포 환경은 전사 표준으로 사용되는 Ubuntu Server를 기준으로 설명합니다.
CI/CD란?
CI/CD는 "지속적 통합(Continuous Integration)"과 "지속적 전달(Continuous Delivery)" 또는 "지속적 배포(Continuous Deployment)"의 약자로, 소프트웨어 개발 프로세스를 자동화하여 개발 속도와 품질을 향상시키는 방법론입니다.
- 지속적 통합(CI):
개발자들이 작성한 코드를 자주(일반적으로 하루에 여러 번) 중앙 저장소에 통합합니다. 통합 시 자동화된 빌드와 테스트를 통해 코드 변경에 따른 오류나 충돌을 조기에 발견하고 해결할 수 있어, 문제를 신속하게 대응할 수 있습니다. - 지속적 전달/배포(CD):
CI를 통해 통합된 코드를 자동으로 빌드, 테스트, 그리고 실제 운영 환경 또는 스테이징 환경에 배포하는 과정을 의미합니다. 지속적 전달은 수동 승인 후 배포하는 방식을, 지속적 배포는 모든 변경 사항이 자동으로 운영 환경에 배포되는 방식을 말합니다. 이를 통해 사용자는 최신 기능이나 개선 사항을 빠르게 이용할 수 있습니다.
결과적으로, CI/CD는 개발 주기를 단축하고, 버그를 조기에 발견하며, 배포 과정을 자동화하여 소프트웨어의 신뢰성과 품질을 높이는 데 큰 역할을 합니다.
Veritas Backup 서비스의 CI/CD Pipeline 구조
상품 개발 초기엔 인프라 구성을 전달받지 못해 배포환경을 구축에 제약이 많았던 상황이었지만, 저희 프론트엔드 개발팀을 위한 서비스 API들을 제공하기 위해 NHN Cloud의 Public 환경에서 구성한 임시 서버에 배포할 수 밖에 없었습니다.
게다가 이 방식은 NHN 전사 Github Enterprise 서버와 직접적으로 접근할 수 없는 구조이기 때문에 Jenkins를 연동할 수도 없었습니다. 그렇기에 임시적으로 로컬에서 빌드를 수행하고 임시 서버에 직접 접속하여 배포를 수동으로 수행하는 방식을 채택할 수 밖에 없었습니다.
배포 담당자나 서버 개발자가 매번 서버에 직접 접속하여 스크립트를 수동으로 실행하는 방식으로 CI/CD를 수행한다면, 이 방식은 다음과 같은 문제점을 야기하게 됩니다.
- 작업 효율 저하: 수동 작업에 의존하면 배포 속도가 늦어지고 인적 오류가 발생하기 쉽습니다.
- 관리 복잡성 증가: 여러 서버에 개별로 접속해 작업하다 보면, 배포 이력 관리 및 문제 추적이 어려워집니다.
이러한 문제점을 해결하기 위해 전사 공통 인프라 환경을 제공받고나선 그 즉시 CI/CD Pipeline을 도입하였고, Jenkins를 통한 빌드 환경과 NHN Cloud Deploy를 연동하여 보다 자동화된 배포 체계를 마련하게 되었습니다.
먼저, NHN 전사에서는 보안을 고려해 서버 접속 시 Gateway 서버를 통해 원하는 서버(Ubuntu)에 접근하는 구조를 채택하고 있습니다.
이런 인프라 환경 속에서 Veritas Backup 서비스의 CI/CD Pipeline을 설계할 때, 제가 가장 중요하게 생각했던 것은 다음과 같습니다.
- 모든 과정에 대한 자동화 처리를 수행하자.
- Build 및 Deploy 스펙을 코드로서 관리하자.
- 배포 담당자가 직접 서버에 들어가야하는 불편함을 줄이자.
이렇다보니, Gateway 서버를 거쳐 서버에 직접 접근하는 방식을 해소하고자 NHN Cloud에서 제공하는 Deploy 서비스를 사용하였습니다.
그 결과 최종적인 CI/CD Pipeline은 다음과 같습니다.
NHN Cloud Deploy 서비스
Deploy 서비스를 사용하면 '원 클릭'으로 쉽고 빠르게 애플리케이션을 배포할 수 있습니다.
- 바이너리 파일을 쉽고 편리하게 관리
- 배포 단계별 실시간 모니터링
- 배포 결과 메일 알림
- 배포 전후 시나리오 설정
무엇보다, 전사 환경에서 제공받은 나의 서버그룹을 편리하게 지정하여 배포 시나리오를 구성할 수 있기 때문에 Gateway 서버에 직접 접근하는 일이 줄어들었습니다.
아티팩트 설정
먼저 아티팩트를 아래와 같이 설정합니다. 알림을 사용하면 Dooray Messenger에 Hook을 연동할 수 있어 배포 알림을 손쉽게 처리할 수 있습니다.
여기서 hook url은 Dooray Messenger의 Incoming 서비스를 생성하면 발급해주는 연동 URL을 기입합니다.
서버 그룹 설정
부서 서버 그룹을 선택하면, NHN 인프라 담당자로부터 제공받은 서버 그룹 중 배포 대상 서버를 지정하여 관리할 수 있으며, 후술할 바이너리 그룹과 연계하여 CI/CD 파이프라인을 구성할 수 있습니다. NHN Cloud 전사 IAM Console에선 제가 제공받은 서버 그룹을 간단하게 지정할 수 있었습니다.
바이너리 그룹 설정
바이너리 그룹을 설정하여 build.spec
파일에 정의하면 해당 CI/CD Job에서 빌드 산출물을 이곳으로 업로드하게 됩니다. 이 후 앞서 설정했던 서버 그룹과 연계하여 산출물을 배포 대상 서버에 전달하고 deploy.spec
파일에 명시했던 스크립트를 수행합니다.
결과적으로, Jenkins에선 빌드 및 아티팩트 업로드만 수행하고 NHN Cloud Deploy에서 해당 아티팩트를 배포 대상 서버 그룹에 전달하여 후행 스크립트를 실행하여 배포하게 됩니다.
전사 Jenkins와 NHN Cloud Deploy 서비스와 연동하기 위한 IaC와 Jenkinsfile
Veritas Backup 서비스는 Git-Flow 브랜치 전략을 기반으로 형상관리를 수행하고 있어 이에 따른 환경별 배포 전략을 구성해야 합니다.
위 전략은 다음과 같이 요약할 수 있습니다.
이를 수행하기 위해, Jenkins 상에선 Multibranch Pipeline을 기반으로 Branch 및 Tag 기반 Job을 구성하였습니다.
Jenkinsfile 구성
Jenkinsfile_{profile-name}
: Beta / Real 환경으로 구분하여 각 build, deploy spec 파일로 묶은 파이프라인 스크립트buildDeploy
: NHN Cloud 전사에서 제공되는 Deploy 서비스와 연동되는 표준 스크립트 템플릿에 해당availableServerGroups
: 배포 대상 서버그룹의 이름buildSpec
: Jenkins에서 수행할 빌드 작업의 스펙과 command를 묶은 IaCdeploySpec
: 빌드 후 산출물을 토대로 배포 대상 서버그룹 내에서 수행하기 위한 command를 묶은 IaC
buildDeploy([availableServerGroups: ["VeritasBackup-Beta-Console"],
buildSpec: ".jenkins/profiles/console/beta/build.spec",
deploySpec: ".jenkins/profiles/console/beta/deploy.spec",
skipConfirm: true
])
build.spec
NHN의 Jenkins 환경에선 크게 다음과 같은 빌드 환경이 제공되고 있습니다.
이 외의 빌드 환경 혹은 지원되지 않는 최신 환경의 경우 Docker 기반으로 빌드를 수행하는 것을 권장합니다.
공통적으론 Jenkins내에서 제공되는 환경을 기반으로 빌드 후 빌드 산출물을 NHN Cloud 전사 IAM Console 내 Deploy 서비스에 업로드 하는 시나리오로 수행해야 CI/CD가 가능합니다.
참고로, 일반적인 Jenkins script를 토대로 각 Step을 구성하여 빌드/배포도 가능하지만, 배포 대상 서버그룹에 자동 연결 및 Deploy를 수행하기 위해선 IaC로 관리되는 .spec
파일을 기반으로 pipeline script를 작성해야 합니다.
그렇기에 저희 Veritas Backup 서비스의 Jenkins Pipeline 구성도 .spec
파일을 기반으로 구성하였습니다. 일반적인 빌드와 Docker 환경을 통한 빌드 모두 사용했기에 케이스별로 설명하겠습니다.
- 📌 참고 : NHN Cloud 전사 IAM Console : 일반 사용자들을 대상으로 하는 NHN Cloud Console과 다르게 사내 SSO 인증으로 권한이 부여된 담당자들만 접근할 수 있는 NHN 내부용 Cloud Console에 해당합니다.
일반적인 빌드 spec을 사용하는 경우
buildEnv
엔 제공되는 빌드 환경을 옵션으로 입력.command
절은 해당 빌드도구로 수행할 명령어 입력.packageDirs
은 바이너리로 압축할 빌드 산출물 및 추가 스크립트 경로를 입력.upload
절은 NHN Cloud Deploy 서비스의 아티팩트 ID, appkey, 바이너리 그룹 정보를 입력하여 연동합니다.
build.spec
예시는 아래와 같습니다.
version: 0.1
parameters:
BUILD_PROFILE: beta
BRANCH_NAME: alpha
buildEnv:
gradle: Gradle 8.4
jdk: adoptjdk17
command: clean build -x test -Pprofile=${BUILD_PROFILE}
packageDirs:
- build/libs
- .jenkins/scripts
upload:
artifactId: 1234
appkey: 123458l4Vww6tUE
binaryGroupKey: 5678
binaryGroupName: Default
Docker를 사용하는 경우
Docker Hub Image를 이용한 Docker Build를 사용하는 경우
docker
옵션을 사용하고 해당 부분에 사용할IMAGE:TAG
를 입력.command
절은 컨테이너 내부에서 실행할 Build Command 전체를 입력.
build.spec
예시는 아래와 같습니다. 여기서 중요한 점은, Docker의 이미지와 태그를 기반으로 컨테이너 환경이 설정되어 Jenkins가 실행하는 구조이기 때문에 반드시 표준 가이드에 따라야 합니다.
version: 0.1
buildEnv:
docker: node:21.1.0
command: |
npm config set prefix "$HOME/.npm-global"
export PATH="$HOME/.npm-global/bin:$PATH"
npm install -g pnpm@8.15.6 --unsafe-perm
pnpm add -D cross-env -w
rm -rf apps/user/dist && rm -rf apps/user/node_modules/ && \
pnpm i --frozen-lockfile && \
pnpm run user:build:beta
packageDirs:
- apps/user/dist
upload:
artifactId: 1234
appkey: 123458l4Vww6tUE
binaryGroupKey: 5678
binaryGroupName: Default
Dockerfile을 이용한 Docker Build를 사용하는 경우
dockerfile
옵션을 사용하고 해당 부분에 Dockerfile 의 절대경로를 입력.command
절은 컨테이너 내부에서 실행할 Build Command 전체를 입력.
build.spec
예시는 아래와 같습니다.
buildEnv:
dockerfile: docker/Dockerfile
command: mvn -f ./custom_pom.xml clean package -Dmaven.test.skip=true
packageDirs: - target - deploy_res
upload:
artifactId: 1234
appkey: 123458l4Vww6tUE
binaryGroupKey: 5678
binaryGroupName: Default
deploy.spec 정의 예시
deploy 스펙에서 명시할 task type은 크게 두 가지가 있습니다.
command
: Ubuntu 서버 내에서 배포 시 실행되는 사용자 정의 명령어를 입력.binary
: 업로드한 바이너리 파일의 배포 내용을 설정. Deploy 서비스 내 zip으로 압축되어 업로드된 빌드 산출물을 기반으로 Ubuntu 서버 내에서 후행 작업을 수행합니다.
deploy.spec
예시는 아래와 같습니다.
version: 0.1
tasks:
- type: command
name: Prepare
command: |
rm -rf /home1/irteam/deploy/console/artifacts
mkdir -p /home1/irteam/deploy/console/artifacts
user: irteam
- type: binary
name: Config Upload
user: irteam
targetDir: /home1/irteam/deploy/console/artifacts
- type: command
name: Unzip and Copy
command: |
cd /home1/irteam/deploy/console/artifacts
unzip -o app.zip
user: irteam
- type: command
name: console.sh copy
user: irteam
command: |
cp -f /home1/irteam/deploy/console/artifacts/.jenkins/scripts/console.sh /home1/irteam/scripts
- type: command
name: Start Server
command: |
export HOSTNAME=${HOSTNAME}
cd /home1/irteam/scripts
chmod 755 console.sh
sh ./console.sh
user: irteam
- type: command
name: After Check Status
command: |
echo "after check status"
user: irteam
마지막으로 요약하자면, IaC(Infra as Code) 방식으로 관리되는 .spec
파일을 통해, 배포 대상 서버그룹에 자동 연결하고 Deploy를 수행합니다. 배포 과정은 준비 작업, 바이너리 파일 업로드, 압축 해제 및 파일 복사, 스크립트 실행 등 여러 단계를 포함하며, 각 단계별로 실행할 커맨드와 사용자 설정을 상세히 정의할 수 있습니다.
.spec
파일을 기반으로 한 파이프라인 구성은 빌드와 배포 과정의 일관성 및 자동화를 보장하며, 다양한 빌드 환경(기본 제공 환경, Docker 이미지, Dockerfile)에 유연하게 대응할 수 있습니다. 이를 통해 NHN Cloud 전사 IAM Console 내 Deploy 서비스를 활용, 빌드 산출물을 손쉽게 관리하고 배포할 수 있어, Veritas Backup 서비스를 비롯한 다양한 서비스에서 효율적인 CI/CD 프로세스를 구현할 수 있습니다.
결과적으로 Jenkins Pipeline에서 .spec
파일을 중심으로 빌드와 배포를 구성하면, 환경에 구애받지 않고 안정적이고 자동화된 CI/CD 시스템을 구축할 수 있습니다.
끝으로,
NHN 전사에서는 개발부터 빌드, 배포까지의 전 과정을 자동화할 수있는 환경을 제공하여, 이를 토대로 저희 서비스 개발팀은 개발 생산성을 크게 향상시켰습니다. Jenkins와 NHN Cloud Deploy의 연동을 통해 불필요한 수동 작업을 줄이고, 안정적이고 일관된 배포 환경을 구축할 수 있었던 점은 매우 큰 성과라 할 수 있습니다.
앞으로도 지속적인 개선과 표준 가이드의 공유를 통해, 더 나은 DevOps 환경을 구축해 나갈 예정입니다.
Veritas Backup 서비스에서 수행했던 저의 CI/CD Pipeline 구축 경험이 여러분의 환경에서도 유용하게 활용되기를 바랍니다.
References
'Infra > Jenkins' 카테고리의 다른 글
Jenkins Server 초기 설정 및 설치 (1) | 2025.01.13 |
---|