构建你的第一个用于CI/CD的Jenkins声明式流水线

构建第一个Jenkins声明式流水线,包含阶段、代理、代码检出、测试、部署门控、凭据和后置操作。

构建你的第一个用于CI/CD的Jenkins声明式流水线

你的第一个Jenkins声明式流水线应该回答一个实际问题:Jenkins能否在正确的分支通过时,检出你的代码、构建、测试并执行部署步骤?Jenkinsfile 将这一工作流作为代码,存放在与你的应用相同的仓库中。

声明式语法是一个很好的起点,因为它提供了可预测的结构:pipelineagentstagesstepspost

理解声明式流水线结构

声明式流水线在名为 Jenkinsfile 的文件中定义整个工作流,该文件与你的应用程序代码一起存储在SCM仓库(例如Git)中。这种做法被称为 Pipeline as Code

声明式流水线的核心元素

一个声明式流水线必须包含以下顶层块:

  1. pipeline:定义流水线内容的必需最外层块。
  2. agent:指定流水线或特定阶段将在哪里执行(例如 anynone 或特定标签)。
  3. stages:包含一个或多个顺序的 stage 块。
  4. stage:定义一个概念性的工作块(例如构建、测试、部署)。
  5. steps:包含在 stage 内执行的一个或多个命令或函数。
pipeline {
    agent any 
    environment { // 可选:定义环境变量
        APP_VERSION = '1.0.0'
    }
    stages {
        stage('Build') {
            steps {
                // 命令写在这里
            }
        }
    }
    post { // 可选:流水线完成后执行的操作
        always { 
            echo 'Pipeline finished.' 
        }
    }
}

步骤1:设置Jenkins任务

要从代码运行流水线,你需要配置一个Jenkins任务,使其从仓库中读取 Jenkinsfile

  1. 导航到Jenkins仪表板,选择 New Item
  2. 为你的流水线输入一个名称(例如 my-first-ci-pipeline)。
  3. 选择 Pipeline 项目类型,点击 OK
  4. 在配置页面,向下滚动到 Pipeline 部分。
  5. 将定义从 Pipeline script 更改为 Pipeline script from SCM
  6. 选择你的 SCM(例如 Git)。
  7. 输入 Repository URL,必要时配置凭据。
  8. 确保 Script Path 设置为 Jenkinsfile(默认值)。

步骤2:为CI/CD定义 Jenkinsfile

我们将创建一个全面的 Jenkinsfile,模拟一个简单的CI/CD工作流,集成成功部署所需的标准阶段。

假设你的仓库结构包含应用程序源代码(例如一个简单的Python或Java项目)以及根目录下的 Jenkinsfile

完整的声明式流水线示例

此流水线使用 node 代理(如果已配置),并利用基本的shell步骤(sh)模拟实际工作。部署阶段是有条件的,仅在前面的阶段成功完成后运行。

// Jenkinsfile
pipeline {
    // 1. 代理定义:指定整个流水线在哪里运行
    agent { 
        label 'my-build-agent' // 如果可用,使用特定标签,否则使用 'any'
    }
    
    // 2. 环境变量:定义可在整个流水线中使用的变量
    environment {
        CONTAINER_REGISTRY = 'registry.example.com'
        IMAGE_NAME = 'myapp'
    }
    
    stages {
        
        // 阶段1:代码检出(源代码管理)
        stage('Checkout Source') {
            steps {
                // 'checkout scm' 步骤根据Jenkins任务配置中定义的设置自动检出代码
                checkout scm
                sh 'echo "Source code successfully checked out."'
            }
        }
        
        // 阶段2:构建制品
        stage('Build Artifact') {
            steps {
                sh 'echo "Starting build for $IMAGE_NAME:$BUILD_ID"'
                // 模拟:构建Docker镜像或编译jar/war文件
                sh "docker build --label build_id=${BUILD_ID} -t ${CONTAINER_REGISTRY}/${IMAGE_NAME}:${BUILD_ID} ."
            }
        }
        
        // 阶段3:测试与质量门控
        stage('Run Tests') {
            steps {
                sh './run_unit_tests.sh'
                sh 'echo "Running integration tests..."'
                // 收集测试结果的示例(需要相应的插件)
                // junit '**/target/surefire-reports/*.xml'
            }
        }
        
        // 阶段4:部署(有条件)
        stage('Deploy to Staging') {
            // 'when' 指令确保该阶段仅在特定条件下运行
            when {
                branch 'main'
            }
            steps {
                sh "docker push ${CONTAINER_REGISTRY}/${IMAGE_NAME}:${BUILD_ID}"
                sh 'kubectl apply -f k8s/deployment-staging.yaml'
                script {
                    // Script块允许在声明式步骤中使用传统的Groovy逻辑
                    echo "Deployment successful to Staging environment."
                }
            }
        }
    }
    
    // 3. 后置操作:根据流水线的最终状态定义操作
    post {
        success {
            echo 'Pipeline completed successfully. Notifying team via Slack...'
            // slackSend channel: '#devops-alerts', message: 'CI/CD Success!'
        }
        failure {
            echo 'Pipeline failed. Review logs for errors.'
        }
        cleanup {
            sh 'docker image prune -f --filter "label=build_id=$BUILD_ID"'
        }
    }
}

步骤3:运行和监控流水线

一旦 Jenkinsfile 被提交并推送到Jenkins任务中配置的分支:

  1. 在Jenkins任务页面,点击 Build Now(或等待SCM轮询/webhook触发)。
  2. Build History 面板中监控构建。
  3. 点击正在运行的构建编号,选择 Console Output 查看逐步执行详情。
  4. 你也可以使用 Stage View 可视化(如果安装了插件)以图形方式查看 CheckoutBuildTestDeploy 阶段的进度。

最佳实践与高级功能

使用库和共享代码

对于复杂或高度重复的步骤,避免在 Jenkinsfile 中直接编写冗长的Groovy代码。相反,使用 Shared Libraries。这些外部库允许你定义常用函数(如标准部署例程或通知函数),可以从多个流水线中调用,使你的 Jenkinsfile 更简洁。

// 调用共享库步骤
stage('Custom Setup') {
    steps {
        customLibrary.initializeEnvironment(env: 'prod')
    }
}

处理凭据

切勿将敏感信息(密码、令牌、API密钥)直接硬编码到 Jenkinsfile 中。使用Jenkins内置的凭据管理系统。

withCredentials 步骤允许你安全地访问存储的密钥:

stage('Authenticate Registry') {
    steps {
        withCredentials([usernamePassword(credentialsId: 'docker-registry-creds', 
                                          passwordVariable: 'PASS', 
                                          usernameVariable: 'USER')]) {
            sh '''
                printf '%s' "$PASS" | docker login \
                  --username "$USER" \
                  --password-stdin "$CONTAINER_REGISTRY"
            '''
        }
    }
}

代理选择

提示: 始终使用 label 具体定义你的 agent,而不是使用 agent any。使用 agent any 意味着流水线可能在Jenkins控制器节点上运行,这存在安全风险并可能影响控制器性能。确保你已正确配置Jenkins代理(节点),并安装了必要的工具(Docker、Maven、Node.js)。

要点

保持第一个流水线简单可靠:选择一个真实的代理标签,检出代码,构建,测试,按分支门控部署,并将密钥保存在Jenkins凭据中。一旦运行正常,再逐步添加制品发布、安全扫描和环境提升。