본문 바로가기
개발인생/DevOps Engneer

DevOps) CI with Jenkins

by DevOps_901126 2023. 3. 15.
반응형

CI/CD Jenkins 설치 및 설정

 

의의

: Docker에서 app git clone > gradlew build > jar 생성 > jar를 기반으로 image 생성 > repository에 image push 의 작업을 Jenkins 하나로 통합관리한다.

사전작업

  • Jenkins 컨테이터 생성

$ docker run -d -p 8080:8080 -p 50000:50000 \

-v /study/jenkins:/var/jenkins_home \

-v /var/run/docker.sock:/var/run/docker.sock \

-v /usr/bin/docker:/usr/bin/docker \

--name jenkins2 jenkins/jenkins:2.346.2-jdk8

  • 8080 포트를 열고, 50000 포트는 추후 jenkins agent 용으로 사용
  • host : jenkins container를 mount 하여 컨테이너 죽으면 날라가는 data 저장
  • docker.sock 을 mount해야 jenkins pipeline에서 docker 명령어 사용가능
  • ( docker는 plugin으로만 되지않고, docker 명령어 사용을 위한 mount가 필요)
  • 이름생성 및 jenkins , jdk 버전
  • GitLab에 project-gitops > manifest 에 deploy.yaml이 있어야함 (예시)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: msa1  
spec:
  replicas: 1
  selector:
    matchLabels:
      app: msa1
  template:
    metadata:
      labels:
        app: msa1
    spec:
      containers:
      - name: msa1
				// 내가 Push해서 올려놓은 image의 주소
        image: yj0326/msa:msa1v_67
        ports:
        - containerPort: 8080

방법

  1. Jenkins pipeline script를 작성하여 수동 구동
  2. pipeline script를 적은 jenkinfile을 gitlab에 넣어놓고 그 gitlab 주소를 읽어온다
  3. GitLab에 webhook으로 연결하여 git push 시 webhook trigger를 발생하고 jenkins에서는 테스트 빌드 배포까지 자동화 (push 후 바로 자동 배포는 좀 위험한 방법임)

※ 여기에서는 1번으로 작업한다.

Jenkins에서 GitLab 연동할 Credential 생성

  • jenkins 관리 > manage Credentials > Jenkins > Global credentials > Add Credentials
    • Username with password > Username 생성 > password와 ID는 gitlab 계정

 

Jenkins에서 Image Repository 연동할 Credential 생성

  • jenkins 관리 > manage Credentials > Jenkins > Global credentials > Add Credentials
    • Username with pwd > pwd 와 ID 는 DockerHub 계정 or Harbor 계정

 

Jenkins에서 Create a job

  • 이름 정의 > Pipeline 클릭 후 OK
  • Pipeline > Definition = Pipeline script

 

Jenkins pipeline 예시 (Gradle, 설명 있음)

node {
    // Jenkins Build Version for ArgoCD sync
    def IMAGE_TAG = env.BUILD_ID
    
    // Check out
	stage('Git Checkout') {
		echo '>>>>>STAGE: CHECKOUT'
		sh "rm -rf ./* ./.git*"
		git branch: 'main', credentialsId: 'yj0326', url: '<https://gitlab.com/msa3040311/hello1.git>'
	}
	
	// Build
	stage('GRADLE BUILD') {
		echo '>>>>>빌드'
		sh "chmod +x ./gradlew"
		sh "./gradlew build"
		
	}
	
	// plain.jar delete & .jar rename
	stage('Archive Setting'){
		echo 'STAGE: ARCHIVE SETTING - GRADLE'
        
        // build file counting
		def fileCount = sh(script:"find ./build/libs -type f | wc -l", returnStdout: true); 
		echo ">>>>> fileCount = ${fileCount}"
		
		if(fileCount.toInteger() > 1){
		    // get plain jar
			def plainFile = sh(script:"""find ./build/libs -regextype egrep -regex '.*plain.(war|jar)\\$'""", returnStdout: true).trim();
			echo ">>>>> PLAIN FILE DELETE = ${plainFile}"
			
            // plain jar delete
			sh """find ./build/libs -regextype egrep -regex '.*plain.(war|jar)\\$' -exec rm {} \\\\;"""
		}
		def archiveFile = sh(script:"find ./build/libs -type f", returnStdout: true).trim();
		echo ">>>>> ARCHIVE FILE = ${archiveFile}"
		sh "cp ${archiveFile} ./hello1.jar"
	}
	
	// Image Build ((Dockerfile & jar))
	stage('Image Build') {
		echo 'STAGE: IMAGE BUILD'
        
		image = docker.build("yj0326/msa", "-f ./Dockerfile ./")
	}
    
    // Image Push to DockerHub
	stage('Image Push') {
		echo 'STAGE: IMAGE PUSH'
        
        // DockerHub URL = cat ~/.docker/config.json 
		docker.withRegistry("<https://index.docker.io/v1/>", "dockerhub"){
			image.push("msa1v_${IMAGE_TAG}")
		}
	}
	
	// deploy
	// deploy.yaml git clone 후 Deploy.yaml 업데이트, 실행
	stage('GitOps YAML Push') {
		echo 'STAGE: Deploy'

		// try 5
		tryCnt=0
		retry(5){
			tryCnt  
			if(tryCnt>1){
				sleep 5 //5sec
			}

			echo ">>>>> GITOPS CHECKOUT"
			sh "rm -rf ./* ./.git*"
			git branch: "main", credentialsId: 'yj0326', url: '<https://gitlab.com/project-gitops1/manifests.git>'

			echo ">>>>> UPDATE DEPLOY.YAML"
			// sed 치환문법 : s/문자열A/문자열B/g 
			// 문자열A를 문자열B로 치환한다.
			sh "sed -i 's/msa:.*/msa:${IMAGE_TAG}/g' ./msa1/deploy.yaml"

			echo ">>>>> GITOPS COMMIT & PUSH"
			withCredentials([gitUsernamePassword(credentialsId:'yj0326')]){
				sh 'git config --local user.email "yj0326@strato.co.kr"'
				sh 'git config --local user.name "yj0326"'
				sh "git add -A"
				sh "git commit -m 'Update App Image Tag to ${IMAGE_TAG}'"
				sh "git push -u origin HEAD:main"
			}
		}
	}
}

 

