Jenkins Pipeline的高效使用

最近在对公司的Jenkins进行优化,发现每个运维人员针对自己的项目都写了一个自己的脚本,70%都是拷贝复制的,剩下的30%风格迥异。我现在也正在负责对整个CI/CD的过程进行进行优化,目前这种状况下如果添加或缩减一个关键,需要把所有的脚本都改一遍,这次的人力成本真的有点高啊。

既然要动刀子,那就一步到位,引入点黑科技为以后铺好路,希望以后做CI/CD环节优化时不要再这么痛苦。

如何提高Jenkins脚本的复用性

根据项目语言抽象出5pipelineGitlab中的项目webhook保持不变,仍然触发Jenkins中对应的Job,该Job只负责将定制化的参数传给与项目语言匹配的Pipeline

Pipeline的stage细节

将每种语言Jenkins中的pipeline拆成如下4-5个环节(有些语言不需要build),环节中规定要执行的命令,项目之间的差异性以变量形式体现。

将每种语言Jenkins中的pipeline拆成如下4-5个环节(有些语言不需要build),环节中规定要执行的命令,项目之间的差异性以变量形式体现。

一次编译多个版本

现有的Jenkins任务中存在这种使用场景,gitlab打tag后Jenkins需要分别编译和交付到测试环境和生产环境。这种情况下调用两次公用pipeline:

实现细节:

1 Gitlab准备部分:

详见:https://blog.csdn.net/yejingtao703/article/details/83065591

2 Jenkins安装

下载地址:https://jenkins.io/download/

jenkins.war方式最简单,准备好java环境直接运行命令:

$java -jar jenkins.war --httpPort=8080

如果不指定httpPort默认端口是8080,第一次启动时注意留意输出日志中最后有admin登陆的密码。

3 准备插件

先默认安装Jenkins初始化插件。

Jenkins实现Pipeline的核心插件有2个,其中实现pipeline 的插件在Jenkins启动时默认安装就可以装好。需要手动安装的第二个插件叫“Parameterized Trigger plugin”,该插件负责Jenkins的Job之间传递参数。

4 pipeline脚本

Jenkins Pipeline以groovy语法定义出每个stage要干的事情,例如我的脚本:

node {
   def staticPara
   def gittag
   
   stage('validate') {
      echo "${params.build_env}"
      echo "${params.project_name}"
      echo "${params.git_commit}"
   }
   
   stage('Preparation') {
      staticPara = 'static-hello'
      echo "${staticPara}"
      sh 'mkdir -p ~/repository/${project_name}/${build_env}'
   }
   
   stage('checkout') {
       echo 'checkout'
       checkout([$class: 'GitSCM', branches: [[name: '*/master']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: '3b762ad3-0fab-4115-8c0c-17b32454d72d', url: '[email protected]:root/${project_name}.git']]])
       gittag = sh(returnStdout: true, script: 'git describe --tags ${git_commit}').trim()
       echo "${gittag}"
   }
   
   stage('build'){
       echo 'build'
       sh 'mvn clean package -DskipTests'
       echo "Finish Build"
   }
   
   stage('deploy') {
      echo "deploy"
      echo "${gittag}"
      sh "mv target/${project_name}.jar ~/repository/${project_name}/${build_env}/${project_name}-${gittag}.jar"
   }
}

定义了5个环节,每个环节规定了要做的事情,项目差异性部分以变量来代替,而变量分为staticPara这种pipeline内部声明的变量和build_envproject_namegit_commit这种前端Jenkins job传来的参数。 

此类参数定义声明:

5 Gitlab集成 

5.1 gitlab添加webhook

 由于我们只在打tag的时候触发Jenkins,所以webhook监听事件这里只需配置Tag Push

5.2 给每个项目在Jenkins中创建一个私有的job

 

Build Trigger那里配置一个轮询SCM,默认即可,默认是每秒钟都去检查一次。 

脚本很简单,只需要打印做下日志就好,因为主要工作都在后面pipeline job中,这里核心的工作是将定制化业务参数传给pipeline

这样就打通了gitlab—>jenkins私有job—>Jenkins公共job这条线。

6 细节部分:

6.1 pipeline并发问题

Jenkins私有job支持一次触发多个公共job,为了保证公共job项目间不会相互干扰可以有两个方案进行选择:需要把pipeline job配置为“不允许并发构建”,或者在pipeline中自己定义执行目录的方式进行隔离。根据自己应用场景的并发程度来定,我的场景并发概率很小,所以选择前者,如果选择后者一定要仔细检查是否会有冲突。

6.2 gitlab打tag的问题

gitlab上项目打tag的方式没有要求,可以maintainer直接在控制台打tag,也可以本地将tag push到服务器,都可以触发jenkins。

重要:这种模式下如何提高并发

公共的pipeline(java-job)在执行时,回到自定义(java-odin)的jenkins的workspace工作目录下去执行pipeline脚本,这样操作会带来2大优点:

1 可以放开公共pipeline并发限制,因为他们脚本工作目录是相互隔离的,不会互相干扰

2 公共pipeline中不需要git,提高了单次执行的效率。

脚本如下:

node {
   def staticPara
   def gittag
   
   stage('Preparation') {
      staticPara = 'static-hello'
      echo "${params.build_env}"
      echo "${params.project_name}"
      echo "${params.git_commit}"
      echo "${staticPara}"
      echo "${params.job_name}"
   }
   
   dir("../${params.job_name}"){
       stage('cd workspace') {
       echo 'cd workspace'
       gittag = sh(returnStdout: true, script: 'git describe --tags ${git_commit}').trim()
       echo "${gittag}"
       }
   
       stage('sleep') {
           sleep 180
       }
   
       stage('build'){
           echo 'build'
           sh 'mvn clean package -DskipTests'
           echo "Finish Build"
       }
   
       stage('deploy') {
          echo "deploy"
          echo "${gittag}"
          sh "mv target/${project_name}.jar ~/jenkins/repository/${project_name}/${build_env}/${project_name}-${gittag}.jar"
       }
   }
   
   
}

这里的核心代码是: dir("../${params.job_name}")

可能你会问有这么好的方案为什么一开始推荐不支持并行呢?因为这种方案受限于你Jenkins所在机器的物理资源的约束。

Jenkins默认只能并行执行2个Job,虽然我们可以修改这个限制,但是一般不能超过CPU核数,所以说对于一个双核CPU的Jenkins机器来说,这两种方案并没啥本质区别,只有当你Jenkins服务器硬件上去之后采用第二种方案才会提现它的价值。

查看CPU核数:

cat /proc/cpuinfo| grep "physical id"| sort| uniq| wc -l

猜你喜欢

转载自blog.csdn.net/yejingtao703/article/details/83449103