mingming

Jenkins + ArgoCD CI/CD Pipeline 구축(1) - Jenkins 본문

DevOps

Jenkins + ArgoCD CI/CD Pipeline 구축(1) - Jenkins

mingming_96 2024. 2. 4. 20:23

지난 포스팅에서 Github Action과 ArgoCD를 이용한 CI/CD Pipeline을 구축해보았습니다. 이번엔 GithubAction 대신 Jenkins를 이용한 CI/CD Pipeline을 구축해보려 합니다.

애플리케이션을 빌드하고 도커 이미지화 하여 EKS 클러스터로 배포하는 CI/CD Pipeline 입니다.

CI/CD Workflow

구축하고자 하는 전체 아키텍쳐는 위의 그림과 같습니다. 다음은 아키텍쳐에 대한 간단한 설명입니다. 

  1. 개발자는 애플리케이션을 수정 후 Git repo에 Commit 후 Push 하게되면 Webhook을 jenkins로 전달하게 된다.
  2. Jenkins에서 git의 webhook을 트리거로 job이 실행되고 해당 job이 완료되면 Jenkins pipeline job이 실행된다.
  3. Jenkins pipeline job이 실행되면 실행 알림이 slack으로 전송된다.
  4. Jenkins pipeline job에서 애플리케이션 빌드 및 도커 빌드가 완료되고 ECR 로 이미지를 push 한다.
  5. ArgoCD로 배포할 manifest repo를 git checkout후 kustomize 명령을 수행하여 새로운 이미지 태그를 업데이트 한다.
  6. 변경 사항을 git commit 후 push를 진행한다.,
  7. ArgoCD에서 변경사항을 감지 후 EKS 클러스터에 배포한다.

Jenkins

Jenkins는 다양한 플러그인을 지원하며 다양한 환경에서 사용 가능합니다. 빌드, 테스트, 배포 등을 자동화하고, 코드 변경 사항이 발생할 때마다 지속적으로 실행할 수 있게 도와주는 오픈소스 CI/CD 도구 입니다. 먼저 Jenkins Job을 생성하기 전에 필요한 Plugin과  Credential을 생성해야 합니다.

Jenkins Plugin

① Git Plugin

Git 플러그인은 Git 저장소를 폴링하거나 가져오고, 체크아웃하고, 브랜치를 만들고, 목록을 조회하며, 병합하고, 태그를 추가하고, 저장소에 푸시하는 등의 기능을 제공합니다.

 

② Kubernetes 

Kubernetes 클러스터에서 동적 에이전트를 실행하기 위한 Jenkins 플러그인으로, Kubernetes에서 실행되는 Jenkins 에이전트의 자동 확장을 자동화합니다. 이 플러그인은 시작된 각 에이전트에 대해 Kubernetes 파드를 생성하고, 각 빌드 후에 해당 파드를 중지합니다.

 

③ Pipeline: Stage View Plugin

Jenkins에서 파이프라인 빌드의 실행 단계를 시각적으로 표시하는 데 사용되는 플러그인으로, 이 플러그인은 Jenkins Blue Ocean과 함께 사용되어 파이프라인의 진행 상황 및 실행 중인 빌드 단계에 대한 정보를 사용자 친화적인 형태로 제공하는 역할을 담당합니다.

 

Jenkins Credentilas

현재 시나리오에서 두 개의 private github 레포지터리에 접근해야 합니다. 따라서 github에서 해당 레포지터리에 대한 권한이 있는 엑세스 토큰을 생성하고 Jenkins에 Credential로 생성합니다.

github 엑세스 토큰 발급

 

Github Credential 생성

다음 항목을 입력하고 Credential을 생성합니다. 해당 Credential을 이용해 Private git 레포지터리에 접근이 가능합니다.

  • Username : Github 사용자 명
  • Password: 엑세스 토큰 
  • ID: Credential 이름

 

Jenkins Webhook

Github Webhook 설정

