TOPIC/DevOps

Jenkins, ArgoCD로 CI/CD Pipeline 구성하기 (2)

H-Y-E-N 2024. 2. 1. 14:22

안녕하세요. HYEN입니다.

지난 글에서는 CI/CD Pipeline에 대한 전체 Flow와 Pipeline을 구성하기 전에 필요한 설정들에 대해 다뤄보았습니다.

 

지난 글 바로 가기 : https://with-cloud.tistory.com/19.

 

Jenkins, ArgoCD로 CI/CD Pipeline 구성하기 (1)

안녕하세요. HYEN입니다. 드디어 길고 길었던 CI/CD Pipeline 구성이 끝이 났습니다. 🥳🥳 개인적으로, CI/CD Pipeline은 구성할 때마다 어렵다 😟 이거 언제 다 연결하지? 라는 마음이 드는데요. 막상

with-cloud.tistory.com

 

이어서 이번 글에서는 본격적으로 Jenkinsfile을 사용하여 Jenkins 내에서 Job을 생성하고 테스트 하는 과정에 대해 적어보도록 하겠습니다. 😝


Contents

     

    ※ Jenkins와 ArgoCD 등 CI/CD Pipeline 구성에 필요한 모든 리소스는 사전에 배포해 두었습니다.※

     

    4. Jenkins에서 Job 생성 (1) Push the image to ACR

    4.1 Project 생성

    •  [+ New Item] > [Pipeline] 선택 > [Ok] 클릭

     

    4.2 Project Configuration - General

    • Build Triggers 중 [GitHub hook trigger for GITScm polling] 옵션을 선택합니다. 
      • 이를 통해 GitHub Repository에 코드 변경 사항이 push될 때마다 Jenkins Job이 자동으로 트리거 됩니다. 

     

    4.3 Project Configuration - Pipeline

    Jenkinsfile을 작성하기에 앞서 Jenkinsfile에 대해 간략하게 알아보겠습니다.

     

    Jenkinsfile이란?

    • Jenkins Pipeline의 정의를 포함하는 텍스트파일로 Jenkinsfile을 사용하면 CI/CD Pipeline의 구성, 실행, 관리를 코드 형식으로 수행할 수 있습니다.

    • 선언형 파이프라인과 스크립트형 파이프라인의 두 가지 방식으로 정의될 수 있습니다. 
      • 선언형 파이프라인 : 파이프라인 block으로 시작하여 stages, steps, environment 등의 지시어를 포함하는 방식으로 구조가 명확하고, 각 단계를 쉽게 이해할 수 있게 해줍니다. ← 이번 글에서 사용한 방식입니다. 

      • 스크립트형 파이프라인 : Groovy 기반의 구문을 사용하며, node block 내 로직을 작성하여 더 복잡한 파이프라인을 구현할 수 있습니다. 선언형 파이프라인보다 더 고급 기능과 더 많은 제어 구조를 제공하지만 작성하거나 이해하기가 보다 어려운 방식입니다. 


    앞서 말씀 드렸듯이, 이번 글에서는 선언형 파이프라인을 사용하여 Jenkinsfile을 작성하였습니다. 

     

     

    Jenkinsfile 작성 내용은 하기와 같습니다. 

    pipeline {
        agent any
    
        environment {
            BUILD_NUMBER = "v5"
            WEB_IMAGE_NAME = "${ACR_LOGINSERVER}/{respository 명}:${BUILD_NUMBER}"
        }
    
        stages {        
            stage('Login to ACR') {
                steps {
                    script {
                        sh "az login -i"
                        echo "Login to Azure Success"
                        sh "az acr login --name ${ACR_LOGINSERVER}"
                        echo "Login to Azure Container Registry Success"
                    }
                }
            }
            
            stage('Build Docker Image') {
                steps {
                    script {
                        echo "Start to Build the Image"
                        sh "docker build -t ${ACR_LOGINSERVER}/{respository 명}:${BUILD_NUMBER} ."
                        echo "Build Success"
                    }
                }
            }
    
            stage('Push Image to ACR') {
                steps {
                    script {
                        // Docker 이미지를 ACR에 푸시
                        echo "Push to ACR"
                        sh "docker push ${ACR_LOGINSERVER}/{respository 명}:${BUILD_NUMBER}"
                        echo "Push Success"
                    }
                }
            }
        }
    }
    • environment block
      • BUILD_NUMBER : Tag에 대한 변수로 GitHub에 변경 사항이 반영될 때마다 바꿔주어야 합니다. 
      • WEB_IMAGE_NAME : image를 build할 때 사용할 이름으로 이미지와 태그를 지정해 주는 변수입니다. 

    • 'Login to ACR' stage
      • script block : Managed Identity를 사용하여 Azure에 로그인하고 ACR에 로그인 합니다. 

    • 'Build Docker Image' stage
      • Github Repository에 있는 Dockerfile을 사용하여 변수로 지정한 이름:태그로 이미지를 build 합니다. 

    • 'Push Image to ACR' stage
      • build가 완료된 후 docker push 명령어를 사용하여 이미지를 ACR로 push 합니다. 

     

     

    Jenkinsfile 어렵지 않으시죠? 🤗🤗

    다음은 Jenkins에서 Pipeline 정의하는 부분에 대해 알아보겠습니다. 

     

    • Definition의 경우 [Pipeline script from SCM]을 선택합니다. 

    • Repository URL에 GitHub Repository의 URL을 입력합니다. 

    • Credentials
      • GitHub Repository가 Private Repository일 경우 [+ Add] 버튼을 클릭하여 User name과 PAT(Personal Access Token)에 대한 값이 저장된 Credentials을 생성해야 합니다. 

    • Script Path를 Jenkinsfile로 지정합니다. (default) 
      • GitHub Repository에서 Jenkinsfile이 있는 위치를 명시해 주어야 합니다. 
      • Repository 가장 상위에 존재할 경우 위와 같이 Jenkinsfile이라고 명시해 주면 되고 특정 directory 내 존재한다면 directory명/Jenkins로 명시해 주면 됩니다. 

     

    4.3 GitHub 코드 수정 후 Job이 자동으로 trigger 되는지 확인 

    Local에서 코드를 수정한 후 GitHub에 변경 사항을 push 해 보았습니다. 

     

    이후 Jenkins에서 Build가 자동으로 Trigger 되는 것을 확인할 수 있습니다. (하기 이미지 참조) 

     

     

    이렇게 첫 번째 job을 생성해 보았는데요.

    첫 번째 job의 flow를 간단하게 정리하고 넘어가 보도록 하겠습니다.

     

    ➡️ 코드를 수정한 후 GitHub에 변경 사항을 push하면 Jenkins는 GitHub webhook에 의해 변경 사항이 발생했다는 것을 감지합니다. 그 후, Jenkins는 자동으로 job을 실행하여 ACR에 변경 사항이 적용된 이미지를 push합니다. 

     

     

    5. Jenkins에서 Job 생성 (2) Update the manifest file

    5.1 Project 생성 

    • [+ New Item] > [Pipeline] 선택 > [Ok] 클릭

     

    5.2 Project Configuration - General 

    두 번째 job은 첫 번째 job이 성공적으로 완료된 이후 자동으로 trigger 되어야 합니다. 

    이 부분은 첫 번재 job에서 추후 구성할 예정이기 때문에 해당 job에서는 별도로 구성해 주어야 할 것이 없습니다. 🎶🎶

     

    5.3 Project Configuration - Pipeline

    첫 번째 job과 마찬가지로 두 번째 job에서 사용될 Jenkinsfile도 선언형 파이프라인 방식을 사용하였습니다. 

     

    Jenkinsfile 작성 내용은 하기와 같습니다. 

    pipeline {
        agent any
        environment {
            IMAGE_TAG = 'initial'
        }
        stages {
            stage('Clone repository') {
                steps {
                  checkout scm
                }
            }
            stage('Update deploy.yaml') {
                steps {
                    script {
                        IMAGE_TAG=sh(script: "az acr repository show-tags --name {acr명} --repository {repository명} --orderby time_desc --top 1 --output tsv", returnStdout: true).trim()
                        echo "Image Tag: ${IMAGE_TAG}"
                        sh "sed -i 's|image: .*|image: {acr server 주소}/{respository}:${IMAGE_TAG}|' deploy.yaml"
                        }
                }
            }
            stage('Commit and Push') {
                steps {
                    script {
                        withCredentials([string(credentialsId: 'sundls', variable: 'GIT_CREDENTIALS_ID')]){
                            sh 'git config user.email "user email 입력"'
                            sh 'git config user.name "user name 입력"'
                            sh 'git add .'
                            sh 'git commit -m "Update image tag in deploy.yaml"'
                            sh 'git push https://${GIT_CREDENTIALS_ID}@github.com/{user name 입력}/Manifest.git HEAD:main'
                        }
                    }
                }
            }
        }
    }
    • environment block
      • IMAGE_TAG의 경우, 초기 값을 지정해 줍니다.

      • 이후 하기 ‘Update deploy.yaml’ stage에서 변수 값을 update 하게 됩니다. 

    • 'Clone repository' stage
      • Jenkins Project 내 Pipeline 정의 탭에서 설정할 SCM(이 경우 GitHub Repository)으로부터 소스 코드를 체크아웃하는 단계를 의미합니다. 

      • 해당 pipeline은 project 내 정의된 GitHub Repository를 바라보고 있습니다. 

    • 'Update deploy.yaml' stage
      • IMAGE_TAG라는 변수에 ACR에 push된 image 중 가장 최신 버전인 값이 할당되도록 합니다. 
        • orderby라는 매개변수의 값을 time_desc으로 하여 가장 최근에 push된 image의 값부터 출력되도록 정렬합니다. 

        • top이라는 매개변수의 값을 1로 하여 정렬한 값들 중 가장 첫 번째 값만 출력되도록 합니다. 

        • returnStdout는 Jenkins 파이프라인 스크립트에서 사용되는 특정 옵션입니다. 일반적으로 script block 내에서 쉘 명령어를 실행할 경우 명령어의 출력값은 문자열 형태로 터미널 또는 콘솔에 직접 출력됩니다. 하지만 returnStdout:true 옵션을 사용하면 Jenkins가 이 출력을 캡처하여 Jenkins script 내의 변수에 저장하게 됩니다.

        • trim() 함수를 통해 문자열의 앞뒤 공백을 제거합니다. (혹시 모를 오인식을 방지하기 위함입니다.)


    • 'Commit and Push' stage
      • withCredentials
        • Jenkins Credentials에 정의한 GitHub PAT와 관련된 값을 사용하기 위한 선언을 하는 field입니다. 

        • credentialsId 값에 Credentials ID 값을 입력하고 variable 값에는 하기 명령어에서 사용할 변수 값을 입력합니다. ← Credentials 값이 variable에 선언한 값에 저장됩니다.

      • git 명령어
        • git 명령어들을 통해 변경된 값을 GitHub repository에 push 합니다. 

     

     

    다음은 Jenkins에서 Pipeline 정의하는 부분에 대해 알아보겠습니다. 

     

     

    첫 번째 job과 동일한 방식으로 정의해 주시면 됩니다!

     

    5.4 Job이 trigger 되었을 때 이미지 값이 자동으로 변경되는지 확인

    • 현재 이미지 값을 확인합니다. (tag가 v5 임을 확인할 수 있습니다.) 

     

    • Pipeline Project에서 [Build Now]를 클릭합니다. 

     

    • Job이 정상적으로 종료된 것을 Jenkins에서 확인할 수 있습니다. 

     

    • Github에서 버전 값이 변경되었는지 확인합니다. (tag 값이 v5에서 v6으로 변경된 것을 확인할 수 있습니다.)

     

     

    이렇게 Jenkins에서 job을 2개 생성하고 각각의 job들이 목적에 맞게 잘 돌아가는지 확인해 보았습니다.

     

    아직까지는 두 개의 job을 연결하는 부분을 추가해 주지 않았기 때문에 두 개의 job이 연결되어 돌아가지는 않는다는 점 다시 한번 말씀드리며, 이번 글을 마무리하도록 하겠습니다.

     


    job들이 시나리오 대로 잘 돌아가는 것을 확인했으니

    다음 글에서는 ① 두 번째 job에 의해 update 될 deploy.yaml file이 있는 GitHub Repository와 AKS 간 sync를 위해 ArgoCD에서 어떤 구성을 해 주어야 하는지 알아보고 ② CI/CD Pipeline 전 과정을 자동화 해 보도록 하겠습니다. 😜

    728x90
    320x100
    SMALL