当前位置: 首页 > 知识库问答 >
问题:

我可以在 Jenkins 中的迭代循环中动态分配节点吗?

楚硕
2023-03-14

我正在构建一个 Jenkins 管道,用于在远程数据中心内使用特定的 Jenkins 代理将我的代码部署到这些数据中心的场景。这是由于一些端口的防火墙限制,特别是WinRM在我们的一些全球数据中心之间被阻止。

我们的部署是这样编写的,即单个deploy阶段可以部署到用户传入参数指定的任意数量的环境中。阶段在环境中循环,并为每个环境调用通用部署脚本。

我知道如何在阶段定义中通过其标签或其他闭包来指定代理:

stage ('a stage') {
  agent { label 'some agent label' }
  steps { ...

但在这种情况下,我正在解决在一个部署阶段部署到多个环境的问题,每个环境都需要自己的代理。

当然,我可以为每个env指定一个唯一的stage,并在适当的时候使用< code>when子句来运行它,但是这很麻烦。

我想做的是告诉管道在部署阶段内部的部署阶段使用什么代理,并能够在该单个阶段中使用多个代理,根据运行的参数动态确定。

共有2个答案

吴高洁
2023-03-14

答案可能不适合您的所有需求,但动态生成阶段,在此基础上,您可以通过以下方式分配/执行生成阶段。

def agents  = ['master', 'agent1', 'agent2']
 
 
def generateStage(nodeLabel) {
    return {
        stage("Runs on ${nodeLabel}") {
            node(nodeLabel) {
                echo "Running on ${nodeLabel}"
            }
        }
    }
}
def parallelStagesMap = agents.collectEntries {
    ["${it}" : generateStage(it)]
}
pipeline {
    agent none
    stages {
        stage('non-parallel stage') {
            steps {
                echo 'This stage will be executed first.'
            }
        }
 
        stage('parallel stage') {
            steps {
                script {
                    parallel parallelStagesMap
                }
            }
        }       
    }
}

此外,您可以使用<code>collectEntries</code>,在功能框<code>parallelStagesMap</code〕之外,这样,您可以为不同的阶段使用每个collect条目,并可以动态分配阶段中的节点,在函数<code>generateStage</code>中,您需要根据需要进行修改。

如果要按顺序执行这些阶段,请从脚本中删除并行生成阶段包含返回,如果没有它,管道将无法按预期工作。

宗安翔
2023-03-14

我最初在SO上找到了这个答案,这给了我在舞台内获取节点的想法,而不是使用agent声明。它没有显示在script块中的获取,但我最初是这样读的,这给了我尝试在script中获取节点的想法。一旦你到了那里,尝试在循环中完成它是一个小小的飞跃。

为了证明这一点,我从代理打印了一些局部环境变量来证明我们正在交换代理,在舞台内部,在循环内部。我还向每个代理传递一个文件,以证明我可以通过防火墙传递文件

请注意,为了连接到防火墙后面的代理,我们必须打开 Jenkins 全局安全配置中定义的端口,从控制器(也称为主节点)入站到代理,以及 https (443) 出站到控制器。入站端口配置为静态端口。

pipeline {
    agent none
    stages {
        stage ('init') {
            agent any
            steps {
                writeFile file: 'tester', text: 'i am a test file'
                stash includes: 'tester', name: 'tester'
            }
        }
        
        stage ('get agents') {
            steps {
                script {
                    ['Agent1', 'Agent2'].each { agent ->
                        node (agent) {
                            echo "I am agent `${NODE_NAME}`\nMy labels are `${NODE_LABELS}`"
                            unstash 'tester'
                            echo "the content of the file is `${readFile 'tester'}`"
                        }
                    }
                }
            }
        }
    }
}

哪些输出:

Started by user Maximilian Cascone Admin
 Running in Durability level: MAX_SURVIVABILITY
 [Pipeline] Start of Pipeline
 [Pipeline] stage
 [Pipeline] { (init)
 [Pipeline] node
 Running on Agent1 in /mnt/data/jenkins/workspace/Sandbox/mcascone/dynamic-agents
 [Pipeline] {
 [Pipeline] writeFile
 [Pipeline] stash
 Stashed 1 file(s)
 [Pipeline] }
 [Pipeline] // node
 [Pipeline] }
 [Pipeline] // stage
 [Pipeline] stage
 [Pipeline] { (get agents)
 [Pipeline] script
 [Pipeline] {
 [Pipeline] node
 Running on Agent2 in D:\workspace\Sandbox\mcascone\dynamic-agents
 [Pipeline] {
 [Pipeline] echo
 I am agent `Agent2`
 My labels are `Cider Redgate Windows Worker02 ant chef npm relativity wix`
 [Pipeline] unstash
 [Pipeline] readFile
 [Pipeline] echo
 the content of the file is `i am a test file`
 [Pipeline] }
 [Pipeline] // node
 [Pipeline] node
 Running on Agent1 in C:\jenkins\workspace\Sandbox\mcascone\dynamic-agents
 [Pipeline] {
 [Pipeline] echo
 I am agent `Agent1`
 My labels are `Itar Agent1`
 [Pipeline] unstash
 [Pipeline] readFile
 [Pipeline] echo
 the content of the file is `i am a test file`
 [Pipeline] }
 [Pipeline] // node
 [Pipeline] }
 [Pipeline] // script
 [Pipeline] }
 [Pipeline] // stage
 [Pipeline] End of Pipeline
 Finished: SUCCESS

所以我已经证明了我可以在一个阶段内动态地获得多个代理。下一步将把它提升到一个共享步骤,这样它就可以在没有script块的情况下被调用,并使管道变得漂亮整洁。但是作为一个POC,这是一个伟大的成就。我不相信我在其他地方见过这个。

 类似资料:
  • 我在看威廉姆·菲斯特的关于贝尔曼·福特算法的视频。 他提到有一种方法可以区分负循环中涉及的节点和10:20时从负循环中可到达的节点。在单源最短路径算法中,这两类节点会导致负inf距离。 我想知道如何做到这一点,但我想不通。我谷歌了一下,但谷歌总是让我了解贝尔曼-福特算法的介绍。 简言之,是否有一种方法来区分负循环中的节点和从负循环中可到达的节点?那么,仅仅通过修改贝尔曼-福特算法就可以得到什么呢?

  • 问题内容: 我有下面的代码: 有谁对我如何延迟循环中的每个循环的建议?假设代码在每次迭代完成后等待10秒。我试过了,但没有设法解决。 问题答案: 您可以设置超时时间,以增加代码间隔,如下所示: 因此,第一个立即运行(间隔* 0为0),第二个在十秒钟后运行,依此类推。 您需要在中作为最终参数发送,以便将其值绑定到function参数。否则,尝试访问数组值将超出范围,您将获得。

  • 问题内容: 我需要在声明式管道中启动一组动态测试。为了更好的可视化目的,我想为每个测试创建一个阶段。有办法吗? 创建一个我知道的阶段的唯一方法是: 我已经看到了这个示例,但是我没有使用声明性语法。 问题答案: 使用声明性语法比声明性语法更具灵活性的脚本化语法,即使声明性文档和建议性更多。 例如,可以循环创建阶段:

  • 我正在尝试使用For循环将一个随机整数(0-2)添加到一个变量中指定的次数。我遇到的问题是,循环不是每次循环时都使用一个新的随机数,所以,如果我输入9,我只能得到0、9,或者18。 我希望一个对象返回的键“a”和“b”具有不同的数值。

  • 我有包含在DataFrame中的链接行。 我的逻辑如下

  • 问题内容: 我有想要应用于多个表的代码,而不是简单地复制和替换表名,而是想使用某种循环或游标来简化代码。 我设想设置一个表名数组,并使用索引遍历该列表,检索每个表名,并在适用于我的代码的情况下使用动态SQL散布表名。 据我所知,由于在SQL中没有“数组”构造,因此我不确定这将如何工作。 关于如何解决这个问题的任何想法? 问题答案: 这是一种实现方法:

  • 本节我们探索的主题是迭代与循环。循环通常在计算机编程用用于自动执行重复性任务。 在Python中最常用的迭代形式就是for循环了。for循环允许你迭代出列表中所有的项,迭代出来后你可以做任何你想做的事情。 比如,我们创建了一个列表,并打印出其中所有元素的平方。 >>> for value in [0, 1, 2, 3, 4, 5]: ... print(value * value) ... 0 1

  • 为了便于示例,让我们定义一个玩具自动机类型: 这种结构被设计成通过循环,我们可以将每个想象成一个具有成功和失败转换到其他状态的状态。因此有限自动机必须递归定义。例如,这里是最简单的自动机: 它由1个总是过渡到自身的状态组成。如果我们愿意,我们可以制造更复杂的自动机: 这些不错。但是接受用户输入并构建一个自动机可能会很好。例如,也许可以从过渡矩阵中构建一个。这里有一个天真的实现: 然而,当我们尝试这