Github 애플리케이션 레포지터리에 Push 혹은 Merge 이벤트를 감지하고 해당 이벤트를 트리거로 삼아 Jenkins Job을 실행시킬 수 있습니다. 애플리케이션 레포지터리에서 다음과 같이 Webhook 설정을 추가해주어야 합니다.

Payload URL은 Webhook을 수신할 URL을 의미합니다. 현재 구성에선 Jenkins 서버의 URL을 적어주어야 합니다. 해당 설정을 완료하면 push 이벤트에 대한 Webhook을 Jenkins 서버로 전달하게 됩니다.

https://Jenkins_Server/jenkins/github-webhook/

 

Slack Webhook 설정

Slack에서 제공하는 Jenkins CI 앱을 다운받으면 Jenkins와 연동할 수 있는 도메인과 Credential 토큰을 얻을 수 있습니다. 다음과 같이 하위 도메인을 Workspace에 입력 후 토큰 값을 Credential로 등록하면 Slack과 연동이 가능하게됩니다.

 

Jenkins Job

Webhook Job

Github의 Webhook을 받는 Jenkins Job입니다. Git repo에 Push 혹은 Merge가 수행되면 해당 Job이 실행됩니다.

 

Webhook Job이 성공적으로 완료되면 Pipeline Job이 수행되도록 설정했습니다.

 

Pipeline Job

실제 애플리케이션 빌드 및 도커 빌드가 수행되는 파이프라인 입니다.

  • agent
