Jenkins分布式与并行
一.简介
在前面的章节中,所有的Jenkins项目都是在Jenkins master的executor上执行的。如果Jenkins master上只有两个executor,那么只有两个项目能同时执行,其他项目都必须要排队。
假如单机足够强大,让更多项目同时执行的方法就是增加executor。但单机的容量总会遇到上限,而且还会有单节点问题。
解决办法就是将Jenkins项目分配到多台机器上执行,这就是分布式构建。
在真正介绍分布式构建前,我们需要了解一下Jenkins的架构,因为它决定了分布式构建的实现。
Jenkins采用的是“master+agent”架构(有时也称为“master+slave”架构),如图14-1所示。Jenkins master负责提供界面、处理HTTP请求及管理构建环境;构建的执行则由Jenkins agent负责(早期,agent也被称为slave。目前还有一些插件沿用slave的概念)。
基于这样的架构,只需要增加agent就可以轻松支持更多的项目同时执行。这种方式称为Jenkins agent的横向扩容。
Jenkins结构
- node:节点,指包含Jenkins环境及有能力执行项目的机器。master和agent都被认为是节点
- executor:执行器,是真正执行项目的单元。一个执行器可以被理解为一个单独的进程(事实上是线程)。在一个节点上可以运行多个执行器。
- agent:代理,在概念上指的是相对于Jenkins master的一种角色,实际上是指运行在机器和容器中的一个程序,它会连接上Jenkins master,并执行Jenkins master分配给它的任务。
- slave:傀儡,与agent表达的是一个东西,只是叫法不同。
executor的概念是相对于node的,没有node也就谈不上executor了。node通常指的是机器(不论物理的还是虚拟的)。agent有时指一个程序,有时指一种角色(相当于master而言),这取决于上下文。
实现分布式构建最常用、最基本的方式就是增加agent。Jenkins agent作为一个负责执行任务的程序,它需要与Jenins master建立双向连接。连接方式有多种,这也代表有多种增加agent的方式。
二.agent
当agent数量变多时,如何知道哪些agent支持JDK8,哪些agent支持node.js环境呢?我们可以给agent打标签来确定。
通过标签将多个agent分配到同一个逻辑组中,这和过程被称为打标签。同一个agent可以拥有多个标签。在标签名中不能包含空格,也不能包含 ! & | <> ()这些特殊字符中的任何一个,因为包含特殊字符的标签名与标签表达式冲突。
对于支持JDK8的agent,我们打上jdk8标签;对于支持nodejs的agent,打上对应的。如果一个agent支持多个,那就打多个标签。
在打标签时,可以根据以下几个维度来进行。
- 工具链:jdk nodejs ruby,也可以加上工具的版本,如jdk6,jdk8
- 操作系统:linux,windows,osx;或者加上操作系统的版本,如ubuntu18.04,centos7.3
- 系统位数: 32, 63
通过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,进入配置
- Name:agent名称
- Remote root directory:agent机器上的工作目录(Jenkins master不关心),使用决定路径
- Lables:agent的标签
- Usage:agent的使用策略。有2种
- Use this node as much as possible,尽可能使用此agent。
- Only build jobs with labe expressions matching this node,只有当构建任务符合本agent的标签时,才使用此agent。
- Launch method:agent的运行方式。JNLP协议的agent选择Launch agent via Java Web Start。配置完成后进入节点列表页面,此时master节点的状态显示是在线的,即可用的。
3.单机节点列表的node1,跳转到Agent node1页面
JNLP协议agent连接Jenkins master还有3种方式。
一是在agent机器的浏览器中打开此页面,单机Launch按钮
二是通过javaws命令从master节点下载java web start程序
三是无界面方式连接,通过命令操作
4.选择第三种方式。ssh登陆到Jenkins agent机器,下载agent.jar文件(JNLP协议的客户端),下载路径为:<Jenkins master地址>/jenkins/jnlpJars/agent.jar
。
安装jdk,执行命令 java -jar agent.jar -jnlpUrl http://1.1.1.1/jenkins/computer/node1/slave-agent.jnlp -workDir "/app"
。其中-workDir参数指定agent的工作目录。
当命令提示连接成功后,打开Jenkins master页面,查看nod1的详情页,会显示已经成功了。
细心的读者会发现,agent与master之间的连接过程没有任何权限控制。这是因为我们没有设置Jenkins的安全控制(默认Jenkins向匿名用户开放所有权限)。当设置了安全控制后,新建node,我们将在node的详情页看到连接master的命令就变成了∶
java -jar agent.jar-jnlpUrl http://192.168.23.11:8667/jenkins/computer/node1/slave-agent. jnlp -secret29c5d8070da37d1ae68238e112b4ca145335843b4177c013795413355f3a3c3f -workDir "/app"
其中-secret******就是agent 与master之间的连接凭证。每一个JNLP客户端的凭证都不一样。
提示:升级Jenkins后,也需要重新下载agent.jar。agent.jar需要与Jenkins master同步升级。
最后,我们看到通过JNLP协议增加agent的方式是需要在Jenkins界面上进行手动操作的(增加节点的操作)。这部分是无法自动化的,因此,我们只在以下场景中使用这种方式。
- 在安全性要求相对较高的情况下,只能手动增加agent
- 增加Windows agent
通过Swarm插件增加agent
Swarm插件可以帮助我们更好的增加agent,安装此插件后,增加agent就不需要在Jenkins界面上进行手动操作了。只需要启动Swarm客户端(指定Jenkins master地址),master与agent就会自动建立连接。
1.安装Swarm插件(swarm)
2.确保Jenkins agent机器上安装有JDK
3.在Jenkins agent机器上下载Swarm客户端 https://repo.jenkins-ci.org/releases/org/jenkins-ci/plugins/swarm-client/3.9/swarm-client-3.9.jar
4.在Jenkins agent上启动swarm-client连接服务器端
java -jar swarm-client-3.9.jar -username admin -password admin -master http://1.1.1.1/jenkins -name swarm-node
连接显示成功,节点页面可以看到swarm客户端连接成功
以下是swarm-client部分参数的介绍
-deleteExistingClients:如果Jenkins master上已经存在同名的node,则先删除(慎用)
-description:描述
-disableClientsUniqueld:默认Swarm会在node名称后加上一个唯一ID。加入此参数后,代表取消加上唯一ID。
-disableSslVerification:取消SSL校验
-executors N:设置executor的个数
-labels VAL:分配给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:最大重连次数,默认无次数限制
-retrylnterval N:每次重连间隔时长,单位为秒。默认值为10秒。
java xx.jar -help可以查看参数
agent部分详解
打完标签后,如何在pipeline中使用标签呢?
Jenkins master根据此agent部分决定将任务分配到哪个agent上执行。agent部分必须在pipeline块内的顶层定义,而在stage块内的定义是可选的。
agent any告诉Jenkins master任何可用的agent都可以执行。
agent部分的定义可以放在阶段中,用于指定该stage执行时的agent
pipeline {
agent any //不能省略
stages {
stage('pull') {
agent any
steps {
echo '开始拉取代码'
}
}
}
}
通过标签指定agent
当pipline需要再Jdk 8环境下进行构建时,就需要通过标签来指定agent
pipeline {
agent {
label 'jdk8'
}
stages {
stage('Build') {
steps {
echo "build"
}
}
}
}
事实上,agent{label'jdk8'}是以下定义方式的简略写法。
agent {
node {
label 'jdk8'
}
}
有些构建任务是需要再JDK8以及windows环境下执行的,也就是说我们需要过滤同时具有windows和jdk8标签的agent
agent {
label 'windows && jdk8'
}
使用&&代表并且关系
上文中,在增加agent时,已经配置好了该agent上的默认工作目录路径,但是agent部分允许我们对工作目录进行自定义。node除了label选项,还提供了另一个选项-customWorkspace,自定义工作目录:
agent {
node {
label 'jdk8'
customWorkspace '/var/lib/custom'
}
}
customWorkspace选项除了写绝对路径,还可以写相对于默认工作目录路径的相对路径。
不分配节点
以上介绍的是如何分配agent,其实还可以指定不分配agent,写法很简单: agent none,指的是不分配任何agent。
没有真正遇到过使用场景,可能就很难想象在什么时候使用agent。如果希望每个stage都运行在指定的agent中,那么pipeline就不需要指定agent了
pipeline {
agent none
stages {
stage('Example Build') {
agent { label 'mvn' }
steps {
echo 'Hello,build'
}
}
stage('Example Test') {
agent { label 'test' }
steps {
echo 'Hello,test'
}
}
}
}
when指令的beforeAgent选项
在默认情况下,阶段内所有的代码都将在指定的Jenkins agent上执行过。when指令提供了一个beforeAgent选项,当它的值为true时,只有符合when条件时才会进入该Jenkins agent。这样就可以避免没有必要的工作空间的分配,也就不需要等待可用的Jenkins agent了。
某些场景下,beforeAgent选项通常用于加速pipeline的执行。
pipeline {
agent none
stages {
stage('Example Build') {
steps {
echo 'Hello World'
}
}
stage('Example Deploy') {
agent {
label "some-label"
}
when {
beforeAgent true
branch 'production'
}
steps {
echo 'Deploying'
}
}
}
}
只有分支为production时,才会进入“Example Deploy”阶段。这样就可以避免在some-label的agent中拉取代码,从而达到加速pipeline执行的目的。
三.agent放入Docker
目前我们所有的构建都执行在机器(物理机器或虚拟机器)上。接下来介绍如何让构建执行在Docker容器中。关于Docker是什么,以及它所带来的好处,市面上介绍的文章已经足够多,本书就不做介绍了。
Jenkins master要将构建任务分配给Docker,就必须在Jenkinsagent上安装Docker。建议给这些agent打上docker的标签。
关于Docker 的具体安装过程就不细表了。但是需要注意,要将Jenkins agent 的用户加入Docker的用户组中,这样Jenkins agent不需要加sudo就能执行docker命令。如果不生效,则可能需要重启Jenkins agent。
使用Docker
pipeline插件从2.5版本开始就内置了Docker插件(docker-plugin)。所以,安装pipeline插件后,就可以直接在pipeline的agent部分指定使用什么Docker镜像进行构建了。
pipeline {
agent {
docker {
label 'docker'
image 'maven:3-alpine'
}
stages {
stage('build') {
steps {
sh 'mvn clean compile'
}
}
}
}
}
与之前不同的,在agent部分我们将node换成了docker。下面分别解释docker的常用选项。
- label(可选):字符串类型,与node的label的作用一样。
- image:字符串类型,指定构建时使用的Docker镜像。
- args(可选):字符串类型,Jenkins执行docker run命令时所带的参数,如args'-v/tmp : /tmp'
- alwaysPull(可选):布尔类型,强制每次执行docker pull命令时都重新拉取镜像。
配置Docker私有仓库
进入Manage Jenkins-》Configure System页面,找到“Pipeline Model Definition”部分
- Docker Label:当pipeline中的agent部分没有指定label选项时,就会使用此配置。如docker{image'maven : 3-alpine'}。
- Docker registry URL:Docker私有仓库地址
- Registry credentials:登陆Docker私有仓库的凭证。
四.并行构建
如果需要分别在Chrome、Firefox、IE等浏览器的各个不同版本中对同一个web应用进行UI测试,怎么做呢?
pipeline {
agent any
stages {
stage('Build') {
steps {
echo 'Building..'
}
}
stage('Test on Chrome') {
steps {
echo 'Testing..'
}
}
stage('Test on Firfox') {
steps {
echo 'Testing..'
}
}
}
}
不论是将UI分别放在不同的阶段还是步骤中,这种按顺序执行的测试都太慢了,慢到执行一次完整的UI测试要一小时以上。
通过仔细分析你会发现,这些测试是可以并行执行的。就像原来只有一个测试人员,要测试4个浏览器,他只能测试完一个浏览器,再测试另一个浏览器,但是现在有4个测试人员,他们就可以同时进行测试。这样测试耗时就降到了原来的1/4。
很明显,Jenkins pipeline插件支持这种并行构建,并且使用起来也非常简单。
pipeline {
agent none
stages {
stage('Run Tests') {
failFast true
parallel {
stage('Test On Chrome') {
agent { label "chrome" }
steps {
echo "Chrome UI测试"
}
}
stage("Test On Firefox") {
agent { label "firefox" }
steps {
echo "Firefox UI测试"
}
}
stage("Test On IE") {
agent { label "ie" }
steps {
echo "IE UI测试"
}
}
}
}
}
}
在stages部分包含一个Run Tests阶段,在这个阶段下包含一个parallel块,在parallel块下又包含了多个阶段。位于parallel块下的阶段都并行执行,而且并行阶段还可以被分到不同的Jenkins agent上执行。
因为parallel本身不包含任何步骤,所以在parallel块下本身不允许包含agent和tools。
在默认情况下,pipeline要等待parallel块下所有的阶段都执行完成,才能确定结果。如果希望所有并行阶段中的某个阶段失败后,就让其他正在执行的阶段都中止,那么只需要在与parallel块同级的位置加入failFast true就可以了。
不同分支并行构建
并行构建不仅可以被应用在UI自动化测试中,还可以被应用在不同的分支上。
pipeline {
agent any
stages {
stage('Parallel Stage') {
failFast true
parallel {
stage('Branch master') {
when { branch 'master' }
agent any
steps {
echo "On Branch master"
}
}
stage('Branch dev') {
when { branch 'dev' }
agent any
steps {
echo "On Branch dev"
}
}
stage('Branch staging') {
when { branch 'staging' }
agent any
stage {
stage('嵌套staging 1') {
steps {
echo "staging 1"
}
}
stage('嵌套staging 2') {
steps {
echo "staging 2"
}
}
}
}
}
}
}
}
我们注意到并行阶段Branch staing下又出现了一个stages部分。是的,阶段是可以嵌套的。但是可以嵌套多少层呢?Jenkins的文档并没有明确说,但推荐不超过3层。
因为在同一个Jenkins pipeline中实现过于复杂的逻辑,说明Jenins pipeline的职责不够单一,需要进行拆分。
并行步骤
前面是阶段级别的并行执行,Jenkins pipeline还支持步骤级别的并行执行。这也是Jenkins pipeline最早支持的并行方式
stage('并行构建') {
steps {
parallel(
jdk8: {
echo "jdk8 build"
},
jdk9: {
echo "jdk9 build"
}
)
}
}
区别
并行阶段与并行步骤之间的区别,除了写法不同,表面看并行阶段与并行步骤并没有太大的区别。但是他们还有一个关键的区别:并行阶段运行在不同的executor上,而并行步骤运行在同一个executor上。这样看起来其实就是并行与并发的区别。并行步骤本质上是并发步骤。
Jenkins分布式与并行的更多相关文章
- Jenkins分布式构建与并行构建
Jenkins分布式构建与并行构建 jenkins的架构 Jenkins采用的是"master+agent(slave)"架构.Jenkins master负责提供界面.处理HTT ...
- Jenkins分布式部署配置
为什要使用Jenkins分布式? 利用jenkins分布式来构建job,当job量足够大的时候,可以有效的缓解jenkins-master上的压力,提高并行job数量, 减少job处于pending状 ...
- Jenkins分布式构建
Jenkins分布式构建 有时,如果有一个实例,它是一个更大,更重的项目,需要定期编译生成在许多计算机上.并运行所有这些构建了中央台机器上可能不是最好的选择.在这种情况下,人们可以配置其他Jenkin ...
- 06 . Jenkins分布式构建和Pipline
Pipline简介 pipline 是帮助 Jenkins 实现 CI 到 CD 转变的重要角色,是运行在 jenkins 2.X 版本的核心插件,简单来 说 Pipline 就是一套运行于 Jenk ...
- [源码解析] PyTorch 分布式(18) --- 使用 RPC 的分布式管道并行
[源码解析] PyTorch 分布式(18) --- 使用 RPC 的分布式管道并行 目录 [源码解析] PyTorch 分布式(18) --- 使用 RPC 的分布式管道并行 0x00 摘要 0x0 ...
- Jenkins - 分布式构建
1 - 简介 Jenkins支持分布式多节点(Master-Slave)运行模式. 将安装Jenkins的主机作为Master节点,然后通过界面配置(或远端启动服务)来添加Slave节点. 在这种部署 ...
- Jenkins 分布式和并发构建
1. 分布式构建 1.1 添加 linux 节点 1.2 添加 windows 节点 2. 并发构建 2.1 原理 2.2 示例:分别用 chrome/IE/Firefox 并行测试 1. 分布式构建 ...
- jenkins 分布式部署
一 什么是Jenkins的分布式构建和部署 Jenkins的分布式构建,在Jenkins的配置中叫做节点,分布式构建能够让同一套代码或项目在不同的环境(如:Windows7\winxp和Linux系统 ...
- jenkins 分布式配置+allure集成+邮件发送
jenkins节点配置+allure集成+邮件发送这一套走下来感觉很麻烦,要配置的东西太多了,所以在此记录一下,防止以后忘了. 环境: 主机master:腾讯云服务器ubuntu18.04 执行机sl ...
随机推荐
- Python 爬取 煎蛋
这个我是拿来参考的 import requests def url_open(url): response = requests.get(url) html = response.content re ...
- 菜鸡的Java笔记 第十三 String 类的两种实例化方法
String 类的两种实例化方法 String 类的两种实例化方式的区别 String 类对象的比较 Stirng 类对象的使用分析 /* 1.String 类的两种实例化方式的区别 ...
- Python学习手册(第四版)——使用入门(自学用)
Python的优点 -可读性 -可移植性 -不是一个独立的工具,可以调用各种库,同时也可以被调用等等 -使编程变得很有趣 -面向对象 -可混合 Python的理念 随便找的一张图 脚本语言? Pyth ...
- Go语言核心36讲(Go语言实战与应用十三)--学习笔记
35 | 并发安全字典sync.Map (下) 我们在上一篇文章中谈到了,由于并发安全字典提供的方法涉及的键和值的类型都是interface{},所以我们在调用这些方法的时候,往往还需要对键和值的实际 ...
- Java 代码审计 — 1. ClassLoader
参考: https://www.bilibili.com/video/BV1go4y197cL/ https://www.baeldung.com/java-classloaders https:// ...
- 什么是H5
H5其实就是HTML5 常说的H5测试,就是移动端web页面,他跟安卓app与IOS app的区别: (1)以往的app是使用的原生系统内核的,相当于直接在系统上操作,是传统意义上的软件,更加稳定 ( ...
- 【POJ3349 Snowflake Snow Snowflakes】【Hash表】
最近在对照省选知识点自己的技能树 今天是Hash 题面 大概是给定有n个6元序列 定义两个序列相等 当两个序列各自从某一个元素开始顺时针或者逆时针旋转排列能得到两个相同的序列 求这n个6元序列中是否有 ...
- Codeforces 1109F - Sasha and Algorithm of Silence's Sounds(LCT)
Codeforces 题面传送门 & 洛谷题面传送门 讲个笑话,这题是 2020.10.13 dxm 讲题时的一道例题,而我刚好在一年后的今天,也就是 2021.10.13 学 LCT 时做到 ...
- 洛谷 P6776 - [NOI2020] 超现实树(找性质,神仙题)
洛谷题面传送门 nb tea 一道! 首先考虑怎样入手分析这个看似非常不可做的问题.首先题目涉及高度无穷的树,根本枚举不了.不过我们冷静一下就会发现,如果我们记 \(mx=\max\limits_{i ...
- CSP-S 2021 游记
福兮祸之所伏 胜利是一种肯定,代表我应该在这条路上坚定不移地走下去. 胜利也是一种危机,它粉饰太平.养虎自齧,并把人最丑陋的一些想法暴露出来:虚荣心.骄傲心都在这个过程中被放大,懒惰心.自满心也找到了 ...