使用jenkins中的Pipeline写一个特殊的流水线,先说一下,我们的一个仓库中包含了多个微服务,为何这样做,这个先不管为什么这样做。现在要实现的问题是我在一个Pipeline里实现整个job的运行,并且在发布过程中可用进行选择性的发布。原来的方案是,让开发在仓库中创建一个文件,然后根据我定义的规则,如果发布那个服务,就把服务名添加到文件中,在Pipeline里我会读取文件内容,然后根据文件内容进行循环操作。这种方式虽然还不错,但是开发习惯了用手点击,不想每次提交的时候修改文件。没办法,我需要在jenkins上下功夫。经过多次测试,发现在jenkins中可用通过两个插件,Extended Choice Parameter Name和git参数两个参见也可以实现。
利用这两个插件,把开发要修改文件的操作,放到jenkins里,只需要在jenkins中每次发布的服务进行循环操作即可,看一下我的样式。
先添加一个分支参数,每次发布的时候,需要根据分支拉取代码,不通环境的编译参数还不一样,所以需要获取分支名称,并把分支作为变量传递给Pipeline,后面会用到。另外,为了避免分支过多,可以进行快速过滤,列表数量就是build的时候显示的分支数量。
这里是把服务名称也作为变量传递,并且服务之间使用逗号分隔,这里可以的6是build的时候可以查看的服务数量。
到此,jenkin的操作替换了文件操作,后面就都一样了,每次发布时需要分支,服务名称选择,然后开始构建就完成了,下面看一下我的Pipeline内容。
def dockerbuild(item) { #镜像生成函数 JAVA_START="java -XX:+UseContainerSupport -javaagent:/opt/skywalking-agent/skywalking-agent.jar -Dskywalking.agent.service_name=${K8S_NAMESPACE}::${item} -Dskywalking.collector.backend_service=skywalking.skywalking:11800 -XX:InitialRAMPercentage=50.0 -XX:MaxRAMPercentage=50.0 -XX:MinRAMPercentage=50.0 -Dlog4j2.formatMsgNoLookups=true -Dfile.encoding=UTF-8 -Duser.timezone=Asia/Shanghai -jar /apps/works/server/${item}.jar" //JAVA_START="java \${JAVA_OPTS} -javaagent:/opt/skywalking-agent/skywalking-agent.jar -Dskywalking.agent.service_name=${K8S_NAMESPACE}::${item} -Dskywalking.collector.backend_service=skywalking.skywalking:11800 -XX:+UseContainerSupport -XX:InitialRAMPercentage=50.0 -XX:MaxRAMPercentage=50.0 -XX:MinRAMPercentage=50.0 -Dlog4j2.formatMsgNoLookups=true -Dfile.encoding=UTF-8 -Duser.timezone=Asia/Shanghai -jar /apps/works/server/${item}.jar" sh "echo -e '#!/bin/bash \n${JAVA_START}' > enpoint.sh" sh """ cat>Dockerfile<<EOF FROM ${DOCKER_IMAGE} COPY target/${item}.jar /apps/works/server/ COPY enpoint.sh /usr/bin/enpoint WORKDIR /apps/works RUN chmod +x /usr/bin/enpoint CMD ["/bin/bash","enpoint"] EOF """ sh "docker build -t ${item}-${ENV} . " sh "docker tag ${item}-${ENV}:latest ${SVC_IMAGE}/${SVC_IMAGENAME}/${item}-${ENV}:${BUILD_NUMBER}" sh "docker tag ${item}-${ENV}:latest ${SVC_IMAGE}/${SVC_IMAGENAME}/${item}-${ENV}:latest" sh "docker push ${SVC_IMAGE}/${SVC_IMAGENAME}/${item}-${ENV}:${BUILD_NUMBER}" sh "docker push ${SVC_IMAGE}/${SVC_IMAGENAME}/${item}-${ENV}:latest" sh "docker rmi ${item}-${ENV}:latest || true" sh "docker rmi ${SVC_IMAGE}/${SVC_IMAGENAME}/${item}-${ENV}:latest || true" sh "docker rmi ${SVC_IMAGE}/${SVC_IMAGENAME}/${item}-${ENV}:${BUILD_NUMBER} || true" } def portserver(SERVER) { #判断服务名称,并添加服务的端口 //sh "echo ${PROJECT} ${SERVER}" if (SERVER == "module-system") { eftFunction(6000,SERVER) } else if (SERVER == "auth") { eftFunction(8030,SERVER) } else if (SERVER == "gateway") { gateFunction(8000,SERVER) } else if (SERVER == "service-oss") { eftFunction(6060,SERVER) } else if (SERVER == "service-job") { eftFunction(7020,SERVER) } else if (SERVER == "module-telegram") { eftFunction(6030,SERVER) } else if (SERVER == "module-data-system-can") { eftFunction(6020,SERVER) } } def eftFunction(SVC_PORT,SERVER) { #发布函数 sh "echo ${SVC_PORT} ${SERVER}" sh """ ansible-playbook -i /etc/ansible/inventory/hosts /etc/ansible/book/deploy_k8s.yml -e "host=k8s SVC_NAME=${SERVER} SVC_NS=${K8S_NAMESPACE} SVC_ENV=${ENV} SVC_PORT=${SVC_PORT} SVC_REPLICAS=${REPLICAS} SVC_CPU=1 SVC_MEM=2 BUILD_NUMBER=${BUILD_NUMBER} SVC_NODE=application SVC_IMAGE=${SVC_IMAGE} SVC_IMAGENAME=${SVC_IMAGENAME}" """ } def gateFunction(SVC_PORT,SERVER) { #发布函数 sh "echo ${SVC_PORT} ${SERVER}" sh """ ansible-playbook -i /etc/ansible/inventory/hosts /etc/ansible/book/deploy_k8s.yml -e "host=k8s SVC_NAME=${SERVER} SVC_NS=${K8S_NAMESPACE} SVC_ENV=${ENV} SVC_PORT=${SVC_PORT} SVC_REPLICAS=${REPLICAS} SVC_CPU=1 SVC_MEM=2 BUILD_NUMBER=${BUILD_NUMBER} SVC_NODE=application SVC_IMAGE=${SVC_IMAGE} SVC_IMAGENAME=${SVC_IMAGENAME}" """ } pipeline { agent any options { timeout(time: 60, unit: 'MINUTES') //SECONDS, MINUTES, HOURS timestamps () } stages { stage('Preparation environment variables') { steps { script { #基础变量 SOURCE_CODE_REPO = '仓库地址' SOURCE_CODE_REPO_CREDENTIALS = '授权jenkin的id' ENV = 'qa' //环境也是分支 SVC_IMAGE = '镜像仓库地址' //镜像地址 SVC_IMAGENAME = '镜像仓库项目名称' //镜像地址命名空间 REPLICAS = '1' //副本数 K8S_NAMESPACE = 'k8s中的namespaces' //命名空间 SVC_NOD = 'application' //节点标签 DOCKER_IMAGE = '基础镜像地址' } } } stage('Preparation source code') { steps { checkout([$class: 'GitSCM', branches: [[name: "${BRANCH_TAG}"]], #这里的BRANCH_TAG就是git参数中定义的分支 doGenerateSubmoduleConfigurations: false, extensions: [ [$class: 'CheckoutOption', timeout: 40], [$class: 'CloneOption', noTags: false, reference: '', shallow: false, timeout: 40] ], gitTool: 'Default', submoduleCfg: [], userRemoteConfigs: [[url: "$SOURCE_CODE_REPO", credentialsId: "$SOURCE_CODE_REPO_CREDENTIALS",]] ]) script { sh "set LESSCHARSET=utf-8" env.GIT_COMMIT_MSG = sh (script: "git log -n 4 --oneline --no-merges --pretty=format:'%s %cn'", returnStdout: true).trim() } } } stage('Maven build') { steps { sh "echo maven" sh 'mvn -Dmaven.test.skip=true -Djacoco.skip=true -Dmaven.test.failure.ignore clean package -P test' } } stage('Docker build') { steps { script { #这里的DEPLOY_MODULES就是定义的服务名称,会循环选择的服务 for (item in "$DEPLOY_MODULES".tokenize(',')){ #因为有多个微服务,所以需要判断服务名称在进入目录,然后在调研dockerfile函数生成镜像 if ( item.contains("module") == true ) { dir("${env.WORKSPACE}/modules/${item}"){ dockerbuild(item) } } else if ( item.contains("service") == true ) { dir("${env.WORKSPACE}/services/${item}"){ dockerbuild(item) } } else { dir("${env.WORKSPACE}/${item}"){ dockerbuild(item) } } } } } } stage('k8s deploy') { steps { sh 'echo "k8s yml"' script { for (item in "$DEPLOY_MODULES".tokenize(',')){ #根据服务选择的服务进行循环,然后进行发布操作。 portserver(item) //sh 'echo $item' } } } } } }
这里写的很简单,就是需要一个判断不同服务编译后的jar包路径,根据选择的服务进行生产镜像,然后在根据选择的服务进行发布操作。是不是很简单,相比原来的发布方式更简单了,
您可以选择一种方式赞助本站
支付宝扫一扫赞助
微信钱包扫描赞助
赏