Jenkins:持续集成和持续交付(CI/CD)工具

目录

一、概念

[1.1 定义与价值](#1.1 定义与价值)

[1.2 核心概念](#1.2 核心概念)

[1.3 核心功能](#1.3 核心功能)

[1.4 工作流程](#1.4 工作流程)

[1.5 常见CI/CD工具对比](#1.5 常见CI/CD工具对比)

二、安装与配置

[2.1 环境准备](#2.1 环境准备)

[2.2 安装Jenkins](#2.2 安装Jenkins)

[2.2.1 方式一:通过包管理器安装(推荐用于生产环境)](#2.2.1 方式一:通过包管理器安装(推荐用于生产环境))

[2.2.2 方式二:通过 WAR 包安装(适合快速测试)](#2.2.2 方式二:通过 WAR 包安装(适合快速测试))

[2.3 防火墙与访问设置](#2.3 防火墙与访问设置)

[2.4 初始配置与插件管理](#2.4 初始配置与插件管理)

三、简单使用(自由风格项目)

[3.1 基本任务创建](#3.1 基本任务创建)

[3.2 源码管理(Git)](#3.2 源码管理(Git))

[3.3 构建触发器](#3.3 构建触发器)

[3.4 构建环境与步骤](#3.4 构建环境与步骤)

[2.5 保存与构建](#2.5 保存与构建)

[2.6 实用技巧](#2.6 实用技巧)

四、使用(流水线项目)

[4.1 创建流水线任务](#4.1 创建流水线任务)

[4.2 配置流水线任务](#4.2 配置流水线任务)

[4.3 保存并运行](#4.3 保存并运行)

五、Jenkinsfile核心指令


一、概念

1.1 定义与价值

Jenkins 是一个开源的、用 Java 编写的持续集成和持续交付(CI/CD)工具 。它本质上是一个自动化服务器,用于自动化软件开发过程中的各种任务,例如编译、测试、打包、部署等。

核心价值:自动化构建、测试和部署过程,尽早发现集成错误,提高软件质量与交付效率。

1.2 核心概念

  • 任务/项目(Job/Project): Jenkins中自动化流程的配置单元,比如一个构建Java应用的任务。

  • 流水线 :这是现代 Jenkins 的核心功能。可以将整个构建、测试、部署流程以代码的形式(称为 Jenkinsfile)定义下来,这使得流程可版本化、可审查、可重复。流水线分为声明式和脚本式两种,前者语法更简洁,后者灵活性更高。

    • 声明式流水线(Declarative Pipeline)推荐使用,提供了更简单、更结构化的语法,降低了上手难度。

    • 脚本式流水线(Scripted Pipeline):基于 Groovy 的 DSL,提供极大的灵活性,但语法相对复杂。

  • 构建(Build): 执行一次任务的过程,包括拉取代码、编译、测试等步骤。

  • 工作空间(Workspace): Jenkins每次构建时,用来存放源代码和生成产物的目录。

  • 插件(Plugin): Jenkins 拥有一个极其丰富的插件生态系统(超过 1800 个插件),这使其能够与 Git、Docker、Kubernetes、Jira 等几乎所有主流开发工具无缝集成,功能得以无限扩展。

1.3 核心功能

  • 持续集成(CI)

    • 自动化构建:当开发人员向版本控制系统(如 Git、SVN)提交代码后,Jenkins 可以自动侦听这一事件(通过 Webhook),拉取最新代码。

    • 自动化编译/打包:根据项目类型(如 Java/Maven、.NET、Node.js、Python),调用相应的构建工具(如 Maven、Gradle、npm、dotnet)将源代码编译成可执行的软件包(如 JAR、WAR、Docker 镜像)。

  • 持续测试

    • 自动化测试:在构建完成后,自动运行各种测试套件,包括单元测试、集成测试等。

    • 测试报告生成:收集测试结果,生成可视化的报告和趋势图,帮助团队快速了解代码质量和测试覆盖率。

  • 持续交付/持续部署(CD)

    • 自动化部署:将构建好的、通过测试的软件包自动部署到各种环境中,如测试环境、预生产环境,乃至生产环境。

    • 多环境管理:通过插件和配置,轻松管理向不同环境的部署流程,通常与审批流程结合(持续交付),或完全自动化(持续部署)。

  • 强大的流水线(Pipeline)

    • 这是 Jenkins 的灵魂功能。它将整个 CI/CD 流程定义为一个"流水线",由多个"阶段"(Stage)组成,例如:代码检出 -> 编译 -> 单元测试 -> 集成测试 -> 构建Docker镜像 -> 部署到测试环境 -> 验收测试

    • Jenkinsfile:使用 Groovy 语法将流水线定义为代码,存储在项目源码库中。这使得流程与代码同在,便于管理和协作。

  • 广泛的插件生态系统

    • Jenkins 拥有超过 1800 个插件,这是它最核心的竞争力之一。几乎所有能想到的第三方工具都可以通过插件与 Jenkins 集成,例如:

      • 版本控制:Git、GitHub、GitLab、Bitbucket。

      • 构建工具:Maven、Gradle、Ant、npm、Yarn。

      • 测试框架:JUnit、Selenium、Cucumber。

      • 部署目标:Kubernetes、Docker、AWS、Azure、Tomcat、SSH。

      • 通知:Email、Slack、钉钉、企业微信。

  • 监控与通知

    • Jenkins 会监控整个构建和部署过程的状态(成功、失败、不稳定)。

    • 当流程中断时,它会通过邮件、即时消息等渠道通知相关人员,确保问题能被及时处理。

1.4 工作流程

  1. 监听触发:Jenkins 会持续监听代码仓库(如 Git)的变动,一旦有新的代码提交,或者到达预设的时间点,它就会被触发开始工作。

  2. 拉取代码:从版本控制仓库拉取最新的源代码。

  3. 执行任务:按照预先定义好的"流水线",一步步执行命令,常见步骤包括编译代码、运行测试、打包项目、进行代码质量检查以及部署到服务器等。

  4. 反馈结果:任务执行完成后,Jenkins 会生成详细报告,并通过邮件、钉钉等方式通知相关人员构建结果。

1.5 常见CI/CD工具对比

工具 托管方式 配置方式 核心优势 主要缺点 最佳适用场景
Jenkins 主要自托管 Jenkinsfile (Groovy) / UI 极度灵活,插件生态丰富,免费 维护成本高,学习曲线陡,界面陈旧 需要高度定制化,有专人维护的复杂环境
GitLab CI/CD SaaS/自托管 .gitlab-ci.yml (YAML) 与GitLab无缝集成,一体化的DevOps体验 与GitLab平台强绑定 已使用GitLab,追求端到端工具链的团队
GitHub Actions SaaS YAML 工作流文件 与GitHub深度集成,事件驱动,Action市场丰富 与GitHub平台强绑定 代码在GitHub,希望利用事件驱动自动化的团队
CircleCI 主要SaaS .circleci/config.yml (YAML) 云版本性能快,Docker支持好,配置清晰 免费计划限制较多 追求速度和稳定性,使用Docker的云原生项目
Azure Pipelines SaaS/自托管代理 YAML / UI 平台无关性,免费额度慷慨,微软栈集成好 微软生态外非首选 微软技术栈,Azure用户,开源项目

二、安装与配置

2.1 环境准备

Jenkins 需要运行在具有 Java 环境的服务器上,以下是针对不同操作系统的安装方法:

安装 Java

Ubuntu/Debian 系统:

bash 复制代码
sudo apt update
sudo apt install openjdk-11-jdk
java -version # 验证安装

CentOS/RHEL 系统:

bash 复制代码
sudo yum install java-11-openjdk
  • 版本选择 :Jenkins 2.357 及更高版本需要 Java 11 或更高版本。建议选择 Java 11Java 17 这些长期支持版(LTS)。

环境配置 :设置 JAVA_HOME 环境变量,例如在 /etc/profile 文件中添加:

bash 复制代码
export JAVA_HOME=/usr/lib/jvm/java-11-openjdk
export PATH=$JAVA_HOME/bin:$PATH

然后执行 source /etc/profile 使配置生效。

2.2 安装Jenkins

2.2.1 方式一:通过包管理器安装(推荐用于生产环境)

这种方法便于后续的管理和升级。

Ubuntu/Debian 系统:

bash 复制代码
# 添加仓库密钥和源
sudo wget -O /usr/share/keyrings/jenkins-keyring.asc https://pkg.jenkins.io/debian-stable/jenkins.io-2023.key
echo "deb [signed-by=/usr/share/keyrings/jenkins-keyring.asc] https://pkg.jenkins.io/debian-stable binary/" | sudo tee /etc/apt/sources.list.d/jenkins.list > /dev/null
sudo apt update
sudo apt install jenkins

CentOS/RHEL 系统:

bash 复制代码
# 添加仓库
sudo wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat-stable/jenkins.repo
sudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io.key
sudo yum install jenkins

安装完成后,启动 Jenkins 并设置开机自启:

bash 复制代码
sudo systemctl start jenkins
sudo systemctl enable jenkins

2.2.2 方式二:通过 WAR 包安装(适合快速测试)

这种方式简单灵活,只需具备 Java 环境即可。

bash 复制代码
wget https://get.jenkins.io/war-stable/2.426.2/jenkins.war
sudo java -jar jenkins.war --httpPort=8090

2.3 防火墙与访问设置

确保服务器防火墙开放了 Jenkins 所使用的端口(例如默认的 8080 端口)。

  • 查看防火墙状态systemctl status firewalld

  • 开放端口(以 8080 为例)

bash 复制代码
firewall-cmd --zone=public --add-port=8080/tcp --permanent
firewall-cmd --reload
  • 访问 Jenkins :在浏览器中输入 http://<你的服务器IP地址>:8080 即可访问 Jenkins 初始页面。

2.4 初始配置与插件管理

首次访问 Jenkins 时:

  1. 获取管理员密码 :在服务器上执行 sudo cat /var/lib/jenkins/secrets/initialAdminPassword 查看初始密码,并将其输入网页。

  2. 选择插件安装方式 :建议先**"安装推荐的插件"**。如果网络环境导致下载缓慢或失败,可以参考后续的"插件加速"部分进行配置后再安装。

由于网络原因,直接从 Jenkins 官方仓库下载插件可能很慢。可以切换至国内镜像源,例如清华大学镜像源。

  1. 登录 Jenkins 管理后台,进入 Manage Jenkins > Manage Plugins > Advanced

  2. Update Site 栏目中,将 URL 修改为:
    https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json

  3. 点击 Submit 保存。

    如果修改配置后插件安装问题依旧,可以尝试重启 Jenkins 服务(sudo systemctl restart jenkins)或手动修改 Jenkins 主机上的更新中心配置文件。

创建管理员用户:在插件安装完成后,系统会提示你创建一个新的管理员用户。建议务必在此步骤创建,以便后续管理。

全局工具配置:为了让 Jenkins 能够执行构建、打包等任务,需要配置所需工具的路径。

进入 Manage Jenkins > Global Tool Configuration

  • JDK :可以取消"自动安装",手动指定 JAVA_HOME 路径,如 /usr/lib/jvm/java-11-openjdk

  • Git :通常使用系统自带的 Git,路径可能是 /usr/bin/git。如果系统未安装,需先执行 yum install gitapt install git

  • Maven:如果构建 Java Maven 项目,可以指定 Jenkins 自动安装特定版本,或手动指定已安装在服务器上的 Maven 路径。

  • Node.js :对于前端项目,可以在插件市场安装 NodeJS Plugin 后,在此处配置 Node.js 版本。

三、简单使用(自由风格项目)

3.1 基本任务创建

  1. 点击 Jenkins 首页的 新建任务(New Item)。

  2. 输入任务名称,例如 My-First-Project

  3. 选择任务类型,对于初学者,常见的类型有:

    • Freestyle project(自由风格项目):提供灵活的图形化配置界面,适合大多数简单场景。

    • Pipeline (流水线项目):使用代码(Jenkinsfile)来定义构建流程,更适合复杂、多阶段的 CI/CD 流程。

      本例中选择 Freestyle project

3.2 源码管理(Git)

在任务配置页面的 Source Code Management 部分:

  1. 选择 Git

  2. Repository URL 中输入 Git 仓库地址,例如 https://github.com/username/repo.git

  3. 如果仓库是私有的,需要配置凭据(Credentials)。点击 Add > Jenkins

    • Kind 选择 "Username with password"。

    • 输入 Git 用户名和密码(或 Personal Access Token)。

  4. Branches to build 指定分支,例如 */main*/master

3.3 构建触发器

Build Triggers 部分,可以设置何时自动触发构建:

  • 手动构建 :不配置任何触发器,每次在 Jenkins 页面上手动点击 Build Now

  • 定时构建 :例如,H 2 * * * 表示每天凌晨 2 点左右构建。

  • 轮询 SCM :定期检查代码仓库是否有变更,如有变更则触发构建。例如 */5 * * * * 表示每 5 分钟检查一次。

  • GitHub Webhook(更高效):当代码推送到仓库时,GitHub 会主动通知 Jenkins 触发构建。这需要额外的 Webhook 配置。

3.4 构建环境与步骤

Build 部分,点击 Add build step,根据项目类型添加相应的步骤。

  • 对于 Maven 项目 :可以选择 Invoke top-level Maven targets ,然后指定 Maven 目标,如 clean package

  • 对于 Shell 脚本 :可以选择 Execute shell,然后输入命令,例如:

bash 复制代码
# 前端项目示例
npm install
npm run build
# 将构建产物复制到指定目录
cp -r dist /path/to/target/

2.5 保存与构建

配置完成后,点击页面底部的 Save 。在项目详情页,点击左侧的 Build Now 即可立即开始一次构建。点击构建历史记录中的链接(例如 #1),再选择 Console Output,可以查看详细的构建日志,这对于调试非常重要。

2.6 实用技巧

  • 修改 JVM 内存设置 :如果构建时出现 java.lang.OutOfMemoryError,需要增加 Jenkins 的堆内存。可以通过修改启动参数实现,例如在 JAVA_OPTS 中加入 -Xms512m -Xmx1024m

  • 设置"丢弃旧的构建":在项目配置中勾选此选项,可以设置保留构建的天数和最大保留个数,有效节省服务器磁盘空间。

  • 权限管理 :安装 Role-based Authorization Strategy 插件,可以为不同用户(如开发、测试)分配不同的项目查看和操作权限。

四、使用(流水线项目)

以一个完整的 Java Maven 项目为例,结合 Docker 部署

4.1 创建流水线任务

  1. 登录 Jenkins 控制台,点击首页左侧的 "新建任务" (New Item)

  2. 输入任务名称,例如 my-pipeline-project

  3. 关键选择 :在任务类型中选择 "流水线" (Pipeline)

  4. 点击 "确定"

4.2 配置流水线任务

进入任务配置页面后,找到 "流水线" (Pipeline) 部分,这里有几种定义流水线的方式:

方式一:直接编写脚本 (Pipeline script)

  • 适用场景:快速测试、简单脚本、学习阶段

  • 操作方法 :在 "脚本" (Script) 文本框中直接粘贴或编写 Jenkinsfile 内容

  • 示例

Groovy 复制代码
pipeline {
    agent any // 指定流水线在任何可用的代理上执行:cite[5]:cite[10]

    // 定义环境变量
    environment {
        REGISTRY_URL = 'harbor.example.com' // 私有镜像仓库地址
        PROJECT_NAME = 'my-java-app'
        DOCKER_CREDENTIALS_ID = 'docker-harbor-login' // Jenkins中配置的Docker凭据ID
    }
    
    stages {
        // 阶段1:拉取代码
        stage('Checkout') {
            steps {
                checkout scm: [
                    $class: 'GitSCM', 
                    branches: [[name: '*/main']], 
                    userRemoteConfigs: [[url: 'http://your-git-repo.com/your-project.git']]
                ]
                echo "代码拉取完成"
            }
        }
        
        // 阶段2:编译和单元测试
        stage('Build and Test') {
            steps {
                sh 'mvn clean compile' // 编译代码
                sh 'mvn test' // 运行单元测试
            }
            post {
                always {
                    junit 'target/surefire-reports/*.xml' // 归档JUnit测试报告:cite[2]
                }
            }
        }
        
        // 阶段3:打包JAR文件
        stage('Package') {
            steps {
                sh 'mvn package -Dmaven.test.skip=true' // 跳过测试进行打包
                archiveArtifacts artifacts: 'target/*.jar', fingerprint: true // 归档生成的JAR包
            }
        }
        
        // 阶段4:构建Docker镜像
        stage('Build Docker Image') {
            steps {
                script {
                    // 动态生成镜像标签,例如使用构建号
                    dockerImage = docker.build "${REGISTRY_URL}/${PROJECT_NAME}:v1.0.${BUILD_NUMBER}"
                }
            }
        }
        
        // 阶段5:推送Docker镜像
        stage('Push Docker Image') {
            steps {
                script {
                    docker.withRegistry("https://${REGISTRY_URL}", DOCKER_CREDENTIALS_ID) {
                        dockerImage.push() // 推送镜像到仓库
                    }
                }
            }
        }
        
        // 阶段6:部署到服务器
        stage('Deploy') {
            steps {
                script {
                    // 使用SSH远程执行部署脚本
                    sshagent(['your-ssh-credentials-id']) {
                        sh """
                            ssh -o StrictHostKeyChecking=no user@your-server-ip '
                                docker stop ${PROJECT_NAME} || true
                                docker rm ${PROJECT_NAME} || true
                                docker pull ${REGISTRY_URL}/${PROJECT_NAME}:v1.0.${BUILD_NUMBER}
                                docker run -d -p 8080:8080 --name ${PROJECT_NAME} ${REGISTRY_URL}/${PROJECT_NAME}:v1.0.${BUILD_NUMBER}
                            '
                        """
                    }
                }
            }
        }
    }
    
    // 构建后处理
    post {
        always {
            echo "流水线执行完成,构建号:${BUILD_NUMBER}"
            // 这里可以添加清理工作,例如删除临时文件
        }
        success {
            echo "构建成功!"
            // 可以在这里添加成功通知,例如发送邮件:cite[3]
        }
        failure {
            echo "构建失败!"
            // 可以在这里添加失败通知
        }
    }
}
阶段 核心任务 关键命令/插件 说明
Checkout 从版本库拉取代码 checkout scm 获取最新的源代码。
Build and Test 编译代码并运行单元测试 mvn clean compile, mvn test, junit 运行测试并生成测试报告。
Package 打包应用程序 mvn package, archiveArtifacts 生成可部署的JAR/WAR包并归档。
Build Docker Image 构建Docker镜像 docker.build 使用项目中的Dockerfile构建镜像。
Push Docker Image 推送镜像到仓库 docker.withRegistry, dockerImage.push 将镜像推送到私有仓库以备部署。
Deploy 部署到目标服务器 sshagent, ssh 通过SSH在目标服务器上拉取新镜像并重启容器。

方式二:从代码仓库获取 (Pipeline script from SCM) - 推荐用于生产

  • 适用场景:实际项目开发,实现"Pipeline as Code"

  • 配置细节

    • SCM:选择版本控制系统(Git、SVN等)

    • Repository URL:输入代码仓库地址

    • 凭据:添加访问仓库的用户名/密码或SSH密钥

    • 分支指定器 :默认 */main*/master

    • 脚本路径关键设置,指定 Jenkinsfile 在仓库中的路径

脚本路径的详细说明:

"脚本路径" (Script Path) 字段中,需要告诉 Jenkins 在哪里找到 Jenkinsfile:

场景 脚本路径示例 说明
根目录下 Jenkinsfile Jenkinsfile 直接在仓库根目录
子目录下 ci/Jenkinsfile Jenkinsfile 在 ci 文件夹下
不同名称 Jenkinsfile.prod 使用非标准名称的流水线文件
多分支 Jenkinsfile 多分支流水线项目中每个分支可有不同的Jenkinsfile

假设项目结构如下:

my-java-app/

├── src/

├── pom.xml

└── Jenkinsfile ← 流水线定义文件

在Jenkins中的配置:

  1. 任务名称my-java-app-pipeline

  2. 流水线定义 :选择 "Pipeline script from SCM"

  3. SCMGit

  4. Repository URLhttps://github.com/yourname/my-java-app.git

  5. 凭据:添加GitHub访问令牌

  6. 分支*/main

  7. 脚本路径Jenkinsfile (保持默认)

对应的 Jenkinsfile 内容举例(无docker):

Groovy 复制代码
pipeline {
    agent any
    tools {
        maven 'Maven-3.8.6'  // 在Jenkins全局工具配置中定义的Maven版本
        jdk 'JDK-11'         // 在Jenkins全局工具配置中定义的JDK版本
    }
    
    stages {
        stage('Checkout') {
            steps {
                checkout scm  // 拉取代码
            }
        }
        
        stage('Build') {
            steps {
                sh 'mvn clean compile'
            }
        }
        
        stage('Test') {
            steps {
                sh 'mvn test'
            }
            post {
                always {
                    junit 'target/surefire-reports/*.xml'  // 归档测试报告
                }
            }
        }
        
        stage('Package') {
            steps {
                sh 'mvn package -DskipTests'
                archiveArtifacts artifacts: 'target/*.jar', fingerprint: true
            }
        }
    }
    
    post {
        always {
            echo "构建完成: ${currentBuild.fullDisplayName}"
        }
        success {
            emailext (
                subject: "SUCCESS: 构建 ${env.JOB_NAME} #${env.BUILD_NUMBER}",
                body: "构建成功!\n详情: ${env.BUILD_URL}",
                to: "dev-team@company.com"
            )
        }
        failure {
            emailext (
                subject: "FAILED: 构建 ${env.JOB_NAME} #${env.BUILD_NUMBER}",
                body: "构建失败,请检查!\n详情: ${env.BUILD_URL}",
                to: "dev-team@company.com"
            )
        }
    }
}

4.3 保存并运行

  1. 点击页面底部的 "保存" (Save)

  2. 返回项目页面,点击 "立即构建" (Build Now)

  3. 查看构建进度和日志

五、Jenkinsfile核心指令

指令/区块 是否必须 说明与示例
pipeline 声明流水线的根区块。
agent 指定整个流水线或特定阶段在哪个 Jenkins 节点上执行。常用选项有 any(任意可用节点)、label '节点标签' 或使用 docker 提供容器化环境。
stages 包含一个或多个 stage 指令的序列,定义了流水线的所有阶段。
stage 定义流水线中的一个具有明确职责的阶段,如构建、测试、部署。stages 内至少包含一个 stage
steps 在每个 stage 中定义具体要执行的命令序列。
environment 定义环境变量,可在流水线级别或阶段级别使用。支持使用 credentials() 方法安全地获取 Jenkins 中存储的密码等凭据。
parameters 定义流水线的参数,实现参数化构建。支持字符串、选择框、布尔值等类型。
options 配置流水线特有的选项,例如设置超时时间 timeout(time: 1, unit: 'HOURS')
post 根据流水线或阶段的最终状态执行附加操作。例如,无论成功失败都发送通知(always),仅在失败时发送警报(failure)。
triggers 定义流水线的自动触发条件,如定时构建 cron('0 8 * * 1-5') 或轮询 SCM。
相关推荐
RoboWizard2 小时前
移动固态硬盘插入电脑后提示“需要格式化”或“文件系统损坏”如何修复?
linux·运维·服务器
m0_619731193 小时前
linux配置数据库
linux·运维·数据库
正在努力的小河3 小时前
platform设备驱动实验
linux·运维·服务器
绛洞花主敏明4 小时前
全缓冲和行缓冲
linux·运维·服务器
文慧的科技江湖4 小时前
开源 | 充电桩 运维 管理平台(IoT+运维工单平台)功能清单 - 慧知开源充电桩平台
运维·分布式·物联网·机器人·开源·充电桩平台
xx.ii4 小时前
59.keepalived实现高可用
运维·nginx·负载均衡
hour_go4 小时前
BPEL:企业流程自动化的幕后指挥家
java·运维·自动化
^Lim4 小时前
Docker搭建ESPIDF环境,程序下载
运维·docker·容器