sh 命令在并行阶段运行时似乎挂起

问题描述 投票:0回答:2

我们有一个主要的构建管道,它使用工作流cps并行步骤同时运行大约50个容器,并且它严重依赖于sh。 随着更多代理添加到并行步骤中,如果 sh 命令包含在 groovy 脚本中,则需要更长的时间才能完成。 (这对于常规 Linux 静态节点和 k8s pod 来说是正确的)

我简化了管道,因此更容易重现:

pipeline {
    agent none
    stages {
        stage('Build and Test') {
            parallel {
                stage('Stage1') {
                    agent {
                        kubernetes {
                            yaml """
apiVersion: v1
kind: Pod
metadata:
  name: test-pod
spec:
  containers:
    - name: test-build
      image: ubuntu
      resources:
        requests:
          memory: 4000Mi
          cpu: 4
        limits:
          memory: 4000Mi
          cpu: 4
      command: ['sleep']
      args: ['6h']
      tty: true
                            """
                        }
                    }
                    steps {
                        container('test-build') {
                            script{
                                for (int i = 0; i < 30; i++) {
                                    sh 'cat /etc/hosts'
                                }
                            }
                        }
                    }
                }
                
                
               stage('Stage2') {
                    agent {
                        kubernetes {
                            yaml """
apiVersion: v1
kind: Pod
metadata:
  name: test-pod
spec:
  containers:
    - name: test-build
      image: ubuntu
      resources:
        requests:
          memory: 4000Mi
          cpu: 4
        limits:
          memory: 4000Mi
          cpu: 4
      command: ['sleep']
      args: ['6h']
      tty: true
                            """
                        }
                    }
                    steps {
                        container('test-build') {
                            script{
                                for (int i = 0; i < 30; i++) {
                                    sh 'cat /etc/hosts'
                                }
                            }
                        }
                    }
                }
                
                // ...
               //  ....
               // in here you can keep pasting duplicates of stages
                
                
            }
        }
    }
}

对每个阶段的硬编码表示歉意,但我无法想出一个可以做得更好的循环。

我的结果如下:

7 个阶段:每个代理大约需要 50 秒完成

17 个阶段:每个代理完成约 120 秒

35 个阶段:每个特工完成约 270 个阶段

如果我在并行部分只留下一个阶段,然后同时运行相同的构建 X50 次,每个构建完成得非常快(大约 15 秒) 所以我不认为这是一个一般的负载问题,而是并行步骤可能以某种方式限制 sh 响应,使它们挂起。 (也许是 CpsFlowExecution 线程?)

请您提出建议。

jenkins jenkins-plugins jenkins-groovy
2个回答
0
投票
操作系统습니다.


-1
投票
您遇到的问题似乎与管理 Jenkins 管道中大量并行步骤的开销有关,特别是在

sh 命令周围使用 Groovy 脚本包装器时。这可能是由于 Jenkins 如何处理和安排这些并行执行,特别是在 Jenkins 用于管道脚本的 CPS(连续传递风格)执行模型下。

以下是缓解此问题的一些策略:

1。减少 Groovy 脚本包装器的数量

Groovy 脚本包装器围绕

sh 命令增加了开销。减少script块的使用可以帮助最大限度地减少这种情况。

2。直接使用sh命令

如果可能,请避免在 Groovy 脚本中包装

sh 命令,除非绝对必要。

steps { container('test-build') { for (int i = 0; i < 30; i++) { sh 'cat /etc/hosts' } } }

3.优化 Pod 规格

确保您的 Kubernetes Pod 规格尽可能优化。减少 pod 的初始化时间。

4。更少阶段的并行执行

不要并行运行多个阶段,而是考虑在可行的情况下将任务合并为更少的阶段。

5。使用声明性语法进行并行执行

确保您使用声明性语法进行并行执行,因为它通常比脚本语法更高效且更易于管理。

6。研究 Jenkins 系统配置

检查您的 Jenkins 系统配置,确保其针对并行执行进行了优化。这包括:

    确保Master和Agent有足够的资源(CPU、 记忆)。
  • 配置 Jenkins master 来处理大量
  • 如果需要的话,执行者。

7。动态舞台创作

考虑以更有效的方式动态创建阶段。这是一个例子:

pipeline { agent none stages { stage('Build and Test') { parallel { script { def stages = [:] for (int i = 1; i <= 50; i++) { stages["Stage${i}"] = { agent { kubernetes { yaml """ apiVersion: v1 kind: Pod metadata: name: test-pod-${i} spec: containers: - name: test-build image: ubuntu resources: requests: memory: 4000Mi cpu: 4 limits: memory: 4000Mi cpu: 4 command: ['sleep'] args: ['6h'] tty: true """ } } steps { container('test-build') { for (int j = 0; j < 30; j++) { sh 'cat /etc/hosts' } } } } } parallel stages } } } } }
这会动态创建 50 个阶段,减少手动编写每个阶段的开销,并可能提高性能。

8。研究 CPS 模型开销

如果 CPS 模型造成大量开销,请考虑使用管道:Groovy 插件的非 CPS 步骤,尽管它可能会使管道复杂化。

9。查看 Jenkins 版本和插件

确保您正在运行最新稳定版本的 Jenkins 和相关插件,因为性能改进和错误修复会不断发布。

10。监控和分析管道执行

使用 Jenkins 监控插件来分析管道执行情况并识别瓶颈。 Performance 和 Pipeline Profiler 等插件可以提供帮助。

实施这些策略应该有助于缓解问题并提高 Jenkins 管道中并行步骤的性能。

如有其他问题请告知。

© www.soinside.com 2019 - 2024. All rights reserved.