IT/CI CD

[Jenkins+Gitlab CI/CD] (4) Jenkins Pipeline Item 생성 및 빌드/배포 테스트

nyub 2023. 9. 21. 17:18
반응형


https://xinyub.tistory.com/172

 

[CI/CD] (1) 깃랩 설치 및 기본 설정

docker, vscode, git 설치는 따로 다루지 않았습니다 Jenkins pipeline에서 docker와 k8s를 사용하기 위해, Jenkins가 올라 가있는 인스턴스에 도커와 k8s 설치되어있습니다. → Jenkins 컨테이너 올릴 때 도커, k8s

xinyub.tistory.com

https://xinyub.tistory.com/173

 

[CI/CD] (2) 젠킨스 설치 및 기본 설정

https://xinyub.tistory.com/172 [CI/CD] (1) 깃랩 설치 및 기본 설정 docker, vscode, git 설치는 따로 다루지 않았습니다 Jenkins pipeline에서 docker와 k8s를 사용하기 위해, Jenkins가 올라 가있는 인스턴스에 도커와 k8s

xinyub.tistory.com

https://xinyub.tistory.com/174

 

[CI/CD] (3) Gitlab Token 발급 및 Jenkins 등록

https://xinyub.tistory.com/172 [CI/CD] (1) 깃랩 설치 및 기본 설정 docker, vscode, git 설치는 따로 다루지 않았습니다 Jenkins pipeline에서 docker와 k8s를 사용하기 위해, Jenkins가 올라 가있는 인스턴스에 도커와 k8s

xinyub.tistory.com


  1. Jenkins Pipeline Item 생성

1. new item → 파이프라인 생성

2. 설정 (Gitlab Connection에는 이전에 만든 Token ID가 있어야합니다.)

3. 계속 설정 (빨간 박스친 URL은 Jenkins Webhook 설정 URL에 사용)

4. 계속 설정 (Secret Token Generate 해주시고, 이 토큰은 Jenkins Webhook 설정 Secret Token에 사용)

5. 파이프라인 작성 후 저장

6. 파이프라인 상세 내용

pipeline {
    agent any

    environment {
        IMAGE_NAME = 'mytest' // 생성되는 Docker 이미지 이름
        NCR_URL = 'df37f1bc-kr2-registry.container.nhncloud.com/lsy-ncr' // NCR URL
    }

    stages {
        stage('Checkout') {
            steps {
                // Git 저장소에서 코드를 가져오기 위해 git 명령을 사용합니다.
                script {
                    // Git 저장소 URL 및 브랜치를 지정합니다.
                    def gitRepoUrl = 'http://125.6.45.180:1980/lsy/lsy-test.git'
                    def gitBranch = 'main'

                    // Git 저장소에서 코드를 가져옵니다.
                    sh "rm -rf *"
                    sh "rm -rf .git"
                    sh "git clone --branch ${gitBranch} ${gitRepoUrl} ."
                }
            }
        }

        stage('Build and Push to NCR') {
            steps {
                // Docker 이미지 빌드, 빌드넘버는 젠킨스에서 확인 할 수 있는 작업번호입니다.
                sh "docker build -t $IMAGE_NAME:${BUILD_NUMBER} ."

                // Docker 이미지를 NCR로 푸시
                sh "docker tag $IMAGE_NAME:${BUILD_NUMBER} $NCR_URL/$IMAGE_NAME:${BUILD_NUMBER}"
                sh "docker push $NCR_URL/$IMAGE_NAME:${BUILD_NUMBER}"
            }
        }


        stage('Clean Up Previous Images') { //이전 버전의 이미지 삭제
            parallel {
                stage('Delete Previous NCR Images') {
                    steps {//버전1부터 현재 이전까지의 버전 모두 삭제. 병렬구조입니다.
                        script {
                            def currentBuildNumber = env.BUILD_NUMBER.toInteger()
                            for (def previousBuildNumber = 1; previousBuildNumber < currentBuildNumber; previousBuildNumber++) {
                                sh "docker rmi -f $NCR_URL/$IMAGE_NAME:$previousBuildNumber || true"
                            }//true문으로 인해 이전 버전이 없어도 오류가 나지 않습니다.
                        }
                    }
                }
                stage('Delete Previous Local Images') {
                    steps {//위와 동일. 로컬 이미지 삭제
                        script {
                            def currentBuildNumber = env.BUILD_NUMBER.toInteger()
                            for (def previousBuildNumber = 1; previousBuildNumber < currentBuildNumber; previousBuildNumber++) {
                                sh "docker rmi -f $IMAGE_NAME:$previousBuildNumber || true"
                            }
                        }
                    }
                }
            }
        }

        
        stage('Update Deployment YAML and Apply') {
            steps {
                script {
                    // BUILD_NUMBER 변수를 사용하여 NCR_URL 태그를 변경
                    sh "sed -i \"s@${NCR_URL}/${IMAGE_NAME}:.*@${NCR_URL}/${IMAGE_NAME}:${BUILD_NUMBER}@g\" ./deployment.yaml"
            
                    // 수정된 deployment.yaml 파일을 kubectl을 사용하여 적용
                    sh 'kubectl apply -f ./deployment.yaml'
                }
            }
        }
    }
}

