声明式流水线基础
Jenkins 支持两种流水线语法:声明式(Declarative)和脚本式(Scripted)。声明式结构清晰、适合团队协作和代码评审,是生产首选。脚本式更灵活但难以维护,仅适合高级场景。
本篇目标:能读懂并写出结构完整的声明式 Jenkinsfile,理解 agent、stages、environment、post 等核心块。
1. 声明式 vs 脚本式
| 维度 | 声明式 | 脚本式 |
|---|---|---|
| 语法 | 结构化(类似 YAML 的 Groovy DSL) | 纯 Groovy 脚本 |
| 上手难度 | 低 | 高 |
| 可读性 / 评审 | 好 | 差 |
| 灵活性 | 有约束(利于规范) | 自由(可任意写代码) |
| 推荐场景 | 生产流水线 | 需要动态逻辑的复杂场景 |
// 声明式:结构固定
pipeline {
agent any
stages {
stage('Build') { steps { ... } }
}
}
// 脚本式:自由编程
node {
stage('Build') { ... }
}
2. 一个最小可运行模板
pipeline {
agent any
environment {
APP_NAME = 'backend-service'
REGISTRY = 'registry.company.com'
}
options {
timestamps() // 日志加时间戳
timeout(time: 30, unit: 'MINUTES') // 整条流水线超时
buildDiscarder(logRotator(numToKeepStr: '20')) // 只保留最近 20 次构建
}
stages {
stage('拉取代码') {
steps {
checkout scm
}
}
stage('编译打包') {
steps {
sh 'mvn clean package -DskipTests'
}
}
stage('归档产物') {
steps {
archiveArtifacts artifacts: 'target/*.jar'
}
}
}
post {
always {
cleanWs() // 清理 Workspace
}
success {
echo "✅ ${APP_NAME} 构建成功"
}
failure {
echo "❌ ${APP_NAME} 构建失败"
}
}
}
2.1 post 区块
post 按构建结果执行收尾动作:
| 条件 | 触发时机 |
|---|---|
always | 无论结果如何 |
success | 构建成功 |
failure | 构建失败 |
unstable | 构建不稳定(如测试失败但未挂) |
aborted | 被取消 |
changed | 结果与上一次不同 |
post {
always { cleanWs() }
success { notifySuccess() }
failure { notifyFailure() }
}
cleanWs() 会删除整个 WorkspacecleanWs() 清空当前 Agent 的 Workspace,避免磁盘累积,但不要依赖它保存跨构建数据。需要保留的产物用 archiveArtifacts 归档到 Master,或上传到制品仓库。
3. agent:在哪运行
| 写法 | 含义 |
|---|---|
agent any | 任何可用节点(最简单,不推荐生产) |
agent { label 'linux' } | 指定带该标签的节点 |
agent { docker { image 'maven:3.9-eclipse-temurin-17' } } | 在 Docker 容器中运行 |
agent { kubernetes { ... } } | 在 K8s 动态 Pod 中运行(见第 10 篇) |
agent none | 顶层不指定,各 stage 单独指定 |
// 按 stage 指定不同环境
pipeline {
agent none
stages {
stage('Java 编译') {
agent { docker { image 'maven:3.9-eclipse-temurin-17' } }
steps { sh 'mvn package' }
}
stage('部署') {
agent { label 'k8s-deploy' }
steps { sh 'kubectl apply -f deploy/' }
}
}
}
4. environment:环境变量
pipeline {
environment {
// 静态值
APP_ENV = 'prod'
// 引用 Jenkins 凭证(见第 4 篇)
DOCKER_CREDS = credentials('harbor-registry-auth')
// 引用其他环境变量
IMAGE = "${REGISTRY}/${APP_NAME}:${BUILD_NUMBER}"
}
}
内置变量速查:
| 变量 | 含义 |
|---|---|
${BUILD_NUMBER} | 构建序号 |
${BUILD_URL} | 本次构建的链接 |
${JOB_NAME} | Job 全名(含文件夹路径) |
${WORKSPACE} | 构建工作目录 |
${GIT_COMMIT} | Git 提交 SHA |
${GIT_BRANCH} | 分支名(部分 SCM) |
5. 常见错误与排障
| 现象 | 原因与处理 |
|---|---|
No such DSL method 'sh' | steps 块内才能写步骤,sh 用错层级 |
script not permitted | Groovy 沙箱拦截,需在 Manage Jenkins → In-process Script Approval 批准 |
agent any 一直排队 | 无可用 Executor,检查 Agent 是否离线 |
| 变量为空 | 环境变量定义在 steps 之后,或作用域(stage 内)不对 |
用
echo 和 options 调试调试流水线时,用 echo 打印关键变量、用 options { timestamps() } 加时间戳定位卡点。先小步验证,再补完整流程。
6. 练习与验收
练习 A
- 新建 Pipeline Job,粘贴本模板,跑通"编译 → 归档 → 清理"全流程
- 在
post中分别写success/failure,故意让一条命令失败,观察failure块执行 - 用
options { timestamps() }确认日志带时间戳
练习 B
- 用
environment定义IMAGE变量,在echo中输出 - 给不同
stage配不同agent(用agent none+ 各 stage 指定) - 触发一次沙箱拦截(如在 steps 中定义变量),体验
In-process Script Approval
验收清单
- 能写出结构完整的声明式
Jenkinsfile - 理解
agent的几种写法与作用域 - 会用
environment管理变量,引用凭证 - 会用
post的always/success/failure做收尾 - 知道
cleanWs()与archiveArtifacts的分工 - 能处理常见沙箱 / 变量 / 排队错误
下一篇:声明式流水线进阶。