[참고]
본 글은 인프런의
<쿠버네티스 어나더 클래스 - Sprint 1, 2 (#실무기초 #설치 #배포 #Jenkins #Helm #ArgoCD)>
강의 내용과 실습을 바탕으로 정리한 기록입니다.
실습에서 다룬 Job (Pipeline)
- 2211-jenkins_pipeline-step1: 분리되어 있던 세 개의 Job을 하나의 Pipeline으로 통합
- 2212-jenkins_pipeline-step2: GitHub 연동 및 Pipeline script from SCM 방식으로 전환
- 2213-jenkins_pipeline-step3: input 스텝을 활용한 수동 Blue/Green 배포
- 2214: 배포 완료 여부를 폴링하는 자동 Blue/Green 배포
1. 분리된 Job을 하나의 Pipeline으로
Sprint 1에서는 2121-source-build, 2121-container-build, 2121-deploy 세 개의 Job을 각각의 stage로 나눠 관리했습니다.

이번 단계에서는 이 Job들을 하나의 Pipeline으로 합치는 작업을 수행했습니다. 실무에서 매일 하던 구성이라 이 부분은 빠르게 넘어갔습니다.
2. Pipeline script from SCM으로 전환
Jenkins UI에 스크립트를 직접 박아 넣는 대신, GitHub 저장소의 Jenkinsfile을 읽어오도록 변경했습니다.
설정 포인트 3가지
- Definition: Pipeline script from SCM 선택 (SCM은 Git)
- Repository URL: https://github.com/sseyeon/kubernetes-anotherclass-sprint2.git, Branch는 /main
- Sparse Checkout paths: Additional Behaviours에서 체크아웃 경로를 2212로 지정




✅ Sparse Checkout을 쓰는 이유: 하나의 저장소에 여러 실습 번호(2211, 2212, 2213…)가 함께 들어 있을 때, 전체를 내려받지 않고 해당 Job이 필요로 하는 디렉토리만 체크아웃할 수 있습니다. 저장소가 커질수록 체크아웃 시간과 워크스페이스 용량에서 차이가 납니다.
3. Blue/Green 배포 실습 (수동)
input 스텝으로 각 단계마다 확인을 받으면서 트래픽이 어떻게 넘어가는지 직접 관찰했습니다.
3-1. Blue 배포 — Green Pod 생성
첫 번째 Yes를 누르면 기존 Blue Pod 2개는 그대로 둔 채, Green Pod 2개가 추가로 생성됩니다. 이 시점에는 Pod가 총 4개입니다.
# 운영 트래픽 — 계속 v1.0.0 응답
while true; do curl http://192.168.56.30:32213/version; sleep 1; echo ''; done;
# [App Version] : Api Tester v1.0.0
# [App Version] : Api Tester v1.0.0
# QA 담당자 전용 — 검증용 Service로 v2.0.0 직접 호출
curl http://192.168.56.30:32223/version
# [App Version] : Api Tester v2.0.0

✅ 핵심: 사용자는 여전히 v1을 보고 있는 상태에서, QA는 별도 포트(32223)로 v2를 미리 검증할 수 있습니다.
3-2. Green 전환
두 번째 Yes를 누르면 Service의 selector가 바뀌면서, 돌고 있던 32213 호출 결과가 v1에서 v2로 전환됩니다.


3-3. Blue 삭제
마지막으로 Done을 누르면 Blue Pod가 삭제되고 Green만 남습니다.

4. Blue/Green 배포 시 고려해야 할 요소

Sprint 1에서 라벨(Label)과 셀렉터(Selector) 매칭 구조를 정리했는데, Blue/Green은 그 설계가 실제로 왜 중요한지 바로 드러나는 지점이었습니다.
1) Blue-Green 배포를 고려한 Deployment 네이밍
Deployment 이름 뒤에 구분자를 붙입니다. api-tester-2213-1(Blue), api-tester-2213-2(Green) 형태로, 두 벌의 Deployment가 동시에 존재할 수 있어야 합니다.
2) Blue-Green 배포를 위한 추가 레이블 및 셀렉터
기존 5개 라벨(part-of, component, name, instance, version)에 blue-green-no 라벨을 하나 더 추가합니다.
|
구분
|
Deployment
|
Pod label
|
Service selector
|
|
Blue
|
api-tester-2213-1
|
blue-green-no: 1, version: 1.0.0
|
blue-green-no: "1"
|
|
Green
|
api-tester-2213-2
|
blue-green-no: 2, version: 2.0.0
|
blue-green-no: "2"
|
✅ 여기서 중요한 점: Service는 part-of, component, name, instance까지는 Blue/Green이 완전히 동일하고, 오직 blue-green-no 값 하나만 다릅니다. 그래서 이 라벨 값 하나만 1 → 2로 바꾸면 트래픽 전체가 넘어갑니다.
5. 리소스 변경 사항 정리

