CI/CD 파이프라인을 구축하기 위한 오픈소스 자동화 서버 Jenkins에 대해 알아봅니다.
Jenkins는 오픈소스 자동화 서버로, 소프트웨어 개발 프로세스의 빌드, 테스트, 배포를 자동화하는 도구입니다.
Continuous Integration (CI)
개발자가 코드를 자주 통합하고, 각 통합마다 자동화된 빌드와 테스트를 실행하여 문제를 조기에 발견하고 해결하는 방식
┌─────────────────────────────────┐
│ Jenkins Controller │
│ - Web UI │
│ - Job 관리 │
│ - 스케줄링 │
└────────────┬────────────────────┘
│
┌────────┴────────┐
│ │
┌───▼────┐ ┌────▼───┐
│ Agent │ │ Agent │
│ (VM) │ │ (VM) │
└────────┘ └────────┘
┌─────────────────────────────────────────┐
│ Jenkins Controller │
│ (Kubernetes Pod) │
│ - Web UI │
│ - Job 관리 │
│ - Kubernetes Plugin │
└────────────┬────────────────────────────┘
│
┌────────┴─────────────┐
│ Kubernetes Cluster │
│ │
┌───▼─────┐ ┌─────────┐ ┌─────────┐
│ Agent │ │ Agent │ │ Agent │
│ Pod 1 │ │ Pod 2 │ │ Pod 3 │
│ (생성) │ │ (실행) │ │ (종료) │
└─────────┘ └─────────┘ └─────────┘
▲ ▲ ▲
│ │ │
필요시 생성 빌드 실행 완료 후 삭제
Jenkins는 GitOps 워크플로우에서 CI (Continuous Integration) 역할을 담당합니다:
┌──────────────────────────────────────────────────────────┐
│ GitOps Workflow │
└──────────────────────────────────────────────────────────┘
1. Developer
└─> Git Push (코드 변경)
2. Jenkins (CI) ← 우리가 다룰 영역
├─> 자동 빌드 트리거
├─> 테스트 실행
├─> Docker 이미지 빌드
├─> Container Registry에 푸시
└─> Manifest Repository 업데이트 (이미지 태그)
3. ArgoCD (CD)
├─> Manifest 변경 감지
├─> Kubernetes와 비교
└─> 자동 배포
4. Kubernetes Cluster
└─> 새 버전 Pod 실행
✅ 소스 코드 체크아웃
✅ 의존성 설치
✅ 단위 테스트 실행
✅ 코드 품질 검사
✅ 컨테이너 이미지 빌드
✅ 이미지 레지스트리에 푸시
✅ Manifest Repository 업데이트
✅ Manifest 변경 감지
✅ 클러스터와 상태 비교
✅ Kubernetes에 배포
✅ Health 체크
✅ 자동 롤백 (문제 발생 시)
Jenkinsfile 예시:
pipeline {
agent {
kubernetes {
yaml '''
apiVersion: v1
kind: Pod
spec:
containers:
- name: docker
image: docker:latest
command:
- cat
tty: true
'''
}
}
stages {
stage('Build') {
steps {
container('docker') {
sh 'docker build -t myapp:${BUILD_NUMBER} .'
}
}
}
stage('Test') {
steps {
sh 'make test'
}
}
stage('Push') {
steps {
container('docker') {
sh 'docker push myapp:${BUILD_NUMBER}'
}
}
}
}
}
장점:
설정:
# Pod Template
apiVersion: v1
kind: Pod
metadata:
labels:
jenkins: agent
spec:
containers:
- name: jnlp
image: jenkins/inbound-agent:latest
- name: docker
image: docker:dind
securityContext:
privileged: true
- name: kubectl
image: bitnami/kubectl:latest
| 플러그인 | 용도 |
|---|---|
| Kubernetes | Kubernetes에서 Agent Pod 관리 |
| Git | Git Repository 통합 |
| Pipeline | Pipeline 기능 제공 |
| Docker Pipeline | Docker 명령어 사용 |
| Credentials | 시크릿 관리 |
| 플러그인 | 용도 |
|---|---|
| Blue Ocean | 현대적인 UI |
| Slack Notification | Slack 알림 |
| SonarQube Scanner | 코드 품질 분석 |
| JUnit | 테스트 결과 리포팅 |
| Vault | HashiCorp Vault 통합 |
pipeline {
agent any
environment {
DOCKER_IMAGE = "myregistry/myapp"
IMAGE_TAG = "${BUILD_NUMBER}"
}
stages {
stage('Checkout') {
steps {
git branch: 'main',
url: 'https://github.com/myorg/myapp.git'
}
}
stage('Install') {
steps {
sh 'npm install'
}
}
stage('Test') {
steps {
sh 'npm test'
}
}
stage('Build Image') {
steps {
sh """
docker build -t ${DOCKER_IMAGE}:${IMAGE_TAG} .
docker tag ${DOCKER_IMAGE}:${IMAGE_TAG} ${DOCKER_IMAGE}:latest
"""
}
}
stage('Push Image') {
steps {
withDockerRegistry([credentialsId: 'docker-hub']) {
sh """
docker push ${DOCKER_IMAGE}:${IMAGE_TAG}
docker push ${DOCKER_IMAGE}:latest
"""
}
}
}
stage('Update Manifest') {
steps {
sh """
git clone https://github.com/myorg/k8s-manifests.git
cd k8s-manifests
sed -i 's|image:.*|image: ${DOCKER_IMAGE}:${IMAGE_TAG}|' deployment.yaml
git commit -am 'Update image to ${IMAGE_TAG}'
git push
"""
}
}
}
post {
success {
echo 'Pipeline succeeded!'
}
failure {
echo 'Pipeline failed!'
}
}
}
✅ 오픈소스: 무료 및 활발한 커뮤니티
✅ 확장성: 풍부한 플러그인 생태계
✅ 유연성: 거의 모든 도구와 통합 가능
✅ 성숙도: 오랜 역사와 안정성
✅ Pipeline as Code: Jenkinsfile로 버전 관리
✅ Kubernetes 통합: 현대적인 클라우드 네이티브 환경 지원
| 도구 | 특징 | 적합한 경우 |
|---|---|---|
| Jenkins | 유연, 확장 가능, 성숙 | 복잡한 워크플로우, 레거시 통합 |
| GitHub Actions | Git 통합, 간단 | GitHub 기반 프로젝트 |
| GitLab CI | Git 통합, 올인원 | GitLab 사용 시 |
| Tekton | Kubernetes 네이티브 | Cloud Native 환경 |
| Drone | 컨테이너 기반, 간단 | 소규모 프로젝트 |
Jenkins 개요를 이해했다면: