龙空技术网

jenkins maven传统构建改造jenkins pipeline方式

80周辉 356

前言:

此刻朋友们对“multiselectcss”都比较讲究,兄弟们都想要知道一些“multiselectcss”的相关知识。那么小编同时在网上搜集了一些关于“multiselectcss””的相关知识,希望小伙伴们能喜欢,姐妹们一起来了解一下吧!

jenkins 在公司内部用了好几年了,之前一直基于jenkins 插件功能实现 代码下载、编码打包、单元测试、自动化测试、安全渗透测试、部署发布上线。通过jenkins 集成实现devops 功能。

现有的jenkins 发布流程图如下:

我们通过第三方工具+jenkins 整合初步实现了devops一套 开发测试运维一体化。以下是我们使用开源或者第三方软件实现devops 工具链。

我们在查看一下jenkins 现有具体配置

以上设置主要是jenkins参数设置功能,可以通过参数化勾选选择性执行 单元测试、静态代码扫描、自动化测试、自动化渗透测试、是否发布程序等功能

通过勾选选择性执行动作,最后项目构建点击“开始构建”按钮执行

下面源码配置,我们用的是SVN做代码库管理,配置信息如下

设置 构建触发器,在这块设置定时触发,这样我们可以在周末定时实现全量构建。

配置制品JAR 仓库管理

编译打包构建配置

上面截图看不清楚,这里把编译打包命令行代码如下

clean package -U -Dmaven.test.skip=true -Dproject.build.finalName=$BUILD_NAME -Dnacos.server=$cloud_nacos org.jacoco:jacoco-maven-plugin:prepare-agent -Dmaven.test.failure.ignore=true -P$mode --settings $mavenSettings dependency:analyze-report

下面我们通过shell命令行执行相关命令执行

具体命令行代码如下

