前言
今天来聊聊 Jenkins Pipeline
,即 CD 的流水线实现,相信对于运维、开发和测试,Jenkins 并不陌生,它实现了我们项目的拉取、构建、发布、构建后等一系列操作。对于传统的构建操作,这一系列操作需要各种点点点的操作,在面对数百上千台服务器的情况下,点点点操作就会显得力不从心。
于是衍生出了 Pipeline
工具,它是 Jenkins 的一个插件(需手动安装该插件),其主要特点为:
- 按序执行;
- Pull 仓库源码;
- 代码复查;
- 审计跟踪。
接下来先讲解一下基础语法,再通过一段实际的流水线脚本来实现 CD 功能。
一、语法结构
官方参考文档:https://www.jenkins.io/doc/
1.1 声明式
1、语法格式
pipeline {
agent any
stages {
stage('Build') {
steps {
//
}
}
stage('Test') {
steps {
//
}
}
stage('Deploy') {
steps {
//
}
}
}
}
2、功能说明
首先声明式语法有一个 pipeline {} 结构体,所有的阶段或步骤都需要再该结构体中执行,其底层基于 groovy
语言实现。
- agent:表示在哪个
节点
上执行流水线任务或使用哪些代理工具,any 表示任意。 - stages:表示
阶段
,一个 pipeline {} 结构体中只能有一个 stages {} 阶段。 - stage:表示
子阶段
,包含于 stages {} 中,可有多个 stage() {}。 - steps:表示
步骤
,包含于 stage() {} 中,只能有一个 steps {}。 - //:这里的双斜杠为注释,表示这部分的内容是 Jenkins 声明式流水线的具体实现。
也就是说声明式语法至少包含以上几个阶段和步骤才能实现。
1.2 脚本式
1、语法格式
node {
stage('Build') {
//
}
stage('Test') {
//
}
stage('Deploy') {
//
}
}
2、功能说明
首先声明式语法有一个 node {} 结构体,所有的阶段都需要再该结构体中执行,其底层同样基于 groovy
语言实现。注意,在脚本式语法中没有 steps
,仅通过 stage 即可实现。
- stage:表示
阶段
,stage() {} 用来实现具体的流水线功能。 - //:这里的双斜杠为注释,表示这部分的内容是 Jenkins 脚本式流水线的具体实现。
也就是说脚本式语法至少包含以上几个阶段和步骤才能实现。
二、应用实践
2.1 如何选择语法?
在实际应用场景中,通常会将两种语法格式结合使用,一般是在声明式语法中使用脚本式语法
,实现一种功能互补的效果。如果你的 CD 中存在较多的逻辑判断,可选择脚本式流水线脚本,否则首选声明式流水线脚本。
2.2 Spring Boot
本案以 Spring Boot 项目来实现流水线功能。
1、编写 Jenkinsfile
可通过 Blue Ocean、片段生成器和手动编写生成该文件,可上传至 Git 仓库进行版本管理。
def getHost(){
def remote = [:]
remote.name = "$SEV"
remote.host = "$SEV"
remote.user = "$UserName"
remote.port = xxxx
remote.password = "$PassWord"
remote.allowAnyHosts = true
return remote
}
pipeline {
agent {
docker {
image 'maven:3-alpine'
args '-v $HOME/.m2:/root/.m2'
}
}
parameters {
gitParameter (name: 'YOU_BRANCH',
type: 'PT_BRANCH_TAG',
branchFilter: 'origin/(.*)',
defaultValue: 'master',
selectedValue: 'DEFAULT',
sortMode: 'DESCENDING_SMART',
description: '请选择构建分支')
choice(name: 'YOU_SEV',
choices: ['xx.xx.xx.xx', 'xx.xx.xx.xx'],
description: '请选择远端服务器',)
extendedChoice(name: 'YOU_JOB',
description: '请选择需要发布的项目',
multiSelectDelimiter: ',',
quoteValue: false,
saveJSONParameterToFile: false,
type: 'PT_CHECKBOX',
value: 'all,a,b,c,d',
visibleItemCount: 10)
choice(name: 'YOU_ENV',
choices: ['test', 'pro'],
description: '请选择环境')
booleanParam(name: 'START',
defaultValue: 'false',
description: '构建后是否启动')
}
stages {
stage('pull代码') {
steps {
checkout([$class: 'GitSCM',
branches: [[name: "${params.BRANCH_TAG}"]],
doGenerateSubmoduleConfigurations: false,
extensions: [],
gitTool: 'Default',
submoduleCfg: [],
userRemoteConfigs: [[url: 'http://xxx/test/project.git',credentialsId: 'git',]]
])
}
}
stage("build所有包") {
when {
environment name: 'YOU_JOB', value: 'all'
}
steps {
sh 'mvn clean package -Dmaven.test.skip=true -P test'
}
}
stage("build指定包") {
when {
not {
environment name: 'YOU_JOB', value: 'all'
}
}
steps {
script {
for (pre_job in YOU_JOB.tokenize(',')){
//自动解决构建依赖问题
sh "&& mvn clean install -pl ${pre_job} -am -Dmaven.test.skip=true"
}
}
}
}
stage ("deploment") {
steps {
script {
for (p_name in YOU_JOB.tokenize(',')){
sshPut remote: server, from: "${WORKSPACE}/${p_name}/target/${p_name}.jar", into: "/opt/$ENV/${p_name}/", override: true
}
}
}
}
stage('start_project') {
steps {
script {
if ( START == 'true' ) {
for (p_item in YOU_JOB.tokenize(',')){
withCredentials([usernamePassword(credentialsId: 'Test-Platform', passwordVariable: 'PassWord', usernameVariable: 'UserName')]){
script {
def remote = [:]
remote.name = "$SEV"
remote.host = "$SEV"
remote.user = "$UserName"
remote.port = xxxx
remote.password = "$PassWord"
remote.allowAnyHosts = true
// 执行启动脚本(启动指定项目)
sshCommand remote: remote, command: "sudo sh start.sh"
}
}
}
} else {
echo '手动启动'
}
}
}
}
}
}
场景:根项目有多个子项目
实现功能:
- 构建:所有项目、指定项目;
- 启动:构建完成后自动启动、构建完成后手动启动。
2、新建流水线工程项目
3、添加流水线脚本
将上面生成的流水线脚本复制粘贴到下框中。
4、最后点击构建
三、总结
1、语法选择:声明式、脚本式结合使用
2、构建:参数化、多(单)项目构建
3、脚本管理:如上图,直接写入脚本即可,当然也可以通过 Git 进行版本管理,如下图所示: