会员登录 - 用户注册 - 设为首页 - 加入收藏 - 网站地图 微服务CI/CD实践-GitOps完整设计与实现!

微服务CI/CD实践-GitOps完整设计与实现

时间:2025-11-05 15:55:56 来源:益强数据堂 作者:人工智能 阅读:505次

 感谢这安静的微服务Cs完环境,没有它们我是践G计实无法完成这篇文章的。

单应用与环境

多应用与环境

CI持续集

成首先准备一个代码库:https://github.com/DevOpsCICDCourse/microservicescicd/blob/main/microservice-demo-service-master.zip

我们来梳理一下CI流水线的整设步骤:

由于此次实现的代码仓库类型为单一存储库,即一个存储库存放多个服务模块代码,微服务Cs完每个子目录为一个服务模块。践G计实 首先,整设我们的微服务Cs完持续集成流水线需要能够正确获取,当前的践G计实commit是哪个服务的代码。 确定好服务,整设然后下载该服务的微服务Cs完代码,进行编译打包、践G计实单元测试、整设代码扫描和构建镜像等步骤。微服务Cs完

如何获取commit的践G计实服务信息?这里我们使用GitLab WebHook功能和Jenkins 的高防服务器job 构建触发器对接来实现。

工作流程是整设:当我在Gitlab提交了代码,会通过GitLab webhook 触发Jenkins Scheduler 作业, 会将此次提交代码所产生的hook data数据信息以POST的方式传给Jenkins Job。此时Jenkins job可以编写使用Generic Hook插件获取此次POST请求传输过来的请求体Body信息。是一段JSON数据, 该job运行后编写Pipeline 解析JSON中的数据拿到所变更的服务模块信息。最后触发对应服务的CI作业进行构建。

CI-Scheduler 作业

此作业只需要开启webhook, 配置触发token(唯一性)。生成hookurl:http://jenkins.idevops.site/generic-webhook-trigger/invoke?token=microservicecicd-scheduler-CI

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)                     //服务构建顺序控制                     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

CI流水线-CI作业

每个微服务创建一个CI作业,具有三个字符串参数:分支名称、commitID、项目ID。

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扩展部分

在原始CI作业的b2b信息网步骤基础上,增加了一个更新环境的步骤。GitOps实践会将当前的基础环境部署文件存放到一个Git仓库中。我们的CI作业在完成镜像上传后,同时更新环境部署文件中的镜像标签信息。(所以我们需要先获取该环境文件并更新上传)

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)                     //替换文件中内容                     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文件内容                     base64Content = newYaml.bytes.encodeBase64().toString()                     // 会有并行问题,同时更新报错                     try {                       UpdateRepoFile(40,"${moduleName}%2fvalues.yaml",base64Content, "${env.branchName}")                       break;                     } catch(e){                       sh "sleep 2"                       continue;                     }                 }             }           }         }  //封装HTTP请求 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 } //获取文件内容 def GetRepoFile(projectId,filePath,branchName){     apiUrl = "projects/${projectId}/repository/files/${filePath}/raw?ref=${branchName}"     response = HttpReq(GET,apiUrl,)     return response.content } //更新文件内容 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

GitOps-CD部分

CD-Scheduler作业

此作业其实也是接收GitLab的webhook请求, 与CI-scheduler作业类似。不同的是这个CD-scheduler作业是用来接收环境仓库的代码变更。开启webhook, 配置触发token。生成hookurl:http://jenkins.idevops.site/generic-webhook-trigger/invoke?token=microservicecicd-scheduler-CD

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)                     //服务构建顺序控制                     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}" )]                         }                     }                 }             }         }     } } 

环境库配置webhook

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

CD流水线-CD作业

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"                   """                 }             }         }     } } 

 

(责任编辑:IT科技)

上一篇:iPadMini232G(极致便携,无限可能)
下一篇:华硕F81se系列电脑的用户在安装Ubuntu12.04系统是出现了错误,导致Ubuntu12.04安装失败,那么是什么原因导致系统安装失败呢?想要在华硕F81se上使用Ubuntu12.04系统怎么办?下面小编就给大家介绍下解决方法。问题:从ubuntu官网上下载了12.04的安装包,下了个usb installer,把系统烧到u盘以后,在u盘里run了下,总是出现下面的错误:Cannot allocate resource for EISA slot 1Cannot allocate resource for EISA slot 2Cannot allocate resource for EISA slot 3Cannot allocate resource for EISA slot 4Cannot allocate resource for EISA slot 5Cannot allocate resource for EISA slot 6Cannot allocate resource for EISA slot 7Cannot allocate resource for EISA slot 8解决方法:华硕电脑开机的时候,按F2进入bios设置,选择security选项,会看到如下图所示:按键盘上的上下键,把光标移动到I/O Interface Security 选项,敲回车,进入下图:默认情况下,这里面的所有的选项都是UNLOCKED 将最后一个选项New Card Interface 设置为LOCKED 这样就可以进入系统了,有人提到要将Wireless NetWork Interface 也设置为LOCED 这样有利于安装,要注意:ODD Interface 和USB Interface 千万不要设置为LOCKED 这样就关闭了USB 和光驱的功能。装完系统以后要把New Card Interface 设置为LOCKED,否则ubuntu 12.04将启动不了,其他的都要设置为UBLOCKED,到这里,基本上系统装的就没问题了。上面就是Ubuntu 12.04在华硕F81se电脑上安装失败的解决方法介绍了,只要你安装本文的步骤实施,你就能轻松使用上Ubuntu 12.04系统了。
推荐内容
  • 小米电视接入电脑教程(一步步教你将电脑与小米电视完美连接,畅享无限可能)
  • 2023 年值得关注的主要网络安全趋势
  • 步步深入MySQL:架构->查询执行流程->SQL解析顺序
  • MySQL统计信息以及执行计划预估方式初探
  • 探讨IPS电视色彩表现的特点与优势(解析IPS电视色彩还原的关键因素及影响因素)
  • MongoDB Stream是如何实现完美数据增量迁移的?