如何防止某些 Jenkins 作业同时运行?

Posted

技术标签:

【中文标题】如何防止某些 Jenkins 作业同时运行?【英文标题】:How to prevent certain Jenkins jobs from running simultaneously? 【发布时间】:2011-09-10 16:49:55 【问题描述】:

我有几个使用共享资源(数据库)的作业,有时会导致构建失败(罕见)事件,即作业碰巧同时被触发。

例如,给定作业 A 到 E,有没有办法指定 A 和 C不应同时运行

除了上述资源之外,构建是相互独立的(不是例如上游/下游关系)。

一种“蛮力”方式是将执行器的数量限制为一个,但如果大多数作业可以同时执行并且构建服务器上不缺少计算资源,这显然不太理想。

【问题讨论】:

看起来这个插件已经被弃用了:( 哪个插件在弃用列表中? @marc.guenther:John 的评论与pwan's answer 中提到的Locks and Latches plugin 有关。它是proposed for deprecation here,但除此之外,我看不到它消失的任何迹象。所以我想你可以使用“Locks and Latches”或“Throttle Concurrent Builds”来实现这一点。 避免使用 Locks and Latches 插件。它在弃用列表中是有原因的。如果您在等待获取锁时手动中断作业,则该作业将不再运行,直到 Jenkins 主服务器重新启动。 Throttle Concurrent Builds 插件是一个更好的选择,它不会影响您的 Jenkins 安装。 【参考方案1】:

锁和闩锁插件here 应该会有所帮助。

这个问题很可能是How do I ensure that only one of a certain category of job runs at once in Hudson?的骗子

【讨论】:

谢谢,成功了!快速参考:1)在 Manage Jenkins -> Configure System -> Locks 中定义锁(在我的例子中,我使用了共享数据库的名称); 2)设置相关作业使用锁:配置->构建环境->锁 我的问题确实似乎归结为与旧问题相同的问题。但我认为这个更清晰(问题正文中没有基本上不相关的文字墙,也没有误导性标签)...... 请注意 - 有时多个作业会同时获得锁定。您可以通过限制该节点上的执行程序数量来避免这种情况。 正如@John T Dyer 指出的,Locks and Latches 在proposed plugin deprecation list 上。阅读该页面上的 cmets,似乎 Throttle Concurrent Builds 应该是一个可行的替代品。 对于詹金斯:Throttle Concurrent Builds plugin【参考方案2】:

目前有两种方法:

使用Throttle Concurrent Builds 插件。 将这些作业设置为在只有 1 个执行器的从属设备上运行。

【讨论】:

由于某种原因,仅使用一个执行器的简单方法对我不起作用。我将其配置为 1,4 天后有人报告说有 2 个正在运行,.. 配置显示:max = 1。 有人知道是否可以使用 Throttle Concurrent Builds 来限制两个管道,但同时允许其中一个管道同时执行自己的作业?例如,我有一个管道 A 和一个管道 B,我确实有 A 正在运行,而 B 将无法运行,因为 A 有一些工作正在运行。如果有任何 A 在运行,我希望能够让 A 的 N 个作业运行而 B 都没有运行。【参考方案3】:

查看External Resource Dispatcher Jenkins 插件,该插件于 2012 年 11 月首次发布。这个(相对)新插件似乎完全涵盖了这个用例。

【讨论】:

它充满了错误(我不得不修改源代码以使某些东西甚至无法正常工作)并且不再适用于最新的 Jenkins。除此之外,这正是我想要的:-)【参考方案4】:

注意您不需要为从站/节点提供物理或虚拟硬件,您可以设置在主服务器上运行的“从站”。

管理 Jenkins > 管理节点 > 新节点

并制作一个“哑奴隶”,每个都有自己的根目录。

创建一些从属服务器,在服务器启动时执行它们,然后您就基本上创建了执行程序池。

你可能有,说...

db - 在您的情况下只有一个执行者。 编译 - 根据硬件或 CPU 数量进行限制。 脚本 - 为 Jenkins 擅长的所有小工作提供许多执行器。

【讨论】:

【参考方案5】:

老问题,这是否适用于您的应用程序我无法确定,因为您没有提及您的应用程序的详细信息。但是,我想在我们的 Rails 应用程序测试套件中添加我处理此问题的方式。

我们的应用程序的数据库配置 (database.yml) 不在源存储库中。相反,它位于运行我们的 Jenkins 实例的 VM 上的 /var/lib/configs/uniquing_database.yml 中。

我们构建过程的步骤之一是将此配置文件复制到项目工作区:

cp /var/lib/jenkins/configs/myapp_unique_database.yml config/database.yml

并且该配置考虑了 Jenkins 向环境公开的工作区和内部版本号信息,以便为该作业创建一个唯一命名的数据库,并且它是特定的执行:

test:
  adapter: postgresql
  encoding: unicode
  host: 127.0.0.1
  port: 5432
  database: myapp_test<%= ENV['JOB_NAME'].split('/').last %><%= ENV['BUILD_NUMBER'] %>

我们构建的其余部分在不知道或不关心它在不同的数据库中运行的情况下继续进行。最后,在构建结束时,我们确保删除该数据库,这样我们就不会有一堆测试数据库污染文件系统:

RAILS_ENV=test bundle exec rake db:drop

【讨论】:

【参考方案6】:

这是一个老问题,但该主题仍然具有相关性,尤其是在 Jenkins 上运行应用程序测试时。

Lockable Resources Plugin 允许您定义可供构建使用的可锁定资源。如果你的构建需要一个资源,它会获取锁。如果第二次构建需要相同的资源(然后已被锁定),它将排队等待资源空闲。

虽然文档使用计算机或打印机作为可锁定资源的示例,但上面的数据库示例也应该可以工作。

与 2012 年的答案中提到的 Locks and Latches Plugin 相反,这个包似乎目前仍在维护(目前 ~2016 年)。

【讨论】:

以上是关于如何防止某些 Jenkins 作业同时运行?的主要内容,如果未能解决你的问题,请参考以下文章

Jenkins - 在作业删除时删除已部署的工件

如何创建参数化的Jenkins作业?

Jenkins - 同时运行单个构建的实例

如何防止 Linux 符号链接中断

Jenkins - 同时运行单个构建的实例

防止共享Jenkinsfile中的默认签出