TIL - 20251020

juni·2025년 10월 20일

TIL

목록 보기
158/316

1020 Jenkins + EKS: 완전 자동화 파이프라인 구축


✅ 1. 그랜드 디자인, 우리의 자동화 청사진

  • 문제점: EKS 클러스터에 애플리케이션을 배포하는 과정은 [코드 변경] -> [수동 빌드] -> [Docker 이미지 생성] -> [Docker Hub/ECR 푸시] -> [EKS 접속] -> [kubectl 명령어 실행] 등 복잡하고 수동적인 단계를 거칩니다. 이는 시간이 오래 걸리고, 휴먼 에러를 유발하며, '지속적 배포'라고 부를 수 없습니다.

  • 해결책(청사진): 개발자가 Git에 코드를 Push하는 순간, 이 모든 과정이 자동으로 실행되어 EKS에 즉시 배포되는 "Push-to-Deploy" 파이프라인을 구축합니다.

  • 자동화 시나리오 (Grand Design):

    1. 개발자가 로컬에서 코드를 수정한 뒤 git push 명령어로 GitHub에 코드를 올립니다.
    2. GitHub는 이 Push 이벤트를 감지하고, 등록된 Webhook URL로 Jenkins 서버에 "새 코드 왔어!"라고 알림을 보냅니다.
    3. Jenkins는 Webhook 신호를 받아 해당 프로젝트의 Pipeline(Jenkinsfile)을 즉시 실행시킵니다.
    4. (CI) 파이프라인이 코드를 빌드하고, Docker 이미지를 생성하여 버전 태그(예: 빌드 번호)를 붙인 뒤, Docker Hub나 AWS ECR 같은 이미지 레지스트리에 Push합니다.
    5. (CD) 파이프라인이 EKS 클러스터에 kubectl 명령어로 접근하여, 방금 Push한 새 이미지 태그로 Kubernetes Deployment를 업데이트합니다.
    6. EKS는 Deployment의 변경 사항을 감지하고, 'Rolling Update' 전략에 따라 기존 Pod를 중단 없이 새로운 버전의 Pod로 교체합니다.

✅ 2. Jenkins의 만능 팔다리 준비하기 (Agent 설정)

  • 문제점: Jenkins 컨트롤러(마스터)는 오케스트라의 '지휘자'입니다. 지휘자가 직접 바이올린, 트럼펫, 드럼을 모두 연주(빌드, 테스트, 배포 실행)하면 과부하가 걸리고, 각종 도구(Java, Node.js, Python, Docker, Kubectl...)가 컨트롤러에 뒤섞여 관리가 불가능해집니다.

  • 해결책: Jenkins Agent(Node)라는 '연주자(만능 팔다리)'를 고용하여 실제 작업을 위임합니다.

    • 컨트롤러는 파이프라인을 지시하고, Agent는 Jenkinsfile에 적힌 실제 작업(sh 'npm install', sh 'docker build ...')을 수행합니다.
    • Docker Agent 활용: Agent 자체를 Docker 컨테이너로 구성하면, docker, kubectl, aws-cli 등 필요한 도구들을 미리 설치한 깨끗한 실행 환경을 이미지로 만들어 두고 필요할 때마다 재사용할 수 있습니다.
  • EKS 환경에서의 고급 전략 (Dynamic Agents):

    • Jenkins Kubernetes Plugin을 사용하면, 파이프라인이 시작될 때마다 EKS 클러스터 내부에 Agent Pod를 동적으로 생성하고, 작업이 끝나면 Pod를 자동으로 삭제합니다.
    • 장점: 리소스를 매우 효율적으로 사용하며(탄력성), 무한대에 가깝게 작업을 확장할 수 있습니다.

✅ 3. 파이프라인 1부 - 빌드와 이미지 생성 자동화 (CI)

  • 목표: Git에 푸시된 소스 코드를 실행 가능한 Docker 이미지로 만들어 원격 레지스트리(예: Docker Hub, AWS ECR)에 저장합니다.

  • Jenkinsfile (CI 단계): Jenkinsfile 내에 CI(지속적 통합)를 담당하는 stage를 정의합니다.

// (Jenkinsfile 예시)
pipeline {
    agent any // (또는 agent { label 'docker-agent' } 등 지정)

    stages {
        // ... (Checkout 단계) ...

        // 1. 애플리케이션 빌드 (예: Node.js)
        stage('Build App') {
            steps {
                sh 'npm install'
                sh 'npm run build'
            }
        }

        // 2. Docker 이미지 빌드 및 푸시
        stage('Build & Push Image') {
            steps {
                script {
                    // 이미지 이름 정의 (빌드 번호로 태그 지정)
                    def imageName = "my-username/my-app:${env.BUILD_NUMBER}"
                    
                    // (1) Docker 이미지 빌드
                    sh "docker build -t ${imageName} ."
                    
                    // (2) Docker Hub 로그인 (Credentials 플러그인 사용)
                    // 'dockerhub-creds'는 Jenkins Credentials에 등록한 ID
                    withCredentials([usernamePassword(credentialsId: 'dockerhub-creds', usernameVariable: 'DOCKER_USER', passwordVariable: 'DOCKER_PASS')]) {
                        sh "docker login -u $DOCKER_USER -p $DOCKER_PASS"
                    }
                    
                    // (3) 이미지 푸시
                    sh "docker push ${imageName}"
                    
                    // (4) (중요) 다음 단계를 위해 이미지 이름 저장
                    env.IMAGE_NAME_WITH_TAG = imageName
                }
            }
        }
        // ... (배포 단계로 이어짐)
    }
}
  • 핵심: Credentials 플러그인을 사용하여 민감한 Docker Hub 비밀번호를 스크립트에서 숨기고, env.BUILD_NUMBER 같은 환경 변수를 활용해 이미지 태그를 동적으로 생성합니다.

