[DevOps] Jenkins의 CICD 활용법

the Other Object·2022년 12월 24일
0

Jenkins의 CICD활용법

CI : GitOps-Jenkins

CD : Argo





Jenkins를 활용한 빌드 및 배포까지의 과정


  • Jenkins pipeline 실행 시 깃랩으로부터 소스코드 clone
  • 빌드작업을 통해 container 이미지 생성
  • 빌드 된 Docker 컨테이너 이미지를 ECR로 push
  • Enviroment repository 의 k8s manifests 정보를 업데이트 (clone & push)
  • ArgoCD 가 enviroment repository 의 k8s manifests 업데이트 정보를 확인
  • ArgoCD 가 EKS 로 빌드 된 컨테이너 이미지를 배포





  • Jenkins를 활용한 배포 플로우 : 빌드 된 프로젝트를 POD로 올리기 위해 배포 전 도커파일로 컨테이너 이미지 생성, 컨테이너 이미지가 나오면 컨테이너 레지스트리에서 push 이후 ArgoCD가 해당 이미지를 k8s에 배포하게 된다.
  • ArgoCD : 소스코드를 깃에 push 하면 build 및 test 가 트리거되고 container registry에서 업로드 된 Docker 이미지를 pull하여 k8s에 배포하면 업데이트 된 manifest file을 ArogoCD가 k8s와 싱크를 맞춘다.
  • GitOps에서는 배포 정의를 한곳에서 관리하고 한가지 방법으로 배포
  • ArgoCD가 배포에 유리한 이유 : 문제 발생시 롤백이 유용하며 버전 업그레이드가 쉽다. 또한 지속적 빌드/배포가 자동으로 실행되고 원하는 배포 state를 작성해두면 해당 상태에 맞게 배포상태의 지속적 확인과 변경 사항을 체크하여 운영에 반영함에 있어 용이하다.



Jenkins 설치

  1. 터미널에
    brew install jenkins-lts 로 젠킨스를 설치

  1. 젠킨스실행
    brew services start jenkins

  1. localhost:8080 으로 접속 후 해당 경로의 secrets 폴더에서 패스워드 확인
    cat /Users/hjeen/.jenkins/secrets/initialAdminPassword

  1. Gradle wrapper 추가

  1. Build Success



Jenkins PlugIn


  • 추천 플러그인(1) : Gitlab
    • 프로젝트를 커밋 또는 merge, update/pull 실행시 빌드가 트리거 된다.
    • Groovy 스크립트를 생성하거나, Groovy Maven Project에 묶어서 사용해도 된다.
    • webhook을 통해 빌드 작업을 실행하려면 파라미터를 구성해야 한다. (Groovy 스크립트 필드에 추가)
def env = currentBuild.getEnvironment(currentListener)
def map = [:]

if (env.gitlabSourceBranch != null) {
  map['sourceBranch'] = env.gitlabSourceBranch
}

if (env.gitlabTargetBranch != null) {
  map['targetBranch'] = env.gitlabTargetBranch
}

return map

  • 추천 플러그인(2) : Telegram Bot
    • Nara Way Bot 과 같은 기능.
    • telegram @BotFather
    • 젠킨스 config 파일에 botName과 userName을 입력한다.
    • commit 메시지와 함께 빌드,테스트,릴리스,배포의 파이프라인 단계에 대한 노티가 온다.
    • maven 설정파일에 dependecy 추가
<dependency>
	<groupId>
		org.jenkins-ci.plugins
	</groupId>
	<artifactId>
		telegram-notifications
	</artifactId>
	<version>
		1.4.0  //최신버전
	</version>
</dependency>



젠킨스의 선언적 파이프라인 : groovy 호환 script를 사용


  • 선언적 파이프라인의 필수 구조
    • Pipeline ⊃ agent ⊃ stage ⊃ steps
    • pipeline은 젠킨스 파이프라인 플러그인을 호출하기 위한 필수 outer block이다.
    • jenkins Pipeline에 비해 최근에 추가 되었다.
    • pipeline 하위 시스템 위에서 더 간단한 문법 제공
    • 유효한 syntax들은 모두 pipeline{} 블록 안에 존재한다.
    • 블록은 : Section, Directives, Steps, AssignmentStatement 로 구성됨
    • pipeline{} 블록 내에서 코드 최대크기를 제한하는 문제가 있다.
