1. 引言

在 Jenkins 中,我们需要合理控制流水线任务的执行方式,以确保资源被正确使用,并避免任务之间的冲突。

一个常见的需求是:防止相同类型的两个流水线任务在同一个节点上同时运行。当多个任务并发运行在同一个节点上时,可能会导致 CPU、内存或磁盘 I/O 资源竞争,也可能因为共享工作区而造成文件冲突甚至执行结果不一致。

本文将介绍几种在 Jenkins 中控制任务并发执行的方法,帮助你构建更稳定、高效的持续集成流水线。


2. 为什么需要限制并行执行

在同一个节点上运行多个相同类型的任务,可能会带来以下几个问题:

资源竞争:两个任务同时占用大量 CPU 或内存时,可能会互相拖慢甚至失败。例如,一个任务执行编译,另一个任务执行测试,它们同时运行可能导致资源耗尽。

工作区冲突:Jenkins 默认使用同一个工作目录。如果多个任务并发执行,文件可能被覆盖或损坏,导致构建过程不稳定,难以排查错误。

共享资源污染:如果任务修改了共享资源(如配置文件或数据库),一个任务可能会干扰另一个任务,造成数据错误或测试失败。

因此,我们的目标是:保证同一节点上,同一类型任务只能有一个实例在运行,同时允许不同节点上并发执行,以提升整体效率。


3. 使用 disableConcurrentBuilds 方法

Jenkins 提供了一个内置选项:disableConcurrentBuilds,用于禁止同一个任务的并发执行。它保证当前任务执行完成前,不会启动新的实例。

这个方法适用于全局限制,无论任务运行在哪个节点上,都只能串行执行。

示例代码:

pipeline {
    agent any
    options {
        disableConcurrentBuilds()
    }
    stages {
        stage('Build') {
            steps {
                // 编译步骤
            }
        }
        stage('Test') {
            steps {
                // 测试步骤
            }
        }
    }
}

⚠️ 注意:该方法限制的是整个任务级别的并发,不是按节点划分的。如果你有多个节点,也只能同时运行一个任务实例,这在某些场景下可能过于严格。


4. 使用 Throttle Concurrent Builds 插件进行精细化控制

如果你希望允许不同节点上的并发执行,但禁止同一节点上的并行任务,推荐使用 Throttle Concurrent Builds Plugin

4.1 安装插件

安装步骤如下:

  1. 进入 Jenkins 管理界面(Manage Jenkins)
  2. 打开插件管理(Manage Plugins)
  3. 在“可用”标签页中搜索 Throttle Concurrent Builds
  4. 勾选后安装,无需重启

4.2 配置限制类别(Category)

  1. 进入 Manage Jenkins > Configure System
  2. 找到 Throttle Concurrent Builds 配置区域
  3. 添加一个新的类别(Category),例如命名为 myThrottleCategory
  4. 设置 Maximum Concurrent Builds Per Node 为 1
  5. 可选设置 Maximum Total Concurrent Builds 控制全局并发数

配置完成后,界面如下图所示:

global_categoryConfig

4.3 在 Jenkinsfile 中使用

pipeline {
    agent any
    options {
        throttleJobProperty(
            categories: ['myThrottleCategory'],
            throttleEnabled: true,
            throttleOption: 'category'
        )
    }
    stages {
        stage('Build') {
            steps {
                // 编译步骤
            }
        }
        stage('Test') {
            steps {
                // 测试步骤
            }
        }
    }
}

通过这种方式,你可以实现:同一节点上只允许一个属于该类别的任务运行,但不同节点可以并发执行


5. 使用 Lockable Resources 插件进行节点级资源锁定

另一种方法是使用 Lockable Resources Plugin,它允许你对特定资源(如节点)进行锁定,从而控制任务的并发执行。

5.1 安装插件

安装步骤与上述插件类似:

  1. 进入 Manage Jenkins > Manage Plugins
  2. 搜索 Lockable Resources Plugin 并安装

5.2 配置可锁定资源

  1. 进入 Manage Jenkins > Configure System
  2. 找到 Lockable Resources 配置区域
  3. 添加一个可锁定资源,例如命名为 MyJobResource
  4. 可选设置标签或描述,便于识别

5.3 在 Jenkinsfile 中使用锁

pipeline {
    agent any
    stages {
        stage('Preparation') {
            steps {
                lock(resource: 'MyJobResource') {
                    echo '锁已获取,执行关键步骤'
                    // 放置需要互斥执行的步骤
                }
            }
        }
        stage('Other Steps') {
            steps {
                echo '执行非关键步骤'
                // 这些步骤可以并发执行
            }
        }
    }
}

优势:这种方式只对关键步骤加锁,不影响其他部分的并发执行。

⚠️ 缺点:需要手动管理资源定义,适合对并发控制有更高灵活性需求的场景。


6. 最佳实践建议

选择并发控制方法时,建议根据你的 Jenkins 环境和任务特性来决定:

方法 适用场景 优点 缺点
disableConcurrentBuilds 简单任务、小规模环境 简洁易用 控制粒度粗,影响整体并发
Throttle Concurrent Builds 多节点部署、需节点级并发控制 支持按节点并发 需要配置插件和类别
Lockable Resources 仅关键步骤需互斥 控制粒度细 需手动定义资源

📌 建议

  • 如果你的节点资源充足,但担心同一节点任务冲突,优先使用 Throttle 插件。
  • 如果任务中只有部分逻辑需要互斥,使用 Lockable Resources 插件更合适。
  • 如果你希望快速实现串行执行,disableConcurrentBuilds 是最直接的选择。

7. 小结

本文介绍了三种防止相同类型 Jenkins 流水线任务在同一个节点上并行运行的方法:

  1. ✅ 使用 disableConcurrentBuilds:适用于全局限制,简单有效
  2. ✅ 使用 Throttle Concurrent Builds 插件:支持按节点限制,适合多节点环境
  3. ✅ 使用 Lockable Resources 插件:实现关键步骤锁定,控制粒度更细

合理使用这些方法,可以有效避免资源竞争、工作区冲突等问题,提升 Jenkins 流水线的稳定性与执行效率。


原始标题:How to Prevent Two Pipeline Jenkins Jobs of the Same Type to Run in Parallel on the Same Node?