改造原因

团队维护的项目是微服务一共30+的模块,每次修改流水线非常痛苦,要30多个Job逐个修改,所以想有没有一个办法通过一套模版,项目传入参数即可构建,统一管理和更新,后来看到有文章提到Jenkins的Global Shared Library功能,就尝试重构了流水线

改造过程

Global Shared Library的使用方法是先在Git上创建一个项目,在指定目录创建groovy文件,Jenkins中配置好GitLab项目地址,在Job中引用即可,下面是我改造的流程

一、创建Git项目

在Gitlab中创建一个新项目,名字根据实际情况创建即可,目录结构如下

shared-library/
├── vars/                          # 全局函数(核心)
│   └── buildPipeline.groovy       # 你的通用构建模板,名字在Jenkins的Job中引用
├── src/                           # 工具类(可选)
│   └── com/company/Utils.groovy
└── resources/                     # 静态资源(可选)
    └── config.yaml

因为项目是微服务,所以我这模版里主要是针对Java项目构建的,可供参考

//buildPipeline.groovy

def call(Map config) {
    // 1. 参数校验,确保必要的参数都已传入,我这里传入的是服务名称,参数可以有多个根据实际情况填写
    // 如果参数有多个,Key这里需要改成这样:def requiredKeys = ['参数1','参数2','参数3']
    def requiredKeys = ['image']
    for (key in requiredKeys) {
        if (!config.containsKey(key)) {
            error "缺少必要的配置参数: ${key}"
        }
    }

    pipeline {
        agent any
        tools {
            //根据实际情况填写全局配置里的jdk名称
            jdk 'jdk21'
        }
        environment {
            // 从传入的 config 中获取环境变量
            IMAGE_NAME = "${config.image}" //服务名称,Job中通过参数传入
            TAG_VERSION = "${params.tag}" //服务的Tag或者版本,我这里是Job中的参数
            GIT_CREDENTIALS_ID = "jenkins" //Git凭证的ID,需要在Jenkins的凭证管理中添加
            DOCKER_REGISTRY = "xxxx-registry-vpc.cn-guangzhou.cr.aliyuncs.com/xxxx" //实际的镜像仓库地址和名称空间
            DOCKER_REGISTRY_URL = "https://xxxx-registry-vpc.cn-guangzhou.cr.aliyuncs.com" //镜像仓库的URL
            DOCKER_CREDENTIALS_ID = "xxxx-cred" //镜像仓库的凭证ID也是需要在Jenkins的凭证管理中添加
            KUBECONFIG_ID = "k8s" //KuberConfig的凭证ID
            // 组合出完整的镜像地址
            FULL_IMAGE_PATH = "${DOCKER_REGISTRY}/${config.image}"
        }
        stages {
            stage('Git Pull') {
                steps {
                    // 使用参数化的 git 地址和凭证,我这里BRANCH是项目的分支
                    git branch: "${params.BRANCH}", 
                        credentialsId: "${env.GIT_CREDENTIALS_ID}", 
                        url: "http://gitlab.xxxx.com/service/${env.IMAGE_NAME}.git"
                }
            }

            stage('Maven Build') {
                steps {
                    sh '''
                        # 执行 Maven 构建
                        mvn -U clean install -B -Dmaven.test.skip=true
                    '''
                }
            }

            stage('Docker Build') {
                steps {
                    script {
                        // 定义带版本号的镜像名和 latest 镜像名,镜像名名称后面是当前Job的构建号
                        def imageWithTag = "${env.FULL_IMAGE_PATH}:v${env.TAG_VERSION}-${BUILD_NUMBER}"
                        def imageWithLatest = "${env.FULL_IMAGE_PATH}:latest"
                        
                        sh """
                            # 构建镜像
                            docker build -t ${imageWithTag} /var/lib/jenkins/workspace/${JOB_NAME}
                            # 打上 latest 标签
                            docker tag ${imageWithTag} ${imageWithLatest}
                        """
                    }
                }
            }

            stage('Docker Push') {
                steps {
                    script {
                        def imageWithTag = "${env.FULL_IMAGE_PATH}:v${env.TAG_VERSION}-${BUILD_NUMBER}"
                        def imageWithLatest = "${env.FULL_IMAGE_PATH}:latest"
                        
                        //推送镜像到仓库
                        withDockerRegistry([credentialsId: env.DOCKER_CREDENTIALS_ID, url: env.DOCKER_REGISTRY_URL]) {
                            sh "docker push ${imageWithTag}"
                            sh "docker push ${imageWithLatest}"
                        }
                        //修改Kubernetes中使用的Deployment文件内版本号
                        sh "sed -i 's/${env.IMAGE_NAME}:v1/${env.IMAGE_NAME}:v${env.TAG_VERSION}-${BUILD_NUMBER}/g' deploy.yaml"
                    }
                }
            }

            stage('Deployment') {
                steps {
                    //推送到集群中进行更新
                    kubernetesDeploy configs: "deploy.yaml", kubeconfigId: env.KUBECONFIG_ID
                }
            }
        }
    }
}

模版创建完成后要在Jenkins中配置共享库,依次点击设置—>系统设置—>Global Trusted Pipeline Libraries

配置完成后去到Job中引用这个模版

引用完成后即可通过共享库的模版进行构建了,后续服务中只需要填写服务名称,更新流水线时修改模版内容即可,不用再30多个Job逐个修改

发表回复