컨테이너 인프라 환경(4) 젠킨스 4. 젠킨스 CI/CD

InSeok·2023년 3월 4일
0

젠킨스로 CI/CD 구현

아이템

  • 새롭게 정의할 작업
  • 프로젝트 외에 실제로 작업에 도움이 되는 내용들을 정의하는 것도 아이템을 생성한다고 한다.

프로젝트

  • 모든 작업의 정의와 순서를 모아 둔 전체 작업
  • 프로젝트 생성방식
    • Freestyle
    • Pipeline

아이템 작업

  1. Freestyle project
    • 스타일의 자유도가 높은 방식
    • 사용자가 직접 설정값과 수행할 동작을 입력 가능
    • 입력한 항목의 명세서슬 별도로 저장하지 않아 공유하기 어려움
  2. Pipeline
    • 젠킨스에서 지원하는 고유의 Pipeline 문법으로 코드를 작성해 작업을 정의하는 프로젝트
    • 변수 정의, 반복,조건문등의 프로그래밍 기법을 사용할 수있어 좀 더 복잡한 방식의 작업을 정의할 수 있다.
    • 작성한 코드를 통해 새로운 프로젝트를 바로 생성할 수 있고 코드를 일부만 수정해 재사용하기도 수월하다.
    • 깃허브에 Pipeline 코드로 작성한 파일을 함께 올려 두면 애플리케이션 코드와 배포방법을 함께관리 할 수 있기 때문에 관리 편의성도 높다.
  3. Mult-configuration project
    • 하나의 소스 코드를 여러 조건의 조합으로 나온 경우의 수에 해당하는 환경에 동시에 배포하는 프로젝트
  4. Foler
    • 분류 가능한 디렉터리를 생성한다.
  5. Multibranch Pipeline
    • 하나의 소스 코드 저장소 내에 존재하는 각 브랜치에서 젠킨스 파이프라인 코드가 작성도니 파일을 불러와 한 번에 여러 브랜치에 대한 품질검증, 테스트, 빌드 등의 작업을 할 수있게 해준다.

Freestyle 배포

  • CI/CD 순서
    1. 깃허브에서 ehco-ip를 빌드할 정보가 담긴 파일들을 내려(pull) 받는다.
    2. 받은 파일들을 이용해서 컨테이너 이미지를 빌드한다.
    3. 빌드한 이미지를 레지스트리에 저장(push)한다.
    4. 레지스트리에 저장한 이미지를 쿠버네티스 클러스터에 디플로이먼트로 생성하고 로드밸런서 서비스로 노출한다.
  • General 탭에서 Restrict where this project can be run 체크를 해제
    • 젠킨스의 에이전트가 특정한 레이블을 가지고 있을 때 해당 레이블을 가진 에이전트에서만 실행될 수 있도록 제한을 가한는 옵션
  • 소스 코드 관리탭에서 외부에 있는 소스코드 저장소를 젠킨스 CI로 사용하도록 지정 가능
  • Build 단계를 추가
    • 젠킨스가 작업을 수행할 방법을 선택

    • Execute Shell을 선택하면 입력한 셸 명령어로 빌드 작업이 수행된다.

      docker build -t 192.168.1.10:8443/echo-ip .
      docker push 192.168.1.10:8443/echo-ip
      kubectl create deployment fs-echo-ip --image=192.168.1.10:8443/echo-ip
      kubectl expose deployment fs-echo-ip --type=LoadBalancer --name=fs-echo-ip-svc --port=8080 --target-port=80
    • 도커 이미지 빌드, 도커 이미지 푸시, 디플로이먼트 생성, 로드밸런서를 통한 노출 4단계로 명령어를 구성

    • 저장하고 Build now를 눌러 프로젝트를 실행

    • CI/CD를 수행하면 Build History에 작업이 추가된다.

    • 빌드에 관련한 자세한 내요을 볼려면 Console Output 메뉴를 클릭해야 한다.

      • 콘솔출력을 확인하면 작업의 진척상황이나 실패원인을 파악할 수 있다.
    • 쿠버네티스 클러스터에 디플로이먼트와 로드밸런서가 정상적으로 배치됐는지 확인한다.

  • Freestyle 프로젝트는 젠킨스의 웹화면에 직접 셸 스크립트를입력하기 때문에 빌드 작업의 명령어에 변경이 있을 경우 작업관리 및 변경사항 추적이 쉽지 않다.