파이프라인에 대한 대략적인 설명은 주석으로 작성하였습니다.

stage('Clean Up Previous Images') 부분은 기존에 작성하였던 파이프라인 오류를 최대한 잡기 위해 수정하였습니다. 기존에는 직전 버전의 이미지를 삭제하는 구문이었지만, 젠킨스 오류로 인해 직전 빌드 넘버의 이미지가 없는경우 (ex. 빌드 넘버 30 성공 후, 빌드 넘버 31 배포 실패 → 빌드 넘버 32배포 성공 이런식으로 작업이 진행 되었을 경우)에는 오류가 발생하여 이후 stage를 진행하지 못한채 배포가 실패로 마무리 되었습니다. 그렇기 때문에 첫 빌드 넘버부터 직전 빌드 넘버까지 존재하는지 확인 후 이전 빌드 넘버 태그를 가진 모든 이미지를 삭제하는 구문으로 변경하였습니다.

변경으로 인해 기존 1초 미만걸리던 stage('Clean Up Previous Images') 구문이 30초 정도 걸리게 되었습니다. 시간을 단축하고자 전체 삭제 작업을 병렬 구조로 변경하였으며 현재는 10초 언저리 걸리고 있습니다. 시간을 더 단축할 의견이 있다면 공유 부탁드립니다.

 

  2. Jenkins 컨테이너 작업

1. Jenkins 컨테이너 안에서 NCR 로그인

2. NCR에서 이미지 가져와야 하므로, 컨테이너 안에서 인증 Secret 생성 (클러스터에서 이전에 되어있다면 할 필요 없음)

kubectl create secret generic regcred \
--from-file=.dockerconfigjson=/root/.docker/config.json \
--type=kubernetes.io/dockerconfigjson

 

  3. 테스트 파일 준비

1. index.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
</head>
<body>
    <h1>Jenkins TEST 테스트</h1>
</body>
</html>

 

2. Dockerfile

# 베이스 이미지를 선택합니다. 여기서는 공식 Apache 이미지를 사용합니다.
FROM httpd:2.4

# 컨테이너 내부에 웹 사이트 파일을 복사합니다.
COPY index.html /usr/local/apache2/htdocs/

# 웹 서버가 인식할 수 있도록 웰컴 파일 설정을 추가합니다.
RUN echo "DirectoryIndex index.html" >> /usr/local/apache2/conf/httpd.conf

 

3. deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploytest
  labels:
    app: deploy
spec:
  replicas: 2
  selector:
    matchLabels:
      app: deploy
  template:
    metadata:
      labels:
        app: deploy
    spec:
      containers:
      - name: jenkins-web
        image: df37f1bc-kr2-registry.container.nhncloud.com/lsy-ncr/mytest:1 # 사용할 이미지 및 태그. 태그는 상관 없습니다. 어차피 apply 될때 파이프라인에서 바뀜.
        ports:
        - containerPort: 80 # 컨테이너가 노출하는 포트
      imagePullSecrets:
      - name: regcred # 이미지 풀 시크릿의 이름을 여기에 추가

 

  4. 최종 테스트

1. 3개의 파일 Git push

2. Git 업로드 확인

3. 젠킨스 빌드 및 배포 확인

4. Jenkins 컨테이너 안에서 확인 (/var/jenkins_home 에서 확인 가능)

5. 이미지 배포 확인

6. NCR 배포 확인

7. deployment를 외부로 노출시킬 svc 생성

8. LB IP로 서비스 확인

9. 변경 확인 할 수 있도록 소스 수정 후 Git에 Push

10. 다시 LB IP로 서비스 확인. pod까지 무중단 자동배포 확인 완료

반응형