Jenkin Pipeline 기본 구성
먼저 새로운 Item을 다음과 같이 생성해줍니다.

이후 해당 Pipeline Item 내부에서 Jenkins Pipeline Script를 작성합니다. 스크립트는 수동으로 직접 작성할 수도 있고, UI로 설정한 뒤 Snippet Generator를 통해 자동 생성할 수도 있습니다.
pipeline {
agent any
tools {
gradle 'gradle-7.6.1'
jdk 'jdk-17'
}
// 환경 변수 지정
environment {
DOCKERHUB_USERNAME = "kmkhm"
GITHUB_USERNAME = "kmkhm"
GITHUB_URL = "https://github.com/${GITHUB_USERNAME}/kubernetes-anotherclass-sprint2.git"
CLASS_NUM = '2211'
}
stages {
stage('Source Build') {
steps {
git branch: 'main', url: 'https://github.com/k8s-1pro/kubernetes-anotherclass-api-tester.git'
sh "chmod +x ./gradlew"
sh "gradle clean build"
}
}
stage('Container Build') {
steps {
checkout scmGit(branches: [[name: '*/main']],
extensions: [[$class: 'SparseCheckoutPaths',
sparseCheckoutPaths: [[path: "/${CLASS_NUM}"]]]],
userRemoteConfigs: [[url: "${GITHUB_URL}"]])
sh "cp ./build/libs/app-0.0.1-SNAPSHOT.jar ./${CLASS_NUM}/build/docker/app-0.0.1-SNAPSHOT.jar"
sh "docker build -t ${DOCKERHUB_USERNAME}/api-tester:v1.0.0 ./${CLASS_NUM}/build/docker"
sh "docker push ${DOCKERHUB_USERNAME}/api-tester:v1.0.0"
}
}
stage('K8S Deploy') {
steps {
// 쿠버네티스 배포
sh "kubectl apply -f ./${CLASS_NUM}/deploy/k8s/namespace.yaml"
sh "kubectl apply -f ./${CLASS_NUM}/deploy/k8s/configmap.yaml"
sh "kubectl apply -f ./${CLASS_NUM}/deploy/k8s/secret.yaml"
sh "kubectl apply -f ./${CLASS_NUM}/deploy/k8s/service.yaml"
sh "kubectl apply -f ./${CLASS_NUM}/deploy/k8s/deployment.yaml"
}
}
}
}

위에서 작성한 pipeline은 총 3단계로 구성되어 있습니다.
- Source Build: GitHub에서 소스 코드를 가져와 Gradle로 빌드합니다.
- Container Build: 빌드된 JAR 파일을 Dockerfile 위치로 복사하고, 도커 이미지를 생성 후 Docker Hub에 푸시합니다.
- K8S Deploy: 쿠버네티스 클러스터에 필요한 리소스(YAML 파일들)를 kubectl 명령어를 통해 배포합니다.
이렇게 구성된 Jenkins Pipeline은 코드 변경 → 빌드 → 이미지 생성 및 푸시 → Kubernetes 배포까지 전체 과정을 자동화해줍니다.

Jenkins Pipeline을 실행하면, 각 단계가 어떻게 진행되었는지 시각적으로 확인할 수 있는 Pipeline Overview 탭이 자동으로 생성됩니다. 위 이미지와 같이 Tool Install, Source Build, Container Build, K8S Deploy 등 파이프라인에서 정의한 각 단계가 순차적으로 수행되며, 각 단계별 소요 시간과 성공 여부를 직관적으로 확인할 수 있습니다. 빌드 실패 시 어느 단계에서 문제가 발생했는지 빠르게 파악하는 데에도 매우 유용합니다. 각 단계에서 실제 실행된 명령어 로그도 상세히 확인할 수 있어 디버깅 시에도 큰 도움이 됩니다.
Jenkins Github 연결 및 파이프라인 세분화
이번에는 세분화하여 GitHub와의 연동을 설정하고, Jenkins가 특정 디렉토리의 Jenkinsfile만을 읽어 들이도록 설정하는 방법을 정리해보겠습니다. 먼저 새로운 Item을 생성해줍니다.

생성한 Item의 설정 화면에서 아래와 같이 GitHub 프로젝트 URL을 지정합니다.

이후 Pipeline 항목에서 다음과 같이 Git SCM을 통해 파이프라인 스크립트를 가져오도록 설정해줍니다.
- SCM: Git
- Repository URL: GitHub 저장소 주소 입력
- Branches to build: */브랜치명
- Additional Behaviours > Sparse Checkout paths 추가 => Path: 2212 (해당 폴더만 체크아웃)
- Script Path: 2212/Jenkinsfile



이와 같이 설정하면 Jenkins는 저장소의 루트가 아닌, 특정 디렉토리(2212/)만을 체크아웃하고, 해당 경로 내의 Jenkinsfile을 기준으로 파이프라인을 실행하게 됩니다.
Pipeline을 생성한 직후 바로 Build Now를 클릭하면, 파라미터가 있는 파이프라인의 경우 에러가 발생할 수 있습니다. 이는 파이프라인에 파라미터가 정의되어 있음에도, 사용자가 값을 입력하지 않고 빌드를 시도했기 때문에 발생하는 문제입니다. Build with Parameters를 클릭한 후, 파라미터들을 입력해준 후 다시 빌드 해줍니다.