pipeline {
	agent any					      # 실행하기 위해 사용가능한 agent
	stages {					      # pipeline 에서의 work
		stage ('Build') {
			steps {					  # stage 지시문에서 실제 실행 될 steps 정의
				echo 'Building...'
			}
		}
		stage ('Test') {
			steps {
				echo 'Testing...'
			}
		}
		stage ('Deploy') {
			steps {
				echo 'Deploying...'
			}
		}
	}
}

  • 위 pipeline Syntax로 가상의 'ntree'프로젝트로 파이프라인을 작성

pipeline {
	agent any
	options {
		# 빌드가 동시에 올라올때 이전 빌드는 중단하는 option 설정
		disableConcurrentBuilds(abortPrevious: true)		
	}

	stages {

		# git clone을 진행할때 실제 실행 될 steps
		stage('Clone git') {
			steps {

				# private repository 접근을 위해 crefentialId 명시
				git branch: "${branchName}", credentialsId: "ntree-ci-bot", url: "${gitUrl}"
			}
			steps ('check version'){
				steps {
					sh """

						# shell에서 호출할 내용					
						if [ ! -d ${buildVersionPath} ]
						then
							mkdir -p ${buildVersionPath}
						fi
						if [ -f version.properties.ini ]
						then
							cp version.properties.ini ${buildVersionPath}/${projectName}_version.properties
							rm version.properties.ini
						fi
						if [ ! -f ${buildVersionPath}/${projectName}_version.properties]
						then
							cp version.properties ${buildVersionPath}/${projectName}_version.properties
						fi

						cat ${buildVersionPath}/${projectName}_version.properties > version.properties
						export VERSION=\$(cat version.properties)

						if [ ${enviroment} == "DEV" ]
						then
							yarn version --no-git-tag-version --new-version \$VERSION
							yarn version --no-git-tag-version --prerelease
						elif [ ${environment} == "PRD" ]
						then
							yarn version --no-git-tag-version --new-version \$VERSION
							yarn version --no-git-tag-version --path
						fi
					"""
					script {
						version = sh(returnStdot: true, script: """
							VERSION=\$(node -pe "require('./package.json').version")
							echo \$VERSION
						""").trim()
						echo "version is $version"
						tagVersion = version
					}
				}
			}

			stage('Build package') {
				parallel {

					# pipeline은 기본적으로 순차 실행이지만 parallel{} 안의 stage는 병렬 수행
					stage('Build package - DEV') {
						when {expression {enviroment == "DEV"}}
						steps {
							sh 'yarn install && yarn upgrade --pattern "ntree" $$ yarn list --pattern "ntree" --depth=0'
							sh 'yarn build-dev'
						}
					}
					stage('Build package - PRD') {
						when {expression {environment == "PRD"}}
						steps {
							sh 'yarn install'
							sh 'yarn build-prod'
						}
					}
				}
			}

			stage('Image Build') {
				steps {
					
					# pod로 올리기 위해 배포 전 만든 도커이미지파일(Dokerfile은 프로젝트의 Directory 'devops'에 생성)
					sh "docker buid -f devops/Dockerfile -t ${env,IMAGE_REGISTRY}/${repositoryName}:${tagVersion} ."
				}
				post {
					failure {
						echo 'Docker image build failure'
					}
					success {
						echo 'Docker image build success'
					}
				}
			}

			stage('Push image') {
				steps {

					# 빌드된 Docker image를 push
					sh "aws ecr get-login-password --region ${AWS_REGION} | docker login --username AWS --password-stdin ${env.IMAGE_RESISTRY}"
					sh "docker push ${env.IMAGE_RESISTRY}/${repositoryName}:${tagVersion}"
					sh "docker image rm ${env.IMAGE_REGISTRY}/${repositoryName}:${targetVersion}"
				}
				post {
					failure {
						echo 'Docker image build failure'
					}
					success {
						echo 'Docker image build success'
					}
				}
			}

			stage('Push version info') {
				steps {
					sh "echo ${version} > version.properties"
					sh "git config --global user.email \"ntree-ci-bot@ntree.io\""
					sh "git config --global user.name \"ntree-ci-bot\""
				
					# 요청에 보낼 인증정보
					withCredentials([gitUsernamePassword(credentialsId: 'ntree-ci-bot', gitToolName: 'Default')]) {
						sh "git add version.properties && git commit -m \"[ci-skip] Version info updated\" && git push origin HEAD:${branchName}"
					}
					sh "cat version.properties > ${buildVersionPath}/${projectName}_version.properties"
				}
			}
		}
	}
}

0개의 댓글