详细介绍:Jenkins:持续集成和持续交付(CI/CD)工具
目录
一、概念
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 工作流程
监听触发:Jenkins 会持续监听代码仓库(如 Git)的变动,一旦有新的代码提交,或者到达预设的时间点,它就会被触发开始工作。
拉取代码:从版本控制仓库拉取最新的源代码。
执行任务:按照预先定义好的“流水线”,一步步执行命令,常见步骤包括编译代码、运行测试、打包项目、进行代码质量检查以及部署到服务器等。
反馈结果:任务执行完成后,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 系统:
sudo apt update
sudo apt install openjdk-11-jdk
java -version # 验证安装
CentOS/RHEL 系统:
sudo yum install java-11-openjdk
版本选择:Jenkins 2.357 及更高版本需要 Java 11 或更高版本。建议选择 Java 11 或 Java 17 这些长期支持版(LTS)。
环境配置:设置 JAVA_HOME 环境变量,例如在 /etc/profile 文件中添加:
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 系统:
# 添加仓库密钥和源
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 系统:
# 添加仓库
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 并设置开机自启:
sudo systemctl start jenkins
sudo systemctl enable jenkins
2.2.2 方式二:通过 WAR 包安装(适合快速测试)
这种方式简单灵活,只需具备 Java 环境即可。
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 为例):
firewall-cmd --zone=public --add-port=8080/tcp --permanent
firewall-cmd --reload
访问 Jenkins:在浏览器中输入
http://<你的服务器IP地址>:8080即可访问 Jenkins 初始页面。
2.4 初始配置与插件管理
首次访问 Jenkins 时:
获取管理员密码:在服务器上执行
sudo cat /var/lib/jenkins/secrets/initialAdminPassword查看初始密码,并将其输入网页。选择插件安装方式:建议先“安装推荐的插件”。如果网络环境导致下载缓慢或失败,可以参考后续的“插件加速”部分进行配置后再安装。
由于网络原因,直接从 Jenkins 官方仓库下载插件可能很慢。可以切换至国内镜像源,例如清华大学镜像源。
登录 Jenkins 管理后台,进入 Manage Jenkins > Manage Plugins > Advanced。
在 Update Site 栏目中,将 URL 修改为:
https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json点击 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 git或apt install git。Maven:如果构建 Java Maven 项目,可以指定 Jenkins 自动安装特定版本,或手动指定已安装在服务器上的 Maven 路径。
Node.js:对于前端项目,可以在插件市场安装 NodeJS Plugin 后,在此处配置 Node.js 版本。
三、简单使用(自由风格项目)
3.1 基本任务创建
点击 Jenkins 首页的 新建任务(New Item)。
输入任务名称,例如
My-First-Project。选择任务类型,对于初学者,常见的类型有:
Freestyle project(自由风格项目):提供灵活的图形化配置界面,适合大多数简单场景。
Pipeline(流水线项目):使用代码(Jenkinsfile)来定义构建流程,更适合复杂、多阶段的 CI/CD 流程。
本例中选择 Freestyle project。
3.2 源码管理(Git)
在任务配置页面的 Source Code Management 部分:
选择 Git。
在 Repository URL 中输入 Git 仓库地址,例如
https://github.com/username/repo.git。如果仓库是私有的,需要配置凭据(Credentials)。点击 Add > Jenkins:
Kind 选择 “Username with password”。
输入 Git 用户名和密码(或 Personal Access Token)。
在 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,然后输入命令,例如:
# 前端项目示例
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 创建流水线任务
登录 Jenkins 控制台,点击首页左侧的 "新建任务" (New Item)
输入任务名称,例如
my-pipeline-project关键选择:在任务类型中选择 "流水线" (Pipeline)
点击 "确定"
4.2 配置流水线任务
进入任务配置页面后,找到 "流水线" (Pipeline) 部分,这里有几种定义流水线的方式:
方式一:直接编写脚本 (Pipeline script)
适用场景:快速测试、简单脚本、学习阶段
操作方法:在 "脚本" (Script) 文本框中直接粘贴或编写 Jenkinsfile 内容
示例:
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中的配置:
任务名称:
my-java-app-pipeline流水线定义:选择 "Pipeline script from SCM"
SCM:
GitRepository URL:
https://github.com/yourname/my-java-app.git凭据:添加GitHub访问令牌
分支:
*/main脚本路径:
Jenkinsfile(保持默认)
对应的 Jenkinsfile 内容举例(无docker):
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 保存并运行
点击页面底部的 "保存" (Save)
返回项目页面,点击 "立即构建" (Build Now)
查看构建进度和日志
五、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。 |
浙公网安备 33010602011771号