jenkins 是一个开源的自动化服务器,广泛用于持续集成(ci)和持续交付/部署(cd)流程。jenkins 通过使用 pipeline(流水线)脚本来定义和管理这些流程。pipeline 脚本可以用两种语法编写:declarative(声明式)和 scripted(脚本式)。以下是对这两种语法的详细解释和示例。
1. declarative pipeline(声明式流水线)
declarative pipeline 是一种更为结构化和易读的语法,适合大多数用户。它提供了一种简单的方式来定义流水线,并且内置了许多常用的功能。
基本结构
pipeline {
agent any
stages {
stage('build') {
steps {
echo 'building...'
}
}
stage('test') {
steps {
echo 'testing...'
}
}
stage('deploy') {
steps {
echo 'deploying...'
}
}
}
}
关键元素
- pipeline: 定义整个流水线的开始。
- agent: 指定在哪个节点上运行流水线。
any
表示可以在任何可用的节点上运行。 - stages: 包含一个或多个
stage
,每个stage
代表流水线中的一个阶段。 - stage: 定义流水线中的一个阶段,包含一个或多个
steps
。 - steps: 定义在每个阶段中执行的具体操作。
示例:带有条件和后处理的流水线
pipeline {
agent any
stages {
stage('build') {
steps {
echo 'building...'
}
}
stage('test') {
steps {
echo 'testing...'
}
}
stage('deploy') {
when {
branch 'main'
}
steps {
echo 'deploying...'
}
}
}
post {
always {
echo 'this will always run'
}
success {
echo 'this will run only if the pipeline succeeds'
}
failure {
echo 'this will run only if the pipeline fails'
}
}
}
2. scripted pipeline(脚本式流水线)
scripted pipeline 提供了更大的灵活性和控制力,但也更复杂。它使用 groovy 语言编写,适合需要复杂逻辑的高级用户。
基本结构
node {
stage('build') {
echo 'building...'
}
stage('test') {
echo 'testing...'
}
stage('deploy') {
echo 'deploying...'
}
}
关键元素
- node: 定义一个节点块,表示在某个节点上运行流水线。
- stage: 定义流水线中的一个阶段。
- echo: 打印消息到控制台。
示例:带有条件和后处理的流水线
node {
try {
stage('build') {
echo 'building...'
}
stage('test') {
echo 'testing...'
}
stage('deploy') {
if (env.branch_name == 'main') {
echo 'deploying...'
}
}
} catch (exception e) {
currentbuild.result = 'failure'
throw e
} finally {
if (currentbuild.result == 'success') {
echo 'this will run only if the pipeline succeeds'
} else {
echo 'this will run only if the pipeline fails'
}
echo 'this will always run'
}
}
3. 常用步骤和插件
常用步骤
- sh: 在 unix 系统上执行 shell 命令。
sh 'echo hello, world!'
- bat: 在 windows 系统上执行批处理命令。
bat 'echo hello, world!'
- checkout: 检出代码库。
checkout scm
- archiveartifacts: 存档构建产物。
archiveartifacts artifacts: '**/target/*.jar', allowemptyarchive: true
- junit: 发布 junit 测试结果。
junit 'reports/**/*.xml'
常用插件
- git plugin: 用于检出 git 代码库。
- pipeline plugin: 提供流水线功能。
- blue ocean plugin: 提供更友好的流水线可视化界面。
- email extension plugin: 用于发送构建通知邮件。
4. 高级特性
并行执行
pipeline {
agent any
stages {
stage('parallel stage') {
parallel {
stage('unit tests') {
steps {
echo 'running unit tests...'
}
}
stage('integration tests') {
steps {
echo 'running integration tests...'
}
}
}
}
}
}
参数化构建
pipeline {
agent any
parameters {
string(name: 'branch_name', defaultvalue: 'main', description: 'branch to build')
}
stages {
stage('build') {
steps {
echo "building branch ${params.branch_name}"
}
}
}
}
通过理解和使用这些语法和特性,您可以在 jenkins 中创建强大且灵活的 ci/cd 流水线,自动化构建、测试和部署过程。
5. 高级特性(续)
动态代理(dynamic agent)
在某些情况下,您可能需要动态地分配代理节点来运行流水线。declarative pipeline 支持动态代理配置。
pipeline {
agent {
label 'my-dynamic-agent'
}
stages {
stage('build') {
steps {
echo 'building on dynamic agent...'
}
}
}
}
环境变量
您可以在流水线中定义和使用环境变量。
pipeline {
agent any
environment {
my_var = 'hello, world!'
}
stages {
stage('build') {
steps {
echo "environment variable my_var is ${env.my_var}"
}
}
}
}
函数和共享库
为了重用代码,您可以在 scripted pipeline 中定义函数,或者使用共享库。
定义函数
def buildproject() {
echo 'building project...'
}
node {
stage('build') {
buildproject()
}
}
使用共享库
共享库允许您在多个流水线中重用代码。首先,您需要在 jenkins 配置中添加共享库,然后在流水线脚本中引用它。
@library('my-shared-library') _
pipeline {
agent any
stages {
stage('build') {
steps {
script {
mysharedlibrary.buildproject()
}
}
}
}
}
错误处理
在流水线中处理错误是确保构建过程健壮性的关键。
declarative pipeline
pipeline {
agent any
stages {
stage('build') {
steps {
script {
try {
sh 'exit 1' // 模拟一个错误
} catch (exception e) {
echo 'caught an error: ' + e.tostring()
}
}
}
}
}
}
scripted pipeline
node {
try {
stage('build') {
sh 'exit 1' // 模拟一个错误
}
} catch (exception e) {
echo 'caught an error: ' + e.tostring()
}
}
6. 实践中的 ci/cd 流水线示例
示例 1:简单的 java 项目流水线
pipeline {
agent any
tools {
jdk 'jdk11'
maven 'maven3'
}
stages {
stage('checkout') {
steps {
checkout scm
}
}
stage('build') {
steps {
sh 'mvn clean package'
}
}
stage('test') {
steps {
sh 'mvn test'
}
post {
always {
junit 'target/surefire-reports/*.xml'
}
}
}
stage('deploy') {
when {
branch 'main'
}
steps {
sh 'mvn deploy'
}
}
}
post {
always {
cleanws()
}
}
}
示例 2:带有 docker 的流水线
pipeline {
agent any
stages {
stage('checkout') {
steps {
checkout scm
}
}
stage('build docker image') {
steps {
script {
docker.build('my-app:latest')
}
}
}
stage('run tests') {
steps {
script {
docker.image('my-app:latest').inside {
sh 'mvn test'
}
}
}
}
stage('deploy') {
when {
branch 'main'
}
steps {
script {
docker.image('my-app:latest').push('my-repo/my-app:latest')
}
}
}
}
}
7. jenkinsfile 的最佳实践
版本控制
将 jenkinsfile 存储在项目的版本控制系统中(如 git),以便与项目代码一起进行版本管理。
参数化构建
使用参数化构建来增加流水线的灵活性。例如,可以通过参数化来选择构建的分支或环境。
pipeline {
agent any
parameters {
string(name: 'branch_name', defaultvalue: 'main', description: 'branch to build')
choice(name: 'environment', choices: ['dev', 'staging', 'prod'], description: 'deployment environment')
}
stages {
stage('build') {
steps {
echo "building branch ${params.branch_name} for environment ${params.environment}"
}
}
}
}
使用共享库
将常用的代码和步骤提取到共享库中,以便在多个流水线中重用。
错误处理和通知
在流水线中添加错误处理和通知步骤,以便在构建失败时及时通知相关人员。
pipeline {
agent any
stages {
stage('build') {
steps {
sh 'exit 1' // 模拟一个错误
}
}
}
post {
failure {
mail to: 'team@example.com',
subject: "build failed: ${env.job_name} #${env.build_number}",
body: "check the jenkins job: ${env.build_url}"
}
}
}
清理工作区
在流水线结束时清理工作区,以释放磁盘空间。
post {
always {
cleanws()
}
}
通过理解和应用这些语法和最佳实践,您可以在 jenkins 中创建高效、可靠的 ci/cd 流水线,自动化构建、测试和部署过程,从而提高开发和运维的效率。
8. 高级特性(续)
并行执行
在复杂的流水线中,您可能需要并行执行多个任务。jenkins pipeline 提供了并行执行的功能。
declarative pipeline
pipeline {
agent any
stages {
stage('parallel stage') {
parallel {
stage('unit tests') {
steps {
echo 'running unit tests...'
}
}
stage('integration tests') {
steps {
echo 'running integration tests...'
}
}
}
}
}
}
scripted pipeline
node {
stage('parallel stage') {
parallel unittests: {
echo 'running unit tests...'
}, integrationtests: {
echo 'running integration tests...'
}
}
}
动态参数
有时您可能需要在流水线运行时动态生成参数。可以使用 input
步骤来实现这一点。
pipeline {
agent any
stages {
stage('build') {
steps {
echo 'building...'
}
}
stage('approval') {
steps {
script {
def userinput = input(
id: 'userinput', message: 'deploy to production?', parameters: [
choice(name: 'deploy', choices: ['yes', 'no'], description: 'should we deploy?')
]
)
if (userinput == 'yes') {
echo 'deploying to production...'
} else {
echo 'skipping deployment...'
}
}
}
}
}
}
使用 docker
jenkins pipeline 可以与 docker 集成,以便在容器中运行构建和测试。
使用 docker 镜像
pipeline {
agent {
docker {
image 'maven:3.6.3-jdk-11'
args '-v /root/.m2:/root/.m2'
}
}
stages {
stage('build') {
steps {
sh 'mvn clean package'
}
}
}
}
构建和推送 docker 镜像
pipeline {
agent any
stages {
stage('checkout') {
steps {
checkout scm
}
}
stage('build docker image') {
steps {
script {
def app = docker.build("my-app:${env.build_id}")
}
}
}
stage('push docker image') {
steps {
script {
docker.withregistry('https://registry.hub.docker.com', 'docker-credentials') {
app.push('latest')
}
}
}
}
}
}
9. jenkinsfile 的最佳实践(续)
使用环境隔离
在流水线中使用 docker 容器或虚拟环境来隔离构建和测试环境,确保一致性和可重复性。
pipeline {
agent {
docker {
image 'python:3.8'
args '-v /root/.cache:/root/.cache'
}
}
stages {
stage('install dependencies') {
steps {
sh 'pip install -r requirements.txt'
}
}
stage('run tests') {
steps {
sh 'pytest'
}
}
}
}
使用缓存
在流水线中使用缓存来加速构建过程。例如,可以缓存 maven 或 npm 的依赖项。
pipeline {
agent any
stages {
stage('build') {
steps {
cache(path: '.m2/repository', key: 'maven-repo') {
sh 'mvn clean package'
}
}
}
}
}
使用凭据
在流水线中安全地使用凭据,例如 api 密钥或 ssh 密钥。
pipeline {
agent any
stages {
stage('checkout') {
steps {
withcredentials([sshuserprivatekey(credentialsid: 'ssh-key-id', keyfilevariable: 'ssh_key')]) {
sh 'git clone git@github.com:my-repo.git'
}
}
}
}
}
使用通知
在流水线中添加通知步骤,以便在构建完成或失败时通知相关人员。
pipeline {
agent any
stages {
stage('build') {
steps {
sh 'mvn clean package'
}
}
}
post {
success {
mail to: 'team@example.com',
subject: "build succeeded: ${env.job_name} #${env.build_number}",
body: "check the jenkins job: ${env.build_url}"
}
failure {
mail to: 'team@example.com',
subject: "build failed: ${env.job_name} #${env.build_number}",
body: "check the jenkins job: ${env.build_url}"
}
}
}
10. 实践中的 ci/cd 流水线示例(续)
示例 3:多分支流水线
多分支流水线可以自动为每个分支创建和运行流水线。
pipeline {
agent any
stages {
stage('checkout') {
steps {
checkout scm
}
}
stage('build') {
steps {
sh 'mvn clean package'
}
}
stage('test') {
steps {
sh 'mvn test'
}
post {
always {
junit 'target/surefire-reports/*.xml'
}
}
}
stage('deploy') {
when {
branch 'main'
}
steps {
sh 'mvn deploy'
}
}
}
post {
always {
cleanws()
}
}
}
示例 4:使用共享库的流水线
共享库可以帮助您在多个流水线中重用代码。
共享库代码(vars/mysharedlibrary.groovy)
def buildproject() {
echo 'building project...'
}
def runtests() {
echo 'running tests...'
}
jenkinsfile
@library('my-shared-library') _
pipeline {
agent any
stages {
stage('build') {
steps {
script {
mysharedlibrary.buildproject()
}
}
}
stage('test') {
steps {
script {
mysharedlibrary.runtests()
}
}
}
}
}
通过理解和应用这些高级特性和最佳实践,您可以在 jenkins 中创建更加高效、灵活和可靠的 ci/cd 流水线,进一步提升开发和运维的效率。
11. jenkins pipeline 的调试和优化
调试技巧
使用 echo
和 print
在流水线脚本中使用 echo
或 print
语句来输出调试信息。
pipeline {
agent any
stages {
stage('build') {
steps {
echo 'starting build...'
sh 'mvn clean package'
echo 'build completed.'
}
}
}
}
使用 sh
的返回值
可以捕获 sh
步骤的返回值来进行调试。
pipeline {
agent any
stages {
stage('build') {
steps {
script {
def result = sh(script: 'mvn clean package', returnstatus: true)
if (result != 0) {
echo 'build failed!'
} else {
echo 'build succeeded!'
}
}
}
}
}
}
使用 catcherror
catcherror
步骤可以捕获错误并继续执行流水线。
pipeline {
agent any
stages {
stage('build') {
steps {
catcherror(buildresult: 'success', stageresult: 'failure') {
sh 'mvn clean package'
}
}
}
}
}
性能优化
并行执行
通过并行执行步骤来减少流水线的总执行时间。
pipeline {
agent any
stages {
stage('parallel stage') {
parallel {
stage('unit tests') {
steps {
echo 'running unit tests...'
}
}
stage('integration tests') {
steps {
echo 'running integration tests...'
}
}
}
}
}
}
使用缓存
缓存依赖项和构建结果以加速后续构建。
pipeline {
agent any
stages {
stage('build') {
steps {
cache(path: '.m2/repository', key: 'maven-repo') {
sh 'mvn clean package'
}
}
}
}
}
使用轻量级检查
在多分支流水线中,使用轻量级检查来减少对 scm 的负载。
pipeline {
agent any
options {
skipdefaultcheckout()
}
stages {
stage('checkout') {
steps {
checkout scm
}
}
}
}
12. jenkins pipeline 的安全性
使用凭据
在流水线中使用 jenkins 的凭据管理器来安全地存储和使用敏感信息。
pipeline {
agent any
stages {
stage('checkout') {
steps {
withcredentials([sshuserprivatekey(credentialsid: 'ssh-key-id', keyfilevariable: 'ssh_key')]) {
sh 'git clone git@github.com:my-repo.git'
}
}
}
}
}
限制脚本执行权限
使用 sandbox
模式来限制流水线脚本的执行权限,防止恶意代码执行。
pipeline {
agent any
stages {
stage('build') {
steps {
script {
// 仅允许在 sandbox 模式下执行的代码
echo 'building project...'
}
}
}
}
}
使用安全的插件
确保使用的 jenkins 插件是最新的,并且来自可信的来源。定期检查和更新插件以修复已知的安全漏洞。
13. jenkins pipeline 的扩展
自定义步骤
您可以创建自定义步骤来扩展 jenkins pipeline 的功能。
自定义步骤示例
def call(string name) {
echo "hello, ${name}!"
}
使用自定义步骤
pipeline {
agent any
stages {
stage('greet') {
steps {
greet('world')
}
}
}
}
使用插件
jenkins 提供了大量的插件来扩展其功能。您可以在流水线中使用这些插件来实现更多的功能。
使用 pipeline utility steps
插件
pipeline {
agent any
stages {
stage('read json') {
steps {
script {
def json = readjson file: 'data.json'
echo "name: ${json.name}"
}
}
}
}
}
14. jenkins pipeline 的监控和维护
监控流水线
使用 jenkins 的内置监控工具和插件来监控流水线的执行情况。
使用 build monitor plugin
安装并配置 build monitor plugin
来实时监控流水线的状态。
定期维护
定期检查和维护 jenkins 实例和流水线,以确保其稳定性和性能。
清理旧的构建
定期清理旧的构建记录以释放磁盘空间。
pipeline {
agent any
stages {
stage('build') {
steps {
sh 'mvn clean package'
}
}
}
post {
always {
cleanws()
}
}
}
更新 jenkins 和插件
定期更新 jenkins 和插件以获取最新的功能和安全修复。
15. 总结
通过掌握 jenkins pipeline 的基本语法、高级特性、最佳实践以及调试和优化技巧,您可以创建高效、可靠的 ci/cd 流水线,自动化构建、测试和部署过程,从而提高开发和运维的效率。定期监控和维护 jenkins 实例和流水线,确保其稳定性和性能,进一步提升团队的生产力。
16. jenkins pipeline 的高级用法
动态生成阶段
在某些情况下,您可能需要根据条件动态生成阶段。可以使用 script
块来实现这一点。
pipeline {
agent any
stages {
stage('dynamic stages') {
steps {
script {
def stages = ['build', 'test', 'deploy']
stages.each { stagename ->
stage(stagename) {
echo "executing ${stagename} stage"
}
}
}
}
}
}
}
使用 groovy 进行复杂逻辑处理
jenkins pipeline 基于 groovy 语言,您可以利用 groovy 的强大功能来处理复杂的逻辑。
pipeline {
agent any
stages {
stage('complex logic') {
steps {
script {
def list = [1, 2, 3, 4, 5]
def sum = list.sum()
echo "sum of list: ${sum}"
}
}
}
}
}
使用外部脚本
可以将复杂的逻辑或重复的代码提取到外部脚本中,并在流水线中调用这些脚本。
外部脚本(scripts/myscript.groovy)
def call() {
echo 'executing external script...'
}
jenkinsfile
pipeline {
agent any
stages {
stage('execute script') {
steps {
script {
def myscript = load 'scripts/myscript.groovy'
myscript()
}
}
}
}
}
17. jenkins pipeline 的集成
集成 github
jenkins 可以与 github 集成,实现自动触发构建。
配置 github webhook
- 在 github 仓库中,导航到
settings
->webhooks
。 - 点击
add webhook
,输入 jenkins 的 url(例如http://your-jenkins-url/github-webhook/
)。 - 选择
application/json
作为内容类型,并选择要触发的事件(例如push
事件)。
jenkinsfile
pipeline {
agent any
stages {
stage('checkout') {
steps {
checkout scm
}
}
stage('build') {
steps {
sh 'mvn clean package'
}
}
}
}
集成 slack
jenkins 可以与 slack 集成,在构建完成或失败时发送通知。
安装和配置 slack 插件
- 在 jenkins 中,导航到
manage jenkins
->manage plugins
,安装slack notification
插件。 - 在
manage jenkins
->configure system
中,配置 slack 插件,输入 slack 工作区和凭据。
jenkinsfile
pipeline {
agent any
stages {
stage('build') {
steps {
sh 'mvn clean package'
}
}
}
post {
success {
slacksend(channel: '#build-notifications', message: "build succeeded: ${env.job_name} #${env.build_number}")
}
failure {
slacksend(channel: '#build-notifications', message: "build failed: ${env.job_name} #${env.build_number}")
}
}
}
集成 kubernetes
jenkins 可以与 kubernetes 集成,在 kubernetes 集群中运行构建和部署任务。
安装和配置 kubernetes 插件
- 在 jenkins 中,导航到
manage jenkins
->manage plugins
,安装kubernetes
插件。 - 在
manage jenkins
->configure system
中,配置 kubernetes 插件,输入 kubernetes 集群的连接信息。
jenkinsfile
pipeline {
agent {
kubernetes {
yaml """
apiversion: v1
kind: pod
spec:
containers:
- name: maven
image: maven:3.6.3-jdk-11
command:
- cat
tty: true
"""
}
}
stages {
stage('build') {
steps {
container('maven') {
sh 'mvn clean package'
}
}
}
}
}
18. jenkins pipeline 的高级调试
使用 catcherror
和 try-catch
在流水线中使用 catcherror
和 try-catch
来捕获和处理错误。
pipeline {
agent any
stages {
stage('build') {
steps {
catcherror(buildresult: 'success', stageresult: 'failure') {
sh 'mvn clean package'
}
}
}
}
}
使用 currentbuild
对象
currentbuild
对象提供了当前构建的详细信息,可以用于调试和控制构建流程。
pipeline {
agent any
stages {
stage('build') {
steps {
script {
try {
sh 'mvn clean package'
} catch (exception e) {
currentbuild.result = 'failure'
echo "build failed: ${e.message}"
}
}
}
}
}
}
使用 timestamps
在流水线中使用 timestamps
步骤来记录每个步骤的时间戳,便于调试和分析。
pipeline {
agent any
options {
timestamps()
}
stages {
stage('build') {
steps {
sh 'mvn clean package'
}
}
}
}
19. jenkins pipeline 的持续改进
定期回顾和优化
定期回顾和优化流水线,识别和解决瓶颈,提高效率。
例子
- 分析构建时间,识别耗时的步骤。
- 使用并行执行和缓存来优化构建时间。
- 定期更新和清理 jenkins 实例和插件。
自动化测试
为 jenkinsfile 编写自动化测试,确保流水线的稳定性和可靠性。
jenkins 是一个开源的自动化服务器,广泛用于持续集成(continuous integration, ci)和持续交付(continuous delivery, cd)流程。它帮助开发团队自动化构建、测试和部署软件项目,从而提高开发效率和软件质量。
以下是 jenkins 的一些关键特性和功能:
-
插件系统:jenkins 拥有丰富的插件生态系统,可以扩展其功能以满足各种需求。无论是与版本控制系统(如 git、svn)集成,还是与构建工具(如 maven、gradle)配合,jenkins 都有相应的插件支持。
-
易于配置:jenkins 提供了一个基于 web 的用户界面,用户可以通过该界面轻松配置和管理构建任务。它还支持通过配置文件(如 jenkinsfile)进行代码化配置。
-
分布式构建:jenkins 支持分布式构建,可以将构建任务分配到多个节点上运行,从而提高构建速度和资源利用率。
-
持续集成和持续交付:jenkins 可以自动化整个软件交付流程,从代码提交到生产环境部署,确保每次代码更改都经过严格的测试和验证。
-
通知和报告:jenkins 可以与各种通知系统集成,如电子邮件、slack 等,及时向团队成员发送构建状态和结果报告。
-
社区支持:作为一个开源项目,jenkins 拥有一个活跃的社区,提供了大量的文档、教程和支持资源。
总的来说,jenkins 是一个功能强大且灵活的工具,广泛应用于各种规模的软件开发项目中,帮助团队实现自动化和高效的开发流程。
jenkins 的主要职责可以归纳为以下几个方面:
-
持续集成(continuous integration, ci):
- 自动化构建:每当代码库发生变化时,jenkins 会自动触发构建任务,编译代码并生成可执行文件或软件包。
- 自动化测试:在构建完成后,jenkins 会自动运行单元测试、集成测试等,确保代码的正确性和稳定性。
- 代码质量检查:通过集成静态代码分析工具(如 sonarqube),jenkins 可以自动检查代码质量,发现潜在的问题和技术债务。
-
持续交付(continuous delivery, cd):
- 部署自动化:jenkins 可以自动将构建产物部署到不同的环境(如开发、测试、生产环境),确保每次部署过程一致且可重复。
- 发布管理:通过流水线(pipeline)功能,jenkins 可以定义和管理复杂的发布流程,包括审批、回滚等步骤。
-
分布式构建:
- 负载分担:jenkins 支持分布式构建,可以将构建任务分配到多个节点上运行,从而提高构建速度和资源利用率。
- 跨平台支持:jenkins 可以在不同操作系统和平台上运行构建任务,满足多样化的构建需求。
-
监控和报告:
- 构建状态监控:jenkins 提供实时的构建状态监控,用户可以通过 web 界面查看构建历史、日志和结果。
- 通知和报警:jenkins 可以与各种通知系统(如电子邮件、slack)集成,及时向团队成员发送构建状态和结果报告。
-
插件和扩展:
- 丰富的插件生态:jenkins 拥有大量的插件,可以扩展其功能以满足各种需求,如与版本控制系统、构建工具、测试框架、部署工具等集成。
- 自定义扩展:用户可以编写自定义插件或脚本,进一步扩展 jenkins 的功能。
-
安全和权限管理:
- 用户管理:jenkins 提供用户和角色管理功能,可以控制不同用户的访问权限。
- 安全配置:jenkins 支持多种安全配置选项,如 https、ldap 集成等,确保系统的安全性。
总的来说,jenkins 的主要职责是通过自动化和集成工具链,帮助开发团队实现高效、可靠的持续集成和持续交付流程,从而提高软件开发和交付的速度和质量。
发表评论