Published on
2992

Jenkins 2.x实践指南-读书笔记

Authors
  • avatar
    Name
    小辉辉
    Twitter

前言

很早之前就开始使用Jenkins搭建前端编译,自动部署流水线,但是大部分的脚步都是以sh执行命令为主,对Jenkins整体基础系统流程还不是非常清楚。

就想着借助着这次元旦假期(平时工作只有休息一天),打算找本关于Jenkins书籍看看来完善这块知识。

最终找到了这本《Jenkins 2.x实践指南》,作者翟志军,一开始还担心2.x的版本是不是太老了,后面特意去官网看了下,目前也还是2.x版本,于是便看了起来。

全书共18个章节,每个章节的页数都不多,全部看完总共就花了1个半小时,但是看的过程中还是有很多新的收获,下面我会按照章节来记录下个人觉得很有必要的知识点。

2.pipeline入门

2.1 什么是pipeline

使用pipeline(代码)的意义有

  • 可以版本控制
  • 可以更好协作
  • 可以重用代码

2.2 Jenkinsfile又是什么

所有部署流水线的逻辑都写在Jeknkinsfile文件中

2.3 pipeline语法的选择

Groovy语言选择作为基础来实现pipeline

写法主要分为脚本式(Scripted)和声明式(Declarative)语法

前者以node开头,后者以pipeline开头,社区推荐声明式语法

2.6 使用Maven构建Java应用

tools是pipeline中的一个指令,用于自动安装工具,同时将路径放到PATH变量中

pipeline语法详解

3.1 必要的Groovy知识

  • 方法调用可以省略括号,比如System.out.println "Hello world"

  • 支持命名参数

def createName(String giveName, String familyName){
  return giveName + " " + familyName
}
// 调用
createName familyName = "Lee", giveName= "Bruce"
  • 支持默认参数值
def sayHello(String name = "humans"){
  print "hello ${name}"
}
sayHello() // 此时括号不能省略
  • 支持单、双引号。双引号支持插值,单引号不支持

  • 支持三单、三双引号,用于换行,只有三双引号支持插值

  • 支持闭包

// 定义闭包
def codeBlock = {print "hello closure"}
// 闭包还可以直接当成函数调用
codeBlock() // 结果打印:hello closure

还可以将闭包看做一个参数传递另一个方法

