一、Pipeline介绍
Pipeline流水线,其实就是将之前的一个任务或者一个脚本就做完的工作,用Pipeline语法划分为多个子任务然后分别执行。二者实现的最终效果是一样的,但是由于原始任务划分为多个子任务之后,以流水线的方式来执行,那么就可以随时查看任意子任务的执行效果,即使在某个阶段出现问题,也可以随时直接定位问题的发生点。
Pipeline基于Groovy DSL(领域特定语言Domain Specific Language )实现,任何发布流程都可以表述为 一段Groovy脚本。
Groovy是一种基于JVM虚拟机的敏捷开发语言,它结合了Python、Ruby和Smalltalk的许多强大的特性,Groovy 是用Java写的,Groovy语法与Java语法类似, Groovy 代码不仅能够与 Java 代码很好地结合,也能用于扩展现有代码。由于其运行在 JVM 上的特性,Groovy也可以使用其他非Java语言编写的库
二、Pipeline优势
- 一致性: pipeline 用统一语法的代码的方式实现各个CICD的阶段的任务,不仅可以被纳入版本控制,还可以通过编辑代码实现目标效果
- 直观性: 构建过程中每一步都可以直接的图形化显示输出,比如每个阶段的执行时间,直观友好,pipeline 帮助我们快速的定位哪个阶段的任务出现错误
- 可持续性:jenkins的重启或者中断后不影响已经执行的pipeline Job
- 支持暂停:pipeline可以选择停止并等待人工输入或批准后再继续执行
- 支持回放: 如果失败,可以使用回放,进行临时性的修改 job,再调试执行,如果成功,再真正修改任务即可
- 可扩展:通过groovy的编程更容易的扩展插件
- 并行执行:通过groovy脚本可以实现step,stage间的并行执行,和更复杂的相互依赖关系
- 多功能:支持复杂CD要求,包括fork/join子进程,条件判断,循环和并行执行工作的能力
三、Pipeline语法
3.1 Pipeline语法介绍&结构
当前 Jenkins 2.X 支持两种语法的流水线:声明式和脚本式
- 脚本式Scripted Pipeline语法: 此语法是 Jenkins最先支持pipeline语法,它采用命令式风格,直接在流水线脚本中定义逻辑和程序流程
- 声明式Declarative Pipeline语法:后来CloudBees公司为Jenkins引入的一种“流水线即代码”的 pipeline语法,它允许用户在pipeline的定义中将更多的精力关注于期望pipeline的状态和输出之上,而非实现逻辑
3.1.1 Pipeline的基本结构
- Pipeline:流水线的最外层结构,代表整条pipeline,包含着pipeline的完整逻辑;是声明式流水线语法的关健特征
- node和agent:用于定义任务在哪里执行.每个node都是一个 Jenkins 节点,可以是 Jenkins master也可以是 Jenkins agent,node是执行 step的具体服务器。node 代码块也是脚本式pipeline语法的关健特性,声明式pipeline使用agent关健字
- stages:用于包含所有stage的定义
- stage:指定 stage 的名称, 用于定义每个阶段 stage 的主要任务.一个pipeline可以划分为若干个stage,每个stage都是一个完整的操作,比如: clone代码、代码编译、代码测试和代码部署,阶段是一个逻辑分组,可以跨多个node执行。
- steps:每个阶段stage需要执行哪些命令.步骤 steps 是jenkins pipeline最基本的操作单元,从在服务器创建目录到构建容器镜像,由各类 Jenkins 插件提供实现,例如: sh “make”
- post:用在stages代码块或整个pipeline执行完成后的附加步骤,此指令非必须项
3.1.2 常用指令
无论是脚本式语法还是声明式语法,他们本质上都是执行各种命令,对于不同的命令需要采用专用的语法来实现指定的功能,常见的语法命令及其样式如下:
- echo: 输出信息,echo "Building"
- sh: 执行命令,sh 'command' sh([script: 'echo hello'])
- git: 克隆代码,git branch: 'main', credentialsId: 'd532ca28-c238-432c-97c3-a001f45f0aaf', url: '[email protected]:dev1/hello-world-war.git'
- env: 设置变量, env.PATH="/usr/local/java/bin:$PATH"
3.1.3 Jenkins内置语法帮助
http://jenkins-server:8080/job/工程名/pipeline-syntax/
#注意:需要安装pipeline插件并且是pipeline风格的任务
3.2 脚本式流水线语法
node {
stage('Source') {
//
}
stage('Build') {
//
}
stage('Test') {
//
}
stage('Deploy') {
//
}
}
3.3 声明式流水线语法
所有有效的声明式流水线必须包含在一个 pipeline 块中, 比如:
pipeline {
/* insert Declarative Pipeline here */
}
Pipeline 的声明式语法要点
- steps内部的命令,每一条单独的命令都在当前任务的工作目录下执行。 即使A命令切换到了一个新的目录,接下来的B命令并不会在对应的新目录中执行,而是在当前任务 的工作目录下执行。如果非要在切换后的目录下执行命令B,那么采用shell中的&&符号将多条命令拼接在一起即可。
- 默认情况下,不支持shell里面的复杂语法,因为groovy有自己的条件表达式
- 如果jenkins的工作目录下存在同名目录,则获取失败
基本语法
pipeline {
agent any
stages {
stage('获取代码') {
steps {
echo '获取代码'
}
}
stage('构建代码') {
steps {
echo '构建项目代码'
}
}
stage('代码测试') {
steps {
echo '测试项目功能'
}
}
stage('项目部署') {
steps {
echo '部署项目'
}
}
}
}
四、安装插件
安装 Pipeline 和 Pipeline Stage View 插件
五、脚本式Pipeline实战
这里就用hello-world-war项目
Pipeline script的内容如下:
node {
stage("clone代码"){
git branch: 'main', credentialsId: 'd532ca28-c238-432c-97c3-a001f45f0aaf', url: '[email protected]:dev1/hello-world-war.git'
}
stage("代码复制"){
sh 'ssh 192.168.1.105 "rm -rf /var/lib/tomcat9/webapps/*"'
sh 'scp -r /var/lib/jenkins/workspace/hello-world-war/* 192.168.1.105:/var/lib/tomcat9/webapps/'
}
stage("停止tomcat服务"){
sh 'ssh 192.168.1.105 "systemctl stop tomcat9"'
}
stage("启动tomcat服务"){
sh 'ssh 192.168.1.105 "systemctl start tomcat9"'
}
}
项目构建效果如下:
六、声明式Pipeline实战
这里用Spring Boot Helloworld项目。
在声明式Pipeline中,steps 内部的命令,每一条单独的命令都在当前任务的工作目录下执行。
之前是选择Pipeline script在那里直接写脚本内容,但是当脚本内容过多时,如果项目运行出现问题,要想检查脚本内容就非常麻烦,不便于维护。因此可以使用Jenkinsfile的形式去运行项目。
在项目目录中新建Jenkinsfile文件,内容即为声明式Pipeline的内容:
pipeline {
agent any
tools {
#这里的配置跟Jenkins全局配置有关系
maven 'maven-3.6.3'
}
stages {
stage('code clone') {
steps {
git branch: 'main', credentialsId: 'd532ca28-c238-432c-97c3-a001f45f0aaf', url: '[email protected]:dev1/spring-boot-helloWorld.git'
}
}
stage('Build') {
steps {
sh 'mvn clean package -Dmaven.test.skip=true'
}
}
stage("停止spring boot服务"){
steps {
sh 'ssh 192.168.1.105 "killall -0 java && killall -9 java"'
}
}
stage("代码复制"){
steps {
sh 'scp target/spring-boot-helloworld-*.jar 192.168.1.105:/data/'
}
}
stage("启动spring boot服务"){
steps {
sh 'ssh 192.168.1.105 "nohup java -jar /data/spring-boot-helloworld-0.9.0-SNAPSHOT.jar --server.port=8888 &>/dev/null & "'
}
}
}
}
将更新的内容再提交
git add .;git commit -m "jenkinsfile";git push origin main
修改Pipeline使用Jenkinsfile文件,注意使用SCM 软件配置管理(Software Configuration Management)选项
构建效果如下: