Jenkins 资源锁:获取多个节点特定资源的锁

Jenkins Resource Locks: Get lock for multiple Node specific resources

我想为某个节点创建多个资源,或者为多个节点使用可重用类型。

在本例中为 "RAM requirement",因此资源名称例如将是 1GBRAM。或者 1GBRAM_Nodexy 如果我需要在每个节点的基础上指定它。

最后我想根据作业在该节点上使用的内存峰值来限制并发作业的数量,以避免由于服务器内存不足而挂起。我可以设置可供执行程序使用的 RAM 数量。

不同的节点将有不同的 RAM 量,并且各个作业有不同的 RAM 要求。

所以我想根据其 RAM 要求配置每个作业

lock(resource: '1GBRAM_Nodexy', quantity: 8)

这可以通过管道和可锁定资源实现吗?

是否有更好的替代方法来实现此目的?理想情况下,可以在选择从站之前检查锁,然后选择最适合的节点。

阅读有关资源锁和标签的信息。我没有找到任何特定于节点的部分,也无法获取同一资源的多个项目。

lock(resource: '1GBRAM_Nodexy', quantity: 8)

我希望作业的每个 运行 在已使用的从属节点上锁定等量的 RAM。如果没有足够的 "RAM" 个单元用完,则作业不会 运行 在这样的节点上。

我认为您不能完全满足您的要求,但也许您可以接近。

首先,你想要的是使用label而不是resource。您将定义与 RAM 一样多的 1GB 表示资源(例如,GB1GB2GB3 等), 给它们所有相同的标签(例如,GB),然后使用这样的 lock 语句(例如,如果所讨论的作业需要 4GB 内存):

lock(label: 'GB', quantity: 4)

这将锁定具有此 GB 标签的资源中的 4 个,在需要时等待直到它能够这样做,然后在离开 locked 范围时释放它们。

特定于节点的锁定是比较棘手的部分。如果您对每个节点使用不同的标签(NodeA_GBNodeB_GB 等)感到满意, 将作业“固定”到特定节点,那么上面的解决方案就足够了,例如:

// Require 4GB of memory on NodeA
lock(label: 'NodeA_GB', quantity: 4) 

我不知道的方法是选择一个特定的节点因为它有可用的 RAM——即,你的“锁可以在之前检查选择从站,并选择最适合的节点”声明。但是您至少可以使用 env.NODE_NAME 检测由常规 agent 语句分配的节点,然后将其用作节点特定锁定标签的一部分:

agent any
stages {
  stage('Build') {
    steps {
      // This assumes that all possible nodes have a label like this defined with their name in it
      lock(label: "${NODE_NAME}_GB", quantity: 4) {
        // ... build steps  
      }
    }
  }
}

顺便说一句,我自己使用的是标签+数量方法,但为了实现基于 lock 的节流——限制跨多分支管道作业所有分支的并发构建总数——因为那段时间的 Throttle Concurrent Builds plugin went through a period of not being maintained and had some significant, open issues

已接受答案的补充(编辑队列已满):
至于选择特定节点 因为 它有可用的 RAM——即,您的“可以在选择从属节点之前检查锁,并选择最适合的节点”语句,org.jenkins.plugins.lockableresources.LockableResourcesManager class 可用于检查节点上的可用内存,并决定使用哪个节点,例如:

def nodeFreeGbThreshold = 2
def resourceManager = new org.jenkins.plugins.lockableresources.LockableResourcesManager()
def nodeAFreeGb = resourceManager.getFreeResourceAmount("NodeA_GB")
def nodeBFreeGb = resourceManager.getFreeResourceAmount("NodeB_GB")
def agentLabel = nodeAFreeGb < nodeFreeGbThreshold ? 'NodeA' : 'NodeB'

pipeline {
    agent { label 'agentLabel' }
    stages {
        stage('Build') {
            steps {
                // This assumes that all possible nodes have a label like this defined with their name in it
                lock(label: "${NODE_NAME}_GB", quantity: 4) {
                    // ... build steps
                }
            }
        }
    }
}

对于脚本化管道:

def nodeFreeGbThreshold = 2
def resourceManager = new org.jenkins.plugins.lockableresources.LockableResourcesManager()
def nodeAFreeGb = resourceManager.getFreeResourceAmount("NodeA_GB")
def nodeBFreeGb = resourceManager.getFreeResourceAmount("NodeB_GB")
def agentLabel = nodeAFreeGb < nodeFreeGbThreshold ? 'NodeA' : 'NodeB'

node(agentLabel) {
    // This assumes that all possible nodes have a label like this defined with their name in it
    lock(label: "${NODE_NAME}_GB", quantity: 4) {
        // ... build steps
    }
}