在所有节点上同时运行Jenkins作业

31
TLDR: 我想在Jenkins的流水线上同时在多个节点上运行作业。[例如,在基于AWS的dev,test和staging节点上构建应用程序x]
我有一组具有相同标签的节点。我希望能够在Jenkins上运行一个作业,该作业在所有具有相同标签的节点上同时执行。
我看到建议在Jenkins中使用矩阵配置选项,但我只能想到一个轴(标签组)。当我尝试运行作业时,似乎它只执行一次,而不是300次(针对该标签组中每个节点1次)。
我的其他轴应该是什么呢?或者......是否有某个插件可以做到这一点?我已经尝试过NodeLabel Parameter Plugin,并选择“在所有可用的在线节点上运行”,但似乎它不会同时运行作业。

有没有另一种方法可以添加作业节点而不必编辑resources.xml文件?我们最终将扩展到数千个节点,手动将它们添加到XML文件中有点繁琐,特别是因为节点可能会发生变化。除此之外,Rundeck看起来具备我想要的很多功能。 - user2406467
@MarkO'Connor - 我认为Rundeck可以完成我们正在做的事情 :) 我们最终将使用EC2。如果您想将您的回复添加为答案,我应该能够接受它。谢谢! - user2406467
10个回答

18

13

您需要两个插件: 参数化触发器插件 以便将其他作业作为主作业的构建步骤来触发,以及NodeLabel插件 (阅读BuildParameterFactory部分以获得所需内容的描述) 来指定标签。


13

矩阵构建将起作用;使用“从属节点”作为轴,并展开“各个节点”列表以选择所有节点。

请注意,每次添加或删除从属节点时,您需要更新选择。

为了获得更易维护的解决方案,您可以使用Job DSL插件设置种子任务,其中包含构建模板,然后循环遍历每个从属节点,并创建具有构建标签设置为从属节点名称的新任务。


1
选择单个节点将非常不方便,因为我们希望在某些时候扩展到几千个。我查看了Job DSL插件,并能够生成一个工作,但我还没有完全明白如何循环遍历每个从机。此外...似乎一旦创建作业,我仍然需要手动执行它们。 - user2406467
@^^^ 这是一个很好的 Job DSL 入门视频,应该能够让你对它有一些了解:https://www.youtube.com/watch?v=Gyccyj6lA8k - dyodji
你可以创建一个任务来触发其他任务。使用 downstream 命令。 - Captain Man

11

基于上述回答的部分内容,对2.0系列进行调整。

现在您可以在所有节点上启动所有作业。

// The script triggers PayloadJob on every node.
// It uses Node and Label Parameter plugin to pass the job name to the payload job.
// The code will require approval of several Jenkins classes in the Script Security mode
def branches = [:]
def names = nodeNames()
for (int i=0; i<names.size(); ++i) {
  def nodeName = names[i];
  // Into each branch we put the pipeline code we want to execute
  branches["node_" + nodeName] = {
    node(nodeName) {
      echo "Triggering on " + nodeName
      build job: 'PayloadJob', parameters: [
              new org.jvnet.jenkins.plugins.nodelabelparameter.NodeParameterValue
                  ("TARGET_NODE", "description", nodeName)
          ]
    }
  }
}

// Now we trigger all branches
parallel branches

// This method collects a list of Node names from the current Jenkins instance
@NonCPS
def nodeNames() {
  return jenkins.model.Jenkins.instance.nodes.collect { node -> node.name }
}

从代码中获取 https://jenkins.io/doc/pipeline/examples/#trigger-job-on-all-nodes


10

最好、最简单的方法是使用Elastic Axis插件。
1. 安装插件。
2. 创建一个多配置任务。(如果没有安装则需要安装)
3. 在任务配置中,您可以找到新添加的弹性轴(Elastic axis)。按照下面的标签添加以便在多个从节点上运行此任务。 enter image description here


