深入浅出DevOps:流水线任务改造

1,421 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第2天,点击查看活动详情

💯 作者: 俗世游子【谢先生】。 8年开发3年架构。专注于Java、云原生、大数据等领域技术。
💥 成就: 从CRUD入行,负责过亿级流量架构的设计和落地,解决了千万级数据治理问题。
📖 同名社区:掘金​、​​github​​​、​​51CTO​​、​​gitee​​​
📂 清单: ​​​goku-framework​​​、​​【更新中】享阅读II​

DevOps系列文章

深入浅出DevOps:DevOps核心思想

深入浅出DevOps:版本控制Git&Gitlab

深入浅出DevOps:持续集成工具Jenkins

深入浅出DevOps:简易Docker入门

深入浅出DevOps:Jenkins实战之CI

深入浅出DevOps:SonarQube提升代码质量

深入浅出DevOps:SonarQube提升代码质量【下】

深入浅出DevOps:Jenkins构建器

深入浅出DevOps:私有镜像仓库Harbor

深入浅出DevOps:Jenkins基于Harbor部署

深入浅出DevOps:初识Pipline流水线任务

前言

前一节我们已经介绍了流水线任务的基本信息和相关的语法说明,接下来我们再次执行改造计划:

  • Jenkins通过流水线任务进行自动化构建

本章内容相对比较简单,都是操作性的内容,大家放心观赏

创建流水线任务

流水线任务在任务配置页面区别于普通任务,所以我们需要重新创建一个任务,将任务类型选择为流水线任务

基本信息和构建触发器之类的没有还是和之前的配置是一样的,大家不清楚的话再看看 深入浅出DevOps:Jenkins构建器

Jenkinsfile

在改造之前我们需要注意的是,本章我们采用Jenkinsfile的方式管理执行脚本,也就是将脚本内容编写到项目中,脚本名称统一为Jenkinsfile,Jenkins在每次构建时会自动拉取项目并且获取项目中Jenkinsfile文件对项目进行构建

流水线语法快速生成

Jenkinsfile语法在实际构建的时候并不像我们上一篇的样例程序那么简单,当涉及到特定执行时,Jenkins给予了充足的提示,通过流水线语法能够生成相对应的命令

我们在这边的片段生成器中能够快速方便的生成对应的脚本执行语句,也方便我们编写​​Jenkinsfile​

项目正式改造

记得常规流程:

  • Git拉取代码
  • Maven构建项目,生成可执行Jar包
  • 代码质量检测
  • 制作镜像提交到Harbor仓库
  • 在目标服务器上拉取镜像
  • 执行程序

那么,废话不多说,现在开始吧!!!

Git拉取代码

按照我们这么长时间管理自由风格任务的经验,第一步肯定是先从代码远程仓库中将代码拉取下来。

在片段生成器中,示例步骤我们选择checkout:Check out from version control

随后接下来的步骤就和之前的配置是一样一样的,看我操作

配置完成之后,点击最下方生成​​流水线脚本​​的按钮,就能够自动生成执行脚本,这样是不是很方便啊

checkout([$class: 'GitSCM', branches: [[name: '*/main']], extensions: [], userRemoteConfigs: [[credentialsId: 'Root', url: 'http://192.168.10.200:88/root/devops_app.git']]])

如果想要切换分支或者tag,只需要修改​​branches​​处即可,虽然我们现在是Jenkinsfile的方式,不过大家尽管放心,这里是支持构建参数

构建项目

构建项目不用说,肯定是基于Maven的方式来构建的,像这种的通过shell脚本执行就可以,所以示例步骤选择sh: Shell Script

接下来就是我们非常熟悉的​​mvn clean​​等的命令,但是这里需要注意的是:

  • Jenkins是基于容器搭建的,第三方工具包都是通过挂载目录实现容器内部共通的,所以这里我们在使用maven命令的时候一定要使用容器内部全路径,不能是宿主机
  • 如果大家不记得maven的路径,那么在全局工具配置中查看

sh '/var/jenkins_home/apache-maven-3.8.5/bin/mvn clean install -pl module01 -am -Dmaven.test.skip=true'

构建指定模块

代码质量检测

《SonarQube章节》 介绍了关于SonarQube的相关介绍,和构建项目一样,我们在这里也选择执行shell脚本的过程

本人在项目下已经做了关于sonar-project.properties的处理,所以我们在执行SonarScanner命令的时候可以手动指定配置,不需要单独写脚本

需要注意的是,我们现在测试的是子模块项目,所以在配置的时候需要把子模块名加上

QA: 为什么要配置子模块名

在Jenkins任务中,任务的根目录和我们的开发目录所对应,我们现在是对​​module01​​​进行构建,那么在这里就需要进入到​​module01​​所对应的目录中才能操作到其中的内容

这也是下面我们通过​​-Dproject.settings​​指定文件的原因

如果本身只属于单体项目,就不需要有这一操作

接下来我们接续

如果大家不记得SonarScanner的路径,那么在全局工具配置中查看,关于接下来我们来看一下生成脚本的操作

sh '/var/jenkins_home/sonar-scanner-4.6.0.2311/bin/sonar-scanner -Dproject.settings=module01/sonar-project.properties'

就是这么简单

中间测试阶段

已经配置了三个阶段了,我们也该来测试一下好让大家心里有个谱了

靠谱的男人

废话不多说,直接来进行构建过程

