iT邦幫忙

2023 iThome 鐵人賽

DAY 27
0
DevOps

從0開始學習DevOps,並部署CICD至Java專案中系列 第 27

CI:建立Jenkins Pipeline結合專案項目:Github pull / package / SonarQube/Docker build / push Harbor

  • 分享至 

  • xImage
  •  

專案項目中的配置,勾選參數化建置,選擇Git Parameter

先下載Git Parameter插件,才可以帶入tag標籤參數

https://ithelp.ithome.com.tw/upload/images/20231012/20162058Te2GE9RVPz.png

Name:設為tag,主要是GitHub中有新增新的版本tag時,去重新構建image

https://ithelp.ithome.com.tw/upload/images/20231012/20162058a5LmfRKo2J.png

使用Pipeline Syntax產生stage執行指令,產出的指令會在最下方

https://ithelp.ithome.com.tw/upload/images/20231012/20162058jmi69pUlIK.png

https://ithelp.ithome.com.tw/upload/images/20231012/20162058Bgaz02INwX.png

將 name: '*/main’ 改為 name: '${tag}’,拉取指令版本的程式碼,加到Jenkinsfile中

Step 2 :通過maven構建項目

Shell Script 要在Jenkins的maven目錄下執行指令 ( 也可以配置tool,就不用指向完整路徑,下方說明)

/var/jenkins_home/maven/apache-maven-3.9.4/bin/mvn clean package -DskipTests

https://ithelp.ithome.com.tw/upload/images/20231012/20162058fVRNSZbwrF.png

使用Maven打包時,遇到了問題,專案Java JDK版本為17,但編譯時卻說找不到JDK 17

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project goalLife-api: Fatal error compiling: error: invalid target release: 17 -> [Help 1]

https://ithelp.ithome.com.tw/upload/images/20231012/20162058XrJVx6WmlR.png

  • 先從Jenkins 容器中確認版本

    → 只會帶出Jenkins 的預設版本,並沒有帶出之前(第19天)引入的JDK17

https://ithelp.ithome.com.tw/upload/images/20231012/201620581QhXE0edpX.png

  • 問題來了,我在Jenkins Tools 已經配置過了呀,之前執行也都沒有問題呀~

https://ithelp.ithome.com.tw/upload/images/20231012/20162058fbbe4obEzC.png

  • 後來確認到是因為在使用Pipeline執行script時,會抓取預設的Jenkins JDK,並不會去讀取工具配置的JDK,所以需要在Pipeline Script中指定JDK版本,才會去讀取這邊的tools配置。

    tools {
        jdk 'jdk17' // 這邊的jdk17是在tools自行設定的名稱,要一致才可對應的到
    }
    

Step 3 :通過sonarqube做代碼檢測

使用 Shell Script

一樣要找到Jenkins容器中下載的sonar-scanner路徑位置,從該路徑執行指令運行

基本上都與原先的一樣,特別留意多加上了login,要輸入sonarqube的token。

(產生script 原先無換行,為了方便閱讀這邊換行顯示,記得不需要換行,只需要用空格分隔)

/var/jenkins_home/tools/hudson.plugins.sonar.SonarRunnerInstallation/sonar-scanner/bin/sonar-scanner 
-Dsoner.source=./ -Dsonar.projectname=${JOB_NAME} 
-Dsonar.projectKey=${JOB_NAME} 
-Dsonar.java.binaries=./impl/target/ 
-Dsonar.login=sqa_4f3dd1800174b74e8a725d6360ff3d309fc3af9b

SonarQube 連接失敗

