0. 개요
- Jenkins CI/CD 파이프라인 구축 방법
- 아키텍처 개요와 설치 선택지
- 2-1. 컨트롤러/에이전트, Docker vs Kubernetes
- 2-2. 플러그인·크리덴셜·RBAC 기본
- 소스 관리와 트리거
- 3-1. 멀티브랜치 파이프라인
- 3-2. GitHub/GitLab Webhook 연동
- Jenkinsfile 설계(Declarative 중심)
- 4-1. stages/steps/when/agent
- 4-2. 캐싱·병렬·매트릭스 빌드
- 빌드·테스트·품질 게이트
- 5-1. Node/Java 예시
- 5-2. JUnit·SonarQube·SAST
- 이미지 빌드·아티팩트 관리
- 6-1. Docker/BuildKit/Kaniko
- 6-2. 태깅 규칙·레지스트리 푸시
- 배포 자동화
- 7-1. Kubernetes(Helm/Kustomize)
- 7-2. VM/서버(Ansible/Systemd)
- 7-3. Blue/Green·Canary·롤백
- 프로모션·승인·보안
- 8-1. 입력 승인 단계
- 8-2. 시크릿·권한·감사
- 관측성·알림·운영
- 9-1. 로그·리포트·Slack
- 9-2. 리소스 최적화·백업
- 레퍼런스 Jenkinsfile
- 10-1. 단일 서비스(REST)
- 10-2. 매트릭스(노드 버전)
- 트러블슈팅
- Webhook 미동작, 권한, 워크스페이스
- 체크리스트 & 운영 플레이북
- 결론 요약
- FAQ
1. Jenkins CI/CD 파이프라인 구축 방법
이 글은 팀 규모와 배포 환경(온프레미스·클라우드·Kubernetes)에 상관없이 재사용 가능한 Jenkins 표준 파이프라인 설계법을 안내합니다. 설치 아키텍처부터 멀티브랜치·Webhook 트리거, Jenkinsfile 작성, 테스트/품질 게이트, 컨테이너 이미지 빌드, 배포/롤백, 승인·보안, 관측성까지 실전 중심으로 정리했습니다.
2. 아키텍처 개요와 설치 선택지
2-1. 컨트롤러/에이전트, Docker vs Kubernetes
- 컨트롤러(마스터): UI·큐·크리덴셜·잡 메타를 관리합니다. 빌드는 에이전트에서 수행해 분리합니다.
- Docker 설치: 단일 호스트에 빠르게 구축.
jenkins/jenkins:lts컨테이너 + 호스트의 Docker 소켓 마운트로 이미지 빌드 가능(보안 주의). - Kubernetes 설치: Kubernetes Plugin으로 에이전트 Pod를 요청 시점에 생성·파괴(탄력적). 컨트롤러는 StatefulSet, 영속 볼륨으로 운영합니다.
2-2. 플러그인·크리덴셜·RBAC 기본
- 필수 플러그인 예: Pipeline, Git, Blue Ocean(선택), Credentials, Kubernetes, Docker, GitHub/GitLab, JUnit, Warnings NG, Slack, SonarQube(선택).
- Credentials: Username/Password, SSH Key, Secret Text, Secret File 유형을 폴더 단위로 관리하고, 잡에서는
credentialsId만 사용합니다. - RBAC: 폴더/잡 단위 권한을 최소화합니다. 민감한 작업(크리덴셜/시스템 설정)은 관리자 전용으로 분리하세요.
3. 소스 관리와 트리거
3-1. 멀티브랜치 파이프라인
- 리포지토리 각 브랜치/PR에 있는 Jenkinsfile을 자동 탐지·빌드합니다. 브랜치 수명주기를 Jenkins가 추적하므로 운영이 단순합니다.
- 브랜치 전략:
main(배포),develop(통합),feature/*를 권장. 태그(semver)는 릴리스 파이프라인을 트리거하도록 규칙화합니다.
3-2. GitHub/GitLab Webhook 연동
- GitHub: Repository → Webhooks에 Jenkins 엔드포인트(예:
/github-webhook/) 등록. 토큰/SSL를 설정해 무결성을 보장합니다. - GitLab: Push events/Merge Request events를 Jenkins의 GitLab Plugin과 연계합니다.
- Webhook 이벤트가 없다면 폴링이 필요해 빌드 지연·낭비가 발생하니, 가능하면 Webhook을 표준으로 채택합니다.
4. Jenkinsfile 설계(Declarative 중심)
4-1. stages/steps/when/agent
- Declarative Pipeline은 표준화·가독성에 유리합니다.
agent로 실행 환경(노드 라벨, Docker 이미지, K8s Pod 템플릿)을 정의합니다. - when 조건으로 브랜치/변수/태그에 따라 빌드 흐름을 분기합니다. 예: 태그일 때만 배포.
- post 블록에서 항상/성공/실패/불안정 상황별 알림과 아티팩트 보존을 정의합니다.
4-2. 캐싱·병렬·매트릭스 빌드
- 언어(예: Maven/NPM)의 캐시 디렉터리를 호스트 마운트 또는 Pod emptyDir에 연결해 속도를 높입니다.
- parallel로 유닛/리눅스·윈도우·다중 런타임 테스트를 병렬화합니다.
- matrix로 Node 18/20, JDK 17/21 등 조합을 한번에 검증합니다.
5. 빌드·테스트·품질 게이트
5-1. Node/Java 예시
- Node:
npm ci로 깨끗한 설치,npm test·커버리지 출력,npm run build로 번들 생성. - Java:
mvn -B -DskipTests=false test package, Surefire 리포트와 JaCoCo 커버리지 게시.
5-2. JUnit·SonarQube·SAST
- JUnit:
junit '**/target/surefire-reports/*.xml'등으로 테스트 결과를 수집, 트렌드와 실패 내역을 대시보드에서 확인합니다. - SonarQube: 분석 토큰을 크리덴셜로 저장하고 품질 게이트 상태에 따라 파이프라인을 중단해 코드 품질을 강제합니다.
- SAST: 상용/오픈소스 도구 실행 후 취약점 임계치 기준으로 실패 처리(예: High 0개 미만 통과).
6. 이미지 빌드·아티팩트 관리
6-1. Docker/BuildKit/Kaniko
- Docker-in-Docker(DinD): 간편하지만 권한 이슈가 큽니다. 빌드 전용 노드/Pod로 격리하세요.
- BuildKit:
DOCKER_BUILDKIT=1로 캐시·속도·보안 강화.--secret로 민감 정보 주입. - Kaniko(K8s): Docker 데몬 없이 컨테이너 이미지 빌드. Jenkins K8s 에이전트와 궁합이 좋습니다.
6-2. 태깅 규칙·레지스트리 푸시
- 태그 전략:
app:1.4.2,app:1.4,app:latest,app:git-<shortSHA>를 함께 푸시하면 추적·롤백에 유리합니다. - 레지스트리: ECR/GCR/Docker Hub/Harbor 등. 크리덴셜은 Jenkins에 저장 후
withCredentials블록으로 사용합니다.
7. 배포 자동화
7-1. Kubernetes(Helm/Kustomize)
- 릴리스 네임·네임스페이스·값 파일을 스테이지별(dev/stg/prod)로 분리하고,
helm upgrade --install로 선언형 배포를 수행합니다. - 프로브(라이브네스/레디니스), 리소스 요청/제한, HPA를 차트 값으로 표준화합니다.
7-2. VM/서버(Ansible/Systemd)
- 아티팩트를 배포 서버로 전송 →
systemd서비스 재시작 → 헬스체크. 무중단이 필요하면 Nginx 업스트림 스위치 또는 Blue/Green을 적용합니다.
7-3. Blue/Green·Canary·롤백
- Blue/Green: 두 환경을 병행 구성하고 트래픽 스위치 후 검증. 실패 시 즉시 롤백.
- Canary: 10%→30%→100%와 같이 점진 전개. Jenkins에서 단계별 승인·자동화 테스트를 끼워 넣습니다.
- 롤백: 이전 이미지 태그·Helm 리비전·이전 아티팩트를 메타데이터로 기록해 원클릭 롤백을 준비하세요.
8. 프로모션·승인·보안
8-1. 입력 승인 단계
- 프로덕션 배포 전
input스텝으로 휴먼 게이트를 두고, 승인자 그룹을 RBAC로 제한합니다.
8-2. 시크릿·권한·감사
- 시크릿은 Credentials·클라우드 시크릿 매니저로 관리하고, 파이프라인에는 환경 변수로만 주입합니다.
- 컨트롤러는 인터넷 노출을 피하고 리버스 프록시/SSL/TLS를 강제합니다. 감사 로그를 외부 스토리지로 보관하세요.
9. 관측성·알림·운영
9-1. 로그·리포트·Slack
- JUnit/코버리지/정적분석 리포트를 게시하고, 실패 시 Slack/Email로 즉시 알립니다.
- 배포 후 헬스체크 API·e2e 스모크 테스트를 자동 실행해 배포 검증을 표준화합니다.
9-2. 리소스 최적화·백업
- 에이전트는 에페메럴이 기본. 오래된 워크스페이스/아티팩트는 만료 정책으로 정리합니다.
- 컨트롤러 구성/잡 정의/크리덴셜을 정기 백업하고, 복구 연습을 분기마다 수행합니다.
10. 레퍼런스 Jenkinsfile
10-1. 단일 서비스(REST) Declarative 파이프라인
pipeline { agent { label 'docker' } environment { REGISTRY = 'registry.example.com' IMAGE = "${REGISTRY}/app" COMMIT = sh(returnStdout: true, script: 'git rev-parse --short HEAD').trim() } options { timestamps() buildDiscarder(logRotator(numToKeepStr: '50')) disableConcurrentBuilds() } triggers { pollSCM('@daily') } // Webhook이 기본, 폴백으로 폴링 stages { stage('Checkout') { steps { checkout scm } } stage('Setup Node') { agent { docker { image 'node:20-alpine' } } steps { sh 'npm ci' sh 'npm run lint' } } stage('Test (parallel)') { parallel { stage('Unit') { steps { sh 'npm test -- --ci --reporters=junit' } } stage('E2E (smoke)') { steps { sh './scripts/e2e-smoke.sh' } } } post { always { junit 'reports/junit/**/*.xml' } } } stage('Build Image') { when { branch 'main' } steps { sh 'export DOCKER_BUILDKIT=1; docker build -t $IMAGE:git-$COMMIT -t $IMAGE:latest .' } } stage('Security Gate') { when { branch 'main' } steps { sh './scripts/sast.sh --fail-on-high' } } stage('Push Image') { when { branch 'main' } steps { withCredentials([usernamePassword(credentialsId: 'REGISTRY_CREDS', usernameVariable: 'U', passwordVariable: 'P')]) { sh 'echo $P | docker login $REGISTRY -u $U --password-stdin' } sh 'docker push $IMAGE:git-$COMMIT && docker push $IMAGE:latest' } } stage('Deploy to Staging') { when { branch 'main' } steps { sh 'helm upgrade --install app charts/app -n staging --set image.tag=git-$COMMIT' } } stage('Approval for Prod') { when { branch 'main' } steps { input message: '프로덕션 배포 승인?', ok: '배포' } } stage('Deploy to Prod') { when { branch 'main' } steps { sh 'helm upgrade --install app charts/app -n prod --set image.tag=git-$COMMIT' } } } post { success { slackSend channel: '#ci', message: "✅ ${env.JOB_NAME} #${env.BUILD_NUMBER} 성공" } failure { slackSend channel: '#ci', message: "❌ ${env.JOB_NAME} #${env.BUILD_NUMBER} 실패" } } }
10-2. 매트릭스 빌드(노드 18/20)
pipeline { agent none stages { stage('Matrix Test') { matrix { axes { axis { name 'NODE_VERSION'; values '18', '20' } axis { name 'OS'; values 'alpine', 'slim' } } agent { docker { image "node:${NODE_VERSION}-${OS}" } } stages { stage('Install & Test') { steps { sh 'node -v && npm ci && npm test' } } } } } } }
11. 트러블슈팅
- Webhook가 동작하지 않음: 방화벽/리버스 프록시 경로, GitHub Secret 검증, Jenkins 로그(
/github-webhook/) 확인. - 권한 오류: 크리덴셜 스코프(시스템/도메인) 확인, 폴더 상속 권한 충돌 점검.
- 워크스페이스 충돌:
disableConcurrentBuilds()사용, 브랜치별 별도 워크스페이스 지정. - Docker 권한: 소켓 마운트 시 루트 권한 이슈 → 전용 빌드 노드 또는 Kaniko로 대체.
- K8s 에이전트 실패: Pod 템플릿 이미지 풀 권한, 네임스페이스/리소스 쿼터,
serviceAccount권한 확인.
12. 체크리스트 & 운영 플레이북
- 아키텍처: 컨트롤러 고가용성(백업/복구), 에이전트는 에페메럴, 플러그인 버전 고정.
- 보안: HTTPS 강제, RBAC 최소 권한, 시크릿은 Credentials/SM, 감사 로그 외부 보관.
- 품질: JUnit/커버리지/정적분석 필수, 품질 게이트 실패 시 배포 차단.
- 배포: 태그 기반 릴리스, Helm/Kustomize 선언형, 롤백 스크립트 상시 준비.
- 속도: 캐시(의존성/도커 레이어), 병렬/매트릭스, 무거운 단계는 전용 에이전트.
- 가시성: Slack/이메일 알림, 대시보드(성공률/리드타임/주기 시간), 포스트 배포 스모크 테스트.
13. 결론 요약
Jenkins 파이프라인의 핵심은 표준화입니다. 멀티브랜치 + Declarative Jenkinsfile + 품질 게이트 + 컨테이너 이미지 빌드 + 선언형 배포(Helm) + 승인/롤백 규칙을 일관되게 적용하면, 팀 규모가 커져도 안정적으로 확장됩니다. 설치 환경은 Docker로 시작해 Kubernetes 에이전트로 확장하고, 시크릿/권한/감사와 같은 운영 가드레일까지 함께 자동화할 때 CI/CD는 비로소 개발 생산성 가속기가 됩니다.
14. FAQ
Q1. Jenkins와 GitOps(Argo CD 등)를 같이 써도 될까요?
A1. 네. Jenkins는 빌드/테스트/이미지 푸시에 집중하고, 배포는 Git 리포지토리의 선언적 매니페스트(Helm/Kustomize)를 업데이트해 Argo CD가 싱크하도록 분리하면 책임이 명확해집니다.
Q2. 파이프라인이 느립니다. 어디부터 최적화할까요?
A2. 의존성 캐시(예: ~/.m2, ~/.npm), Docker 레이어 캐시/BuildKit, 병렬 테스트, 매트릭스 축소, 에이전트 스펙 조정 순서로 진행하세요. 병목은 스테이지별 시간 분포로 파악합니다.
Q3. 보안상 Docker 소켓 마운트가 불가합니다. 대안은?
A3. Kubernetes 환경이면 Kaniko/Buildah를, VM 환경이면 Rootless BuildKit을 고려하세요. 레지스트리 크리덴셜은 Jenkins Credentials로 주입합니다.
'Backend > Study' 카테고리의 다른 글
| [DevOps] Kubernetes 초보자 가이드 (백엔드 개발자를 위한 입문) (0) | 2025.10.30 |
|---|---|
| [DevOps] GitLab CI/CD vs GitHub Actions 비교 (0) | 2025.10.29 |
| [DevOps] AWS Lambda로 서버리스 백앤드 구축하기 (0) | 2025.10.27 |
| [DevOps] AWS S3 + CloudFront 이미지 업로드 & 캐싱 전략 (0) | 2025.10.22 |
| [DevOps] AWS EC2와 RDS 연결 설정 가이드 (0) | 2025.10.21 |