본문 바로가기
CI.CD/Jenkins

[Jenkins] Kubernetes(K8s) 완벽 연동: 무중단 배포 자동화의 끝판왕

반응형

앞선 22단계를 통해 애플리케이션 코드를 아름다운 도커 이미지(Docker Image)로 굽고 레지스트리에 푸시(Push)하는 것까지 성공하셨습니다. 이제 남은 과제는 단 하나, "이 이미지를 실서비스가 돌아가고 있는 운영 서버들에 띄워서 고객들에게 선보이는 것"입니다. 현대의 대규모 인프라에서는 이 서버들을 지휘하기 위해 Kubernetes(쿠버네티스, 이하 K8s)라는 막강한 오케스트레이션 툴을 사용합니다. 젠킨스가 빌드마스터라면, K8s는 함대 사령관입니다. 이번 [Jenkins 실무 완벽 가이드] 시리즈에서는 젠킨스가 원격 K8s 클러스터에 접속하여 새로운 버전의 이미지를 무중단(Rolling Update)으로 교체하라고 명령을 내리는 완벽한 배포 연동 전략에 대하여 3,000자 분량으로 아주 치밀하게 딥다이브 해보겠습니다.

🔐 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. 실무 적용 극한의 예제 파헤치기

위의 두 가지 핵심 원리(Kubeconfig 바인딩 + sed 문자열 치환)를 결합한 가장 완벽한 형태의 Declarative Pipeline 코드를 살펴보겠습니다.

pipeline {
    agent any
    environment {
        // 앞선 22단계에서 푸시했던 바로 그 고유 이미지 태그
        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(지속적 배포) 환경으로 안전하고 우아하게 밀어 넣는 실무 연동 기법에 대해 3,000자 분량으로 밀도 있게 다루어 보았습니다. 이제 개발자가 코드를 커밋하면, 젠킨스가 코드를 분석하고, 도커를 굽고, K8s가 새 컨테이너를 하나씩 띄우며 사용자의 끊김 없이(Zero Downtime) 서비스를 교체하는 완벽한 인프라가 완성되었습니다.

하지만 여기서 인프라 팀장님의 이마에 식은땀이 흐르기 시작합니다. "잠깐, 코드를 푸시하기만 하면 아무런 통제도 없이 운영 서버(Production)까지 다이렉트로 배포돼버린다고? 만약 주말 새벽에 신입이 실수로 코드를 푸시해버리면 상용 서버가 바로 작살나는 거잖아!"
그렇습니다. 테스트 환경은 100% 자동화가 맞지만, 실제 돈이 오가는 상용 환경 배포 앞에는 반드시 '사람의 눈(결재)'이 필요합니다. 이어지는 24단계 포스팅에서는 폭주 기관차처럼 질주하는 파이프라인을 잠시 멈춰 세우고 관리자의 버튼 승인을 요구하는 강력한 브레이크, 'Input Step 수동 승인 제어법'에 대해 아주 치밀하게 파헤쳐 보겠습니다!

반응형