但產生了錯誤:ERROR: SonarQube server [http://localhost:9000] can not be reached

看到這個錯誤應該會就想起,第21天踩過的那個坑,因為在container中,所以需要使用container名稱做連線,那要如何改成 http://sonarqube:9000 連線呢?

(如果SonarQube是使用IP配置的話,可以直接加上參數 -Dsonar.host.url=http://:9000)

直接引用Jenkins System 配置 SonarQube 的設定

使用 withSonarQubeEnv('你的SonarQube servers名稱')

因為這邊已經有token登入配置了,上方的 -Dsonar.login 就不用加囉!

stage('通過sonarqube做代碼檢測') {
      steps {
        withSonarQubeEnv('sonarqube') {
            sh '/var/jenkins_home/tools/hudson.plugins.sonar.SonarRunnerInstallation/sonar-scanner/bin/sonar-scanner -Dsonar.source=./ -Dsonar.projectname=${JOB_NAME} -Dsonar.projectKey=${JOB_NAME} -Dsonar.java.binaries=./impl/target/'
        }
      }
    }

並且要 把選項Environment variables打勾,允許Jenkins將SonarQube服務的連線配置注入到建構的環境變量中。

https://ithelp.ithome.com.tw/upload/images/20231012/20162058CdRkt67zYj.png

這三個階段調整完畢,可以先嘗試build看看結果,遇到問題提早排除。

https://ithelp.ithome.com.tw/upload/images/20231012/201620585zhIi2FLc5.png

(第三個步驟,可以引入JaCoCo做測試報告檢測, 整合在sonarqube一起分析,但這次30天不會特別說明到這個套件。)

Step4:docker build image

第四步驟的pipeline script如下

前面maven打包後預設會儲存在target內的位置,接著使用docker構建image,image名字為 這個Jenkins工作項目的名稱:版本號為tag的版本,最後的 ” . ”表示Dockerfile的位置在專案的當前目錄下的意思,這邊要依照自己的Dockerfile放在專案路徑的位置,去調整。

stage('通過Docker構建image') {
    steps {
		    sh 'docker build -t ${JOB_NAME}:${tag} .'
        echo '通過Docker構建image - SUCCESS'
      }
   }

加上tools maven

這邊的’maven’名稱,是要使用你在tool所設定的命名,接下來使用maven指令就不用指向他的路徑位址了。

pipeline{
  agent any

  tools {
    jdk 'jdk17'
    maven 'maven'
  }
...
}

透過console結果可以清楚看到每一個流程環節

如果有錯誤也會明顯指出是哪一個環節有誤(通常這邊會錯的是路徑位址指錯)

https://ithelp.ithome.com.tw/upload/images/20231012/20162058amHpHvOpEm.png

使用docker images 確認是否構建成功

https://ithelp.ithome.com.tw/upload/images/20231012/20162058Rk9zdJdQY7.png

Step5:將image推送到harbor

把前兩天執行的Harbor指令,轉為pipeline script

https://ithelp.ithome.com.tw/upload/images/20231012/20162058AjLvbyWjrh.png

產出來的指令,把需要替換為環境變數的參數,都加上${…}

stage('將image推送到harbor') {
      steps {
          sh '''docker login -u ${harborUser} -p  ${harborPwd} ${harborUrl}
                docker tag ${JOB_NAME}:${tag} ${harborUrl}/${harborRepo}/${JOB_NAME}:${tag}
                docker push ${harborUrl}/${harborRepo}/${JOB_NAME}:${tag}'''
        echo '將image推送到harbor - SUCCESS'
      }
    }

並且加上pipeline script 環境變數,換為你使用的ip

environment {
      harborUser = 'admin'
      harborPwd = 'Harbor12345'
      harborUrl = '<ip>:80'
      harborRepo = 'goal-life'
  }

再次執行build之後,確認Harbor結果,已推送成功,且版本也為0.1.0跟Github上的tag相符合

https://ithelp.ithome.com.tw/upload/images/20231012/20162058Z5uRGIQ9Qm.png

https://ithelp.ithome.com.tw/upload/images/20231012/20162058XRJjl13rPx.png

完整的CI Pipeline Script

以下 harborUrl ip 記得換為自己的ip

pipeline{
  agent any

  tools {
    jdk 'jdk17'
    maven 'maven'
  }
  
  environment {
      harborUser = 'admin'
      harborPwd = 'Harbor12345'
      harborUrl = '<ip>:80'
      harborRepo = 'goal-life'
  }

  stages {
    stage('pull code') {
      steps {
        echo '---start pull code from git-hub---'
        checkout scmGit(branches: [[name: '${tag}']], extensions: [], userRemoteConfigs: [[credentialsId: 'luluchen622', url: 'https://github.com/luluchen622/goal-life.git']])
        echo '---pull code from git-hub success---'
      }
    }
    stage('compile') {
      steps {
          sh 'mvn clean package -DskipTests'
          echo '---compile success---'
        }
    }
    stage('通過sonarqube做代碼檢測') {
      steps {
        withSonarQubeEnv('sonarqube') {
            sh '/var/jenkins_home/tools/hudson.plugins.sonar.SonarRunnerInstallation/sonar-scanner/bin/sonar-scanner -Dsonar.source=./ -Dsonar.projectname=${JOB_NAME} -Dsonar.projectKey=${JOB_NAME} -Dsonar.java.binaries=./impl/target/'
        }
        echo '---sonarqube success---'
      }
    }

    stage('通過Docker構建image') {
      steps {
				sh 'docker build -t ${JOB_NAME}:${tag} .'
        echo '通過Docker構建image - SUCCESS'
      }
    }
    stage('將image推送到harbor') {
      steps {
          sh '''docker login -u ${harborUser} -p  ${harborPwd} ${harborUrl}
                docker tag ${JOB_NAME}:${tag} ${harborUrl}/${harborRepo}/${JOB_NAME}:${tag}
                docker push ${harborUrl}/${harborRepo}/${JOB_NAME}:${tag}'''
        echo '將image推送到harbor - SUCCESS'
      }
    }
  }
}

上一篇
Jenkins Pipeline是什麼?如何建立?
下一篇
使用Docker Dektop或Minikube下載Kubernetes、安裝kubernetes-dashboard
系列文
從0開始學習DevOps,並部署CICD至Java專案中30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言