Jenkins分布式构建与并行构建
jenkins分布式构建与并行构建
jenkins的架构
jenkins采用的是“master+agent(slave)”架构。jenkins master负责提供界面、处理http请求及管理构建环境;构建的执行则由jenkins agent负责
jenkins agent的横向扩容:只需要增加agent就可以轻松支持更多的项目同时执行
• node:节点,指包含jenkins环境及有能力执行项目的机器。master和agent都被认为是节点。
• executor:执行器,是真正执行项目的单元。一个执行器可以被理解为一个单独的进程(事实上是线程)。在一个节点上可以运行多个执行器。
• agent:代理,在概念上指的是相对于jenkins master的一种角色,实际上是指运行在机器或容器中的一个程序,它会连接上jenkins master,并执行jenkins master分配给它的任务。
增加agent支持并行构建
jenkins agent作为一个负责执行任务的程序,它需要与jenkins master建立双向连接。连接方式有多种,这也代表有多种增加agent的方式。
标签是什么
当agent数量变多时,如何知道哪些agent支持jdk 8、哪些agent支持node.js环境呢?我们可以通过给agent打标签(有时也称为tag)来确定。
同一个agent可以拥有多个标签。在标签名中不能包含空格,也不能包含!、&、|、<、>、(、)这些特殊字符中的任何一个。因为包含特殊字符的标签名与标签表达式(用于过滤agent)冲突。
通过jnlp协议增加agent
java网络启动协议(jnlp)是一种允许客户端启动托管在远程web服务器上的应用程序的协议。jenkins master与agent通过jnlp协议进行通信。而java web start(jws)可以被理解为jnlp协议的一个客户端。
(1)进入manage jenkins→global security→tcp port for jnlp配置页面,如图所示。我们可以选择开放固定端口或者随机开放jenkins master的一个端口来提供jnlp服务。
随机开放端口不利于自动化,所以选择开放固定端口。此端口用于master与agent之间的tcp通信,与访问jenkins界面时的端口有别。
(2)进入manage jenkins→manage nodes→new node页面,如图所示。选项“permanent agent”指的是常驻代理客户端。
单击“ok”按钮后,进入node配置页面
• name:agent名称。
• remote root directory:agent机器上的工作目录(jenkins master不关心),使用绝对路径。
• labels:agent的标签。
• usage:agent的使用策略。有两种:
◦ use this node as much as possible,尽可能使用此agent。
◦ only build jobs with label expressions matching this node,只有当构建任务符合本agent的标签时,才使用此agent。
• launch method:agent的运行方式。jnlp协议的agent选择“launch agent via java webstart”。配置完成后进入节点列表页面,此时master节点的状态显示是在线的,即可用的
当节点不可用时,如node1节点,jenkins master不再分配任务给它
(3)单击节点列表中的node1,跳转到“agent node1”页面,显示详情如图所示。
jnlp协议agent连接jenkins master还有3种方式。一是在agent机器的浏览器中打开此页面,单击“launch”按钮。二是通过javaws命令从master节点下载java web start程序。三是*面方式连接。第3种方式不需要界面操作,我们毫不犹豫地选择它,因为只有这样才方便自动化。
(4)ssh登录到jenkins agent机器,下载agent.jar文件(jnlp协议的客户端),下载路径为:<jenkins master地址>/jenkins/jnlpjars/agent.jar。假设这台机器已经安装好jdk,则执行命令:java-jar agent.jar-jnlpurl http::8667/jenkins/computer/node1/slave-agent.jnlp-workdir "/app"。其中-workdir参数用于指定agent的工作目录。当命令提示连接成功后,我们打开jenkins master页面,查看node1的详情页,如图所示,表示已经连接成功。
agent与master之间的连接过程没有任何权限控制。这是因为我们没有设置jenkins的安全控制(默认jenkins向匿名用户开放所有权限)。当设置了安全控制后,新建node,我们将在node的详情页看到连接master的命令就变成了:
其中-secret******就是agent与master之间的连接凭证。每一个jnlp客户端的凭证都不一样。
提示:升级jenkins后,也需要重新下载agent.jar。agent.jar需要与jenkins master同步升级。
最后,我们看到通过jnlp协议增加agent的方式是需要在jenkins界面上进行手动操作的(增加节点的操作)。这部分是无法自动化的,因此,我们只在以下场景中使用这种方式。
• 在安全性要求相对较高的情况下,只能手动增加agent。
• 增加windows agent。
通过swarm插件增加agent
swarm插件只需要启动swarm客户端(指定jenkins master地址),master与agent就会自动建立连接。
(1)安装swarm插件。
(2)确保jenkins agent机器上安装有jdk。
(3)在jenkins agent机器上下载swarm客户端
(4)在jenkins agent上启动swarm-client连接服务器端。
当日志显示连接成功后,在节点列表页面可以看到swarm客户端连接成功
swarm-client部分参数的介绍。
•-deleteexistingclients:如果jenkins master上已经存在同名的node,则先删除。(慎用)
•-description:描述。
•-disableclientsuniqueid:默认swarm会在node名称后加上一个唯一id。加上此参数后,代表取消加上唯一id。
•-disablesslverification:取消ssl校验。
•-executors n:设置executor的个数。
•-labels val:分配给agent的标签,如果有多个,则使用空格分隔。注意,这是给agent打标签。
•-master val:指定jenkins master的url。
•-mode mode:jenkins master分配项目给agent时使用的格式,即有两种格式,即normal(尽可能分配job)和exclusive(当与指定label匹配时才分配项目)。
•-username val:连接时使用的用户名。
•-password val:连接时使用的密码。不推荐使用。
•-passwordenvvariable val:从环境变量中读取密码。推荐使用。
•-passwordfile val:从文本文件中读取密码。推荐使用。
•-retry n:最大重连次数,默认无次数限制。
•-retryinterval n:每次重连间隔时长,单位为秒。默认值为10秒。
agent部分详解
如何在pipeline中使用标签呢
agent部分描述的是整个pipeline或在特定阶段执行任务时所在的agent。换句话说,jenkinsmaster根据此agent部分决定将任务分配到哪个agent上执行。agent部分必须在pipeline块内的顶层定义,而stage块内的定义是可选的。
agent any告诉jenkins master任何可用的agent都可以执行。
agent部分的定义可以放在阶段中,用于指定该stage执行时的agent。
注意:pipeline块内的agent部分是必需的,不能省略。
通过标签指定agent:
当pipeline需要在jdk 8环境下进行构建时,就需要通过标签来指定agent。代码如下:
有些构建任务是需要在jdk 8及windows环境下执行的。也就是说,我们需要过滤同时具有windows和jdk8标签的agent。
上文中,在增加agent时,已经配置好了该agent上的默认工作目录路径,但是agent部分允许我们对工作目录进行自定义。node除了label选项,还提供了另一个选项——customworkspace,自定义工作目录,写法如下:
customworkspace选项除了写绝对路径,还可以写相对于默认工作目录路径的相对路径。
不分配节点 : agent none
when指令的beforeagent选项 :
在默认情况下,阶段内所有的代码都将在指定的jenkins agent上执行。when指令提供了一个beforeagent选项,当它的值为true时,只有符合when条件时才会进入该jenkins agent。这样就可以避免没有必要的工作空间的分配,也就不需要等待可用的jenkins agent了。在某些场景下,beforeagent选项通常用于加速pipeline的执行。示例如下:
只有分支为production时,才会进入“example deploy”阶段。这样就可以避免在some-label的agent中拉取代码,从而达到加速pipeline执行的目的。