✅ 4. 파이프라인 2부 - EKS 배포 자동화 (CD)

  • 목표: CI 단계에서 ECR/Docker Hub에 올린 최신 이미지를 가져와, EKS 클러스터의 Deployment에 적용(배포)합니다.

  • 사전 준비: Jenkins Agent는 kubectlaws-cli를 설치하고 있어야 하며, EKS 클러스터에 접근할 수 있는 권한(IAM Role 또는 kubeconfig)이 설정되어 있어야 합니다.

  • Jenkinsfile (CD 단계):

// (Jenkinsfile 예시 - 계속)
        // ... (CI 단계 이후) ...

        // 3. EKS 클러스터에 배포
        stage('Deploy to EKS') {
            steps {
                script {
                    // (1) EKS 클러스터 인증 (AWS Credentials 필요)
                    // 'aws-creds' ID로 인증 후 kubeconfig 업데이트
                    withCredentials([aws(credentialsId: 'aws-creds')]) {
                         sh 'aws eks update-kubeconfig --name my-eks-cluster --region ap-northeast-2'
                    }

                    // (2) Deployment의 이미지 업데이트
                    // 'kubectl set image' 명령어로 롤링 업데이트 트리거
                    // (Deployment 이름: my-app-deploy, 컨테이너 이름: my-app-container)
                    sh "kubectl set image deployment/my-app-deploy my-app-container=${env.IMAGE_NAME_WITH_TAG} --record"
                    
                    // (3) 배포 상태 확인
                    sh "kubectl rollout status deployment/my-app-deploy"
                }
            }
        }
    } // stages 끝
} // pipeline 끝
  • 핵심: kubectl apply -f deployment.yaml 방식은 YAML 파일의 이미지 태그를 직접 수정해야 하는 번거로움이 있습니다. 반면 kubectl set image 명령어는, YAML 파일을 건드리지 않고도 **"어떤 Deployment의 어떤 컨테이너 이미지를 이 태그로 바꿔줘"**라고 EKS에 직접 명령할 수 있어 CD 파이프라인에 매우 유용합니다.

✅ 5. 마지막 스위치, GitHub Webhook 연동

  • 문제점: 파이프라인을 완성했지만, Jenkins가 Git 저장소의 변경을 감지하는 방식이 Poll SCM(주기적 확인)이면, 1분마다 "변경된 거 있어?"라고 물어봐야 하므로 비효율적이고 배포가 즉각적이지 않습니다.

  • 해결책: GitHub Webhook을 사용하여, GitHub가 Jenkins에게 **"지금 Push 왔어!"**라고 능동적으로 알려주게 만듭니다.

➕ 설정 방법

  1. Jenkins 설정:

    • 자동화할 Pipeline 프로젝트의 [구성] > [Build Triggers] 섹션으로 이동합니다.
    • GitHub hook trigger for GITScm polling 옵션을 체크합니다. (이름은 Polling이지만, 실제로는 Webhook을 '수신'하겠다는 의미입니다.)
  2. GitHub 설정:

    • 코드가 있는 GitHub Repository > [Settings] > [Webhooks] > [Add webhook] 클릭
    • Payload URL: http://[내 Jenkins 서버 주소]/github-webhook/
      • (주의: 반드시 /github-webhook/ 경로와 마지막 /까지 정확히 입력해야 합니다.)
    • Content type: application/json
    • Which events...: Just the push event. (기본값)
    • [Add webhook]을 클릭하여 저장합니다.
  • 최종 결과: 이제 개발자가 git push를 하면, GitHub가 즉시 Jenkins의 Webhook URL을 호출하고, Jenkins는 GitHub hook trigger 옵션에 따라 파이프라인을 자동으로 실행시켜 CI(빌드/푸시)와 CD(EKS 배포) 전 과정을 논스톱으로 완료합니다.

📌 요약

  • **자동화 청사진(Grand Design)**은 개발자의 Git Push로부터 EKS 배포까지의 모든 과정을 연결하는 Push-to-Deploy 파이프라인을 구축하는 것입니다.
  • Jenkins Agent는 컨트롤러의 과부하를 막고 깨끗한 빌드 환경을 제공하는 '만능 팔다리' 역할을 하며, EKS 환경에서는 K8s 플러그인으로 동적 생성이 가능합니다.
  • **파이프라인 1부(CI)**는 Jenkinsfilestage를 통해 소스 코드를 빌드하고 docker build, docker push를 실행하여 Docker 이미지를 레지스트리에 저장합니다. (이때 Credentials가 필수입니다.)
  • **파이프라인 2부(CD)**는 kubectl set image 명령어를 사용하여, EKS 클러스터의 Deployment 이미지를 최신 버전으로 교체하도록 명령합니다.
  • GitHub Webhook은 GitHub와 Jenkins를 연결하는 '마지막 스위치'로, Git Push 이벤트를 Jenkins에 즉시 전달하여 파이프라인을 트리거하는 핵심 요소입니다.

0개의 댓글