Pipeline 프로젝트로 배포

  • Pipeline은 연속적인 작업을 코드 또는 파일로 정의해주는 젠킨스 기능
  • 고유의 문법으로 작성도니 코드 or 이러한 내용을 담고 있는 파일로 구성
  • 젠킨스에서는 Pipeline을 통해서 CI/CD 내용을 코드 or 파일로 정의해 단순히 해당 코드 나 파일을 가져다 쓰면 모든것이 쉽게 되도록 지원한다.
  • 젠킨스 Pipeline 문법
    1. 스크립트 문법
    2. 선언적인 문법
      1. 익숙한 yaml 형식 그대로 사용가능
  • 실행 단계
    • 깃허브에서 소스코드와 젠킨스 내부 작업을 선언적인 문법으로 정의해둔 Jenkinsfil을 내려받는다.
    • 내려받은 Jenkinsfile을 해석해서 작성자의 의도에 맞는 작업을 자동으로 수행
  • General 탭은 프로젝트의 일반적인 설정을 기록하는 곳이다.
    • 프로겢트 설명 및 빌드 작업의 동작방식에 대한 여러 설정이있다.
  • Build Triggers 탭은 빌드를 유발하기 위한 조건을 설정하는 탭
    • 사용자 환경에 따라 빌드에 필요한 조건이 달라질 수있기 때문에 존재한느 설정

    • Build after other projets are built

      • 다른 프로젝트를 빌드한 이후에 이 프로젝트를 빌드한다.
    • Build periodically
      - 주기적으로 프로젝트 빌드를 수행
      - 크론 이란느 스케줄 도구의 문법을 활용해 주기를 작성

      야간 빌드(Nightly build) 매일 최신 버전의 소프트웨어를 배포하는 방식

    • Poll SCM

      • 깃 허브 등의 소스코드 저장소에서 주기적으로 내요을 검사해 빌드한다.
      • 크론 문법을 사용한다.
      • 빌드를수행하기전 소스코드 저장소의 내용에 변경이 있는지 확인하고 이후 변경이 있을 때만 빌드를 수행
    • 빌드 안함

      • 임시로 사용하지 않을 프로젝트 등에 설정 가능
    • Quiet period

      • 빌드를 실행할 때 약간의 지연시간을 주는 옵션
      • 지연시간 범위 이내에서 들어온 요청은 한건을 ㅗ처리하기 때문에 불피요한 작업의 중복 방지 가능
    • 빌드를 원격으로 유발

      • 외부와 연계를 위해 젠킨스의 빌드 작업으 ㄹ외부에서 URL을 호출해 시작할 때 사용
    • 작업 실행 권한의 인증을 위한 토큰을 입력할 수 있다.

    • 토큰을 설정할 경우 <JENKINS_URL>/job/<작업명>/build?token=<토큰 이름>의 형식으로 URL을 호출하면 빌드 작업이 시작된다.

  • Advanced project Options
    • 프로젝트의 고급 옵션으로 설정하는 곳 젠킨스의 플러그인 설치에 따라 생성된다.
  • Pipeline
    • 젠킨스의 빌드 작업 절차를 정의할 수있다.
      • 빌드 작업을 위한 스크립트를 직접 입력하거나 외부의 소스 코드 저장소에서 선언적인 문법으로 작성된 파일을 가지고 와서 빌드 작업을 수행할 수 있다.
      • Definition에서 Pipeline script from SCM으로 깃허브에서 선언적인 문버으로 작성된 파일을 가져와서 실행한다.
      • 젠킨스에서 처리할 작업 정보를 지닌 파일이 Script Path에 Jenkinsfile(기본값)으로 입력돼 있다.\
  • Jenkinsfile 구성요소
    • pipeline

      • 선언적인 문법이 시작하는 부분
      • pipleline {}의 사이에 작업 내용을 작성해야 한다.
    • agent

      • 작업을 수행할 에이전트를 지정하고 필요한 설정을 한다.
      • 지정된 에이전트 내부에서 젠킨스 빌드작업이 실제로 수행되는데 여러가지 방식이 있다.
        • any : 사용가능한 에이전트를 젠킨스가 임의로 지정
        • label: 특정 레이블과 일치하는 에이전트 노드를 지정
        • docker: 에이전트 노드의 이미지를 도커로 지정
        • kubernetes: 에이전트 노드를 쿠버네티스 파드로 지정
    • stages

      • stage들을 모아서 정의하고 이를 순서대로 진행하게 해준다.
    • stage

      • step들을 정의하는 영역
      • 괄호안에 여러 개의 step들을 정의할 수 있는데 이 step들 내부에서 실제로 동작하는 내용들이 정의된다.
      • 젠킨스에서 빌드가 진행될 때 stage별로 진행 단계를 확인 가능
    • steps

      • stage 내부에서 실제 작업 내용을 작성하는 영역

      • stage 내부에 여러 step이 존재할 수 있다.

      • step 영역 내부에서 script, sh, git과 같은 작업(work)를 통해서 실제로 동작

        Jenkinsfile
        
        pipeline {
        	agent any
        	stages {
        		stage('git scm update') {
        			steps {
        				git url: 'https://github.com/IaC-Source/echo-ip.git', branch: 'main'
        			}
        		}
        		stage('docker build and push') {
        			steps {
        				sh '''
        				docker build -t 192.168.1.10:8443/echo-ip .
        				docker push 192.168.1.10:8443/echo-ip
        				'''
        			}
        		}
        		stage('deploy kubernetes') {
        			steps {
        				sh '''
        				kubectl create deployment pl-bulk-prod --image=192.168.1.10:8443/ehco-ip
        				kubectl expose deployment pl-bulk-prod --type=LoadBalancer --port=8080 \
        																							 --target-port=80 --name=pl-bulk-prod-
        		'''
        		}
        	 }
        	}
        }
    • git scm update stage

      • 깃허브로 부터 소스 코드를 내려받는 단계
      • 소스코드를 내려받기 위해 git 작업을 사용
    • 도커 명령을 이용해서 컨테이너 이미지 빌드하고 이미지를 레지스트리에 저장하는 작업을 수행

      • sh 작업을 통해 docker 명령을 사용한다.
    • kubectl 명령으로 전 단계에서 레지스트리에 저장한 이미지를 deployment 로 배포하고, 배포한 디플로이먼트를 로드밸런서 타입으로 노출하는 작업을 수행 ,
      - sh 작업을 통해 kubetl 명령을 사용

      Pipeline 프로젝트로 블로그린 배포

    • 블루그린 전략 : 변경된 애플리케이션을 중단없이 배포하는 방법

    • 파드- 롤링업데이트

      • 파드를 레플리카셋 단위로 나누어 모든 레플리카셋에 속해 있는 파드가 업데이트 된 이후에 레플리카셋을 삭제한다.
      • 이때 내부의 파드 개수가 많으면 업데이트 과정이 길어져 다른 두가지의 버전이 오랫동안 공존하는 경우가 있는데, 이를 방지하기 위해 블루그린 배포전략을 사용한다.
    • 블루그린 배포 전략

      • 모든 파드가 업데이트된 이후에 트래픽을 전달한다.

      • 2개의 디플로이먼트를 생성하고 기존에 배포된 디플로이먼트(블루)로 계속 트래픽을 전달하다가 새로 배포되는 디플로이먼트(그린)에 모든 파드가 업데이트돼 트래픽을 처리하는데 문제가 없을 때 서비스를 모두 새로 배포된 디플로이먼트로 넘긴다.

      • 기존에 디플로이먼트를 삭제한다.

      • 이를 통해 서비스의 중단없이 연속적으로 배포가 가능해진다.

      • 하지만 2배이상의 리소스가 필요하다는 제약 사항이 있다.

        pipeline{
        	agent {
        		kubernetes { #쿠버네티스 파드를 젠킨스 작업이 수행되는 에이전트로 사용
        									#{ } 내부에 에이전트로 사용할 파드에 대한 명세를 yaml 형태로정의
        			yaml '''
        			apiVersion: v1
        			kind: Pod  
        			metadata:
        				labels:
        					app: blue-green-deploy
        				name: blue-green-deploy
        			spec:
        				containers:
        				- name: kustomize
        					image: sysnet4admin/kustomize:3.6.1
        					tty: true
        					volumeMounts:
        					- mountPath: /bin/kubectl
        						name: kubectl
        					command:
        					- cat
        					serviceAccount: jenkins
        					volumes:
        					- name: kubectl
        						hostPath:
        							path: /bin/kubectl
        				'''
        			} #kustomize가 설치된 컨테이너를 에이전트 파드에 포함하고 있다.
        	}
        stages {
        	stage('git scm update') {
        		stpes {
        			git url: 'https://github.com/Iac-Source/blue-green.git', branch: 'main'
        		}
        }
        	stage('define tag') {
        		steps {  #젠킨스 빌드 횟후마다 부여되는 번호에 따라 블루와 그린이 전환되는 것을
        			script { #구현하기 위해 젠킨스 스크립트를 사용 
        				if(env.BUILD_NUMBER.toInteger() % 2 == 1) { #젠킨스 빌드 번호가 홀수일 때 tag 환경변수값을 blue로 설정하고, 짝수일때는 tag 환경변숫값을 greend로설정)
        					env.tag = "blue"
        					} else {
        						env.tag = "green"
        					}
        				}
        			}
        		}
         stage('deploy configmap and deployment') { # ConfigMap을 배포한 다음 디플로이먼트 배포
        	stpes {
        		container('kustomize') {
        		dir('deployment'){   #ㄱ배포작업에 필요한 yaml파일이 깃허브저장소 하위 디플로이먼트 디렉터리에 위치해 있기 때문에 dir('deployment)작어으로 디플로이먼트 디렉터리로 이동해서 작업을 수행하도록 지정
        													# 디플로이먼트 이미지, 이름, 레이블에 설정한 tag 환경변수를 덧붙이는 것을 일일이 수정하지 않기 위해 kustomize명령 수행
        													# 이 kustomize 명령을 사용하기 위해서 container('kustomize)작업으로 컨테이너 내부에서 sh 작업을 수행하도록 작성
        sh '''			
        			kubectl apply -f configmap.yaml 
        			kustomize create --resources ./deployment.yaml
        			echo "deployment new deployment"			
        			kustomize edit add label deploy:$tag -f
        			kustomize edit set namesuffix -- -$tag
        			kustomize edit set image sysnet4admin/dashboard:$tag
        			kustomize build . | kubectl apply -f -
        			echo "retrieve new deployment"
        			kubectl get deployements -o wide
        			'''
        		}
        	}
         }
        }
        stage('switching LB') { #블루그린 배포 전략을 위한 디플로이먼트 배포가 끝난 후 클러스터 외부에서 들어온 요청을 로드밸런서에서 보내줄 대상을 다시 설정하는 단께
        	steps {  #로드 밸런서  설정에 필요한 yaml파일이 깃허브 저장소 하위 service 디렉터리에 위치해 있기 때문에 dir('service') 작업으로 service 디렉터리로 이동해서 작업을 수행
        		container('kustomize') {   #service의 셀렉터 값들을 앞서 설정한 tag 환경변수를 덧붙이는 작업도 편집기 프로그램이 아닌 명령으로 처리하기 위해 kustomize 명령을 사용한다. 이를 위해 container('kustomize') 작업으로 컨테이너 내부에서 sh작업을 통해 다음과 같이 설정
        			dir('service'){#전단계에서 배포한 디플로이먼트의 replicas값과 readyReplicas값을 비교해 값이 같은 경우 배포가 완료됬다고 판단
        				#로드밸런서가 트래픽을 전송하는 대상을 배포 완료된 디플로이먼트로설정한 다음 배포 이전에 존재하는 디플로이먼트를 삭제해 배포 완료된 디플로이먼트로 트래픽을 보내준다.
        sh '''
        			kustomize create --resources ./lb.yaml
        			while true;
        			do
        				export replicas=$(kubectl get deployments \
        				--selector=app=dashboard,deploy=$tag \
        				-o jsonpath --template="{.items[0].status.replicas}")
        				export ready=$(kubectl get deployments \
        				--selector=app=dashboard,deploy=$tag \
        				-o jsonpath --template="{.items[0].status.readyReplicas}")
        				echo "total replicas: $replicas, ready replicas: $ready"
        				if [ "$ready" -eq "$replicas" ]; then
        					echo "tag change and build deployment file by kustomize"
        					kustomize edit add label deploy:$tag -f
        					kustomize build . | kubectl apply -f -
        					echo "delete $tag deployment"
        					kubectl delete deployment --selector=app=dashboard,deploy!=$tag
        					kubectl get deployments -o wide
        					break
        				else
        					sleep 1
        				fi
        				done
        				'''
        			}
        		}
        		}
        	}
        }
        }
        					
  • kubectl get ~ --selector 로 조건에 만족하는 오브젝트 검색
    • 레이블은 쿠버네티스 오브젝트를 검색할 때 사용하는 메타데이터 중 하나이다.
    • kubectl get <오브젝트> —show-labels 명령으로 오브젝트 레이블 확인가능
profile
백엔드 개발자

0개의 댓글