그럼 아래와 같이 정상적으로 빌드된 것을 확인할 수 있습니다.

이번 방식처럼 Sparse Checkout과 Script Path를 활용하면 하나의 저장소에 각 팀/클래스/기능별 Jenkinsfile을 구분하여 관리할 수 있고, Jenkins에서도 각각 별도 Job으로 관리할 수 있습니다. 예를 들어, 2211, 2212, 2213과 같은 디렉토리별로 Jenkinsfile을 두고, 각기 다른 Jenkins Pipeline에서 해당 경로만 지정해주는 방식으로 CI/CD 작업을 세분화할 수 있습니다. 또한
Blue & Green 배포
이번에는 한 단계 더 나아가, Blue/Green 배포 전략을 Jenkins Pipeline에 적용하여 실습해보겠습니다. 이전 단계에서 작성한 Pipeline을 복제해 새로운 Item을 생성해줍니다.

이전 단계에서 작성한 Jenkinsfile과는 경로가 다르기 때문에, Sparse Checkout Path와 Script Path 항목만 아래와 같이 수정해주었습니다.

모든 설정이 완료되었으면, 바로 빌드를 실행하여 배포를 진행합니다.
배포가 완료되면, Master Node에서 애플리케이션의 버전을 확인하기 위해 다음과 같이 지속적으로 요청을 보내보았습니다.
while true; do curl http://192.168.56.30:32213/version; sleep 1; echo ''; done;
요청 결과는 다음과 같이 v1 버전의 응답이 꾸준히 반환되며, Blue 배포가 정상적으로 이루어졌음을 확인할 수 있습니다.
[App Version] : Api Tester v1.0.0
[App Version] : Api Tester v1.0.0
[App Version] : Api Tester v1.0.0
.
.

이 상황에서 Jenkins Console 내에서 Green 배포 단계의 ‘Yes’ 버튼을 클릭하게 되면, 서비스 트래픽이 v2로 전환되게 됩니다.
앞서 실행 중이던 버전 확인 명령어는 아래와 같은 출력으로 변화하며, 트래픽이 정상적으로 v1 → v2로 전환된 것을 확인할 수 있습니다.
즉, 사용자는 서비스 중단 없이 새 버전으로 자연스럽게 전환되었음을 확인할 수 있습니다.
[App Version] : Api Tester v1.0.0
[App Version] : Api Tester v1.0.0
[App Version] : Api Tester v1.0.0
[App Version] : Api Tester v1.0.0
[App Version] : Api Tester v1.0.0
[App Version] : Api Tester v1.0.0
[App Version] : Api Tester v1.0.0
[App Version] : Api Tester v2.0.0
[App Version] : Api Tester v2.0.0
[App Version] : Api Tester v2.0.0

위와 같이 v1과 v2 Pod가 각각 2개씩 배포되어 총 4개의 Pod가 존재하는 것을 확인할 수 있습니다. 이 상태는 트래픽 분산 및 전환 준비를 위한 Blue/Green 배포의 중간 단계입니다.

