溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

微服務(wù)CI/CD實(shí)踐之GitOps完整設(shè)計(jì)與實(shí)現(xiàn)的方法教程

發(fā)布時(shí)間:2021-10-19 09:55:31 來源:億速云 閱讀:153 作者:iii 欄目:web開發(fā)

本篇內(nèi)容主要講解“微服務(wù)CI/CD實(shí)踐之GitOps完整設(shè)計(jì)與實(shí)現(xiàn)的方法教程”,感興趣的朋友不妨來看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“微服務(wù)CI/CD實(shí)踐之GitOps完整設(shè)計(jì)與實(shí)現(xiàn)的方法教程”吧!

單應(yīng)用與環(huán)境

微服務(wù)CI/CD實(shí)踐之GitOps完整設(shè)計(jì)與實(shí)現(xiàn)的方法教程

多應(yīng)用與環(huán)境

微服務(wù)CI/CD實(shí)踐之GitOps完整設(shè)計(jì)與實(shí)現(xiàn)的方法教程

CI持續(xù)集

成首先準(zhǔn)備一個(gè)代碼庫:https://github.com/DevOpsCICDCourse/microservicescicd/blob/main/microservice-demo-service-master.zip

微服務(wù)CI/CD實(shí)踐之GitOps完整設(shè)計(jì)與實(shí)現(xiàn)的方法教程

我們來梳理一下CI流水線的步驟:

微服務(wù)CI/CD實(shí)踐之GitOps完整設(shè)計(jì)與實(shí)現(xiàn)的方法教程
  • 由于此次實(shí)現(xiàn)的代碼倉庫類型為單一存儲(chǔ)庫,即一個(gè)存儲(chǔ)庫存放多個(gè)服務(wù)模塊代碼,每個(gè)子目錄為一個(gè)服務(wù)模塊。

  • 首先,我們的持續(xù)集成流水線需要能夠正確獲取,當(dāng)前的commit是哪個(gè)服務(wù)的代碼。

  • 確定好服務(wù),然后下載該服務(wù)的代碼,進(jìn)行編譯打包、單元測(cè)試、代碼掃描和構(gòu)建鏡像等步驟。

如何獲取commit的服務(wù)信息?這里我們使用GitLab WebHook功能和Jenkins 的job 構(gòu)建觸發(fā)器對(duì)接來實(shí)現(xiàn)。

微服務(wù)CI/CD實(shí)踐之GitOps完整設(shè)計(jì)與實(shí)現(xiàn)的方法教程

工作流程是:當(dāng)我在Gitlab提交了代碼,會(huì)通過GitLab webhook 觸發(fā)Jenkins Scheduler 作業(yè),  會(huì)將此次提交代碼所產(chǎn)生的hook data數(shù)據(jù)信息以POST的方式傳給Jenkins Job。此時(shí)Jenkins job可以編寫使用Generic  Hook插件獲取此次POST請(qǐng)求傳輸過來的請(qǐng)求體Body信息。是一段JSON數(shù)據(jù), 該job運(yùn)行后編寫Pipeline  解析JSON中的數(shù)據(jù)拿到所變更的服務(wù)模塊信息。最后觸發(fā)對(duì)應(yīng)服務(wù)的CI作業(yè)進(jìn)行構(gòu)建。

CI-Scheduler 作業(yè)

此作業(yè)只需要開啟webhook,  配置觸發(fā)token(唯一性)。生成hookurl:http://jenkins.idevops.site/generic-webhook-trigger/invoke?token=microservicecicd-scheduler-CI

微服務(wù)CI/CD實(shí)踐之GitOps完整設(shè)計(jì)與實(shí)現(xiàn)的方法教程
微服務(wù)CI/CD實(shí)踐之GitOps完整設(shè)計(jì)與實(shí)現(xiàn)的方法教程

Jenkinsfile

