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' } } } } } }
代码说明
- 结构化流水线:使用
pipeline块替代嵌套的podTemplate写法,阶段划分更清晰,执行顺序更可控。 - 分阶段Agent定义:构建阶段和测试阶段分别声明独立的Kubernetes Agent,测试Pod只会在构建完成后才被创建,此时镜像已推送至仓库。
- 准确获取提交ID:通过
git rev-parse HEAD获取当前代码的精确提交ID,避免变量替换失效问题,确保测试Pod能拉取到正确的镜像。 - 避免提前启动测试Pod:测试Pod的定义放在测试阶段内部,Jenkins仅在进入该阶段时才尝试拉取镜像,解决了镜像未就绪导致的Pod启动失败问题。
内容的提问来源于stack exchange,提问作者Cyril Duchon-Doris
相关产品推荐
相关产品推荐

