Jenkins声明式流水线中的阶段并行处理

58次阅读
没有评论

问题描述

在使用Jenkins(版本2.204.2)的声明式流水线时,用户想要在不同的机器上并行运行以映射方式生成的阶段。虽然过去可以通过在script块中混合使用来实现,但从文档和其他StackOverflow问题中,用户无法弄清楚为什么这种格式不起作用。用户已经尽可能地简化了问题,尝试在流水线之外静态创建映射,以弄清楚所需的语法。

问题代码示例:

#!/usr/bin/env groovy
def map = [:]
map['Passed Stage'] = {
    stage("Passed Map Inner Stage"){
        agent{ label "nodeLabel" }
        steps{
            echo "PASSED MAP STEP"
        }
    }
}

pipeline {
    agent { label "nodeLabel" }
    stages {
        stage("Non map stage"){
            agent{ label "nodeLabel" }
            steps{
                echo "NON MAP STEP"
            }
        }
        stage("Direct Map Outer Parallel Stage"){
            parallel{
                direct:
                    stage("Direct Map Inner Stage"){
                        agent{ label "nodeLabel" }
                        steps{
                            echo "DIRECT MAP STEP"
                        }
                    }
            }
        }
        stage("Passed Map Outer Parallel Stage"){
            parallel{ map }
        }
    }
}

前两个阶段方法可以工作,但如果注释掉映射的那一部分,”Passed Map Outer Parallel Stage” 阶段总是失败,报错如下:

Running in Durability level: MAX_SURVIVABILITY
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
WorkflowScript: 33: Expected a stage @ line 33, column 23.
               parallel{ map }
                         ^
WorkflowScript: 33: No stages specified @ line 33, column 13.
               parallel{ map }
               ^
WorkflowScript: 33: No stages specified @ line 33, column 13.
               parallel{ map }
               ^
3 errors

阶段的格式从我整天的阅读中看起来没有问题,而且将相同的阶段直接传递给 parallel 在映射之外也是可以正常工作的。用户不明白自己漏掉了什么,为什么 parallel 不接受他的映射?声明式的 parallel 只接受静态传递的阶段吗?是Jenkins版本过低吗?

解决方案

使用脚本块解决声明式的并行问题

在声明式流水线中,parallel 的用法和在 script 块中的脚本并行是不同的。你的问题在于在映射方式下使用了parallel,但是声明式流水线的parallel期望在块中调用stage函数。

下面是如何解决这个问题的方案:

pipeline {
    agent { label "nodeLabel" }
    stages {
        stage("Non map stage"){
            agent{ label "nodeLabel" }
            steps{
                echo "NON MAP STEP"
            }
        }
        stage("Direct Map Outer Parallel Stage"){
            parallel{
                direct:
                    stage("Direct Map Inner Stage"){
                        agent{ label "nodeLabel" }
                        steps{
                            echo "DIRECT MAP STEP"
                        }
                    }
            }
        }
        stage("Passed Map Outer Parallel Stage"){
            steps {
                script {
                    parallel map
                }
            }
        }
    }
}

在上述解决方案中,我们对 “Passed Map Outer Parallel Stage” 阶段使用了 steps 块,并在其中使用 script 块来调用 parallel 函数并传递映射。

此外,确保你的Jenkins版本支持使用这种方式。

脚本管理启动顺序

如果你想要更精细地控制并行启动的顺序,你可以使用脚本或者一些工具来实现。下面是一个简单的bash脚本示例,用于在容器A启动后启动容器B:

#!/bin/bash
# 启动容器A
docker run -d --name container_a your_image_a
# 等待容器A完全启动
while ! docker exec container_a echo "Container A is ready"; do
  sleep 1
done
# 启动容器B
docker run -d --name container_b your_image_b

在这个示例中,我们使用docker run命令启动容器A,然后使用一个循环来等待容器A完全启动。一旦容器A就绪,我们再使用docker run命令启动容器B。

总结

在使用Jenkins的声明式流水线中,处理并行阶段的方式与在script块中处理的方式不同。对于并行阶段,你需要在steps块中使用script块,并在其中调用parallel函数并传递映射。另外,你还可以使用脚本或工具来精细控制容器的启动顺序。在进行操作时,务必注意你的Jenkins版本是否支持所使用的功能。

正文完