Jenkins如何实现单阶段调用2个及以上代理节点执行任务
Jenkins单阶段调用多代理节点实现方案
原生Jenkins声明式流水线的stage默认只能绑定单个agent节点,但不需要从零自研插件,通过成熟的现有生态组件就能实现「同一测试阶段同时占用TD、SUT两类节点,Jenkins统一管控锁与资源竞争」的需求,完全不用手动实现SUT资源锁逻辑。
前置配置
- 节点标签划分:给所有TD测试驱动节点统一打上
td-node标签;给SUT集群节点按操作系统类型打对应标签(比如sut-centos7、sut-ubuntu2204),同时给所有SUT节点打上公共标签sut-node,方便按测试需求筛选匹配资源。提前在每个SUT节点的节点配置中添加自定义环境变量SUT_IP,值为对应节点的业务IP,供测试脚本调用。 - 插件安装:仅需安装2款长期维护的插件即可:
- Lockable Resources:提供统一的资源锁、资源池管理能力,自动处理资源排队、抢占、死锁规避问题
- Pipeline:支持流水线编排能力
流水线实现
不要直接给stage绑定固定agent,而是在stage内部通过锁机制同时申请两类节点资源,再分别在对应节点上下文执行操作,整个流程在Jenkins UI上会呈现为单个阶段。参考写法如下:
pipeline { agent none // 顶层不绑定全局agent,避免资源浪费 stages { stage('跨节点执行TFS测试') { steps { // 一次性申请1台空闲TD、1台匹配OS要求的空闲SUT,资源不足时自动排队 lock(label: 'td-node', quantity: 1, variable: 'LOCKED_TD') { lock(label: 'sut-centos7', quantity: 1, variable: 'LOCKED_SUT') { script { def targetSutIp = "" // 切到锁定的SUT节点,获取节点IP,也可在此处执行SUT侧的环境清理、版本部署等前置操作 node(env.LOCKED_SUT) { targetSutIp = env.SUT_IP // 例:执行SUT侧前置清理 sh "cleanup_test_env.sh" } // 切到锁定的TD节点,运行测试脚本,传入SUT IP参数 node(env.LOCKED_TD) { checkout scm sh "chmod +x tfs.sh && ./tfs.sh --sut=${targetSutIp}" } } } } } post { // 可在此处统一处理测试报告收集、日志归档操作,同样可以跨节点拉取对应文件 always { node(env.LOCKED_TD) { archiveArtifacts artifacts: 'test-results/**', allowEmptyArchive: true } } } } } }
实现说明
- 锁的生命周期完全和lock代码块绑定:只要代码运行在lock块范围内,对应的TD、SUT节点就不会被其他测试任务抢占;无论测试执行成功、失败还是异常中断,Jenkins都会在块执行结束后自动释放两类节点资源,不会出现资源死锁、残留占用的问题。
- 如果要优化资源申请效率、避免循环等待导致的死锁,可以在Lockable Resources配置页将TD、SUT节点统一划入同一个资源组,配置为「同时申请组内多资源」,申请时会一次性拿到两类空闲资源才会继续执行,不会出现占住TD等SUT、占住SUT等TD的资源浪费情况。
- 如果需要在同一个阶段调用2个以上节点,只需要对应增加lock申请的资源数量、增加对应node块的执行逻辑即可,没有数量限制。
- 不建议从零自研插件实现该能力:Lockable Resources插件已经过多年生产环境验证,资源排队、优先级调度、锁超时、死锁规避等边缘场景逻辑都已覆盖,自研重复实现这类逻辑的成本和稳定性风险都很高。
内容的提问来源于stack exchange,提问作者Ari Sweedler
相关产品推荐
相关产品推荐

