You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jenkins Pipeline:如何用前置阶段构建的镜像启动新Pod

问题描述

我在Kubernetes集群A中部署了Jenkins,它可在同一集群中生成Pod。我的工作流如下:

  • 启动一个用于构建Docker镜像的Pod,生成的镜像带有确定标签example/appname:${GIT_COMMIT}
  • 在前一Pod完成镜像构建后,启动使用该镜像的新Pod,运行多项测试工具

目前我已通过以下代码成功完成构建:

podTemplate(yaml: """
apiVersion: v1
kind: Pod
spec:
  containers:
  - name: aws-dockerizer
    image: example/aws-dockerizer:0.1.7
    command: ['cat']
    tty: true
    volumeMounts:
    - name: dockersock
      mountPath: /var/run/docker.sock
  volumes:
  - name: dockersock
    hostPath:
      path: /var/run/docker.sock
""") {
  node(POD_LABEL) {

    stage('Clone') {
      git url: 'https://github.com/example/my-app/', branch: '${build_branch_name}', credentialsId: 'github-app'

      container('aws-dockerizer') {
        stage('Build and deploy') {
          withAWS(credentials: 'aws-credentials', region: 'eu-central-1') {
            sh '''#!/usr/bin/env bash
              git config --global --add safe.directory ${WORKSPACE}
              scripts/build_and_push_docker_image_to_aws.sh
            '''
          }
        }
      }
    }  

  }
}

我想添加以下测试阶段,但新Podexperience-${GIT_COMMIT}因镜像未生成无法启动。若提前声明两个podTemplate,任务会因等待未就绪的第二个Pod而挂起:

podTemplate(
  label: "experience-${GIT_COMMIT}"
  yaml: """
apiVersion: v1
kind: Pod
spec:
  containers:
  - name: experience
    image: example.dkr.ecr.eu-central-1.amazonaws.com/example/appname:${GIT_COMMIT}
    command: ['cat']
    tty: true
"""
) 

  stage('Run tests') {
    node("experience-${GIT_COMMIT}") {
      stage('Run tests') {
        container('experience') {
          stage('Run Rspec') {
            sh 'bundle exec rspec'
          }
          post {}
        }
      }
    }
  }
}

请问该需求是否可行?需要使用哪些DSL/概念?如何合并代码实现目标?


解决方案

可行性说明

该需求完全可行。核心问题是不能提前声明依赖未构建镜像的PodTemplate,必须在镜像构建并推送完成后,再动态创建测试Pod。

所需Jenkins DSL/概念

  • 分阶段动态创建Agent:每个阶段单独定义Kubernetes Agent,确保测试Pod仅在镜像就绪后才被创建启动。
  • 环境变量传递:在构建阶段捕获GIT_COMMIT并存入全局环境变量,让测试阶段能准确引用镜像标签。
  • 流水线阶段顺序控制:通过结构化流水线保证构建阶段完全执行完毕后,再进入测试阶段。

合并后的完整代码

pipeline {
  agent none
  stages {
    stage('Build Docker Image') {
      agent {
        kubernetes {
          yaml """
apiVersion: v1
kind: Pod
spec:
  containers:
  - name: aws-dockerizer
    image: example/aws-dockerizer:0.1.7
    command: ['cat']
    tty: true
    volumeMounts:
    - name: dockersock
      mountPath: /var/run/docker.sock
  volumes:
  - name: dockersock
    hostPath:
      path: /var/run/docker.sock
"""
        }
      }
      steps {
        container('aws-dockerizer') {
          git url: 'https://github.com/example/my-app/', branch: '${build_branch_name}', credentialsId: 'github-app'
          withAWS(credentials: 'aws-credentials', region: 'eu-central-1') {
            sh '''#!/usr/bin/env bash
              git config --global --add safe.directory ${WORKSPACE}
              scripts/build_and_push_docker_image_to_aws.sh
            '''
          }
          // 捕获当前提交ID,存入全局环境变量
          script {
            env.GIT_COMMIT = sh(script: 'git rev-parse HEAD', returnStdout: true).trim()
          }
        }
      }
    }

    stage('Run Tests') {
      agent {
        kubernetes {
          yaml """
apiVersion: v1
kind: Pod
spec:
  containers:
  - name: experience
    image: example.dkr.ecr.eu-central-1.amazonaws.com/example/appname:${env.GIT_COMMIT}
    command: ['cat']
    tty: true
"""
        }
      }
      steps {
        container('experience') {
          stage('Run Rspec') {
            sh 'bundle exec rspec'
          }
        }
      }
    }
  }
}

代码说明

  1. 结构化流水线:使用pipeline块替代嵌套的podTemplate写法,阶段划分更清晰,执行顺序更可控。
  2. 分阶段Agent定义:构建阶段和测试阶段分别声明独立的Kubernetes Agent,测试Pod只会在构建完成后才被创建,此时镜像已推送至仓库。
  3. 准确获取提交ID:通过git rev-parse HEAD获取当前代码的精确提交ID,避免变量替换失效问题,确保测试Pod能拉取到正确的镜像。
  4. 避免提前启动测试Pod:测试Pod的定义放在测试阶段内部,Jenkins仅在进入该阶段时才尝试拉取镜像,解决了镜像未就绪导致的Pod启动失败问题。

内容的提问来源于stack exchange,提问作者Cyril Duchon-Doris

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 05:48:24