Jenkins Pipeline 详解
梗概(20%核心概念)
Pipeline 是 Jenkins 中用于定义整个构建、测试、部署流程的工具,通过代码化(Jenkinsfile)管理流程,相比传统方式更灵活且易于版本控制。
核心概念
- Jenkinsfile:存放 Pipeline 脚本的文件,通常放在项目根目录,与代码一起纳入版本控制
- 步骤(Step):最小执行单元,如
sh(执行 shell 命令)、git(拉取代码)、build(触发其他任务)等 - 阶段(Stage):将流程划分为不同阶段(如”拉取代码""编译""测试""部署”),直观展示流程进度
- 节点(Node):执行步骤的计算资源(Jenkins 主节点或代理节点)
Jenkins 基础概念
- 流水线(Pipeline):将软件发布流程(如拉取代码、编译、测试、部署)定义为一个可执行的脚本,是Jenkins的核心功能
- 插件(Plugins):Jenkins的功能通过插件扩展,比如Git插件用于拉取代码,Maven插件用于编译Java项目等
- 节点(Node):执行任务的服务器,包括Jenkins自身所在的”主节点”和其他”从节点”
- 任务(Job):Jenkins中具体的工作单元,比如一个构建任务、测试任务等,详见运维Job
详细语法与实践(80%深入内容)
Pipeline类型对比
声明式 vs 脚本式
| 特性 | 声明式Pipeline | 脚本式Pipeline |
|---|---|---|
| 语法结构 | 预定义的结构化语法 | 完全的Groovy脚本 |
| 学习难度 | 相对简单 | 需要Groovy知识 |
| 灵活性 | 有限但够用 | 完全灵活 |
| 错误处理 | 内置错误处理 | 需要手动处理 |
| 推荐使用 | 大多数场景 | 复杂逻辑场景 |
脚本式Pipeline核心语法
脚本式Pipeline使用更灵活的Groovy语法,适合复杂的条件逻辑和动态配置:
// 脚本式Pipeline基本结构
node('worker') { // 指定执行节点
try {
// 定义变量
def buildNumber = env.BUILD_NUMBER
def gitCommit = ''
stage('拉取代码') {
// Git操作
checkout scm
gitCommit = sh(returnStdout: true, script: 'git rev-parse HEAD').trim()
echo "Git commit: ${gitCommit}"
}
stage('构建测试') {
parallel( // 并行执行
'单元测试': {
sh '''
echo "运行单元测试..."
mvn test
'''
// 条件判断
def testResult = sh(returnStatus: true, script: 'mvn test')
if (testResult != 0) {
error "单元测试失败"
}
},
'代码扫描': {
sh '''
echo "执行代码质量扫描..."
sonar-scanner
'''
}
)
}
stage('构建部署') {
// 动态条件判断
if (env.BRANCH_NAME == 'main') {
echo "主分支,执行生产部署"
sh 'mvn package -DskipTests'
// 部署到生产环境
sh '''
docker build -t myapp:${BUILD_NUMBER} .
docker push registry.company.com/myapp:${BUILD_NUMBER}
'''
} else if (env.BRANCH_NAME.startsWith('feature/')) {
echo "特性分支,部署到测试环境"
sh 'mvn package -Ptest'
} else {
echo "其他分支,跳过部署"
}
}
} catch (Exception e) {
currentBuild.result = 'FAILURE'
echo "构建失败: ${e.getMessage()}"
throw e
} finally {
// 清理工作
sh 'docker system prune -f'
// 发送通知
if (currentBuild.result == 'FAILURE') {
emailext (
subject: "构建失败: ${env.JOB_NAME} - ${env.BUILD_NUMBER}",
body: "构建失败,请检查日志。",
to: "${env.CHANGE_AUTHOR_EMAIL}"
)
}
}
}脚本式Pipeline的核心要素:
- node 块:必选,指定任务运行的节点(通过标签筛选),内部包含具体步骤
- 步骤(Steps):Jenkins 提供的内置命令,如
git(拉代码)、sh(执行Shell)、bat(Windows命令)、echo(输出日志)等 - 变量与返回值:用
def定义变量,sh returnStatus: true可获取命令执行结果(0为成功,非0为失败) - 条件判断:支持
if-else,可根据执行结果控制流程(如测试失败则终止)
基础语法(Declarative 声明式)
pipeline {
agent any // 在任意可用节点执行
stages {
stage('拉取代码') {
steps {
git url: 'https://github.com/xxx/xxx.git', branch: 'main'
}
}
stage('编译') {
steps {
sh 'mvn clean compile' // 假设是 Maven 项目
}
}
stage('测试') {
steps {
sh 'mvn test'
}
}
stage('部署') {
steps {
sh './deploy.sh' // 执行部署脚本
}
}
}
post {
success {
echo '构建成功!'
}
failure {
echo '构建失败!'
}
}
}多环境部署最佳实践
1. 环境变量配置
把服务器地址、路径等配置集中管理,避免硬编码:
pipeline {
environment {
PROD_SERVER = 'prod.example.com'
TEST_SERVER = 'test.example.com'
DEPLOY_PATH = '/var/www/app'
}
// ...
}2. 人工确认(input 步骤)
在生产环境前加人工确认,防止误操作:
stage('生产环境部署确认') {
steps {
input message: '确认部署到生产环境?', ok: '确认部署',
parameters: [choice(choices: ['y', 'n'], description: '选择是否继续', name: 'DEPLOY_CHOICE')]
}
}3. 安全凭证管理(withCredentials)
Jenkins凭据功能在自动化流程中用于安全存储密码、密钥、令牌等敏感信息(如Git仓库密码、服务器SSH密钥、API令牌),避免在脚本中硬编码。
常用凭据类型:
usernamePassword:用户名密码对sshUserPrivateKey:SSH私钥string:单个密钥字符串
使用示例:
stage('部署到生产环境') {
steps {
withCredentials([sshUserPrivateKey(credentialsId: 'prod-ssh-key', keyFileVariable: 'KEY_FILE')]) {
sh """
scp -i \$KEY_FILE app.jar user@\$PROD_SERVER:\$DEPLOY_PATH/
ssh -i \$KEY_FILE user@\$PROD_SERVER 'systemctl restart app'
"""
}
}
}多种凭据组合使用:
withCredentials([
usernamePassword(credentialsId: 'docker-registry-creds',
usernameVariable: 'DOCKER_USER',
passwordVariable: 'DOCKER_PASS'),
string(credentialsId: 'api-token', variable: 'API_TOKEN')
]) {
sh "docker login -u \$DOCKER_USER -p \$DOCKER_PASS"
sh "curl -H 'Authorization: Bearer \$API_TOKEN' https://api.example.com/deploy"
}代理节点(Agent)配置
当主节点负载过高时,可配置代理节点分担任务:
- 主节点操作:进入”系统管理”→“节点管理”→“新建节点”,输入节点名称,选择”固定节点”
- 配置节点信息:填写远程工作目录(如
/opt/jenkins_agent)、标签(用于指定任务在该节点执行)、启动方式(如”通过 SSH 启动代理”,需填写代理节点的 IP、用户名、密码) - 在 Pipeline 中指定节点:
pipeline {
agent { label 'test-node' } // 仅在标签为 test-node 的节点执行
// ...
}实际应用场景
Java 项目自动部署到 Kubernetes
前提条件:安装 Kubernetes Plugin、Docker Plugin
核心 Pipeline 步骤:
stage('构建镜像') {
steps {
sh 'mvn package -DskipTests' // 打包 Jar
sh 'docker build -t myapp:${BUILD_NUMBER} .'
sh 'docker push registry.example.com/myapp:${BUILD_NUMBER}' // 推送到私有仓库
}
}
stage('部署到 K8s') {
steps {
sh 'kubectl set image deployment/myapp myapp=registry.example.com/myapp:${BUILD_NUMBER}'
sh 'kubectl rollout status deployment/myapp' // 检查部署状态
}
}相关概念链接
- parent::CI_CD
- related::github CI_CD
- related::蓝盾
- child::Jenkins K8s部署实例
- child::Jenkins节点管理