第1章 Jenkins简介
Jenkins 2是什么
JobConfigHistory:这个插件可以追溯XML配置的历史版本信息, 并且允许你查看每次变更的内容。
JenkinsFile
Jenkinsfile可以起到标记文件(marker file) 的作用, 这意味着只要Jenkins发现你的工程源码中包含了Jenkinsfile文件, 那么这个项目或分支就可以被Jenkins自动解析和运行。 Jenkins同样可以识别出需要用到的源码版本控制管理(SCM) 项目和分支, 并加载和执行Jenkinsfile中的代码。
声明试流水线
脚本式流水线:在以前版本的Jenkins中, 流水线即代码大体就是Groovy脚本, 其中插入了部分针对Jenkins的DSL步骤。 这种方式几乎没有结构上的约束,程序流程也基于Groovy语法结构实现。 错误报告和检查同样基于Groovy程序的执行, 而非从期望通过Jenkins实现功能的角度来检查。
声明式流水线:更加严谨的结构同样有助于错误检查。 于是我们不再需要在发生错误时查看Groovy的调试信息(traceback) , 而是将错误信息以更加直观、 简单的方式展现给用户, 在大多数情况下可以直接定位到具体的错误。
Blue Ocean界面
全新Jenkins可视化界面——的基础。 Blue Ocean为流水线的每个阶段添加了图形化展示, 可以显示成功/失败和进展等标识, 并对每个任务都提供了点选式日志查看功能。 Blue Ocean还提供了一个简单的可视化编辑器。
第2章 基础知识
如何选择脚本式语法和声明式语法
脚本式流水线具有以下优点。
- 更少的代码段落和弱规范要求。
- 更强大的程序代码能力。
- 更像编写代码程序。
- 传统的流水线即代码模型, 用户熟悉并向后兼容性。
- 更灵活的自定义代码操作。
- 能够构建更复杂的工作流和流水线。
脚本式流水线具有以下缺点。
- 普遍要求更高的编程水平。
- 语法检查受限于Groovy语言及环境。
- 和传统Jenkins模型有很大差异。
- 与声明式流水线的实现相比, 同一工作流会更复杂。
声明式流水线具有以下优点。
- 更结构化, 贴近传统的Jenkins Web表单形式。
- 更强大的声明内容能力, 高可读性。
- 可以通过Blue Ocean图形化界面自动生成。
- 段落可映射到常见的Jenkins概念, 比如通知。
- 更友好的语法检查和错误识别。
- 提升流水线间的一致性。
声明式流水线具有以下缺点。
- 对迭代逻辑支持较弱(相比程序而言) 。
- 仍在开发完善中(对于传统Jenkins中的部分功能缺乏支持) 。
- 更严格的结构(更难实现自定义流水线代码) 。
- 目前对于复杂的流水线和工作流难以胜任。
简而言之, 对于新用户和那些希望流水线具备传统Jenkins一样可读性的用户来说, 声明式流水线更容易学习和维护。 这是以灵活性为代价换取结构不支持的功能。
主节点
Jenkins主节点是一个Jenkins实例(instance) 的主要控制系统。 它能够完全访问所有Jenkins配置选项和任务(job) 列表。 如果没有指定其他系统(system) , 它也是默认的任务执行节点。
不过并不推荐在主节点上执行高负载任务, 任何需要大量处理的任务都应该在主节点之外的系统上运行。
这样做的另一个原因是, 凡是在主节点上执行的任务, 都有权限访问所有的数据、 配置和操作, 这会构成潜在的安全风险。 同样值得注意的是, 在主系统上不应该执行任何包含潜在阻塞的操作, 因为主系统需要持续响应和管理各类操作过程。
节点
在Jenkins 2中, 节点是一个基础概念, 代表了任何可以执行Jenkins任务的系统。 节点中包含主节点和代理节点, 有的时候也用于指代这些概念。此外, 节点也可以是一个容器, 比如Docker。
代理节点
在早先版本的Jenkins中, 代理节点被称为从节点(slave) , 其代表了所有非主节点的系统。 这类系统由主系统管理, 按需分配或指定执行特定的任务。 例如, 我们可以分配不同的代理节点针对不同的操作系统构建任务, 或者可以分配多个代理节点并发地运行测试任务。
为了减少系统负载, 降低安全风险, 通常在子系统上只会安装一个轻量级的Jenkins客户端应用来处理任务, 这个客户端应用对资源访问是受限的。
执行器
简单地说, 执行器只是节点/代理节点用于执行任务的一个插槽。一个节点可以有任意多个执行器。 执行器的数量定义了该节点可以执行的并发任务数量。 当主节点将任务分配给特定节点时, 该节点上必须有可用的执行器插槽来立即执行该任务, 否则任务会一直处于等待状态,直到一个执行器变为可用。
创建节点
环境变量(environment variable)和工具路径(Too- Locations)复选框。 勾选这些复选框可以为该节点定义特殊变量和工具。 只有当你希望使用与主节点不同的配置时, 才会用到这些复选框。
标签可以满足系统和用户的不同需求, 比如可以用于以下场景。
- 识别一个特定的节点(通过一个专有标签) 。
- 对一类节点进行分组(通过分配相同的标签) 。
- 识别节点的特征, 方便使用(通过一个有意义的标签, 比如“Windows”或者“West Coast”)
结构: 使用****Jenkins DSL
DSL代表领域特定语言(Domain-Specific Language) ,这是一种针对特定上下文的程序语言。 Jenkins中的上下文用于创建流水线。
Jenkins流水线的DSL基于Groovy语言实现。
但在通常情况下, 我们倾向于避免使用过于复杂的Groovy代码, 或者至少将其与主脚本分开。 这样做的原因是, 使用过多的Groovy代码会降低脚本的可读性和可维护性, 尤其是对那些不了解Groovy的人来说。
声明式流水线禁止使用定义结构之外几乎所有的Groovy代码, 并且还提供了更多类似于传统Jenkins特性的功能, 因此你必须尽量减少使用自定义Groovy代码。
Jenkins DS- 示例
node(‘worker1’)
worker1:jenkins机子被标签
如果忽略标签, 则需要了解它的运作机制。
- 如果master被配置为默认的执行节点, 那么Jenkins会在master上执行任务(可以配置master为不执行任何任务) 。
- 否则, 节点标签为空(或者在声明式语法中使用agent any) ,Jenkins会在任意节点上找到第一个可用的执行器来执行任务。
在节点配置中,你可以在标签输入框中指定多个标签,通常使用空格分隔。当在流水线中指定一个节点来执行任务的时候, 你可以使用标准的逻辑运算符来指定多个标签, 比如, “||”表示或,“&&”表示与。
Ps:标签之间的运算,这就很方便了。比如jenkins可能运行在多个系统上,比如windows,linux;而jenkins有支持ios、android不同版本的编译,那么通过标签的组合,就可以制定 window ios 的jenkins进行处理。
阶段、阶段、步骤之间的关系
支持环境: 开发一个流水线脚本
Jenkins的流水线脚本既可以在流水线类型的Jenkins任务中创建, 也可以定义在一个叫作Jenkinsfile的外部文件中。 Jenkinsfile可以同代码保存在一起。 我们会采用在流水线任务中创建脚本的方式来学习创建DSL脚本。
使用代码片段生成器
Snippet generatoràstepsàsample step—>git:git
将poll选项设置为false, 意味着源码控制仓库中的变更将无法自动检测和重新构建。 否则, 如果轮询功能打开, 在第一次运行完成后,源码控制仓库中的变更将被自动检测, 并触发另一次任务的执行。
将changelog选项设置成false, 意味着Jenkins将不会自动获取变更记录,也不会在任务输出的Changes部分中显示。 这么做唯一的好处在于,它可以减轻对版本控制系统的压力。
运行一条流水线
Stage view 颜色快的含义
蓝色条纹:运行中
白色:阶段尚未执行
红色条纹:阶段执行失败
绿色:阶段执行成功
浅红色:阶段执行成功,但是下游的某个阶段出现失败
回放
当错误发生时, 我们希望用一种临时方法进行重试, 而不是每次都要修改并保存代码, 或者有时我们希望在正式提交代码之前进行一次变更的快速验证并查看效果。回放功能可以让你在一次运行结果的基础上修改代码并再次触发流水线。 这会保存一次全新的构建记录, 但原始代码依然保持从前的状态。
第3章 流水线执行流程
触发任务
SCM轮训
这是标准的轮询功能,周期性地扫描源码版本控制系统的变更。如果发现任何更新,任务就会处理这些变化。这种方式可能是相当昂贵的操作(在系统资源方面),取决于SCM类型、 扫描哪些内容以及多久扫描一次。
静默期
这里指定的值将作为构建被触发(检测到代码更新) 和Jenkins真正执行构建之间的一个“等待时间”或者偏移量。这对于那些经常同一时间有很多变更的任务很有用。 如果Jenkins项目中没有配置静默期,将会使用全局配置中的设置。
用户输入
Jenkins任务都具有一个很重要的特性,那就是可以根据用户输入改变它们的行为。
输入
顾名思义, input步骤允许你的流水线停下来等待用户响应。在Jenkins应用中,默认的表单是打印一条消息和提供给用户一个选择,即继续进行(Proceed) 或者中止(Abort)
请注意这一点很重要,当系统执行了一个input步骤时,相应节点上的进程会被暂停。 这会导致系统资源被独占
OK按钮文字
可以使用不同的标签取代“Proceed”,例如“YES”
允许的提交者(submitter)
逗号分隔的用户ID或组名列表, 用于授权哪些人可以给予响应
在使用提交者选项的时候, 需要注意两点:
- 不要使用空格(只能使用逗号) 分隔列表中的用户/组。
- 至少在某些情况下, 不在列表中的用户可能也可以中止input步骤。
参数
布尔型(boolean)
这是基本的true/false参数。 布尔类型参数的子参数是名称、默认值及描述。
选项型(choice)
这个参数允许用户从一个选项列表中选择。 选项型参数的子参数是名称、 选项及描述。
凭证(credential)
这个参数允许用户选择一个类型并且设置凭证。 可用的子参数包括名称、 凭证类型、 是否必需、 默认值及描述。可选择的凭证类型包括任何、 用户名和密码、 Docker主机证书验证、 SSH用户名及私钥, 机密文件、 机密文本及证书。
文件(file)
这个参数允许用户选择一个文件给流水线使用。
列出Subversion标签(List Subversion tag)
这个参数允许你指定一个Subversion 标签的集合, 在构建运行时可以从中选择一个。 其子参数包括名称、 代码仓库URL、 凭证、 标签过滤器、 默认值、 显示标签的最大值, 以及按最新标签优先排序和(或) 按字母顺序排列选项。
多行字符串(Multiline String)
这个参数允许用户输入多行文本。
密码(password)
这个参数允许用户输入一个密码。对于密码文本,用户键入的时候会被隐藏起来。可用的子参数包括名称、默认值及描述。
运行(RUN)
这个参数允许用户从一个任务中选择一个特定的运行(已经执行过的构建) 。 这个参数可能会被用在如测试环境之中。 可用的子参数包括名称、 项目、 描述及过滤器。
字符串(string)
这个参数允许用户输入一个字符串(类似密码参数, 但是字符串的值不会被隐藏) 。 其子参数包括名称、 默认值及描述。
多个输入参数的返回值
如果没有参数, 例如, 只有继续进行和中止选项, 那么这个返回值就会是null。 如果有多个参数,将会返回一个映射(map) , 你可以通过参数的名称抽取每一个参数的返回值。
参数与声明式流水线
使用parameters指令
声明式流水线结构
这种方法是使用声明式流水线所推荐的方法。
使用Jenkins应用来参数化构建
如果你已经在Jenkins应用中创建了一个任务(而不是使用Jenkinsfile自动创建) , 添加参数的第二个途径就是简单地使用传统的方法来参数化一个任务。 也就是说, 在基本配置部分中, 勾选这个项目是参数化的(This project is parameterized) 复选框, 然后就可以照常在任务的Web界面上定义你的参数
这种方法的生效范围只在Jenkins应用中并且是其中的个别任务, 因此不推荐在生产环境中使用。 而且这种方法还会覆盖Jenkins任务中定义的同名属性。
使用一个script代码块
虽然声明式流水线一直在持续进化并添加更多功能, 但是仍然有些场景是声明式风格不支持的或者实现起来非常困难的。 对于这些情况,声明式语法支持一个script代码块。
一个script代码块允许你在该代码块中使用非声明式的语法。 其中就包括定义变量, 而这在声明式流水线的script代码块外是不被允许的。 这也意味着你不能在script代码块之外引用该代码块中定义的变量。
使用外部代码
另一个可用的方法是, 把脚本式语句(类似调用输入语句) 存放在外部共享库中或者存放在一个可以加载执行的外部Groovy文件中。
流程控制选项
超时(timeout)
这个timeout步骤允许你限制等待某个行为发生时脚本所花费的时间。
重试(retry)
这个retry闭包将代码封装为一个步骤, 当代码中有异常发生时,该步骤可以重试过程n次。
睡眠(sleep)
这是一个基本的延时步骤。 它接收一个数值并且延迟相应的时间后再继续执行。 默认的时间单位是秒
等待直到(waitUntil)
这个步骤会导致整个过程一直等待直到某件事发生。
如果代码块中的过程返回false, 那么waitUntil步骤将会在等待更长的时间后进行下一次尝试。 你可能会想这里“更长的”是什么意思。 当前, 系统从0.25s等待时间开始。 如果需要再次循环, 会乘以一个1.2的因子得到0.3s, 作为下一次的等待时间。 在后续的循环中, 最近一次的等待时间再乘以1.2得到新的等待时间。 所以, 等待时间的序列是0.25、 0.3、 0.36、0.43、 0.51……
处理并发
使用lock步骤对资源加锁
如果你安装了可锁定资源插件(Lockable Resources plugin),系统中就会有一个DS- lock步骤可以用来阻止多个构建在同一时间试图使用同样的资源。
使用milestone来控制并发创建
为了防止出现构建运行顺序(按照启动顺序) 混乱而互相覆盖的情况, 在Jenkins流水线中可以使用milestone步骤。 当一个milestone步骤被放在流水线中时, 如果较新的构建已经到达了那里, 系统就会阻止较老的构建通过这个里程碑。
对于里程碑的处理规则, 可以总结如下。
- 构建按照构建编号依次通过这些里程碑。
- 如果一个较新的构建已经通过了里程碑, 较旧的构建会中止运行。
- 当一个构建通过了一个里程碑, Jenkins会中止那些已经通过了前一个里程碑但还没有达该里程碑的较旧的构建。
- 如果一个较旧的构建通过了某个里程碑, 那些还没有通过该里程碑的较新的构建不会被中止
在多分支流水线中限制并发
流水线DSL包含了一个可以限制多分支流水线每次只构建一个分支的方法。 在脚本式或声明式流水线中, 这是通过设置一个属性来完成的。 在这个属性被设置后(在分支对应的Jenkinsfile里) , 当前正在构建的分支以外的其他分支所申请的构建会被放入队列中排队
并行地运行任务
除了一些用于控制流水线逻辑流程的结构, 步骤也可以并行地运行。
有条件的执行功能
有史以来,条件性构建步骤插件(Conditiona- BuildStep plugin) 可以让用户在Jenkins自由风格类型的任务中添加一些有条件的执行功能。它允许选择一种方法来测试某些条件, 然后基于结果执行一个或者多个构建步骤
构建后处理
传统的(基于Web的) Jenkins自由风格类型任务包含一个构建后操作部分, 在那里用户可以添加一些在构建结束后一定发生的行为, 不管构建的状态是成功、 失败或者被中止。
脚本式流水线构建后处理
- catch-finally 机制
- catchError
Jenkins流水线语法还提供了一个更加高级的处理异常的方法。catchError代码块提供了一种方法, 可以探测异常以及改变整个构建的状态, 还能继续执行流水线进程。
使用catchError结构, 如果一个代码块抛出了一个异常, 那么这个构建会被标记成失败状态。 但是, 流水线中从catchError代码块往后的语句可以继续执行。
这样处理的优点是, 在处理失败后, 你依然可以做一些类似发送通知的事情。 这不仅拟了我们所习惯的传统Jenkins模型中的构建后处理过程, 而且还提供了一个try-catch代码块的快捷方式。
声明式流水线与构建后处理
一个post部分可以放在一个阶段的结尾或者一个流水线的结尾——或者同时放在这两个地方。
- Always:总是执行代码块中的步骤
- Changed:如果当前构建的状态与先前构建的状态不同,则执行代码块中的步骤
- Success:如果当前构建状态为成功的,则执行代码块中的步骤
- Failure:如果当前构建状态为失败的,则执行代码块中的步骤
- Unstable:如果构建状态为不稳定的,则执行代码块中的步骤
第4章 通知与报告
这些选项在管理Jenkins 区域的系统配置(Configure System) 页面上进行管理操作。
通知
电子邮件
在Jenkins中, 电子邮件是通知功能的主要途径。
两个插件的使用E-mai- Notification、Extension Emai- plugin, email-ext
协作服务
插件Slack和HipChat
报告
Jenkins使用的许多插件或工具都会为各种任务生成HTML报告。 这样的任务包括代码分析、 代码覆盖率和单元测试报告等。 其中一些工具(如SonarQube和JaCoCo) 甚至可以和Jenkins任务输出做定制集成。
第5章 访问与安全
启用此选项后, 安全性可以在两个维度上进行配置——身份验证和授权。
这里的身份验证是指用户如何在系统中确认他们的身份,比如,通过用户ID和密码。 Jenkins现在称之为安全域(Security Realm) 。 授权是指允许授权用户拥有哪些权限。
启用安全性
访问控制安全域
servlet容器代理。 这里提到的servlet容器就是运行Jenkins实例的一种方法。 现在, 通常会使用Jetty, 但如果是定制化安装的话, 则有可能是Tomcat或其他的servlet。 使用这个选项, 你可以通过servlet容器支持的任何机制来进行身份验证。
当前由于其他选项的出现, 已经不太可能使用这种方法了, 但是向后兼容依旧是有价值的, 或者你已经在servlet容器的配置中为身份验证做了大量的设置。
Jenkins专有用户数据库。 此选项将身份验证委托给Jenkins维护/熟悉的人员列表。 这不是一个典型的用例, 但适用于轻量的、 基本的安装设置。 需要注意的是, 这不仅包括Jenkins明确知道的用户, 也包括提交信息中提到了的用户。
LDAP。 轻量级目录访问协议(LDAP, Lightweight DirectoryAccess Protocol) 是用于在网络上定位人员、 组织、 设备和其他资源的一种软件协议。 如果你的公司使用LDAP, 你就可以为Jenkins配置它。你可以添加一个以上的LDAP服务器(如果需要的话, 每一个服务器都有不同的配置) 。
UNIX用户/组数据库。 此选项将身份验证委托给UNIX主机系统的用户数据库。 如果使用此方法, 用户可以使用UNIX用户名和密码登录Jenkins。
访问控制——授权
任何用户可以做任何事。 使用此选项将不会进行真正的身份验证。 总的来说, 每个人都被认为是“可信的”——包括匿名用户(即使他们还没登录) 。 这是不被推荐的, 但在一个完全可信的环境中, 为了简单和高效, 它适应于允许无限制访问的情况。
传统模式。任何具有“管理员”角色的人都有完全的控制权, 而其他人只有只读权限。
登录用户可以做任何事。 顾名思义, 用户必须先登录, 然后才能完全访问。 如果你不介意每个人都能完全访问, 而只是想要追踪谁正在做什么的话(通过他们的登录) , 这是有用的。这里还有一个子选项能开启匿名用户拥有只读权限。
安全矩阵。此选项允许你通过矩阵排列中的复选框为单个用户或组指定非常详细的权限。 矩阵中的列被划分为类别(分组) , 比如总体、任务、 运行等。 然后在这些项的下面是与该类别相关的更细的权限。矩阵的每一行代表一个用户或组。 有两个默认组是自动添加的: 匿名用户(未登录的用户) 和已验证用户(登录的用户) 。 矩阵下的文本框可以允许你添加新用户。
项目矩阵授权策略。 此选项是前面章节中描述的“安全矩阵”模型的扩展。 在选择此选项后, 会为每个项目的配置页添加一个类似的矩阵。这允许每个项目可以以用户/组来配置, 因此你可以限制对某些项目的访问, 但同时允许访问其他项目。
其他全局安全设置
主要目的是保证Jenkins的隐式安全, 而不是显式地定义访问权限。
标记格式化程序:Jenkins允许用户在各种文本域中放置自由形式的文本, 比如, 任务描述、 构建描述等。 你可以选择将这些格式设置为纯文本或HTML。
代理:这部分用于配置通过JNLP进程启动的代理的TCP端口。 (JNLP是指Java网络启动协议(Java Network LaunchProtocol) —— 一种可以在客户端桌面上通过使用远程服务器上的资源来启动应用的方式) 。如果你没有使用JNLP功能, 你可以在这里使用禁用选项(Disable option) 来保证你的系统更加安全。
防止跨站请求伪造攻击:
插件管理:此选项是“使用浏览器进行元数据下载”, 并且通常情况下它处于未选中(关闭) 状态。 打开这个选项就是告诉Jenkins让浏览器通过插件下载元数据而不是Jenkins自己来做。 除非你有特殊原因要激活它, 否则最好让它保持关闭状态并允许Jenkins进行下载操作。
隐藏安全警告****:此选项与从已安装组件的更新站点获取的安全警告有关。如果你有一个警告列表, 那么已被勾选的警告会被显示, 没被勾选的那些则不显示。Ps:内网使用,这些警告根本无法获取到,所以是否配置,并不影响。大多数情况下,警告也并不是一定要修复,因而如果不是要求吹毛求疵的安全,则可以屏蔽。
SSH服务器:为了通过SSH执行命令行子集,Jenkins可以充当SSH服务器。一些插件也可能会使用这个功能。如果需要用到这个功能,可以在这里设置一个固定端口以简化安全性。 也可以使用随机端口来避免冲突。 如果不需要此功能, 则最好使用禁用选项来禁用已打开的端口。
Jenkins中的凭证
除了全局地对Jenkins的不同方面进行安全加固外, 使用特定、 安全的凭证构成了一个安全的Jenkins环境中的关键部分。
凭证类型的列表如下。
- 用户名和密码——可能被结合起来(当作一项) 或者分开使用。
- Docker凭证目录(现在不推荐使用了) 。
- Docker主机凭证验证。
- SSH用户名和私钥。
- 机密ZIP文件——带凭证的ZIP文件。
- 机密文件——带凭证的未压缩文件。
- 机密文本——令牌或其他链。
- 凭证——带凭证或凭证链的Java密钥库
具体的示例可能如下。
- 结合用户名和密码去获取一个源码版本控制仓库的访问权限。
- 一个数字键或凭证, 用于标记一个实体。
- 一个机密文本字符串, 通过匹配来验证内容是否来自特定源。
- 一个SSH键集合, 可以用于部署到一个服务器。
凭证范围
凭证具有与它们相关联的范围。 这是一种表示它们如何才能被暴露的方式。 Jenkins使用的主要范围有如下3种。
系统:顾名思义, 这个范围与根上下文, 也就是Jenkins系统关联。 此范围中的凭证只被暴露给系统和后台任务, 并且一般被用于连到构建节点/代理节点等事情。
全局****:全局范围是默认选项, 通常用来确保Jenkins中的任务以使用凭证。 此范围中的凭证暴露了它们的上下文和该上下的所有子上下文。
用户:顾名思义, 这个范围是每个用户。 这意味着只有当Jenkin中的线程作为该用户进行身份验证时, 凭证才可用。
凭证域
凭证域提供了一种在共同域名下组合凭证集合的方法。 通常, 公共域名意味着某些期望使用凭证的功能和应用类型。
Jenkins总是有至少一个凭证域——那就是全局域。 全局凭证域没有任何规范, 因此它适用于Jenkins中的任何东西去使用。
凭证提供者
凭证提供者是可以存储和获取凭证的地方。 这可以是内部凭证存储, 也可以是外部凭证库。
系统凭证提供者(Jenkins凭证提供者):这会在根上下文中暴露凭证(Jenkins本身) 。 两个凭证范围可用:系统和全局。 你可以在Jenkins→凭证→系统中看到这些。
用户凭证提供者:这为用户暴露了每个用户的凭证存储。 只有用户范围是可用的, 并且一个用户不能看到另一个用户的用户凭证。 你可以在Jenkins→<username>→凭证→用户或者Jenkins→人们→<username>→凭证→用户中看到这些凭证。