【问题标题】:Can I assign a node dynamically within an iterative loop in Jenkins?我可以在 Jenkins 的迭代循环中动态分配节点吗?
【发布时间】:2021-06-02 01:38:38
【问题描述】:

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

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

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

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

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

当然,我可以为每个环境指定一个唯一的阶段,并在适当的时候使用when 子句来运行它,但这很麻烦。

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

【问题讨论】:

    标签: jenkins jenkins-pipeline


    【解决方案1】:

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

    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
                    }
                }
            }       
        }
    }
    

    此外,您可以使用collectEntries,在功能框parallelStagesMap之外,这样您可以将每个收集条目用于不同的阶段,并且可以动态分配阶段中的节点,并且在功能generateStage中您需要根据您的要求进行修改。

    如果您想按顺序执行这些阶段,请从脚本中删除 parallelgenerateStage 包含 return,否则很重要,管道将无法按预期工作。

    【讨论】:

    • 伟大的补充!谢谢!
    【解决方案2】:

    我最初在 SO 上找到了this answer,这让我想到了在舞台内获取一个节点,而不是使用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,这是一项了不起的成就。我不相信我在其他地方见过这种情况。

    【讨论】:

      猜你喜欢
      • 2021-03-28
      • 1970-01-01
      • 2019-08-14
      • 1970-01-01
      • 2020-12-03
      • 2014-01-03
      • 1970-01-01
      • 1970-01-01
      • 2013-02-24
      相关资源
      最近更新 更多