1
这个不起作用。在轴上放置一个单独的标签将会在具有该标签的单个节点上构建作业。 - jwg
1
是的,它将在单个节点上构建作业。通常我们有通用标签,即多个节点使用相同的标签名称根据其用途。(我们不为所有节点使用唯一的标签名称,因为节点名称已经是唯一的并且已经发挥了这个作用)。此外,您可以在提供的文本区域中提供多个标签名称。这是我找到的唯一解决方案。如果您有更好的解决方案,请帮助我。 - Amol Manthalkar
标签的作用是能够将它们分组在一起,当进行缩放时,只需确保有一个标签,例如“script-1”,它就会添加到轴上。 - jonypony3

9

8

我在寻找一种运行docker system prune命令的方法,以在所有节点(带有标签docker)上运行该命令。最终,我使用了一个相当简单的脚本管道,据我所知,它只需要管道插件即可运行:

#!/usr/bin/env groovy

def nodes = [:]

nodesByLabel('docker').each {
  nodes[it] = { ->
    node(it) {
      stage("docker-prune@${it}") {
        sh('docker system prune -af --filter "until=1440h"')
      }
    }
  }
}

parallel nodes

注意:需要 Pipeline Utility Steps插件支持。
这个功能会查找所有标记为docker的节点,然后对它们进行迭代,并创建一个关联数组nodes,每个找到的节点都有一个步骤(准确来说,这个功能是清理所有旧的Docker内容,时间超过60天)。parallel nodes开始并行执行(同时在所有找到的节点上执行)。
希望这能帮助到某些人。

3
功能良好,但需要安装“Pipeline Utility Steps”插件才能使用nodesByLabel - jds210

7

明白了 - 不需要任何特殊的插件!

我创建了一个父任务,触发/调用另一个构建, 当我调用它时,我传递给它标签,以便让子任务在其上运行。

因此,父任务只会触发我所需的任务, 并且子任务将根据该标签中的从属数量运行多次 (在我的情况下运行4次)。

enter image description here


当所选标签的节点启动一个触发的构建过程花费太长时间时,会发生什么情况?它不会在已经运行触发构建的同一标签的另一个节点上运行吗? - ldnunes
1
@ldnunes 不,除非它在此标签上的所有节点(仅限连接的从节点)上运行,否则构建不会完成。 - Shahar Hamuzim Rajuan
7
这需要“参数化触发器+节点标签参数插件”,对于那些在Jenkins中找不到这些参数的人(比如我)。 - medwards

1

启用此项目是参数化的,添加一个类型为标签的参数,输入标签的任意名称并选择默认值,例如涵盖多个节点的标签或这些标签的合取(&&)。启用在匹配标签的所有节点上运行,保持无论结果如何都运行,将节点资格保持为所有节点

enter image description here


1
如果不是因为它显示“(pending—没有带有标签‘dev03&&Windows-7-x64’的节点)”,这个方法本来会起作用的。 - Vikramaditya Gaonkar
2
我在我的Jenkins参数选项中没有看到任何“类型为Label的参数”。@eel - Akhil

0
解决方案:您可以在多个Jenkins节点上简洁地并行构建相同的构建。
这对于在不同环境中构建相同的项目非常有用(例如:在测试、开发和预发布环境中构建节点应用程序)。 示例:
pipeline {
agent { docker {  image 'node:14-alpine' } }
stages {
    stage('build') {
        steps {
            parallelTasks
        }
      }
   }
}


def parallelTasks() {
  def labels = ['test', 'dev', 'staging'] // labels for Jenkins node types we will build on
  def builders = [:]
  for (x in labels) {
      def label = x
      
      builders[label] = {
          node(label) {
              sh """#!/bin/bash -le
                    echo "build app on ${label} node"
                    cd /home/app
                    npm run build
              """
          }
      }
  }
  parallel builders


}

这个任务在所有节点上运行的位置在哪里? - Clintm

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接