pipeline {
    agent {
        kubernetes {
            yaml '''
            apiVersion: v1
            kind: Pod
            spec:
              containers:
              - name: kaniko
                image: public.ecr.aws/p1v2z7r6/minkian:v2
                command:
                - sleep
                args:
                - infinity
                volumeMounts:
                - name: ecr-secret
                  mountPath: /kaniko/.docker/config.json
                  subPath: config.json
                resources:
                  requests:
                    memory: "1Gi"
                    cpu: "500m" 
                  limits:
                    memory: "2Gi"
                    cpu: "2000m"
              volumes:
              - name: ecr-secret
                secret:
                  secretName: dockerconfig
            '''
        }
    }

 

kubernetes Plugin을 이용해 agent를 파드로 실행시켰다. Docker 이미지 빌드를 위해 Kaniko 이미지를 사용했습니다. Kaniko 이미지는 Google에서 제공하는 도구로 Docker 이미지 빌드하기 위한 도구입니다. 일반적으로 Docker 이미지 빌드를 위해 Docker 엔진 설치 후 CLI를 사용하지만 Kaniko는 Docker 엔진을 필요로 하지 않고 Dockerfile을 처리하고 이미지를 빌드할 수 있습니다.

기존 Google에서 제공하는 이미지에 Kustomize 명령어를 추가 설치한 Custom 이미지를 사용합니다. Kaniko를 통해 Docker 이미지 빌드 후 ECR로 Push하기 위해서 해당 레포지터리에 대한 인증이 필요하고, 이를 위해 ECR로그인 정보가 담긴 config.json 파일을 Secret으로 생성 후 컨테이너의 볼륨으로 마운트합니다.

 

  • environment
 environment {
        IMAGE_NAME = '<AWSID>.dkr.ecr.ap-northeast-2.amazonaws.com/sessac-app'
    }

 

빌드시 사용할 이미지명을 Jenkins pipeline 내 환경변수로 등록해 사용했습니.

 

  • stages
  stages {
        stage("pipeline Start") {
            steps {
                echo 'pipeline start'
            }
            post {
                success {
                    slackSend channel: '#sesac-project', color: 'good', message: "jenkins pipeline start"
                }
                failure {
                    slackSend channel: '#sesac-project', color: 'danger', message: "jenkins pipeline fail"
                }
            }
        }
        
        stage('git sessac-app') {
            steps {
                container('kaniko') {
                    git credentialsId: 'Git-credentials', branch: 'main', url: 'https://github.com/Sessac-project/sessac-app-eks.git'
                }
            }
        }
        
        stage('Docker build') {
            steps {
                container('kaniko') {
                    script {
                        sh '/kaniko/executor --dockerfile Dockerfile --context ${WORKSPACE} --destination=${IMAGE_NAME}:${BUILD_NUMBER} --cleanup && mkdir -p /workspace'
                    }
                }    
            }
            post {
                failure {
                    slackSend channel: '#sesac-project', color: 'danger', message: "jenkins docker config fail"
                }
            }
        }
        
        stage('git manifest') {
            steps {
                container('kaniko') {
                    git credentialsId: 'Git-credentials', branch: 'main', url: 'https://github.com/Sessac-project/sessac-manifest.git

                }
            }
        }
        
        stage('Kustomize') {
            steps {
                container('kaniko') {
                    script {
                        dir('overlays/product') {
                            sh 'kustomize edit set image ${IMAGE_NAME}=${IMAGE_NAME}:${BUILD_NUMBER}'
                        }
                    }
                }
            }
        }
        
        stage('git push') {
            steps {
                script {
                    sh 'git config --global user.email "<사용자 이메일>"'
                    sh 'git config --global user.name "<사용자명>"'
                    sh 'git add .'
                    sh "git commit -m 'sessac-app ${BUILD_TAG} image update'"

                    withCredentials([usernamePassword(credentialsId: 'Git-credentials', usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD')]) {
                        sh "git push https://${USERNAME}:${PASSWORD}@github.com/Sessac-project/sessac-manifest.git HEAD:main"
                    }
                }
            }
        }
        
        stage("Pipeline End") {
            steps {
                echo 'pipeline End'
            }
            post {
                success {
                    slackSend channel: '#sesac-project', color: 'good', message: "jenkins pipeline success"
                }
                failure {
                    slackSend channel: '#sesac-project', color: 'danger', message: "jenkins pipeline fail"
                }
            }
        }
    }
}

 

pipeline Start stage

  • Jenkins pipeline의 시작을 Slack으로 알림을 보내는 단계입니다. 파이프라인이 성공했을 때 jenkins pipeline start 메세지를 전송하도록 구성했습니다.

git sessac-app stage

  • 애플리케이션 소스코드가 담겨있는 git repo를 checkout 하는 단계입니다. 미리 등록해둔  Git-credentials Credential을 이용해 Private git repo에 접근해 main branch를 checkout 합니다.

Docker build stage   

  • Kaniko를 통해 Docker image를 빌드하는 단계입니다. 위에서 정의한 ${IMAGE_NAME} 변수를 사용하고 태그는 Jenkins 내장 변수인 ${BUILD_NUMBER}를 사용해 새로운 이미지 태그를 부여합니다. 빌드 작업이 끝나면 ECR로 이미지 Push를 수행합니다. 모든 작업이 마무리되면 캐시된 중간 이미지를 정리 후 Jenkins 작업 공간을 /workspace로 다시 생성합니다.

git manifest stage

  • ArgoCD가 바라보고 있는 manifest 파일이 등록되어 있는 git repo를 checkout하는 단계입니다.

Kustomize stage

  • kustomize명령을 수행하여 이미지 태그를 변경하는 단계입니다. 앞서 가져온 git repo에서 kustomize명령을 통해 새로운 이미지 태그를 부여합니다. 이때 kustomization.yaml 파일에 새로운 이미지 태그가 기록됩니다.

git push stage

  • 앞서 수행한 kustomize 명령으로 변경된 사항을 commit 후 push 작업을 수행하는 단계입니다.

Pipeline End stage

  • pipeline의 결과를 slack으로 전송하는 단계입니다.

'DevOps' 카테고리의 다른 글

Jenkins Maven Project JDK 버전 설정  (0) 2025.02.08
Jenkins + ArgoCD CI/CD Pipeline 구축(2) - Kustomize, ArgoCD  (1) 2024.02.07
Jenkins Blue/Green Deployment  (0) 2023.09.14
Jenkins 메뉴 소개  (0) 2023.09.11
jenkins on kubernetes  (0) 2023.09.10