수동 배포 전체 흐름을 리소스 관점에서 3단계로 정리하면 다음과 같습니다.
- 생성: Green Deployment 생성 + 검증 전용 Service(api-tester-2) 생성
- 전환: 운영 Service의 selector blue-green-no를 "1" → "2"로 변경
- 정리: Blue Deployment 삭제, Green 전용 Service 삭제, 그리고 남은 리소스들의 version 라벨을 1.0.0 → 2.0.0으로 갱신
3번에서 문제가 드러납니다. Deployment만 정리하면 끝이 아니라 Service, ConfigMap, Secret에 붙은 version 라벨까지 전부 따라가야 합니다. 리소스가 늘어날수록 하나씩 누락될 위험이 커지고, 이걸 사람 손으로 챙기는 건 현실적이지 않습니다. Helm을 쓰는 이유가 여기서 나옵니다.
참고로 instance 라벨은 Blue/Green 간에 다르게 주는 경우가 많지는 않습니다.
6. 자동 배포 만들어보기
수동 단계의 input을 걷어내고, Green Pod가 전부 Ready가 될 때까지 폴링하도록 만들었습니다.
stage('쿠버네티스 Green배포') {
steps {
sh "kubectl apply -f ./${CLASS_NUM}/deploy/k8s/green/deployment.yaml"
}
}
stage('Green 배포 확인중') {
steps {
script {
def returnValue
// Pod 2개가 모두 Ready("true true")가 될 때까지 5초 간격으로 확인
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
}
}
}
}
stage('Green 전환 완료') {
steps {
// 라벨 하나만 바꿔서 트래픽 전환
sh "kubectl patch -n anotherclass-221 svc api-tester-2214 -p '{\"spec\": {\"selector\": {\"blue-green-no\":\"2\"}}}'"
}
}
stage('Blue 삭제') {
steps {
sh "kubectl delete -f ./${CLASS_NUM}/deploy/k8s/blue/deployment.yaml"
// 남은 리소스들의 version 라벨 갱신
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\"}}}'"
}
}

✅ 코드에서 읽어야 할 포인트
- while 문이 핵심: jsonpath로 Pod의 containerStatuses[*].ready를 뽑아 "true true"가 될 때까지 대기합니다. Pod가 2개니까 true도 2개여야 합니다.
- 전환은 kubectl patch 한 줄: Service의 selector.blue-green-no만 바꾸면 끝입니다. 4번 항목의 라벨 설계가 그대로 코드에 반영된 모습입니다.
- 뒷정리 patch가 3줄: Service, ConfigMap, Secret의 version 라벨을 각각 수동으로 갱신하고 있습니다. 5번에서 말한 누락 위험이 코드에서 그대로 보입니다.
다만 이건 실무용이 아닙니다. while로 무한 대기하는 구조라 타임아웃도 없고, 실패 시 롤백 처리도 없습니다. Blue/Green이 원리적으로 이렇게 돌아간다는 것을 보여주는 코드에 가깝습니다.
그럼 실무에서는? → ArgoCD 같은 GitOps 툴을 활용합니다.
마무리
Sprint 1에서 라벨과 셀렉터 매칭 구조를 다이어그램으로 그려봤을 때는 “규칙을 잘 지키면 관리가 편해지겠구나” 정도의 감이었는데, Blue/Green을 직접 만들어보니 그 효용이 훨씬 구체적으로 와닿았습니다. 라벨 설계가 잘 되어 있으면 무중단 전환이 patch 한 줄로 끝나고, 안 되어 있으면 배포 때마다 리소스를 손으로 뒤져야 합니다.
동시에 왜 Helm과 ArgoCD가 필요한지도 자연스럽게 이해됐습니다. Jenkinsfile에 kubectl patch를 세 줄 쌓고 있는 순간, 이건 리소스가 늘어나면 관리가 안 되는 방식이라는 게 코드 자체로 드러났기 때문입니다.
'Infra > Kubernetes' 카테고리의 다른 글
| [쿠버네티스 어나더 클래스 - Sprint2] #3. 배포를 시작하기 전에 반드시 알아야 할 것들 (0) | 2026.09.18 |
|---|---|
| [쿠버네티스 어나더 클래스 - Sprint2] #2. 손쉽게 데브옵스 환경을 구축하는 방법 (0) | 2026.09.17 |
| 2026 CKA 합격 후기 (0) | 2026.09.14 |
| [쿠버네티스 어나더 클래스 - Sprint1] #8. Component 동작으로 이해하기 (0) | 2026.08.27 |
| [쿠버네티스 어나더 클래스 - Sprint1] #7. Application 기능으로 이해하기#3 - PV/PVC, Deployment, Service, HPA (0) | 2026.08.26 |