#如果是周末,则执行单元测试和依赖检查等,忽略构建时选的参数weekDay=$(date +%w)#weekDay=6#if [[ $weekDay -eq 6 || $weekDay -eq 0 ]];then#echo "今天是周六或者周末"#单元测试#unitTest=true#sonar扫描#sonarScan=true#依赖检查#dependencyCheck=true#不进行部署#deploy=false#进行安全扫描#securityScan=true#fi#maven settings.xml目录#mavenSettings="/usr/local/apache-maven-3.5.3-yf2b/conf/settings.xml "#maven打包#mvn clean package -Dmaven.test.skip=true  -Dproject.build.finalName=$BUILD_NAME  -Dnacos.server=$cloud_nacos org.jacoco:jacoco-maven-plugin:prepare-agent -Dmaven.test.failure.ignore=true -P$mode --settings $mavenSettings   dependency:analyze-report if [ $unitTest = 'true' ];thenecho "------------------------执行单元测试------------------------"Dmvn test --settings $mavenSettings fiif [ $sonarScan = 'true' ];thenecho "------------------------执行sonar扫描------------------------"mvn org.jacoco:jacoco-maven-plugin:prepare-agent org.jacoco:jacoco-maven-plugin:report  -Dmaven.test.failure.ignore=true  sonar:sonar -Dsonar.host.url= -Dsonar.login=8063215ecb67d87d6c249f84b76ec87f44fae997 -Dsonar.sources=./src -Dsonar.tests=. -Dsonar.test.inclusions=**/*test*/** -Dsonar.exclusions=**/*test*/** -Dsonar.java.source=1.8 -Dsonar.exclusions=src/main/java/com/base/web/common/adapter/DruidSlf4jLoggerFilterEx.java,**/domain/**,**/vo/**,/*DO.java,src/main/java/com/base/web/openapi/xxxx/**,src/main/java/com/base/web/openapi/base/**,src/main/java/com/base/web/system/**,/*Utils.java,/*Util.java,src/main/java/com/base/web/common/utils/**,src/main/java/com/base/web/common/base/**,src/main/java/com/base/web/xxxx/utils/**,src/main/java/com/base/web/openapi/utils/**,**/*.js,**/*.html,**/*.css -Dsonar.test.exclusions=**/*.js,**/*.html,**/*.css  -Dsonar.language=java  -Dsonar.java.binaries=target/classes  -Dsonar.projectVersion=1.0 -Dsonar.projectName=xxx_dev_java_docker_xxx -Dsonar.sourceEncoding=UTF-8 -Dsonar.projectKey=xxx_dev_java_docker_xxx  -Dsonar.dependencyCheck.summarize=true  -Dsonar.projectBaseDir=/opt/jenkins/workspace/xxx_dev_java_docker_xxx  -Dsonar.java.coveragePlugin=jacoco  -Dsonar.core.codeCoveragePlugin=jacoco -Dsonar.jacoco.reportPath=target/jacoco.exec -Dsonar.coverage.jacoco.xmlReportPaths=target/site/jacoco/jacoco.xmlfi  #if [ $dependencyCheck = 'true' ];then#echo "------------------------执行依赖检查------------------------"#/usr/local/dependency-check/bin/dependency-check.sh --disableRetireJS -s `pwd`/ -f XML -o `pwd`/dependency-check-report.xml#fi#if [ $deploy = 'false' ];then#echo "------------------------不进行部署,部署脚本结束------------------------"#exit 0#fiif [ $deploy = 'true' ];thenecho "------------------------执行部署脚本------------------------"#===========以下是通用配置============#项目名projectName=xxxx-dev-java-docker-xxxx#镜像名称#IMAGE_NAME=192.168.xx.202/xx/sjzxpt/jcpt/v1.0.0/dev:v1.0.0_${BUILD_TIMESTAMP}.${BUILD_NUMBER}IMAGE_NAME=yf.registry.xxx.com/xxx/sjzxpt/jcpt/v1.0.0/dev:v1.0.0_${BUILD_TIMESTAMP}.${BUILD_NUMBER}#IMAGE_NAME=192.168.xxx.202/xxx/sjzxpt/jcpt/v1.0.0/dev:v1.0.0_20210308.47#192.168.xx.202/xxxx/sjzxpt/jcpt/v1.0.0/dev:v1.0.0_${BUILD_TIMESTAMP}.${BUILD_NUMBER}#删除之前的镜像#sudo docker rmi -f $IMAGE_NAMEecho '================生成镜像================'sudo docker build -t $IMAGE_NAME ./echo '================推送镜像================'sudo docker login --username=xxx--password=xxxx  yf.registry.xxxxx.com #登录私有库sudo docker push $IMAGE_NAMEecho '================结束推送镜像================'#新加k8s镜像地址K8S_IMAGE_NAME=yf.p2p.registry.xxxx.com:65001/xxx/sjzxpt/xxx/v1.0.0/dev:v1.0.0_${BUILD_TIMESTAMP}.${BUILD_NUMBER}echo -------------------------------------# 创建k8s容器cat >k8s-$projectName-rc.yaml <<EFOapiVersion: apps/v1  kind: StatefulSet  metadata:    name: $projectName  namespace: xxxx  labels:      app: $projectName  spec:    replicas: 2  revisionHistoryLimit: 10  serviceName: $projectName  selector:      matchLabels:        app: $projectName  template:      metadata:        labels:          app: $projectName     spec:      containers:          - name: $projectName        image: $K8S_IMAGE_NAME        resources:          limits:            cpu: "400m"            memory: "4096Mi"          requests:             cpu: "400m"            memory: "2048Mi"        ports:          - containerPort: 9099          protocol: TCP          imagePullPolicy: Always              env:        - name: TZ          value: Asia/Shanghai      hostAliases:      - hostnames:        - xxx-lf-elkserver-node01        ip: 192.168.xxx.185      - hostnames:        - xxx-lf-elkserver-node02        ip: 192.168.xxx.184      - hostnames:        - xxx-lf-elkserver-node03        ip: 192.168.xxx.186      - hostnames:        - xxxx-lf-elkserver-node04        ip: 192.168.xxx.76      - hostnames:        - xxx-lf-elkserver-node05        ip: 192.168.xxx.78      tolerations:        - key: node-role.kubernetes.io/master          effect: NoSchedule    EFO# 先删除,再创建kubectl delete -f k8s-$projectName-rc.yaml --ignore-not-found=true#sleep 5kubectl create -f k8s-$projectName-rc.yamlecho -------------------------------------# 创建k8s网络服务cat >k8s-$projectName-service.yaml <<EFOapiVersion: v1  kind: Service  metadata:    name: $projectName  namespace: xxx  labels:      app: $projectNamespec:    ports:      - name: $projectName      port: 9099        targetPort: 9099      nodePort: 31662  selector:      app: $projectName   type: NodePort  EFO# service不存在则创建kubectl apply -f k8s-$projectName-service.yaml --record=truetrap "k8s启动成功" SIGHUP SIGINT SIGTERMfiif [ $securityScan = 'true' ];thenecho "------------------------执行安全扫描------------------------"sleep 900currDate=$(date "+%Y-%m-%d")BUILD_ID=dontKillMenohup python3 /home/shell/scan_report/sendAwvsScan2.py '; '19a6790d60cc64004825b2383ec18825e4afa945c736549b98afc1e09b70a0d0e' '303c97e6-17fc-49fa-a45d-2b8d1fd04c38' '11111111-1111-1111-1111-111111111111' 10.xx.0.178 10001 '71087305-73c8-xxxx-a380-34788f1bc4bd' 'sgas' >> /home/shell/scan_report/sendAwvsScan2_$currDate.log &# 缓冲三十秒(可选/可自定义时长),确保构建完成sleep 300# 调用python3脚本 # 传参内容:启动用户,企业微信机器人key,项目名称,登录URL,登录用户,登录密码python3 /home/shell/scan_report/13scan.py 'xxxx' '71087305-73c8-xxxx-a380-34788f1bc4bd' 'xxxxxx平台' '; 'xxxx' 'xxx.zp'exit 0fi

