앞선 를 통해 애플리케이션 코드를 아름다운 도커 이미지(Docker Image)로 굽고 레지스트리에 푸시(Push)하는 것까지 성공하셨습니다. 이제 남은 과제는 단 하나, "이 이미지를 실서비스가 돌아가고 있는 운영 서버들에 띄워서 고객들에게 선보이는 것"입니다.
현대의 대규모 인프라에서는 이 서버들을 지휘하기 위해 Kubernetes(쿠버네티스, 이하 K8s)라는 막강한 오케스트레이션 툴을 사용합니다. 젠킨스가 빌드마스터라면, K8s는 함대 사령관입니다.
이번에는 젠킨스가 원격 K8s 클러스터에 접속하여 새로운 버전의 이미지를 무중단(Rolling Update)으로 교체하라고 명령을 내리는 완벽한 배포 연동 전략에 대하여 다뤄보겠습니다.
1. Kubeconfig 보안과 원격 접속 인증
우리가 터미널에서 kubectl get pods라고 치면 쿠버네티스가 응답하는 이유는, 홈 디렉토리 어딘가에 숨겨진 kubeconfig 파일 안에 클러스터의 주소와 강력한 마스터 인증서가 들어있기 때문입니다. 젠킨스가 K8s에 명령을 내리게 하려면 이 절대 반지(Kubeconfig)를 젠킨스에게 쥐여주어야 합니다.
하지만 이 파일을 서버 구석에 하드코딩해두는 것은 미친 짓입니다. 젠킨스의 금고인 [Manage Credentials] 메뉴를 활용합시다.
- 자격 증명 종류(Kind)를
Secret file로 선택합니다. - 로컬 PC에 있는
kubeconfig파일을 그대로 업로드(Choose File)합니다. - ID를
k8s-kubeconfig-prod처럼 직관적으로 짓고 저장합니다.
이제 젠킨스는 이 파일을 꽁꽁 암호화해서 보관하다가, 파이프라인에서 배포 명령이 떨어질 때만 임시로 꺼내서 K8s에 접속하고 즉시 폐기하게 됩니다.
2. 동적 이미지 태그 치환 (실무의 핵심)
K8s에 배포를 선언하는 deployment.yaml 파일을 보면 이미지 주소가 적혀있습니다. image: my-app:latest 처럼 고정된 태그를 쓰면 절대 안 됩니다. K8s는 이미지 태그 글자가 바뀌어야만 "어? 새로운 버전이 나왔네? 기존 Pod(컨테이너)를 부수고 새 Pod를 띄워야겠다"라고 인식하여 무중단 롤링 업데이트(Rolling Update)를 시작하기 때문입니다.
따라서 파이프라인 도중에 리눅스의 문자열 치환 도구인 sed 명령어를 사용하여, deployment.yaml 속의 더미 문자열(Placeholder)을 이번 젠킨스의 고유 빌드 번호(예: 42)로 싹 바꿔치기한 뒤 kubectl apply를 때려야 합니다.
3. 실무 적용 극한의 예제 파헤치기</h3
위의 두 가지 핵심 원리(Kubeconfig 바인딩 + sed 문자열 치환)를 결합한 가장 완벽한 형태의 Declarative Pipeline 코드를 .
pipeline {
agent any
environment {
// 앞선 에서 푸시했던 바로 그 고유 이미지 태그
IMAGE_TAG = "${env.BUILD_NUMBER}"
}
stages {
stage('Deploy to Kubernetes (Prod)') {
steps {
// 1. 금고에서 Secret file을 꺼내 임시 경로(KUBECONFIG 변수)에 할당합니다.
withCredentials([file(credentialsId: 'k8s-kubeconfig-prod', variable: 'KUBECONFIG')]) {
// 2. K8s yaml 파일 내의 'IMAGE_TAG_PLACEHOLDER' 글자를 진짜 태그(예: 42)로 덮어씌웁니다.
sh """
echo "Yaml 파일의 이미지 태그를 ${IMAGE_TAG} 로 교체합니다..."
sed -i 's/IMAGE_TAG_PLACEHOLDER/${IMAGE_TAG}/g' k8s/production-deployment.yaml
"""
// 3. K8s 클러스터에 배포 명령을 발사합니다! (--kubeconfig 옵션 필수)
sh """
echo "K8s 클러스터에 Rolling Update 배포를 시작합니다!"
kubectl apply -f k8s/production-deployment.yaml --kubeconfig=${KUBECONFIG}
"""
// 4. (매우 중요) 배포 명령만 던지고 끝나는게 아니라, 모든 Pod가 정상적으로 다 뜰 때까지 기다리며 모니터링합니다.
// 만약 새 Pod가 에러가 나서 뜨지 못하면 파이프라인을 실패(Failure) 처리합니다.
sh """
kubectl rollout status deployment/my-awesome-app --timeout=300s --kubeconfig=${KUBECONFIG}
"""
}
}
}
}
}
4. 마무리 및 주요 발전 방향
지금까지 CI(지속적 통합)의 결정체인 도커 이미지를 K8s 클러스터라는 거대한 CD(지속적 배포) 환경으로 안전하고 우아하게 밀어 넣는 실무 연동 기법에 대해 다루어 보았습니다. 이제 개발자가 코드를 커밋하면, 젠킨스가 코드를 분석하고, 도커를 굽고, K8s가 새 컨테이너를 하나씩 띄우며 사용자의 끊김 없이(Zero Downtime) 서비스를 교체하는 완벽한 인프라가 완성되었습니다.
하지만 여기서 인프라 팀장님의 이마에 식은땀이 흐르기 시작합니다. "잠깐, 코드를 푸시하기만 하면 아무런 통제도 없이 운영 서버(Production)까지 다이렉트로 배포돼버린다고? 만약 주말 새벽에 신입이 실수로 코드를 푸시해버리면 상용 서버가 바로 작살나는 거잖아!"
그렇습니다. 테스트 환경은 100% 자동화가 맞지만, 실제 돈이 오가는 상용 환경 배포 앞에는 반드시 '사람의 눈(결재)'이 필요합니다. 본 설명에서는 폭주 기관차처럼 질주하는 파이프라인을 잠시 멈춰 세우고 관리자의 버튼 승인을 요구하는 강력한 브레이크, 'Input Step 수동 승인 제어법'에 대해 아주 치밀하게 파헤쳐 보겠습니다!
"CI/CD 자동화가 너무 완벽하게 구축된 나머지, 누군가 실수로 main 브랜치에 올린 불량 코드가 5분 만에 전 세계 고객이 접속 중인 운영 서버(Production)에 꽂혀버렸다." 이는 구글, 아마존 같은 빅테크에서도 종종 벌어지는 악몽 같은 장애 시나리오입니다. 개발(Dev) 서버나 스테이징(Staging) 환경까지는 코드가 푸시되는 즉시 100% 논스톱 자동 배포가 이루어지는 것이 맞습니다. 하지만 회사의 명운이 달린 운영 상용 배포 앞에는 반드시 '책임자의 눈과 버튼 승인'이라는 휴먼 브레이크 장치가 필요합니다.
본 글에서는 질주하는 파이프라인을 잠시 일시 정지(Pause)시키고, 권한을 가진 자만이 문을 열어줄 수 있게 만드는 강력한 'Input Step 수동 승인 제어 기법'에 대하여 다뤄보겠습니다.
1. Input Step 이란 무엇인가?
파이프라인의 특정 steps 안에 input이라는 명령어를 선언해두면, 젠킨스는 코드를 한 줄씩 실행하며 내려오다가 input을 만나는 순간 마법처럼 파이프라인의 시간을 멈춥니다(Suspend).
그리고 젠킨스 웹 UI나 Blue Ocean 대시보드 화면 한가운데에 팝업창을 띄워놓고 "배포할까요?"라고 묻습니다. 이때 관리자가 Proceed(진행) 버튼을 누르면 멈춰있던 파이프라인이 다시 숨을 쉬며 다음 줄의 코드(배포 스크립트)를 실행하고, Abort(중단) 버튼을 누르면 그 즉시 파이프라인을 실패 처리하고 종료시킵니다.
2. 무한 대기의 늪: Timeout과의 영혼의 단짝 결합
초보자들이 input을 쓸 때 저지르는 가장 흔하고 치명적인 실수가 있습니다. 승인 팝업만 띄워놓고 그대로 퇴근해 버리는 것입니다. 팀장님도 휴가를 가서 아무도 버튼을 눌러주지 않는다면 어떻게 될까요?
그 젠킨스 Job은 서버의 프로세스와 메모리를 점유한 채 영원히, 10년이 지나도 멈춰서 기다리게 됩니다. 이런 좀비 빌드들이 수십 개 쌓이면 결국 젠킨스는 리소스 고갈로 뻗어버립니다. 따라서 input 스텝은 반드시 timeout(타임아웃) 블록으로 감싸주어, "1시간 안에 응답이 없으면 자동 취소(Abort)하라"는 방어 로직을 필수로 구성해야 합니다.
3. 권한 제어: 아무나 승인 버튼을 누를 수 없게 만들기
승인 버튼을 띄웠는데, 방금 입사한 신입 사원이 "이 버튼은 뭐지?" 하고 눌러서 운영에 배포돼버린다면 승인 창을 만든 의미가 없습니다. input 명령어는 submitter라는 강력한 옵션을 제공하여, 젠킨스 시스템에 등록된 특정 유저(예: admin) 혹은 특정 그룹(예: dev-leaders)에 속한 사람만 버튼을 클릭할 수 있도록 완벽하게 접근 제어(RBAC)를 설정할 수 있습니다.
4. 실무 적용 극한의 예제 파헤치기
Timeout과 권한 제어, 그리고 심지어 승인 시 추가적인 런타임 매개변수(Parameter)까지 동적으로 입력받아 분기 처리하는 최고 수준의 실무 예제 코드를 분석해 봅시다.
pipeline {
agent any
stages {
stage('Build & Test') {
steps { echo '코드를 빌드하고 Staging 서버 테스트까지 모두 마쳤습니다!' }
}
stage('Approval for Production Deploy') {
steps {
// 1. 무한 멈춤을 방지하기 위해 1시간의 제한 시간을 둡니다.
timeout(time: 1, unit: 'HOURS') {
script {
// 2. input을 변수(userInput)에 담으면, 팝업에서 선택한 값을 받아올 수 있습니다.
def userInput = input(
message: ' 운영 서버(Production)에 배포를 진행할까요?', // 팝업창 제목
ok: '네, 배포를 승인합니다!', // 진행 버튼 텍스트 변경
submitter: 'admin, dev_team_lead', // 특정 권한을 가진 자만 클릭 가능
parameters: [
// 승인 버튼을 누를 때 추가 옵션을 물어봅니다.
choice(name: 'DEPLOY_MODE', choices: ['CANARY', 'BLUE_GREEN'], description: '배포 전략을 선택하세요')
]
)
// 사용자가 선택한 값을 환경변수로 등록하여 다음 스테이지에서 쓰게 만듭니다.
env.CHOSEN_MODE = userInput
}
}
}
}
stage('Deploy to Production') {
steps {
echo " 승인이 완료되었습니다. 선택하신 전략(${env.CHOSEN_MODE})으로 상용 배포를 가동합니다!"
// sh "./deploy-prod.sh --mode=${env.CHOSEN_MODE}"
}
}
}
}
5. 마무리 및 주요 발전 방향
지금까지 폭주하는 자동화의 굴레에 안전장치를 채우고, 책임 소재를 명확히 하며 서버 리소스를 보호하는 가장 우아한 승인 결계, 'Input Step'의 완벽 활용법에 대해 다루어 보았습니다. 이 기법 하나로 여러분의 파이프라인은 신뢰할 수 없는 자동화 기계에서 신중하고 든든한 동료로 격상되었습니다.
파이프라인을 이토록 완벽하게 깎아놓았는데, 만약 내일 아침 출근했더니 AWS 장애로 젠킨스 서버의 하드디스크가 통째로 날아갔다면 어떻게 될까요? 수백 개의 Job 설정 파일과 파이프라인 히스토리, 암호화된 Credentials까지 모두 영원히 사라져 버리는 대참사가 일어납니다. 복구에만 꼬박 일주일이 걸릴지도 모릅니다.
다음 글에서는 서버가 불타 없어져도 3분 만에 어제 상태 그대로 젠킨스를 살려내는 Jenkins 백업 스크립트 작성 및 자동화 에 대해 아주 다뤄보겠습니다!
'CI. CD > Jenkins' 카테고리의 다른 글
| [Jenkins] Maven Gradle 빌드 캐시 최적화 빌드 시간 10배 단축의 비밀 (0) | 2026.10.08 |
|---|---|
| [Jenkins] Jenkins 백업 스크립트 복구 (0) | 2026.10.07 |
| [Jenkins] SonarQube 연동 불량 코드 자동 차단 시스템 Quality Gate (0) | 2026.10.05 |
| [Jenkins] 병렬 빌드로 파이프라인 속도 혁신하기(Parallel Build) (0) | 2026.10.05 |
| [Jenkins] 멀티브랜치 파이프라인 무한 증식 브랜치 자동화 (0) | 2026.10.04 |