// 定义一个pipeline函数,它接收一个闭包参数
def pipeline(closure){
  closure()
}
// 在调用pipeline函数时,可以这样
pipeline(codeBlock)
// 如果把闭包定义的语句去掉
pipeline({print "hello closure})
// 由于括号非必须,所以
pipeline {
  print "hello closure"
}
  • 闭包另类用法

我们定义一个stage函数:

def stage(String name, closure){
  print name
  closure()
}
// 在正常情况下,我们这样使用stage函数
stage("stage name", {println "closure"})
// 但是,groovy提供了另一种写法
stage("stage name") {
  pring "closure"
}

这一章节对理解Jenkins基本语法怎么来的,怎么写的很有帮助。

pipeline的组成

pipeline {
  agent any
  stages {
    stage('build'){
      steps {
        echo 'hello world'
      }
    }
  }
}
  • pipeline:代表整条流水线,包含整条流水线的逻辑。

  • stage部分:阶段,代表流水线的阶段。每个阶段都必须有名称。本例中,build就是此阶段的名称。

  • stages部分:流水线中多个stage的容器。stages部分至少包含一个stage。

  • steps部分:代表阶段中的一个或多个具体步骤(step)的容器。steps部分至少包含一个步骤,本例中,echo就是一个步骤。在一个stage中有且只有一个steps。

  • agent部分:指定流水线的执行位置(Jenkins agent)。流水线中的每个阶段都必须在某个地方(物理机、虚拟机或Docker容器)执行,agent部分即指定具体在哪里执行。

3.3 post部分

post部分包含的是在整个pipeline或阶段完成后一些附加的步骤。post部分是可选的,所以并不包含在pipeline最简结构中。

根据pipeline或阶段的完成状态,post部分分成多种条件块,包括:

  • always:不论当前完成状态是什么,都执行。

  • changed:只要当前完成状态与上一次完成状态不同就执行。

  • fixed:上一次完成状态为失败或不稳定(unstable),当前完成状态为成功时执行。

  • regression:上一次完成状态为成功,当前完成状态为失败、不稳定或中止(aborted)时执行。

  • aborted:当前执行结果是中止状态时(一般为人为中止)执行。

  • failure:当前完成状态为失败时执行。

  • success:当前完成状态为成功时执行。

  • unstable:当前完成状态为不稳定时执行。

  • cleanup:清理条件块。不论当前完成状态是什么,在其他所有条件块执行完成后都执行。post部分可以同时包含多种条件块。

post还可以放在单个stage指令里面

3.4 pipeline支持的指令

Jenkins pipeline通过各种指令(directive)来丰富自己。指令可以被理解为对Jenkins pipeline基本结构的补充。Jenkins pipeline支持的指令有:

  • environment:用于设置环境变量,可定义在stage或pipeline部分。

  • tools:可定义在pipeline或stage部分。它会自动下载并安装我们指定的工具,并将其加入PATH变量中。

  • input:定义在stage部分,会暂停pipeline,提示你输入内容。

  • options:用于配置Jenkins pipeline本身的选项

  • parallel:并行执行多个step。在pipeline插件1.2版本后,parallel开始支持对多个阶段进行并行执行。

  • parameters:与input不同,parameters是执行pipeline前传入的一些参数。

  • triggers:用于定义执行pipeline的触发器。

  • when:当满足when定义的条件时,阶段才执行。

每个指令都有自己的“作用域”,位置不正确,将会报错。

3.5配置pipeline本身

  • buildDiscarder:保存最近历史构建记录的数量。当pipeline执行完成后,会在硬盘上保存制品和构建执行日志,如果长时间不清理会占用大量空间,设置此选项后会自动清理。此选项只能在pipeline下的options中使用。

  • buildDiscarder:保存最近历史构建记录的数量。当pipeline执行完成后,会在硬盘上保存制品和构建执行日志,如果长时间不清理会占用大量空间,设置此选项后会自动清理。此选项只能在pipeline下的options中使用。

  • disableConcurrentBuilds:同一个pipeline,Jenkins默认是可以同时执行多次的,如图3-2所示。此选项是为了禁止pipeline同时执行。

  • disableConcurrentBuilds:同一个pipeline,Jenkins默认是可以同时执行多次的,此选项是为了禁止pipeline同时执行。

  • retry:当发生失败时进行重试,可以指定整个pipeline的重试次数。需要注意的是,这个次数是指总次数,包括第1次失败。当使用retry选项时,options可以被放在stage块中。

  • timeout:如果 pipeline 执行时间过长,超出了我们设置的timeout 时间,Jenkins 将中止pipeline。还可以以 SECONDS(秒)、MINUTES(分钟)为单位。当使用timeout选项时,options可以被放在stage块中。

这里没有贴代码,到时候有需要再单独查看配置文档。

3.6 在声明式pipeline中使用脚本

可以在script块中执行groovy代码,这里推荐将script脚本放到共享库里,后面会提到怎么用。

steps {
  script {
    // groovy代码
  }
}

3.7 pipeline内置基础步骤

考虑使用内置流水线语法生成代码功能

环境变量与构建工具

Jenkins内置变量

Jenkins通过一个名为env的全局变量,通过访问<Jenkins master的地址>/pipeline-syntax/globalsenv来获取完整列表,使用通过env.xxx来获取。

通过environment指令来自定义环境变量,可以在pipeline中定义,代表变量作用域为整个pipeline;也可以在stage中定义,代表变量只在该阶段有效。

自定义环境变量会覆盖系统环境变量

6. 触发pipeline执行

触发分为时间和事件触发两种

在Jenkins pipeline中使用trigger指令来定义时间触发,tigger指令只能被定义在pipeline块下,Jenkins内置支持cron、pollSCM,upstream三种方式

具体每个方式的参数这里跳过

多分支构建

配合stage和when指令来实现不同分支构建不同任务功能

stage("deploy to test") {
  when {
    branch "master'
  }
  steps {
    echo 'deploy test'
  }
}

stage("deploy to prod") {
  when {
    branch "release'
  }
  steps {
    echo 'deploy prod'
  }
}

when指令具体参数用法这里不展开说明

8 参数化pipeline

在Jenkins pipeline中定义参数使用的是parameters指令,其只允许被放在pipeline块下

parameters指令具体参数用法这里不展开说明

使用input可以暂停等待用户操作后继续执行

上游调用下游pipeline时,可以手动提供参数

build job : "xxx", parameters: {
  string(name: 'xxx', value: "${xxxx}")
}

14. 分布式构建和并行构建

所有的Jenkins项目都是在Jenkins master的executor上执行的。如果Jenkins master上只有两个executor,那么只有两个项目能同时执行,其他项目都必须要排队。

假如单机足够强大,让更多项目同时执行的方法就是增加executor。但单机的容量总会遇到上限,而且还会有单节点问题。解决办法就是将Jenkins项目分配到多台机器上执行,这就是分布式构建。

Jenkins采用的是“master+agent”架构(有时也称为“master+slave”架构),如图14-1所示。Jenkins master负责提供界面、处理HTTP请求及管理构建环境;构建的执行则由Jenkins agent负责(早期,agent也被称为slave。目前还有一些插件沿用slave的概念)。

基于这样的架构,只需要增加agent就可以轻松支持更多的项目同时执行。这种方式称为Jenkins agent的横向扩容。

  • node:节点,指包含Jenkins环境及有能力执行项目的机器。master和agent都被认为是节点。

  • executor:执行器,是真正执行项目的单元。一个执行器可以被理解为一个单独的进程(事实上是线程)。在一个节点上可以运行多个执行器。

  • agent:代理,在概念上指的是相对于Jenkins master的一种角色,实际上是指运行在机器或容器中的一个程序,它会连接上Jenkins master,并执行Jenkins master分配给它的任务。

  • slave:“傀儡”,与agent表达的是一个东西,只是叫法不同。

15. 扩展pipeline

15.2 在pipeline中定义函数

直接定义groovy函数,在steps中进行调用

15.3 使用共享库扩展

Jenkins pipeline提供了“共享库”(Shared library)技术,可以将重复代码定义在一个独立的代码控制仓库中,其他的Jenkins pipeline加载使用它。

在Jenkins pipeline的顶部,使用@Library指定共享库。注意,global-shared-library就是我们在上一个步骤中定义的共享库标识符。

引入共享库后,我们可以直接在Jenkins pipeline中使用vars目录下的sayHello,和Jenkins pipeline的普通步骤的使用方式无异。

主要步骤:

(1)按照共享库约定的源码结构,实现自己的逻辑。

(2)将共享库代码托管到代码仓库中。

(3)在Jenkins全局配置中定义共享库,以让Jenkins知道如何获取共享库代码。

(4)在Jenkinsfile中使用@Library引用共享库。

总结

书本中虽然说提到了很多概念,但是完全不要全部死记硬背,我的推荐是只要知道有这个方法,到时候用到了能联想起来并且通过在线查看文档实现方案即可,总体来说通过这本书来实现Jenkins入门还是很简单的。