简体   繁体   中英

Jenkins lock by label

What I'm trying to achieve

  • I have jobA that needs 1 executor on one machine.
  • I have jobB that needs 2 executors on the same machine and 1 executor on X machines.
  • I want them to be able to use the same machines (not at the same time though) -> They currently use different machines.
  • All of their tasks use 100% CPU. So, no two builds can concurrently exist on the same machine.

How I'm tackling the problem

  • Because jobB requires at least 2 executors on a single node and jobA requires 1, I need to change the numbers of executors to have 2 per node.
  • There should be a lock mechanism so that if jobA or jobB build runs on a node, no jobA nor jobB build can start on it.

What I've done

I changed the number of executors on my machines from 1 to 2.

Solution 1: Locking the resource

In jobA 's pipeline, I have:

node('windows-agent-label') {
    lock("${env.NODE_NAME}-exclusive") {
        //...
    }
}

Running the job (1st time) gives me:

[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]

And the 2nd time (while the first one is still building):

[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...

It works! The second build is blocked until the first one releases the lock. However, the second one is already dispatched to the node and uses an executor slot . Really not nice! If I move the lock() directive outside of the node() one, I don't have the env.NODE_NAME yet, so the lock cannot work.

Apparently, there's another way...

Solution 2: Locking by requesting a label

I have a label named windows-agent-label which contains 2 nodes: build1 and build2 .

In jobA 's pipeline, I have:

lock(label: 'windows-agent-label', quantity: 1) {
    node('windows-agent-label') {
        //...
    }
}

Running the job gives me:

[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...

Absolutely nothing is running on build1 .

All of my /lockable-resources/ are FREE .

Questions

  • Why cannot it find an available resource? Am I misusing it?
  • I am in the right direction?

The solution

In the lock documentation, there's a missing (undocumented) parameter: variable . When used with label , it stores into an env variable the name of the acquired lock.

Missing here: https://plugins.jenkins.io/lockable-resources

Visible there: https://issues.jenkins-ci.org/browse/JENKINS-40997

lock(label: 'windows-agent-label', quantity: 1, variable: 'LOCK_NAME') {
    node(env.LOCK_NAME - '-exclusive') {
        //...
    }
}

So, this requests a lock from all the ones that are under a certain label. They are always formed (by choice) as ${NODE_NAME}-exclusive . If I can't get a lock on resource, that means they're all used up. If I get one, that means NODE_NAME (could be build1 , build2 , ...) is available. So, I go to the given node.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM