jenkins + ecs静态agent实现代码持续集成

Jenkins简介

Jenkins是一个开源软件项目,是基于Java开发的一种持续集成工具,用于监控持续重复的工作,旨在提供一个开放易用的软件平台,使软件项目可以进行持续集成。

部署安装

安装部署步骤此文不再具体讲解,具体的安装步骤可参考官方文档 安装部署
本文中演示所用为一台master节点,一台slave节点,slave节点用于代码拉取,编译打包,镜像构建,服务发布

Java服务CI/CD实现流程详解

工程页面展示

在这里插入图片描述

功能说明

  • 触发动作包括:构建,发布至测试/预发/生产环境,回滚 共五个操作步骤
  • branch:为选取分支(构建阶段此项为必填项)
  • commit为代码仓库当前提交的commitid,此处非必填项,只在代码回滚时使用

功能实现详细配置

参数化构建配置

  • 动作选项

List item

  • 分支选择
    groovy script脚本会在下面详细说明
  • groovy script脚本说明,因为本案例使用的是jenkins "流水线"类型,不能直接使用git插件来获取代码仓库分支,所以针对此类型,需要单独使用groovy脚本实现
  • commitid填写(仅供回滚代码使用)
    在这里插入图片描述

流水线功能代码详解(Pipeline script)

