如何防止同一类型的两个管道jenkins作业在同一节点上并行运行?

sor*_*rin 57 jenkins-pipeline

我不希望允许两个相同类型的作业(相同的存储库)不在同一节点上并行运行.

如何在Jenkinsfile中使用groovy来做到这一点?

小智 42

/sf/answers/3077432081/中提供的答案已弃用.

禁用并发构建的当前方法是设置选项:

options { disableConcurrentBuilds() }
Run Code Online (Sandbox Code Playgroud)

详细说明如下:https: //jenkins.io/doc/book/pipeline/syntax/#options

  • 我正在尝试这个并且它全局禁用并发构建,OP想要禁用每个节点的并发构建,但仍然允许同时发生多个构建,每个可用节点只有一个. (5认同)

hyp*_*y2k 39

你得到了disableConcurrentBuilds属性:

properties properties: [
  ...
  disableConcurrentBuilds(),
  ...
]
Run Code Online (Sandbox Code Playgroud)

然后工作将等待较旧的工作先完成

  • 我认为这是最明智的回应 (3认同)
  • 这到底是什么意思?代码段生成器仍会为脚本化管道显示此选项。您是否有提到的弃用链接? (3认同)

Mat*_*ton 29

另一种方法是使用Lockable Resources插件:https://wiki.jenkins-ci.org/display/JENKINS/Lockable+Resources+Plugin

您可以根据需要定义锁(互斥锁),并可以将变量放在名称中.例如,防止多个作业在构建节点上同时使用编译器:

stage('Build') {
    lock(resource: "compiler_${env.NODE_NAME}", inversePrecedence: true) {
      milestone 1
      sh "fastlane build_release"
    }
}
Run Code Online (Sandbox Code Playgroud)

因此,如果您想要防止每个节点同时运行同一分支的多个作业,您可以执行类似的操作

stage('Build') {
    lock(resource: "lock_${env.NODE_NAME}_${env.BRANCH_NAME}", inversePrecedence: true) {
      milestone 1
      sh "fastlane build_release"
    }
}
Run Code Online (Sandbox Code Playgroud)

来自:https://www.quernus.co.uk/2016/10/19/lockable-resources-jenkins-pipeline-builds/


luk*_*a5z 14

我认为解决这个问题不仅仅是一种方法.

管道

  • 使用最新版本的Lockable Resources Plugin及其lock步骤,如其他答案所示.
  • 如果构建相同的项目:
    • 取消选中Execute concurrent builds if necessary.
  • 如果建立不同的项目:
    • 为每个项目设置不同nodelabel.

詹金斯

  • 限制节点执行者的数量1

插件

  • 限制节点执行器的数量是不可能的,因为其他作业需要它们。我只是想防止并行构建相同的存储库。 (2认同)
  • "Throttle Concurrent Builds Plugin"现在确实有Pipeline支持.请参阅下面的答案. (2认同)

Bry*_*yji 12

在声明性管道语法中使用options块的示例:

pipeline {

  options { 
    disableConcurrentBuilds() 
  }

...
}
Run Code Online (Sandbox Code Playgroud)


Mig*_*g82 10

" Throttle Concurrent Builds Plugin "现在支持管道throttle-concurrents-2.0.所以现在你可以这样做:

// Fire me twice, one immediately after the other
// by double-clicking 'Build Now' or from a parallel step in another job.
stage('pre'){
    echo "I can run in parallel"
    sleep(time: 10, unit:'SECONDS')
}
throttle(['my-throttle-category']) {

    // Because only the node block is really throttled.
    echo "I can also run in parallel" 

    node('some-node-label') {

        echo "I can only run alone"

        stage('work') {

            echo "I also can only run alone"
            sleep(time: 10, unit:'SECONDS')

        }
    }
}
stage('post') {
    echo "I can run in parallel again"
    // Let's wait enough for the next execution to catch
    // up, just to illustrate.
    sleep(time: 20, unit:'SECONDS')
}
Run Code Online (Sandbox Code Playgroud)

从管道阶段视图,您将能够理解这一点:

在此输入图像描述

但是,请注意,这仅适用于node区块内的throttle区块.我确实有其他管道,我首先分配一个节点,然后做一些不需要限制的工作,然后做一些.

node('some-node-label') {

    //do some concurrent work

    //This WILL NOT work.
    throttle(['my-throttle-category']) {
        //do some non-concurrent work
    }
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,该throttle步骤不能解决问题,因为throttle步骤是node步骤内的步骤而不是相反.在这种情况下,锁定步骤更适合于任务


rai*_*isd 6

安装Jenkins Lockable Resources插件.

在您的管道脚本中,将该部分包装在锁定块中,并为此可锁定资源指定名称.

lock("test-server"){
    // your steps here
}
Run Code Online (Sandbox Code Playgroud)

使用您锁定的任何资源的名称.根据我的经验,它通常是测试服务器或测试数据库.

  • 补充一下 - 我找到了锁定功能,但认为它没有解决我的问题。但是,您可以使用变量名称来定义锁定资源 - 使用 env.NODE_NAME 解决了我需要锁定阶段以不在同一节点上同时运行的问题(它可以在不同节点上同时运行) (2认同)

Joh*_*Sig 5

如果你和我的团队一样,那么你喜欢用户友好的参数化 Jenkins 工作,这些工作是管道脚本分阶段触发的,而不是维护所有的声明性/常规汤。不幸的是,这意味着每个管道构建占用 2 个以上的执行器插槽(一个用于管道脚本,另一个用于触发作业),因此死锁的危险变得非常真实。

我到处寻找解决这个困境的方法,但disableConcurrentBuilds()只能防止同一个作业(分支)运行两次。它不会让不同分支的管道构建排队等待,而不是占用宝贵的执行器插槽。

对我们来说,一个 hacky(但非常优雅)的解决方案是将主节点的执行器限制为 1,并使管道脚本坚持使用它(并且只使用它),然后将本地从代理连接到 Jenkins 以处理所有其他工作。