运行Jenkins代理的方法有很多。其中大部分方法存在的问题是我们不得不通过Jenkins UI逐个添加代理,但我们不会这么做,而是尝试利用Docker Swarms的功能来扩展这些代理服务。
Jenkins Swarm Plugin(https://wiki.jenkins-ci.org/display/JENKINS/Swarm+Plugin)是一种可以用来实现可缩放代理的方法。在你开始得出错误的结论之前,我们必须说明这个插件与Docker Swarm无关,它们的唯一关系只是共用了Swarm(群集)这个单词。
Jenkins Swarm Plugin(https://wiki.jenkins-ci.org/display/JENKINS/Swarm+Plu gin)允许我们自动发现附近的master并自动加入它们,这里只使用自动加入的功能。我们会创建一个Docker Swarm服务,它将充当Jenkins代理并自动加入master。
首先需要安装插件。
请按照以下代码打开插件管理器界面:
给Windows用户的说明
Git Bash可能不支持open命令,如果真是这样的话,则执行docker-machine ip <SERVER_NAME>来查找机器的IP,然后直接在浏览器中打开URL,比如上面的命令应该被替换为docker-machine ip swarm-1,如果命令输出的是1.2.3.4,则应该在浏览器里打开http://1.2.3.4:8082/jenkins。
接下来要搜索Self-Organizing Swarm Plug-in Modules plugin。最简单的方法是在屏幕右上角的Filter框中输入插件名称。找到插件之后,请选中并单击“Install without restart”按钮。
现在插件已经安装好,可以设置第二个由三节点组成的集群。和以前一样,我们称之为swarm-test。可以使用脚本scripts/dm-test-swarm-2.sh(https://github.com/ vfarcic/cloud-provisioning/blob/master/scripts/dm-test-swarm-2.sh)来运行创建机器并将它们加入集群所需的所有命令。
node ls命令的输出如下(为简洁起见,删除了ID):
刚刚运行的脚本与之前使用的dm-test-swarm.sh脚本之间唯一的明显区别是这个脚本添加了一些标签。第一个节点被标记为jenkins-agent,另外两个节点标记为prod-like。这些标签背后的原因是,尽量区分开用于运行诸如构建和测试jenkins-agent等任务的节点,以及用于在模拟生产prod-like的环境中运行服务的节点。
现在来看看swarm-test-1节点:
如你所见,这个节点带有键值为env和jenkins-agent的标签。如果检查其他两个节点,就会发现它们也被标记了,只是标记值为prod-like,如图6-4所示。
图6-4 添加标签后的节点
现在已经搭建好了swarm-test集群,准备创建Jenkins代理服务,但是在这之前,让我们快速看一下要使用的镜像的定义。vfarcic/jenkins-swarm-agent Dockerfile(https://github.com/vfarcic/docker-jenkins-slave-dind/blob/master/Dockerfile)如下所示:
它使用docker作为基础镜像,接着是几个环境变量,这些变量定义了将要安装的软件版本。添加了jenkins用户以运行Jenkins。随后安装OpenJDK、Python和pip。Jenkins Swarm客户端依赖JDK,Docker Compose依赖Python和pip,设置好了前面这些前置条件之后,下载Swarm JAR并使用pip来安装Docker Compose。
最后,复制run.sh(https://github.com/vfarcic/docker-jenkins-slave-dind/blob/ master/run.sh)脚本,设置其执行权限,并定义运行时命令来运行它。该脚本使用Java来运行Jenkins Swarm客户端。
在继续创建Jenkins代理服务之前,需要在运行代理的每个主机中创建/workspace目录,目前只在swarm-test-1节点上这么做。很快你会明白为什么需要这个目录:
进入swarm-test-1节点,创建目录,给它全部权限,然后退出机器。
理解了vfarcic/jenkins-swarm-agent镜像(或者至少它包含的内容)之后,可以继续并创建服务。
给Windows用户的说明
为了下一个命令使用的--mount参数能够正常工作,你需要阻止Git Bash修改文件系统路径。按照下面设置环境变量:
这次创建服务的命令比我们之前遇到的要长一些。COMMAND_OPTIONS环境变量包含代理程序连接到master需要的所有信息。我们指定了master的地址-master http://$(docker-machine ip swarm-1):8082/jenkins,定义了用户名和密码-username $USER-password $PASSWORD,标记了代理-labels 'docker',并设置执行器的数量-executors 5。
另外,我们声明服务为global并将其限制在jenkins-agent节点上。这意味着它将在每个带有匹配标签的节点上运行。虽然目前只有一台服务器,但我们很快会看到这样的设置提供的好处。
我们挂载了Docker socket,这样发送到在容器内运行的Docker客户端的任何命令都将在主机上运行Docker Engine(本例中为Docker Machine)。因此,可以避免通过在Docker中运行Docker或者叫DinD造成的陷阱。有关更多信息请阅读文章Using Docker-in-Docker for your CI or testing environment? Think twice(http://jpetazzo.github.io/2015/09/03/do-not-use-docker-in-docker-for-ci/)。
我们还挂载了包含密钥的主机(笔记本电脑)目录。这将允许我们向在另一个集群内运行的引擎发送请求。最后一个挂载命令将容器内的/workspace目录暴露给了主机。在Jenkins代理中运行的所有构建都将使用该目录,如图6-5所示。
图6-5 Jenkins代理作为全局服务运行
我们来看看服务进程:
输出如下(为简洁起见,删除了ID):
正如你所看到的那样,这个服务是全局的,所以期望的状态是它在每个节点上运行。但是,由于我们将其限制在带有标签jenkins-agent的节点,因此容器仅在具有匹配标签的那些节点内运行。换句话说,服务只在jenkins-agent节点上运行。
让我们打开显示已注册代理的Jenkins页面:
给Windows用户的说明
Git Bash可能不支持open命令,如果真是这样的话,则执行docker-machine ip <SERVER_NAME>来查找机器的IP,然后直接在浏览器中打开URL,比如上面的命令应该被替换为docker-machine ip swarm-1,如果命令输出的是1.2.3.4,则应该在浏览器里打开http://1.2.3.4:8082/jenkins。
正如你所看到的,已经注册了两个代理(见图6-6)。主代理在每个Jenkins实例中都默认运行。在笔者的机器上,作为jenkins-agent服务运行的代理被标识为e0961f7c1801-d9bf7835:
图6-6 加入master的Jenkins Swarm代理
由于使用了标签将服务限制在swarm-test-1节点上,所以目前我们只注册了一个代理(除master外,大多数情况下不应该这么做(指仅运行一个实例))。
代理配置为使用五个执行器,这意味着五个构建可以并行执行。请注意,这种情况下,执行器的数量是虚高的,因为每台机器只有一个CPU。没有任何附加信息的话,我会将执行器的数量设置为与CPU的数量相同。这将是仅有的随时间变化而变化的基本计算。如果通过这些执行器执行的任务是CPU密集型的,那么可能需要减少执行器的数量。然而,为了达到这个练习的目的,五个执行器应该没有问题。我们只有一个服务,所以不会并行运行构建。
让我们假设这是真实的系统,并行构建的数量比执行器的数量多。这种情况下,有任务会排队等待执行器完成并释放资源。如果这是一个临时情况,则可以不需要做任何事情,执行的构建会结束,释放资源并运行排队的构建。但是,如果这种情况重复发生,排队构建的数量可能会开始增加,然后一切都会变慢。既然已经确认速度是持续集成、交付和部署过程的关键要素,当遇到阻碍时,就要想一些办法。这种情况下,需要增加可用执行器的数量,也就是增加代理的数量。
假设我们达到了极限并且需要增加代理的数量,那么在了解了全局Swarm服务如何工作之后,所要做的只是创建一个新节点:
我们创建了swarm-test-4节点,并在里面创建了/workspace目录。然后得到令牌并将新创建的服务作为worker加入集群。
让我们确认新节点确实已添加到集群中:
node ls命令的输出如下(为简洁起见,删除了ID):(www.xing528.com)
Jenkins代理是否在新创建的节点内运行呢?让我们来看看:
service ps命令的输出如下(为简洁起见,删除了ID):
由于该节点未标记为jenkins-agent,因此该代理没在swarm-test-4服务器内运行。
添加标签,代码如下:
这一次,输出有些不同(为简洁起见,删除了ID):
Swarm检测到了新标签,然后运行容器,并将状态更改为运行状态。
让我们回到列出已连接代理的Jenkins页面:
给Windows用户的说明
Git Bash可能不支持open命令,如果真是这样的话,则执行docker-machine ip <SERVER_NAME>来查找机器的IP,然后直接在浏览器中打开URL,比如上面的命令应该被替换为docker-machine ip swarm-1,如果命令输出的是1.2.3.4,则应该在浏览器里打开http://1.2.3.4:8082/jenkins。
如你所见,新的代理b76e943ffe6c-d9bf7835被添加到了列表里,如图6-7所示。
图6-7 加入master的第二个Jenkins Swarm代理
这很简答,不是吗?通常情况下,我们不仅要创建新的服务器,还要运行代理并通过UI将其添加到Jenkins配置中。通过结合Jenkins Swarm插件和Docker Swarm全局服务,我们成功实现了大部分步骤的自动化。现在所要做的就是创建一个新节点并将其添加到Swarm集群中。
在继续并通过Jenkins实现持续部署流程自动化之前,我们应该在生产和类生产环境中创建服务。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。