Jenkins pipeline 예시 (Maven)

node {
    // Jenkins Build Version for ArgoCD sync
    def IMAGE_TAG = env.BUILD_ID
    
    // Check out
	stage('Git Checkout') {
		echo '>>>>>STAGE: CHECKOUT'
		sh "rm -rf ./* .git*"
		git branch: 'main', credentialsId: 'yj0326', url: '<https://gitlab.com/msa3040311/hello3-mvn.git>'
	}
	
	// Build
	stage('MAVEN BUILD') {
		echo '>>>>>빌드'
		sh "chmod 777 ./mvnw"
            sh "./mvnw clean install"
	}
	
	// jar.original delete & .jar rename
	stage('Original Setting'){
		echo 'STAGE: Original SETTING - MAVEN'
      
        // jar file count
		def fileCount = sh(script:"find ./target -type f -regextype egrep -regex '.*.(war|jar)' | wc -l", returnStdout: true); 
		echo ">>>>> fileCount = ${fileCount}"
		
		// jar file copy
		def originalFile = sh(script:"find ./target -type f -regextype egrep -regex '.*.(war|jar)'", returnStdout: true).trim();
		echo ">>>>> ORIGINAL FILE = ${originalFile}"
		sh "cp ${originalFile} ./hello3.jar"
	}
	
	// Image Build ((Dockerfile & jar))
	stage('Image Build') {
		echo 'STAGE: IMAGE BUILD'
        
		image = docker.build("yj0326/msa", "-f ./Dockerfile ./")
	}
	
	    // Image Push to DockerHub
	stage('Image Push') {
		echo 'STAGE: IMAGE PUSH'
        
        // DockerHub URL = cat ~/.docker/config.json 
		docker.withRegistry("<https://index.docker.io/v1/>", "dockerhub"){
			image.push("msa3_mvn_v_${IMAGE_TAG}")
		}
	}
	
	// deploy
	// deploy.yaml git clone 후 Deploy.yaml 업데이트, 실행
	stage('GitOps YAML Push') {
		echo 'STAGE: Deploy'

		// try 5
		tryCnt=0
		retry(5){
			tryCnt  
			if(tryCnt>1){
				sleep 5 //5sec
			}

			echo ">>>>> GITOPS CHECKOUT"
			sh "rm -rf ./* ./.git*"
			git branch: "main", credentialsId: 'yj0326', url: '<https://gitlab.com/project-gitops1/manifests.git>'

			echo ">>>>> UPDATE DEPLOY.YAML"
			// sed 치환문법 : s/문자열A/문자열B/g 
			// 문자열A를 문자열B로 치환한다.
			sh "sed -i 's/msa:.*/msa:${IMAGE_TAG}/g' ./msa3/deploy.yaml"

			echo ">>>>> GITOPS COMMIT & PUSH"
			withCredentials([gitUsernamePassword(credentialsId:'yj0326')]){
				sh 'git config --local user.email "yj0326@strato.co.kr"'
				sh 'git config --local user.name "yj0326"'
				sh "git add -A"
				sh "git commit -m 'Update App Image Tag to ${IMAGE_TAG}'"
				sh "git push -u origin HEAD:main"
			}
		}
	}
}

 

저장 후 Dashboard > Build Now 클릭

  • Docker images 이미지 생성 확인
  • 연결된 Repository에서 이미지 Push 확인
  • GitLab에 deploy.yaml 생성확인
반응형