经过本人不断的努力测试调整4次之后,终于在最后一次迎来了成功的。这是不是已经让大家备受鼓舞。

放心,以上三步有问题的地方都已经修正过,在文章的最后我会给大家做一个汇总,方便大家查看和测试

制作镜像提交到Harbor

制作镜像的脚本这不是也很简单么,我们在 深入浅出DevOps:私有镜像仓库Harbor 也已经介绍过了脚本的实现,现在我们只需要将之前的实现方式拿过来,改成流水线支持的语法就可以了

为了方便操作,我们先定义一个全局属性块,配置Harbor的基本信息,接下来的两个步骤都能用得到。下面看我操作

sh '''cd module01
docker build -t ${JOB_NAME}:v0.0.${BUILD_NUMBER} .
docker tag ${JOB_NAME}:v0.0.${BUILD_NUMBER} 192.168.10.201/presentation/${JOB_NAME}:v0.0.${BUILD_NUMBER}'''

接下来生成推送镜像的脚本

sh '''docker login -u admin -p Harbor12345 192.168.10.201
docker push 192.168.10.201/presentation/${JOB_NAME}:v0.0.${BUILD_NUMBER}'''

不过这里要记住,我们在Jenkinsfile中已经定义属性值,所以我们这里就可以进行如下替换,所以如下看到的才是我们在Jenkinsfile中要配置的内容

environment {
    HarborHost = '192.168.10.201'
    HarborUsername = 'admin'
    HarborPassword = 'Harbor12345'
    HarborRepo = 'presentation'
}
stage('制作镜像提交到Harbor') {
    steps {
        sh '''cd module01
              docker build -t ${JOB_NAME}:v0.0.${BUILD_NUMBER} .
              docker tag ${JOB_NAME}:v0.0.${BUILD_NUMBER} ${HarborHost}/${HarborRepo}/${JOB_NAME}:v0.0.${BUILD_NUMBER}'''

        sh '''docker login -u ${HarborUsername} -p ${HarborPassword} ${HarborHost}
              docker push ${HarborHost}/${HarborRepo}/${JOB_NAME}:v0.0.${BUILD_NUMBER}'''

    }
}

在目标服务器拉取镜像并执行

最后一步就是告诉目标服务器:我这边全部准备好了,你可以开始执行了。

老样子,还是通过SSH Publishers的执行机制来处理。进入到片段生成器中

在万花从中找到关于sshPublisher的选项,随后和之前的配置是一样的,我就直接生成流水线脚本了

sshPublisher(publishers: [sshPublisherDesc(configName: '201', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '''docker pull ${HarborHost}/${HarborRepo}/${JOB_NAME}:v0.0.${BUILD_NUMBER}
docker container stop ${JOB_NAME}  && docker container rm ${JOB_NAME}
docker run -d -p 8081:8080 --name ${JOB_NAME} ${HarborHost}/${HarborRepo}/${JOB_NAME}:v0.0.${BUILD_NUMBER}''', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])

把其中相关属性值进行替换,然后我们将Jenkinsfile提交到远程仓库再次进行执行,看看我们的最终效果

对外开放端口大家也可以自己进行调整,和之前的配置是一样样的

小坑

经过本人测试,发现如下小坑

经过不断尝试发现其最主要的原因是因为

  • execCommand中我们定义了属性变量和Jenkins自带的变量值来代表某些数据,但是在真正执行构建的时候这些变量并没有被转换过来,这样就导致在执行命令的过程中执行的命令是原样输出的
  • 所以这里我们还需要对最后一步简单的改造:通过shell脚本然后在目标服务器上执行

定义deploy.sh脚本,可以将其放到对应的模块代码下

HarborHost=$1
HarborRepo=$2
JOB_NAME=$3
BUILD_NUMBER=$4

docker pull ${HarborHost}/${HarborRepo}/${JOB_NAME}:v0.0.${BUILD_NUMBER}
docker container stop ${JOB_NAME}  && docker container rm ${JOB_NAME}
docker run -d -p 8081:8080 --name ${JOB_NAME} ${HarborHost}/${HarborRepo}/${JOB_NAME}:v0.0.${BUILD_NUMBER}

随后我们就通过​​SSH Publisher​​​将​​deploy.sh​​文件推送到目标服务器上并且执行该脚本

所以最终的一个执行流水过程是这样的

sshPublisher(publishers: [sshPublisherDesc(configName: '201', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "cd /opt/app/module01_pipeline && sh deploy.sh ${HarborHost} ${HarborRepo} ${JOB_NAME} ${BUILD_NUMBER}", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '/opt/app/module01_pipeline', remoteDirectorySDF: false, removePrefix: 'module01/', sourceFiles: 'module01/deploy.sh')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])

这里一定要将​​execCommand​​下的单引号变成双引号

改造测试

经过我们这么多步骤的改造,终于将自由风格的任务改造为了流水线任务,接下来就进入到非常紧张的测试阶段,在中间我们已经有过一轮的测试,接下来我们继续下一轮的测试过程

虽然过程稍显曲折,但是结果还是好的,我们可以看到最终的测试已经全部成功。好了本章到此结束,大家可以下去试试了

这里为大家提供出最终的文件内容,仅供参考,推荐大家按照自己的流程通过流水线语法生成对应的脚本

最后

通过一系列的测试来看,流水线任务确实是有自己的优势,不过整体的配置过程略显繁琐。

大家可以根据自己的需求选择合适的任务类型。