公共部分
import java.util.List
import java.util.ArrayList
import java.net.URLEncoder
#定义多k8s集群的kubectl命令     
def kubectl(cmd,namespace="default") {
    return sh(script: "kubectl --namespace=${namespace} ${cmd}", returnStdout: true)
}
def kubetest(cmd,configfile=/root/.kube/config-test,namespace="default") {
    return sh(script: "kubectl --kubeconfig=${configfile} --namespace=${namespace} ${cmd}", returnStdout: true)
}
def kubepre(cmd,configfile=/root/.kube/config-pre,namespace="default") {
    return sh(script: "kubectl --kubeconfig=${configfile} --namespace=${namespace} ${cmd}", returnStdout: true)
}
#在全局变量中获取构建用户ID
def user = env.BUILD_USER_ID
#模板公共参数,这对同类型pipeline创建,只需修改一下两个变量的value即可
git_repo = "https://gitee.com/xxx/.git"
project_name = "project-demo"
#获取pipeline开始时间
starttime = new Date().format('yyyy/MM/dd HH:mm:ss')
#定义消息通知发送方法(此按时使用钉钉机器人)
def SendMsg(status,envs) {
    if(envs == "build"){
        environment = "编译打包"
    }
    if(envs == "test"){
        environment = "测试环境发布"
    }
    if(envs == "pre"){
        environment = "预生产环境发布"
    }
    if(envs == "prod"){
        environment = "生产环境发布"
    }
    if(envs == "refuse"){
        environment = "无生产环境发布权限,请联系xx同学发布"
    }
    if(envs == "rollback"){
        environment = "生产环境回滚"
    }
    if(status == "false"){
        context = "组件名称: ${JOB_NAME}\\n执行结果: ${environment}失败\\n执行人:$env.BUILD_USER_ID\\n执行时间:$starttime"
    }
    else if(status == "reject"){
        context = "组件名称: ${JOB_NAME}\\n执行结果: ${environment}\\n执行人:$env.BUILD_USER_ID\\n执行时间:$starttime"
    }else{
        context = "组件名称: ${JOB_NAME}\\n执行结果: ${environment}成功\\n执行人:$env.BUILD_USER_ID\\n执行时间:$starttime"
    }
    def msg = """{
        \"msgtype\": \"text\",\"text\" : {\"content\":\"${context}\"}
      }"""
    response = httpRequest (consoleLogResponseBody: true, 
      contentType: 'APPLICATION_JSON_UTF8', 
      acceptType: 'APPLICATION_JSON_UTF8',
      httpMode: 'POST', 
      requestBody: msg,
      url: "https://oapi.dingtalk.com/robot/send?access_token=xxxxxxxxxxxxxxxxx", 
      validResponseCodes: '200')
    return response
}
#定义一个方法来判断分支是否为空
def branch_not_null(){
    if( env.branch.length()>0 ){
        echo "ok"
    }else{
        echo "branch不允许为空,请检查参数......"
        error "branch不允许为空"
    }
}
构建部分
if( 触发动作 == "代码构建"){
    stage('建立任务'){
        try{
    		node('slave-be01') {
    			stage('拉取代码'){
    			    branch_not_null() #判断分支是否为空
    				dir("${BUILD_ID}"){
    					checkout ( [$class: 'GitSCM',
    					branches: [[name: env.branch ]],
    					userRemoteConfigs: [[
    					credentialsId: 'xxx-xxx-xxx-xxx-xxxx', 
    					url: git_repo]]])
    					commitid = sh(returnStdout: true, script: "git --no-pager show -s --format=%H").trim()
    					ref_branch = sh(returnStdout: true, script: "git branch -r --contains ${commitid}").trim()
    					echo commitid
    					
    					sh "echo ${commitid} > /data/jenkins/current_version/${JOB_NAME}.commit" #此处这么做的目的是:commitid作为容器镜像的版本号,写文件的目的就是保证构建和部署是容器镜像版本号的一致性
    				}
    			}
    			stage('编译jar包'){ 
    				dir("${BUILD_ID}"){
    				    sh "/opt/gradle-7.6.1/bin/gradle clean"
    					sh "/opt/gradle-7.6.1/bin/gradle bootJar"
    				}
    			}
    			stage('打包镜像'){ 
    				dir("${BUILD_ID}"){
    					sh "docker build -t ${project_name}:${commitid} ."
    				}
    			}
    			stage('推送镜像'){ 
    				dir("${BUILD_ID}"){
    					sh "docker tag ${project_name}:${commitid} swr.cn-east-3.myhuaweicloud.com/saas-prod/${project_name}:${commitid}"
    					sh "docker push swr.cn-east-3.myhuaweicloud.com/saas-prod/${project_name}:${commitid}"
    				}
    			}
    		}
            SendMsg("SUCCESS","build")
        }catch(all){
            SendMsg("false","build")
        }
    }
}
各环境部署(此演示实例,项目均部署在k8s集群里面)
if( 触发动作 == "发布至测试环境" ){
    try{
       stage('发布至测试环境'){
            node('slave-be01'){
                dir("${BUILD_ID}"){
                    commit = sh(script: "cat /data/jenkins/current_version/${JOB_NAME}.commit", returnStdout: true)
                    echo "${commit}"
                    created = kubetest("set image deployment/${project_name} ${project_name}=swr.cn-east-3.myhuaweicloud.com/saas-prod/${project_name}:${commit}","/root/.kube/config-test","default").trim()
                    echo created
                }  
            }
        }
        SendMsg("SUCCESS","test")
    }catch(all){
        SendMsg("false","test")
    }    
}
if( 触发动作 == "发布至预发环境" ){
    try{
       stage('发布至预发环境'){
            node('slave-be01'){
                dir("${BUILD_ID}"){
                    commit = sh(script: "cat /data/jenkins/current_version/${JOB_NAME}.commit", returnStdout: true)
                    echo "${commit}"
                    created = kubepre("set image deployment/${project_name} ${project_name}=swr.cn-east-3.myhuaweicloud.com/saas-prod/${project_name}:${commit}","/root/.kube/config-pre","default").trim()
                    echo created
                }  
            }
        }
        SendMsg("SUCCESS","pre")
    }catch(all){
        SendMsg("false","pre")
    }    
}
if( 触发动作 == "发布至生产环境" ){
    if ( "$user" == "zhangsan" || "$user"  == "lisi" || "$user"  == "admin"){
        try{
           stage('发布至生产环境'){
                node('slave-be01'){
                    dir("${BUILD_ID}"){
                        commit = sh(script: "cat /data/jenkins/current_version/${JOB_NAME}.commit", returnStdout: true)
                        echo "${commit}"
                        created = kubectl("set image deployment/${project_name} ${project_name}=swr.cn-east-3.myhuaweicloud.com/saas-prod/${project_name}:${commit}","default").trim()
                        echo created
                    }  
                }
            }
            SendMsg("SUCCESS","prod")
        }catch(all){
            SendMsg("false","prod")
        } 
    }else{
        SendMsg("reject","refuse")
        echo "无生产环境发布权限,请联系xx同学发布"
    }       
}
if( 触发动作 == "回滚" ){ #此处必须填写需要回滚版本的commit,以便在镜像仓库中找到对应的容器镜像
    if ( "$user" == "zhangsan" || "$user"  == "lisi" || "$user"  == "admin"){ #只有指定用户才有权限进行回滚
        try{
           stage('生产环境代码回滚'){
                node('slave-be01'){
                    dir("${BUILD_ID}"){
                        created = kubectl("set image deployment/${project_name} ${project_name}=swr.cn-east-3.myhuaweicloud.com/saas-prod/${project_name}:${commit}","default").trim()
                        echo created
                    }  
                }
            }
            SendMsg("SUCCESS","rollback")
        }catch(all){
            SendMsg("false","rollback")
        } 
    }else{
        SendMsg("reject","refuse")
        echo "无回滚权限,请联系xx同学"
    }       
}

对接k8s使用动态容器作为jenkins slave节点jenkins + k8s实现代码持续部署

  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值