以上代码行简单解释一下,其中大致可以分为 4大块。

1. 编译打包阶段(通过代码行控制 是否单元测试、是否静态代码扫描、是否第三方安全JAR 检查、是否部署发布控制。

2. docker 镜像编译打包上传habor 私有化镜像仓库

3. K8S 创建app pod

4. K8S 创建网络服务

5. 容器发布K8S 后执行自动化安全渗透扫描

下面我们通过jenkins 集成了metersphere 自动化测试

我们又编写了接口自动化后发报告,把报告生产后自动通知企业微信里面

最后构建成功后在发企业微信通知项目构建成功的消息通知

jenkins 构建后日志记录

我们通过以上构建方式发现一个问题,jenkins配置非常繁琐,很多配置功能需要依赖jenkins插件。而且编写的shell 脚本太长了,一旦shell脚本修改或者jenkins 服务器宕机,之前配置全部丢失。(研发环境资源有限,不太可能考虑jenkins 双机备份等工作)

我们能不能简化jenkins 配合,将复杂的配置简化掉,减少shell 容易修改的问题呢? 答案是肯定的。可以利用jenkisn pipeline 改造发布流程。 可以让大家先看一下 效果。

通过上面是不是很直观的知道某个环节花费了多少时间,哪个环节执行失败还是成功。界面是不是美观多了呢。呵呵,我们在看jenkins 里面的配置。

构建头换成

参数化的地方没有太大变化,这里面不做介绍。项目打包变成流水线配置

后面呢,后面都没了。那么东西都弄哪里了呢? 都弄到jenkinsfile 中了

相当于jenkinsfile 文件放到SVN 通过代码库管理起来(这样可以规避SHELL脚本丢失的问题)

利用流水线执行SVN 代码库里面jenkinsfile 脚本来实现以上繁琐的步骤。

下面重点介绍一下jenkinsfile 里面有哪些东西

以上是jenkinsfile 文件定义部分,在后面项目个构建中通过参数换传值替换使用。

下面我们介绍 parameters参数,这里面主要是结合jenkins 勾选功能使用

jenkins 界面选择效果图

通过以上方式,我们再增加jenkins流程 就在上面代码中添加相应parameters 定义,后面我们在jenkinsfile 文件中增加具体实现就行了, 不需要考虑各种jenkins 插件功能了。

下面具体介绍stages 步骤,我们拿初始化参数 为案例来说

这个对应上面parameters定义部分步骤具体实现。

后面的 拉取代码、Maven设置、获取需要部署的模块、编译构建、单元测试、sonar扫描、自动化渗透扫描、打包docker生成镜像、部署到K8S平台、上次制品到JAR仓库中,这里面就不细细展开说明了。

细心的小伙伴可以研究一下jenkinsfile 来具体分析。这类我们只提供实现的思路,具体可以根据实际项目来修改。Jenkinsfile 文件具体内容如下:

import groovy.json.JsonSlurperClassic//默认副本数def DEFAULT_REPLICAS = "1"//默认最小cpu限制def DEFAULT_REQUESTS_CPU = "100m"//默认最小内存限制def DEFAULT_REQUESTS_MEMORY = "2048Mi"//默认最大cpu限制def DEFAULT_LIMITS_CPU = "1000m"//默认最大内存限制def DEFAULT_LIMITS_MEMORY = "4096Mi"//判断是否工作日接口地址  true:是  false: 否def IF_WORD_DAY_URL = ";def DEF_PROJECT_NAMES = "xxx-dev-java-xxx-v2"//定义仓库对象,其中“artifactory”是在jenkins中配置的仓库iddef artiServer = Artifactory.server "artifactory"// Create an Artifactory Maven instance.def rtMaven = Artifactory.newMavenBuild()def buildInfopipeline {    agent any    environment {        //部署配置对象        deployConfig = null        //svn源码地址        svnRespository = ""        //svn凭证id        svnCredentialsId = ""        //harbor地址        harborUrl = ""        //harbor用户名        harborUserName = ""        //harbor密码        harborPwd = ""		// 开发组名,例如:dsj\java\py		devGroupName=""		// 镜像版本		imageVersion=""		// Maven配置		mavenSettings = "/usr/local/apache-maven-3.6.3-jfrog/conf/settings.xml"				// 配置IAST路径		addAgentJar=";        //企业微信推送url        def qyWechatUrl = ""        //推送用户        def pushMember = ""        //企业微信机器人key        def qyWechatKey = ""    }    parameters {        extendedChoice description: '请选择需要构建的项目', descriptionPropertyValue: DEF_PROJECT_NAMES, multiSelectDelimiter: ',', name: 'projectNames', quoteValue: false, saveJSONParameterToFile: false, type: 'PT_SINGLE_SELECT', value: DEF_PROJECT_NAMES,defaultValue: DEF_PROJECT_NAMES, visibleItemCount: 6        booleanParam defaultValue: false, description: '是否进行单元测试(仅工作日生效)', name: 'unitTest'        booleanParam defaultValue: false, description: '是否进行sonar扫描(仅工作日生效)', name: 'sonarScan'        booleanParam defaultValue: false, description: '是否进行自动化渗透扫描(仅工作日、开发环境生效)', name: 'acunetixScan'        booleanParam defaultValue: true, description: '是否部署(仅工作日生效)', name: 'deploy'        booleanParam defaultValue: true, description: '是否推送企业微信(仅开发和生产环境生效)', name: 'pushWechat'    }    options {        //保留最近历史构建记录的数量        buildDiscarder logRotator(artifactDaysToKeepStr: '', artifactNumToKeepStr: '', daysToKeepStr: '7', numToKeepStr: '30')    }    stages {        stage('初始化参数') {            steps {                script {                    if (projectEnv != 'pro'){						//当前是否工作日						def workDay = getWorkDay(IF_WORD_DAY_URL)						echo "workDay: ${workDay}"						if(workDay == 'false'){							unitTest = true							sonarScan = true							acunetixScan = true							deploy = false						}					}                    //只有开发环境需要自动化渗透扫描                    if (projectEnv != 'dev') {                        acunetixScan = false                    }                    echo "unitTest: ${unitTest}"                    echo "sonarScan: ${sonarScan}"                    echo "acunetixScan: ${acunetixScan}"                    echo "deploy: ${deploy}"                    echo "projectEnv: ${projectEnv}"                    //读取公共配置                    def jsonstr = readFile "deploy/config/deployconfig-common.json"                    deployConfig = new JsonSlurperClassic().parseText(jsonstr)                    svnCredentialsId = deployConfig["${projectEnv}"].svnCredentialsId                    harborUrl = deployConfig["${projectEnv}"].harborUrl                    harborUserName = deployConfig["${projectEnv}"].harborUserName                    harborPwd = deployConfig["${projectEnv}"].harborPwd                    qyWechatUrl = deployConfig["${projectEnv}"].qyWechatUrl                    pushMember = deployConfig["${projectEnv}"].pushMember					svnRespository = deployConfig["${projectEnv}"].svnRespository					devGroupName = deployConfig["${projectEnv}"].devGroupName					imageVersion = deployConfig["${projectEnv}"].imageVersion					// 初始化流水线配置文件					initConfig(DEF_PROJECT_NAMES)                    //如果是开发环境,读取自动化渗透扫码所需的参数                    if (projectEnv == 'dev') {                        qyWechatKey = deployConfig["${projectEnv}"].qyWechatKey                    }                }            }        }		stage('拉取代码') {            steps {                //从svn检出                checkout([$class: 'SubversionSCM', additionalCredentials: [], excludedCommitMessages: '', excludedRegions: '', excludedRevprop: '', excludedUsers: '', filterChangelog: false, ignoreDirPropChanges: false, includedRegions: '', locations: [[cancelProcessOnExternalsFail: true, credentialsId: "${svnCredentialsId}", depthOption: 'infinity', ignoreExternalsOption: true, local: '.', remote: "${svnRespository}"]], quietOperation: true, workspaceUpdater: [$class: 'CheckoutUpdater']])            }        }        stage('Maven设置') {            steps {                script {                        // Tool name from Jenkins configuration                        rtMaven.tool = "xxx-Jfrog"                        // 设置产物上传到仓库中的位置                        rtMaven.deployer releaseRepo: 'yf_xxs_releases', snapshotRepo: 'yf_xxx_snapshots', server: artiServer                        //设置处理项目依赖jar包的仓库地址                        rtMaven.resolver releaseRepo: 'yf_virtual', snapshotRepo: 'yf_virtual', server: artiServer                        buildInfo = Artifactory.newBuildInfo()                }            }        }        stage("获取需要部署的模块") {            steps {                    script {                        if (env.ProjectNames == null || env.ProjectNames=="") {                            //如果项目为空,代表是jenkins检查有新代码提交后自动触发构建的,则获取需要构建的子模块                            ProjectNames = getNeedBuildModules(DEF_PROJECT_NAMES)                        }                        echo "需要构建的子模块:${ProjectNames}"                    }            }        }        stage('编译构建') {            steps {                    script {                        //编译整个项目                        rtMaven.run pom: 'pom.xml', goals: 'clean package -U -Dmaven.test.skip=true  -Dproject.build.finalName=${ProjectNames}   -Dmaven.test.failure.ignore=true -P${projectEnv} --settings ${mavenSettings}', buildInfo: buildInfo                    }            }        }        stage('单元测试') {            when {                expression { unitTest == true || unitTest == 'true' }            }            steps {                    script {                        rtMaven.run pom: 'pom.xml', goals: 'test'                    }            }        }        stage('sonar扫描') {            when {                expression { sonarScan == true || sonarScan == 'true' }            }            steps {                    script {                        rtMaven.run pom: 'pom.xml', goals: 'clean install test org.jacoco:jacoco-maven-plugin:prepare-agent org.jacoco:jacoco-maven-plugin:report  -Dmaven.test.failure.ignore=true  sonar:sonar -Dsonar.host.url= -Dsonar.login=8063215ecb67d87d6c249f84b76ec87f44fae997 -Dsonar.sources=. -Dsonar.tests=. -Dsonar.test.inclusions=src/test/java/** -Dsonar.java.source=1.8 -Dsonar.java.coveragePlugin=jacoco  -Dsonar.language=java  -Dsonar.java.binaries=target/classes -Dsonar.exclusions=src/main/java/com/ddddd/hwd/config/**,src/main/java/com/ddddd/hwd/dao/baseky/**,**/*Constants.java,src/main/java/com/ddddd/hwd/domain/**,**/sss_dao_mapperky/*,src/main/java/com/ddddd/hwd/job/**,src/main/java/com/ddddd/hwd/utils/**,src/main/java/com/ddddd/hwd/web/ErrorRequestController.java,com.ahhx.qyfxc.StartMain,src/main/java/com/ddddd/HsyhSjmxAppMain.java,**/*.js,**/*.html,**/*.css -Dsonar.test.exclusions=**/*.js,**/*.html,**/*.css -Dsonar.projectVersion=1.0 -Dsonar.projectName=xxx-dev-java-docker-xxx-v2 -Dsonar.sourceEncoding=UTF-8   -Dsonar.projectKey=xxxx-dev-java-docker-xxxx-v2  -Dsonar.dependencyCheck.summarize=true  -Dsonar.dependencyCheck.reportPath=dependency-check-report.xml -Dsonar.projectBaseDir=/opt/jenkins/workspace/xxxx-dev-java-docker-xxx-v2 -Dsonar.java.coveragePlugin=jacoco  -Dsonar.core.codeCoveragePlugin=jacoco -Dsonar.jacoco.reportPath=target/jacoco.exec -Dsonar.coverage.jacoco.xmlReportPaths=target/site/jacoco/jacoco.xml'                    }            }        }        stage('自动化渗透扫描') {            when {                expression { acunetixScan == true || acunetixScan == 'true' }            }            steps {                    script {                        sh "sleep 30"                        sh "BUILD_ID=dontKillMe"                        sh "nohup python3 /home/shell/scan_report/sendAwvsScan2.py '; '19a6790d60cc64004825b2383ec18825e4afa945c736549b98afc1e09b70a0d0e' '812d5714-93b5-4b23-aaec-6f8df42199c3' '11111111-1111-1111-1111-111111111111' '10.xx.0.51' '10001' '71087305-73c8-44ba-a380-34788f1bc4bd' 'sjjcb' >> /home/shell/scan_report/sendAwvsScan2_${env.BUILD_TIMESTAMP}.log &"                        sh "sleep 30"                        sh "python3 /home/shell/scan_report/13scan.py 'sjjcb' '71087305-73c8-44ba-a380-34788f1bc4bd' 'xxxxx服务平台' ';"                    }            }        }        stage('生成镜像') {            when {                expression { deploy == true || deploy == 'true' }            }            steps {                    script {                        for (projectNames in ProjectNames.split(",")) {                            //每个项目的配置                            def projectConfig = getProjectConfig(projectNames)                            //docker等相关配置文件拷贝到target下							copyConfigToTarget(projectNames)							sh "cp -rf ${WORKSPACE}/target/${ProjectNames}.jar ${WORKSPACE}/target/settings/${ProjectNames}.jar"							sh "sed -i 's#\$projectName#${ProjectNames}.jar#' ${WORKSPACE}/target/settings/Dockerfile"														sh "sed -i 's#\$projectNameJar#${ProjectNames}.jar#' ${WORKSPACE}/target/settings/up.sh"														// 只有开发环境替换							if (projectEnv == 'dev') {							    def nameAndAgent="${ProjectNames} -javaagent:/home/ahhx/agent.jar -Dproject.name=${ProjectNames}"								sh "sed -i 's#\$projectName#${nameAndAgent}#' ${WORKSPACE}/target/settings/up.sh"								sh "sed -i 's#\$addAgentJar#ADD ${addAgentJar} /home/ahhx/.#' ${WORKSPACE}/target/settings/Dockerfile"							}else{							    sh "sed -i 's#\$projectName#${ProjectNames}#' ${WORKSPACE}/target/settings/up.sh"							    addAgentJar=""							    sh "sed -i 's#\$addAgentJar#${addAgentJar}#' ${WORKSPACE}/target/settings/Dockerfile"															}														                            //镜像名称                            imageName = "${harborUrl}/${harborUserName}/${devGroupName}/${projectNames}/${imageVersion}/${projectEnv}:${imageVersion}_${env.BUILD_TIMESTAMP}.${env.BUILD_NUMBER}"                            //构建镜像                            sh "sudo docker build --build-arg env=${projectEnv} --build-arg projectNames=${projectNames} -t ${imageName} ${WORKSPACE}/target/settings"                            //harbor登录                            sh "sudo docker login --username=${harborUserName} --password=${harborPwd} ${harborUrl}"                            //推送镜像                            sh "sudo docker push ${imageName}"                        }                    }            }        }        stage('部署到K8S平台') {            when {                expression { deploy == true || deploy == 'true' }            }            steps {                    script {                        for (projectNames in ProjectNames.split(",")) {                            //定义命名空间                            def nameSpace = "sjjcb"                            //镜像名称                            imageName = "${harborUrl}/${harborUserName}/${devGroupName}/${projectNames}/${imageVersion}/${projectEnv}:${imageVersion}_${env.BUILD_TIMESTAMP}.${env.BUILD_NUMBER}"                            echo  "镜像名称: ${imageName}"							//部署副本数                            def replicas = deployConfig["${projectEnv}"] && deployConfig["${projectEnv}"]["replicas"] ? deployConfig["${projectEnv}"]["replicas"] : DEFAULT_REPLICAS                            echo  "部署副本数: ${replicas}"							//最小cpu限制                            def requestsCpu = deployConfig["${projectEnv}"] && deployConfig["${projectEnv}"]["requestsCpu"] ? deployConfig["${projectEnv}"]["requestsCpu"] : DEFAULT_REQUESTS_CPU                            echo  "最小cpu限制: ${requestsCpu}"							//最小内存限制                            def requestsMemory = deployConfig["${projectEnv}"] && deployConfig["${projectEnv}"]["requestsMemory"] ? deployConfig["${projectEnv}"]["requestsMemory"] : DEFAULT_REQUESTS_MEMORY                            //默认最大cpu限制                            def limitsCpu = deployConfig["${projectEnv}"] && deployConfig["${projectEnv}"]["limitsCpu"] ? deployConfig["${projectEnv}"]["limitsCpu"] : DEFAULT_LIMITS_CPU                            echo  "默认最大cpu限制: ${limitsCpu}"							//默认最大内存限制                            def limitsMemory = deployConfig["${projectEnv}"] && deployConfig["${projectEnv}"]["limitsMemory"] ? deployConfig["${projectEnv}"]["limitsMemory"] : DEFAULT_LIMITS_MEMORY                            echo  "默认最大内存限制: ${limitsMemory}"							def projectName = deployConfig["${projectEnv}"] && deployConfig["${projectEnv}"]["projectName"] ? deployConfig["${projectEnv}"]["projectName"] : "TEST_PROJECT"                            def containerPort = deployConfig["${projectEnv}"] && deployConfig["${projectEnv}"]["containerPort"] ? deployConfig["${projectEnv}"]["containerPort"] : 7001						   //如果是生产环境,部署的镜像地址需要做下替换,命名空间还用没改动之前的命名                            if (projectEnv == "pro") {                                imageName = imageName.replaceAll("${harborUrl}", "192.168.xxxx.89:10032")                                nameSpace = "sjjcb"                            }                            sh """                                sed -i 's#\$projectNames#${projectName}#' ${WORKSPACE}/target/settings/k8s-rc.yaml                                sed -i 's#\$nameSpace#${nameSpace}#' ${WORKSPACE}/target/settings/k8s-rc.yaml                                sed -i 's#\$imageName#${imageName}#' ${WORKSPACE}/target/settings/k8s-rc.yaml                                sed -i 's#\$replicas#${replicas}#' ${WORKSPACE}/target/settings/k8s-rc.yaml                                sed -i 's#\$requestsCpu#${requestsCpu}#' ${WORKSPACE}/target/settings/k8s-rc.yaml                                sed -i 's#\$requestsMemory#${requestsMemory}#' ${WORKSPACE}/target/settings/k8s-rc.yaml                                sed -i 's#\$limitsCpu#${limitsCpu}#' ${WORKSPACE}/target/settings/k8s-rc.yaml                                sed -i 's#\$limitsMemory#${limitsMemory}#' ${WORKSPACE}/target/settings/k8s-rc.yaml								sed -i 's#\$containerPort#${containerPort}#' ${WORKSPACE}/target/settings/k8s-rc.yaml                            """                            sh "/usr/bin/kubectl delete -f ${WORKSPACE}/target/settings/k8s-rc.yaml --ignore-not-found=true"                            sh "/usr/bin/kubectl create -f ${WORKSPACE}/target/settings/k8s-rc.yaml"                            //判断service文件是否存在                            if (fileExists("${WORKSPACE}/target/settings/k8s-service.yaml") == true) {                                sh """                                    sed -i 's#\$projectNames#${projectName}#' ${WORKSPACE}/target/settings/k8s-service.yaml                                    sed -i 's#\$nameSpace#${nameSpace}#' ${WORKSPACE}/target/settings/k8s-service.yaml									sed -i 's#\$containerPort#${containerPort}#' ${WORKSPACE}/target/settings/k8s-service.yaml                                """                                sh "/usr/bin/kubectl apply -f ${WORKSPACE}/target/settings/k8s-service.yaml --record=true"                            }                            sh "trap 'k8s启动成功' SIGHUP SIGINT SIGTERM"                        }                    }            }        }        stage('Publish to Artifactory') {            steps {                    script {                        //上传产物到仓库                        artiServer.publishBuildInfo buildInfo                    }            }        }    }    post {        always{            script{                if(pushWechat == "true" && (projectEnv == "pro" || projectEnv == "dev")){                    //构建结果                    def status = getStatus(currentBuild.currentResult)                    sh """                    curl '${qyWechatUrl}' -s \\                       -H 'Content-Type: application/json' \\                       -d '                       {                            "markdown": {                                "content": "<font color=\\"info\\">【${env.JOB_NAME}】</font>构建${status}\\n >构建用时:<font color=\\"comment\\">${currentBuild.durationString}</font>\\n >[查看控制台](${env.BUILD_URL})"                            },                            "msgtype": "markdown"                        }                       '                            """                }            }        }    }}/** * 获取项目公共配置 * @param projectNames 模块名称 * @return */def getProjectConfig(projectNames) {    echo "获取项目配置:${projectNames}"}/** * 获取需要部署的子模块 * @param projectNames 模块名称 * @return */def getNeedBuildModules(defProjectNames) {    def changeLogSets = currentBuild.rawBuild.changeSets    //需要构建的module    def buildModules = new HashSet()    //计算出需要构建的模块    def buildModulesStr = buildModules.join(",")    //如果需要构建的子模块为空格,则构建全部    if (buildModulesStr == null || buildModulesStr == "") {        buildModulesStr = defProjectNames    }    return buildModulesStr}/** * 获取构建状态 * @param currentResult * @return */def getStatus(currentResult) {    if(currentResult == "FAILURE"){        return "<font color=\\\"warning\\\">失败!!!</font>\uD83D\uDE2D";    }else if(currentResult == "ABORTED"){        return "<font color=\\\"warning\\\">中断!!</font>\uD83D\uDE28";    }else if(currentResult == "UNSTABLE"){        return "<font color=\\\"warning\\\">异常!!</font>\uD83D\uDE41";    }else if(currentResult == "SUCCESS"){        return "<font color=\\\"info\\\">成功~</font>\uD83D\uDE0E";    }    return "<font color=\\\"warning\\\">情况未知</font>";}/** * 调接口获取是否工作日 * @return */def getWorkDay(url){    def workDay = sh(script: "curl $url -s", returnStdout: true)    return workDay}/***初始化流程水线配置文件*/def initConfig(projectName){	def dirName = "../jenkinsfile_config/${projectName}/deploy"	if(!fileExists(dirName)){	   sh  "mkdir -p ${dirName}"	}    sh "cp -rf deploy/docker/* ${dirName}"    sh "cp -rf deploy/docker/filebeat.yml ${dirName}"    sh "cp -rf deploy/k8s/* ${dirName}"	sh "cp -rf deploy/config/deployconfig-${projectEnv}.properties ${dirName}/deployconfig.properties"}/***拷贝配置文件到目标目录下*/def copyConfigToTarget(projectName){    def dirName = "../jenkinsfile_config/${projectName}/deploy"    if(fileExists(dirName)){	   sh "mkdir -p ${WORKSPACE}/target/settings"       sh "cp -rf ${dirName}/* ${WORKSPACE}/target/settings"	}}

下面介绍流水线脚本结构

以上配置文件 dockfiel k8s 脚本 和本身流水线 无关,每个公司管理要求不一样。这里面我就不细介绍了。感兴趣的小伙伴 可以留言,后面如果有需求我会再介绍这方面的知识、欢迎关注、留言、点赞。

jenkins 流水线如何配置呢,下面简单介绍一下

选择 jenkins新建“流水线”工程

配置jenkinsfile文件的svn地址

如果项目是微服务架构,可以设置多模块,具体构建勾选一个或者多个模块也可。

改造后jenkins 整体界面少很多了。而且构建的灵活性大大增加。

总之,jenkins是一个持续构建发布的平台,利用它我们大大简化平时部署实时和发布工作,让研发把精力放在写代码上面,提高研发效率。

标签: #multiselectcss