Skip to content

Jenkins - 持续部署

Jenkins - Pipeline 工作流与持续部署

Section titled “Jenkins - Pipeline 工作流与持续部署”

持续部署(CD)是持续集成(CI)的扩展,它将每次通过验证的更改自动化部署到生产环境。Jenkins Pipeline 是定义和执行这些复杂的端到端工作流的主要机制。

典型的 CI/CD 工作流包含多个阶段:

代码提交 -> 构建 -> 单元测试 -> 静态分析 -> 集成测试 ->(可选手动审批)-> 部署到预发布环境 -> 自动化验收测试 ->(可选手动审批)-> 部署到生产环境 -> 部署后监控

Jenkins 允许你使用 Jenkinsfile 中的阶段来建模这个流程。

注意: 较旧的 ‘Build Pipeline Plugin’ 和 ‘Delivery Pipeline Plugin’ 提供了可视化视图,但已很大程度上被内置的 Pipeline 功能以及核心 Pipeline 阶段视图或 Blue Ocean 插件提供的可视化所取代。

让我们增强一个基本的构建 Pipeline,以包含部署阶段。

pipeline {
agent any // 定义全局或阶段 agent
environment {
// 定义环境变量,可在各阶段访问
STAGING_SERVER = 'staging.example.com'
PROD_SERVER = 'prod.example.com'
APP_NAME = 'my-web-app'
// 凭据应安全加载,不应硬编码
DEPLOY_CREDENTIAL_ID = 'ssh-deploy-key'
}
options {
// 构建前自动清理工作区
// cleanWs()
// 只保留最近 5 次构建
buildDiscarder(logRotator(numToKeepStr: '5', artifactNumToKeepStr: '3'))
// 整个 Pipeline 的超时时间
timeout(time: 1, unit: 'HOURS')
}
stages {
stage('Checkout') {
steps {
echo '正在检出代码...'
git url: 'https://github.com/your-org/your-repo.git',
branch: 'main',
credentialsId: 'github-credentials'
}
}
stage('Build') {
agent { label 'build-agent' } // 如果需要,使用特定的 agent
steps {
echo "正在构建 ${env.APP_NAME}..."
sh 'mvn clean package -DskipTests'
// 归档构建产物供后续阶段使用
archiveArtifacts artifacts: 'target/*.war', fingerprint: true
}
}
stage('Unit & Integration Tests') {
agent { label 'test-agent' } // Agent 可能需要访问数据库
steps {
echo '正在运行测试...'
sh 'mvn verify'
}
post {
always {
junit '**/target/surefire-reports/*.xml'
junit '**/target/failsafe-reports/*.xml'
}
}
}
stage('Static Analysis') {
steps {
echo '正在运行 Checkstyle, SpotBugs...'
// 示例:sh 'mvn checkstyle:check spotbugs:check'
}
post {
always {
// 需要安装 Warnings Next Generation 插件
recordIssues tools: [
checkStyle(pattern: '**/target/checkstyle-result.xml'),
spotbugs(pattern: '**/target/spotbugsXml.xml')
]
}
}
}
// --- 持续交付点 ---
// 到此为止通过的代码具有潜在的可发布性
stage('Deploy to Staging') {
steps {
echo "正在将 ${env.APP_NAME} 部署到预发布环境 (${env.STAGING_SERVER})..."
// 从构建阶段解归档构建产物 (artifact)
unarchiveMapping(mapping: ['target/*.war': '.'])
// 使用 SSH 的示例
sshagent(credentials: [env.DEPLOY_CREDENTIAL_ID]) {
sh "scp *.war user@${env.STAGING_SERVER}:/path/to/deploy/"
sh "ssh user@${env.STAGING_SERVER} /path/to/restart-script.sh"
}
}
}
stage('Acceptance Tests on Staging') {
agent { label 'acceptance-test-agent' } // 带有测试工具/浏览器的 Agent
steps {
echo '正在对预发布环境运行验收测试...'
// 示例:sh 'run-selenium-tests.sh --env=staging'
// 示例:sh 'npx cypress run --env environment=staging'
}
post {
always {
// 发布验收测试结果
junit '**/test-results/acceptance/*.xml'
// publishHTML ... 用于 HTML 报告
}
}
}
// --- 持续部署点 ---
// 如果此阶段自动运行,这就是持续部署
stage('Deploy to Production') {
// 添加 input 步骤以进行手动审批,在生产部署之前
input {
message "将 ${env.APP_NAME} ${env.BUILD_NUMBER} 部署到生产环境?"
ok '是,部署到生产环境'
submitter 'approver-group,admin-user' // 可选:限制谁可以审批
}
steps {
echo "正在将 ${env.APP_NAME} 部署到生产环境 (${env.PROD_SERVER})..."
// 部署步骤与预发布环境类似,但目标是生产服务器
unarchiveMapping(mapping: ['target/*.war': '.'])
sshagent(credentials: [env.DEPLOY_CREDENTIAL_ID]) {
sh "scp *.war user@${env.PROD_SERVER}:/path/to/deploy/"
sh "ssh user@${env.PROD_SERVER} /path/to/restart-script.sh"
}
}
}
}
post {
// 用于整体 Pipeline 状态的通知
success {
slackSend channel: '#deployments', message: "SUCCESS: Pipeline '${env.JOB_NAME} [${env.BUILD_NUMBER}]' completed successfully. Deployed to Production."
}
failure {
slackSend channel: '#alerts', color: 'danger', message: "FAILURE: Pipeline '${env.JOB_NAME} [${env.BUILD_NUMBER}]' failed. (${env.BUILD_URL})"
}
}
}
  • Pipeline 即代码 (Jenkinsfile): 将整个工作流定义在存储于版本控制中(通常与你的应用程序代码一起)的 Jenkinsfile 文本文件中,这对于可重复性、协作和灾难恢复至关重要。
  • 阶段 (Stages): 将工作流分解为逻辑步骤(构建、测试、部署预发布、部署生产)。
  • 构建产物/制品管理 (Artifact Management): 使用 archiveArtifacts 保存构建输出,并使用 unarchiveMapping 或 stash/unstash 在阶段之间传递它们,特别是当阶段在不同的 agent 上运行时。
  • 环境变量 (Environment Variables): 使用 environment 块定义在阶段之间重用的配置。
  • 凭据 (Credentials): 使用 Jenkins 凭据系统安全地存储所有敏感信息(secrets)(API 密钥、密码、SSH 密钥),并通过绑定(withCredentials 步骤)或直接在支持它们的步骤中使用它们(如 git、sshagent)。
  • 手动审批 (Manual Approval): 使用 input 步骤暂停 Pipeline,并在关键操作(如生产部署)之前需要人工确认。
  • 条件执行 (Conditional Execution): 使用 when 指令根据条件跳过阶段(例如,只在 main 分支上运行部署阶段)。
  • 通知 (Notifications): 使用 post 块根据最终 Pipeline 状态或阶段状态发送通知(电子邮件、Slack、Teams)。

Jenkins 提供内置的 Pipeline 可视化功能:

  • Pipeline 阶段视图 (Pipeline Stage View): 经典 UI 构建页面上的默认视图,显示阶段、其状态和持续时间。
  • Blue Ocean 插件: 提供 Pipeline 流程的现代图形化表示,突出显示成功、失败、每个阶段的日志以及待处理的输入。强烈推荐用于可视化复杂的 Pipeline。

通过利用 Jenkins Pipeline 和最佳实践,你可以构建健壮、自动化的工作流以实现持续交付或持续部署。