Jenkins 按标签锁定
Jenkins lock by label
我想要达到的目标
- 我有
jobA
需要一台机器上的 1 个执行程序。
- 我有
jobB
需要同一台机器上的 2 个执行程序和 X 机器上的 1 个执行程序。
- 我希望他们能够使用相同的机器(虽然不是同时)-> 他们目前使用不同的机器。
- 他们所有的任务都使用 100% CPU。因此,同一台机器上不能同时存在两个构建。
我是如何解决这个问题的
- 因为
jobB
需要在单个节点上至少有 2 个执行程序,而 jobA
需要 1 个,我需要将执行程序的数量更改为每个节点有 2 个。
- 应该有一个锁定机制,这样如果
jobA
或 jobB
构建在节点上运行,则 jobA
或 jobB
构建都不能在其上启动。
我做了什么
我将机器上的执行程序数量从 1 更改为 2。
解决方案 1:锁定资源
在jobA
的管道中,我有:
node('windows-agent-label') {
lock("${env.NODE_NAME}-exclusive") {
//...
}
}
运行 工作(第一次)给我:
[Pipeline] Start of Pipeline
[Pipeline] node
Running on build1 in J:\jenkins\workspace\jobA
[Pipeline] {
[Pipeline] lock
Trying to acquire lock on [build1-exclusive]
Resource [build1-exclusive] did not exist. Created.
Lock acquired on [build1-exclusive]
第二次(第一次还在建设中):
[Pipeline] Start of Pipeline
[Pipeline] node
Running on build1 in J:\jenkins\workspace\jobA@2
[Pipeline] {
[Pipeline] lock
Trying to acquire lock on [build1-exclusive]
Found 0 available resource(s). Waiting for correct amount: 1.
[build1-exclusive] is locked, waiting...
有效!第二个构建被阻止,直到第一个构建释放锁。然而,第二个已经被分派到节点并使用了一个执行器插槽。真的不好看!如果我将 lock()
指令移到 node()
指令之外,我还没有 env.NODE_NAME
,所以锁无法工作。
显然,还有另一种方法...
解决方案 2:通过请求标签进行锁定
我有一个名为 windows-agent-label
的标签,其中包含 2 个节点:build1
和 build2
。
在jobA
的管道中,我有:
lock(label: 'windows-agent-label', quantity: 1) {
node('windows-agent-label') {
//...
}
}
运行这份工作给我:
[Pipeline] Start of Pipeline
[Pipeline] lock
Trying to acquire lock on [Label: windows-agent-label, Quantity: 1]
Found 0 available resource(s). Waiting for correct amount: 1.
[Label: windows-agent-label, Quantity: 1] is locked, waiting...
build1
运行绝对没有。
我所有的/lockable-resources/
都是FREE
。
问题
- 为什么找不到可用的资源?我在滥用它吗?
- 我的方向对吗?
解决方案
在 lock
文档中,缺少一个(未记录的)参数:variable
。当与 label
一起使用时,它将获取的锁的名称存储到 env
变量中。
此处遗漏:https://plugins.jenkins.io/lockable-resources
在那里可见:https://issues.jenkins-ci.org/browse/JENKINS-40997
lock(label: 'windows-agent-label', quantity: 1, variable: 'LOCK_NAME') {
node(env.LOCK_NAME - '-exclusive') {
//...
}
}
因此,这会向所有处于特定标签下的对象请求锁定。它们总是(通过选择)形成为 ${NODE_NAME}-exclusive
。如果我不能锁定资源,那就意味着它们都用完了。如果我得到一个,那就意味着 NODE_NAME
(可能是 build1
、build2
、...)可用。所以,我转到给定的节点。
我想要达到的目标
- 我有
jobA
需要一台机器上的 1 个执行程序。 - 我有
jobB
需要同一台机器上的 2 个执行程序和 X 机器上的 1 个执行程序。 - 我希望他们能够使用相同的机器(虽然不是同时)-> 他们目前使用不同的机器。
- 他们所有的任务都使用 100% CPU。因此,同一台机器上不能同时存在两个构建。
我是如何解决这个问题的
- 因为
jobB
需要在单个节点上至少有 2 个执行程序,而jobA
需要 1 个,我需要将执行程序的数量更改为每个节点有 2 个。 - 应该有一个锁定机制,这样如果
jobA
或jobB
构建在节点上运行,则jobA
或jobB
构建都不能在其上启动。
我做了什么
我将机器上的执行程序数量从 1 更改为 2。
解决方案 1:锁定资源
在jobA
的管道中,我有:
node('windows-agent-label') {
lock("${env.NODE_NAME}-exclusive") {
//...
}
}
运行 工作(第一次)给我:
[Pipeline] Start of Pipeline
[Pipeline] node
Running on build1 in J:\jenkins\workspace\jobA
[Pipeline] {
[Pipeline] lock
Trying to acquire lock on [build1-exclusive]
Resource [build1-exclusive] did not exist. Created.
Lock acquired on [build1-exclusive]
第二次(第一次还在建设中):
[Pipeline] Start of Pipeline
[Pipeline] node
Running on build1 in J:\jenkins\workspace\jobA@2
[Pipeline] {
[Pipeline] lock
Trying to acquire lock on [build1-exclusive]
Found 0 available resource(s). Waiting for correct amount: 1.
[build1-exclusive] is locked, waiting...
有效!第二个构建被阻止,直到第一个构建释放锁。然而,第二个已经被分派到节点并使用了一个执行器插槽。真的不好看!如果我将 lock()
指令移到 node()
指令之外,我还没有 env.NODE_NAME
,所以锁无法工作。
显然,还有另一种方法...
解决方案 2:通过请求标签进行锁定
我有一个名为 windows-agent-label
的标签,其中包含 2 个节点:build1
和 build2
。
在jobA
的管道中,我有:
lock(label: 'windows-agent-label', quantity: 1) {
node('windows-agent-label') {
//...
}
}
运行这份工作给我:
[Pipeline] Start of Pipeline
[Pipeline] lock
Trying to acquire lock on [Label: windows-agent-label, Quantity: 1]
Found 0 available resource(s). Waiting for correct amount: 1.
[Label: windows-agent-label, Quantity: 1] is locked, waiting...
build1
运行绝对没有。
我所有的/lockable-resources/
都是FREE
。
问题
- 为什么找不到可用的资源?我在滥用它吗?
- 我的方向对吗?
解决方案
在 lock
文档中,缺少一个(未记录的)参数:variable
。当与 label
一起使用时,它将获取的锁的名称存储到 env
变量中。
此处遗漏:https://plugins.jenkins.io/lockable-resources
在那里可见:https://issues.jenkins-ci.org/browse/JENKINS-40997
lock(label: 'windows-agent-label', quantity: 1, variable: 'LOCK_NAME') {
node(env.LOCK_NAME - '-exclusive') {
//...
}
}
因此,这会向所有处于特定标签下的对象请求锁定。它们总是(通过选择)形成为 ${NODE_NAME}-exclusive
。如果我不能锁定资源,那就意味着它们都用完了。如果我得到一个,那就意味着 NODE_NAME
(可能是 build1
、build2
、...)可用。所以,我转到给定的节点。