이후 Jenkins Pipeline에서 Proceed(Yes) 버튼을 클릭하면, 트래픽 전환과 함께 v1 Pod 2개는 종료되고, v2 Pod만 남게 됩니다.
이를 통해 v2로의 전환이 완료되며, 사용자는 무중단으로 새로운 버전의 서비스를 이용할 수 있게 됩니다.
Blue/Green 배포 전략은 일반적으로 일시적으로 리소스를 2배 사용하게 됩니다.
- 메모리 사용량의 경우, 기존 버전(v1)과 신규 버전(v2)이 동시에 실행되므로, 두 애플리케이션 모두에게 메모리를 할당해야 하며, 결과적으로 배포 시점에는 메모리 사용량이 거의 2배 수준이 됩니다.
- CPU 사용량은 상황에 따라 다르지만, 특히 Spring Boot와 같이 부팅 과정에서 CPU 사용량이 급증하는 애플리케이션의 경우, v2가 부팅되는 동안 일시적으로 CPU 사용량이 증가할 수 있습니다.
다만 트래픽은 점차 v2로만 전환되기 때문에, 전환이 완료되면 v1 Pod가 삭제되고, 리소스 사용량은 다시 정상 수준으로 회복됩니다.
stage('쿠버네티스 Blue배포') {
steps {
sh "kubectl apply -f ./${CLASS_NUM}/deploy/k8s/blue/namespace.yaml"
sh "kubectl apply -f ./${CLASS_NUM}/deploy/k8s/blue/configmap.yaml"
sh "kubectl apply -f ./${CLASS_NUM}/deploy/k8s/blue/secret.yaml"
sh "kubectl apply -f ./${CLASS_NUM}/deploy/k8s/blue/service.yaml"
sh "kubectl apply -f ./${CLASS_NUM}/deploy/k8s/blue/deployment.yaml"
}
}
Jenkinsfile 중 Blue 배포 부분인데, 보통 쿠버네티스에서는 create 대신 apply를 사용합니다. 이유는 apply가 선언적 방식으로 리소스가 존재하면 수정하고, 없으면 생성하기 때문에 반복 실행에도 안전하기 때문입니다. create의 경우에는 리소스가 이미 존재하면 에러를 일으킵니다.
stage('배포 시작') {
steps {
input message: '수동배포 시작', ok: "Yes"
}
}
또한 이 부분은 Jenkinsfile에서 메시지 박스를 생성하는 부분으로, input 스텝을 통해 수동 확인이 이루어질 때까지 파이프라인의 진행을 잠시 멈추는 역할을 합니다. 운영 환경에 배포하기 전 사용자의 최종 확인을 받거나, 특정 조건을 점검할 때 유용하게 사용됩니다.
kubectl patch -n anotherclass-221 svc api-tester -p '{"spec": {"selector": {"blue-green-no": "2"}}}'
kubectl patch 명령어를 사용하면 리소스 전체가 아닌 일부분만 수정할 수 있습니다.
- -n anotherclass-221 : 네임스페이스를 지정합니다.
- svc api-tester : 수정할 리소스는 api-tester라는 이름의 서비스(Service)입니다.
- -p '{...}' : JSON 형식으로 패치할 내용을 지정합니다.
즉, 서비스의 selector 값을 변경하여 트래픽이 버전 1(Pod)에서 버전 2(Pod)로 전환되도록 설정하는 것입니다. 이는 Blue/Green 배포 전략에서 버전 전환을 트래픽 라우팅 수준에서 수행하는 핵심 작업입니다.
Blue & Green 자동 배포 실습
이전 단계에서 사용자가 직접 input 메시지를 통해 배포 시점을 제어하고, kubectl patch를 사용해 트래픽 전환을 수동으로 수행하는 방식이었습니다. 하지만 실제 운영 환경에서는 이러한 작업을 매번 수동으로 수행하기 어렵고, 신뢰성 있는 자동화가 필요합니다.
이번에는 Blue/Green 배포를 Jenkins Pipeline으로 자동화 실습을 해보겠습니다. 빌드부터 트래픽 전환, 그리고 기존 Blue 리소스 정리까지의 전 과정을 하나의 스크립트로 구성함으로써 완전 자동화된 무중단 배포 파이프라인을 구축해보겠습니다.
stage('Green 배포 확인중') {
steps {
script {
def returnValue
while (returnValue != "true true"){
returnValue = sh(returnStdout: true, encoding: 'UTF-8', script: "kubectl get -n anotherclass-221 pods -l instance='api-tester-2214',blue-green-no='2' -o jsonpath='{.items[*].status.containerStatuses[*].ready}'")
echo "${returnValue}"
sleep 5
}
}
}
}
- 위 스크립트는 blue-green-no=2 레이블을 가진 Green 버전의 Pod들이 모두 ready 상태인지 5초마다 확인합니다.
- .status.containerStatuses[*].ready 필드를 조회하면 컨테이너가 준비되었는지를 확인할 수 있습니다.
- 예를 들어 true true가 출력되면 2개의 컨테이너가 모두 정상적으로 실행되고 요청을 받을 준비가 되었다는 의미입니다. 그리고 이 true true가 되면 자동으로 다음 단계로 넘어가 v2(Green 버전)로의 트래픽 전환이 이루어지게 됩니다.
즉, 모든 Green Pod가 준비되었을 때에만 다음 단계로 넘어가기 때문에 무중단 배포가 가능한 것입니다.
마지막으로 리소스 정리는 다음과 같이 정리합니다.
stage('Blue 삭제') {
steps {
sh "kubectl delete -f ./${CLASS_NUM}/deploy/k8s/blue/deployment.yaml"
sh "kubectl patch -n anotherclass-221 svc api-tester-2214 -p '{\"metadata\": {\"labels\": {\"version\": \"2.0.0\"}}}'"
sh "kubectl patch -n anotherclass-221 cm api-tester-2214-properties -p '{\"metadata\": {\"labels\": {\"version\": \"2.0.0\"}}}'"
sh "kubectl patch -n anotherclass-221 secret api-tester-2214-postgresql -p '{\"metadata\": {\"labels\": {\"version\": \"2.0.0\"}}}'"
}
}'Infra' 카테고리의 다른 글
| [K8S] Kustomize 사용해보기 (2) | 2025.05.31 |
|---|---|
| [K8S] Helm 사용해보기 (2) | 2025.05.30 |
| [K8S] 배포를 하기전에 알아야 할 것들 (2) | 2025.05.28 |
| [K8S] DevOps 환경 구축하기 (0) | 2025.05.28 |
| [K8S] DevOps (0) | 2025.05.26 |
댓글