pipeline {  agent any    stages{    stage("GetData"){    steps{     script {      echo "${webHookData}"       data = readJSON  text: "${webHookData}"       println(data)       env.branchName = data.ref - "refs/heads/"      env.commitId = data.checkout_sha      env.projectId = data.project_id      commits = data["commits"]       println("${env.branchName}")      println("${env.commitID}")      println("${env.projectId}")       //env.moduleName = "service01"      changeServices = []                     for(commit in commits) {                         println(commit.id)                          //added                         for (add in commit.added) {                             s = add.split("/") as List                             if (s.size() > 1){                                 if (changeServices.indexOf(s[0]) == -1){                                     changeServices.add(s[0])                                 }                             }                         }                          //modified                         for (m in commit.modified) {                             s = m.split("/") as List                             // println s                             // println s.size()                             // println s[0]                             if (s.size() > 1){                                 // println changeServices.indexOf(s[0])                                 if (changeServices.indexOf(s[0]) == -1){                                     changeServices.add(s[0])                                 }                             }                         }                          //removed                         for (r in commit.removed) {                             s = r.split("/") as List                             println s                             if (s.size() > 1){                                 if (changeServices.indexOf(s[0]) == -1){                                     changeServices.add(s[0])                                 }                             }                         }                     }                      println(changeServices)                     //currentBuild.description = " Trigger by  ${eventType} ${changeServices}      }    }   }    stage('DefineService') {             steps {                 script{                     println(changeServices)                     //服務(wù)構(gòu)建順序控制                     services = ['service02', 'service01']                     for (service in services){                         if (changeServices.indexOf(service) != -1){                             jobName = 'microservicecicd-'+service+'-service-CI'                             build job: jobName, wait: false,  parameters: [string(name: 'branchName', value: "${env.branchName}" ),                                                                            string(name: 'commitId',   value: "${env.commitId}" ),                                                                             string(name: 'projectId',  value: "${env.projectId}" )]                         }                     }                 }             }         }  } }

GitLab 配置WebHook

開啟webhook,配置hookurl:http://jenkins.idevops.site/generic-webhook-trigger/invoke?token=microservicecicd-scheduler-CI

微服務(wù)CI/CD實(shí)踐之GitOps完整設(shè)計(jì)與實(shí)現(xiàn)的方法教程

CI流水線-CI作業(yè)

每個(gè)微服務(wù)創(chuàng)建一個(gè)CI作業(yè),具有三個(gè)字符串參數(shù):分支名稱、commitID、項(xiàng)目ID。

微服務(wù)CI/CD實(shí)踐之GitOps完整設(shè)計(jì)與實(shí)現(xiàn)的方法教程

Jenkinsfile

String branchName = "${env.branchName}" String moduleName = "${JOB_NAME}".split("/")[1].split("-")[1] String srcUrl = "http://gitlab.idevops.site/microservicecicd/microservicecicd-demo-service.git" String commitId = "${env.commitId}" String projectId = "${env.projectId}"  pipeline {     agent { node { label "build" } }      stages {         stage('GetCode') {             steps {                 script {                     checkout([$class: 'GitSCM',                              branches: [[name: "${branchName}"]],                              doGenerateSubmoduleConfigurations: false,                             extensions: [[$class: 'SparseCheckoutPaths',                                          sparseCheckoutPaths: [[path: "${moduleName}"],[path: 'Dockerfile']]]],                              submoduleCfg: [],                              userRemoteConfigs: [[credentialsId: 'gitlab-admin-user',                                                 url: "${srcUrl}"]]])                 }                              }         }          stage("Build&Test"){             steps{                 script{                     echo "Build..........."                      sh """                     cd ${moduleName}                      mvn clean package                      """                 }             }             post {                 always {                     junit "${moduleName}/target/surefire-reports/*.xml"                 }             }         }          stage("SonarScan"){             steps{                 script{                      def sonarDate = sh returnStdout: true, script: 'date  +%Y%m%d%H%M%S'                     sonarDate = sonarDate - "\n"                      withCredentials([string(credentialsId: 'sonar-admin-user', variable: 'sonartoken'),                                     string(credentialsId: 'gitlab-user-token', variable: 'gitlabtoken')]) {                         // some block                         sh """                         cd ${moduleName}                          sonar-scanner \                         -Dsonar.projectKey=${JOB_NAME} \                         -Dsonar.projectName=${JOB_NAME} \                         -Dsonar.projectVersion=${sonarDate} \                         -Dsonar.ws.timeout=30 \                         -Dsonar.projectDescription="xxxxxxx" \                         -Dsonar.links.homepage=http://www.baidu.com \                         -Dsonar.sources=src \                         -Dsonar.sourceEncoding=UTF-8 \                         -Dsonar.java.binaries=target/classes \                         -Dsonar.java.test.binaries=target/test-classes \                         -Dsonar.java.surefire.report=target/surefire-reports \                         -Dsonar.host.url="http://sonar.idevops.site" \                         -Dsonar.login=${sonartoken} \                         -Dsonar.gitlab.commit_sha=${commitId} \                         -Dsonar.gitlab.ref_name=${branchName} \                         -Dsonar.gitlab.project_id=${projectId} \                         -Dsonar.dynamicAnalysis=reuseReports \                         -Dsonar.gitlab.failure_notification_mode=commit-status \                         -Dsonar.gitlab.url=http://gitlab.idevops.site \                         -Dsonar.gitlab.user_token=${gitlabtoken} \                         -Dsonar.gitlab.api_version=v4                          """                      }                   }             }         }          stage("BuildImage"){             steps{                 script{                       withCredentials([usernamePassword(credentialsId: 'aliyun-registry-admin', passwordVariable: 'password', usernameVariable: 'username')]) {                                           env.nowDate = sh  returnStdout: true, script: 'date  +%Y%m%d%H%M%S'                          env.nowDate = env.nowDate - "\n"                           env.releaseVersion = "${env.branchName}"                          env.imageTag = "${releaseVersion}-${nowDate}-${commitId}"                          env.dockerImage = "registry.cn-beijing.aliyuncs.com/microservicecicd/microservicecicd-${moduleName}-service:${env.imageTag}"                          env.jarName = "${moduleName}-${branchName}-${commitId}"                          sh """                              docker login -u ${username} -p ${password}  registry.cn-beijing.aliyuncs.com                              cd ${moduleName} && docker build -t ${dockerImage} -f ../Dockerfile --build-arg SERVICE_NAME=${jarName} .                              sleep 1                              docker push ${dockerImage}                              sleep 1                              docker rmi ${dockerImage}                           """                     }                   }             }         }               } }

GitOps-CI擴(kuò)展部分

在原始CI作業(yè)的步驟基礎(chǔ)上,增加了一個(gè)更新環(huán)境的步驟。GitOps實(shí)踐會(huì)將當(dāng)前的基礎(chǔ)環(huán)境部署文件存放到一個(gè)Git倉庫中。我們的CI作業(yè)在完成鏡像上傳后,同時(shí)更新環(huán)境部署文件中的鏡像標(biāo)簽信息。(所以我們需要先獲取該環(huán)境文件并更新上傳)

微服務(wù)CI/CD實(shí)踐之GitOps完整設(shè)計(jì)與實(shí)現(xiàn)的方法教程
stage("PushFile"){           // when {           //   expression { "${env.branchName}".contains("RELEASE-") }           // }           steps{             script{               if ("${env.branchName}".contains("RELEASE-")){                 println("branchName = branchName")                 env.branchName = "master"                } else {                 env.branchName = "feature"               }                  for (i = 0; i < 3; i++) {                     //下載版本庫文件                      response = GetRepoFile(40,"${moduleName}%2fvalues.yaml", "${env.branchName}")                     //println(response)                                          //替換文件中內(nèi)容                     yamlData = readYaml text: """${response}"""                      println(yamlData.image.version)                     println(yamlData.image.commit)                     yamlData.image.version = "${releaseVersion}-${env.nowDate}"                     yamlData.image.commit  = "${commitId}"                      println(yamlData.toString())                      sh "rm -fr test.yaml"                     writeYaml charset: 'UTF-8', data: yamlData, file: 'test.yaml'                     newYaml = sh returnStdout: true, script: 'cat test.yaml'                                          println(newYaml)                     //更新gitlab文件內(nèi)容                     base64Content = newYaml.bytes.encodeBase64().toString()                      // 會(huì)有并行問題,同時(shí)更新報(bào)錯(cuò)                     try {                       UpdateRepoFile(40,"${moduleName}%2fvalues.yaml",base64Content, "${env.branchName}")                       break;                     } catch(e){                       sh "sleep 2"                       continue;                     }                 }             }           }         }           //封裝HTTP請(qǐng)求 def HttpReq(reqType,reqUrl,reqBody){     def gitServer = "http://gitlab.idevops.site/api/v4"     withCredentials([string(credentialsId: 'gitlab-token', variable: 'gitlabToken')]) {       result = httpRequest customHeaders: [[maskValue: true, name: 'PRIVATE-TOKEN', value: "${gitlabToken}"]],                  httpMode: reqType,                  contentType: "APPLICATION_JSON",                 consoleLogResponseBody: true,                 ignoreSslErrors: true,                  requestBody: reqBody,                 url: "${gitServer}/${reqUrl}"                 //quiet: true     }     return result }   //獲取文件內(nèi)容 def GetRepoFile(projectId,filePath,branchName){     apiUrl = "projects/${projectId}/repository/files/${filePath}/raw?ref=${branchName}"     response = HttpReq('GET',apiUrl,'')     return response.content }  //更新文件內(nèi)容 def UpdateRepoFile(projectId,filePath,fileContent, branchName){     apiUrl = "projects/${projectId}/repository/files/${filePath}"     reqBody = """{"branch": "${branchName}","encoding":"base64", "content": "${fileContent}", "commit_message": "update a new file"}"""     response = HttpReq('PUT',apiUrl,reqBody)     println(response)  }

images

微服務(wù)CI/CD實(shí)踐之GitOps完整設(shè)計(jì)與實(shí)現(xiàn)的方法教程

GitOps-CD部分

微服務(wù)CI/CD實(shí)踐之GitOps完整設(shè)計(jì)與實(shí)現(xiàn)的方法教程

CD-Scheduler作業(yè)

此作業(yè)其實(shí)也是接收GitLab的webhook請(qǐng)求,  與CI-scheduler作業(yè)類似。不同的是這個(gè)CD-scheduler作業(yè)是用來接收環(huán)境倉庫的代碼變更。開啟webhook,  配置觸發(fā)token。生成hookurl:http://jenkins.idevops.site/generic-webhook-trigger/invoke?token=microservicecicd-scheduler-CD

微服務(wù)CI/CD實(shí)踐之GitOps完整設(shè)計(jì)與實(shí)現(xiàn)的方法教程
微服務(wù)CI/CD實(shí)踐之GitOps完整設(shè)計(jì)與實(shí)現(xiàn)的方法教程

Jenkinsfile

pipeline {     agent any      stages {         stage('GetCommitService') {             steps {                 script{                     echo 'Hello World'                     echo "${WebHookData}"                                          // Git Info                     webhookdata = readJSON text: """${WebHookData}"""                     eventType = webhookdata["object_kind"]                     commits = webhookdata["commits"]                     branchName = webhookdata["ref"] - "refs/heads/"                     projectID = webhookdata["project_id"]                     commitID = webhookdata["checkout_sha"]                       changeServices = []                     for(commit in commits) {                         println(commit.id)                          //added                         for (add in commit.added) {                             s = add.split("/") as List                             if (s.size() > 1){                                 if (changeServices.indexOf(s[0]) == -1){                                     changeServices.add(s[0])                                 }                             }                         }                          //modified                         for (m in commit.modified) {                             s = m.split("/") as List                             // println s                             // println s.size()                             // println s[0]                             if (s.size() > 1){                                 // println changeServices.indexOf(s[0])                                 if (changeServices.indexOf(s[0]) == -1){                                     changeServices.add(s[0])                                 }                             }                         }                          //removed                         for (r in commit.removed) {                             s = r.split("/") as List                             println s                             if (s.size() > 1){                                 if (changeServices.indexOf(s[0]) == -1){                                     changeServices.add(s[0])                                 }                             }                         }                     }                      println(changeServices)                     currentBuild.description = " Trigger by  ${eventType} ${changeServices} "                 }             }         }          stage('DefineService') {             steps {                 script{                     println(changeServices)                     //服務(wù)構(gòu)建順序控制                     services = ['service02', 'service01']                     for (service in services){                         if (changeServices.indexOf(service) != -1){                             jobName = 'microservicecicd-'+service+'-service-CD'                             build job: jobName, wait: false,  parameters: [string(name: 'branchName', value: "${branchName}" )]                         }                     }                 }             }         }     } }

環(huán)境庫配置webhook

開啟webhook,配置hookurl:http://jenkins.idevops.site/generic-webhook-trigger/invoke?token=microservicecicd-scheduler-CD

微服務(wù)CI/CD實(shí)踐之GitOps完整設(shè)計(jì)與實(shí)現(xiàn)的方法教程

CD流水線-CD作業(yè)

微服務(wù)CI/CD實(shí)踐之GitOps完整設(shè)計(jì)與實(shí)現(xiàn)的方法教程

Jenkinsfile

String serviceName ="${JOB_NAME}".split("-")[1] String nameSpace = "${JOB_NAME}".split("-")[0].split("/")[-1]   //pipeline pipeline{     agent { node { label "k8s"}}          stages{         stage("GetCode"){             steps{                 script{                     println("${branchName}")                     println("${env.branchName}".contains("RELEASE-"))                     println "獲取代碼"                     checkout([$class: 'GitSCM', branches: [[name: "${env.branchName}"]],                                        doGenerateSubmoduleConfigurations: false,                                        extensions: [[$class: 'SparseCheckoutPaths',                                                      sparseCheckoutPaths: [[path: "${serviceName}"]]]],                                        submoduleCfg: [],                                        userRemoteConfigs: [[credentialsId: 'gitlab-admin-user', url: "http://gitlab.idevops.site/microservicecicd/microservicecicd-env.git"]]])                 }             }         }          stage("HelmDeploy"){             steps{                 script{                   sh """                       kubectl create ns "${nameSpace}-uat"  || echo false                        helm install "${serviceName}" --namespace "${nameSpace}-uat" ./"${serviceName}" ||  helm upgrade "${serviceName}" --namespace "${nameSpace}-uat" ./"${serviceName}"                        helm list --namespace "${nameSpace}-uat"                       helm history "${serviceName}" --namespace "${nameSpace}-uat"                    """                 }             }         }     } }

 微服務(wù)CI/CD實(shí)踐之GitOps完整設(shè)計(jì)與實(shí)現(xiàn)的方法教程

到此,相信大家對(duì)“微服務(wù)CI/CD實(shí)踐之GitOps完整設(shè)計(jì)與實(shí)現(xiàn)的方法教程”有了更深的了解,不妨來實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI