5

devops学习笔记-jenkins pipeline流水线发布

 1 year ago
source link: https://blog.51cto.com/u_11555417/5738107
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

jenkins pipeline

要实现CD,先要实现CI。CD Pipeline就是一个代码文件,里面把你项目业务场景都通过Groovy代码和Pipeline语法实现,一个一个业务串联起来,全部实现自动化,从代码仓库到生产环境完成部署的自动化流水线。这个过程就是一个典型的CD Pipeline。官网建议我们把Pipeline代码放在一个名称为Jenkinsfile的文本文件中,并且把这个文件放在项目代码的根目录,采用版本管理工具管理。

一个Jenkinsfile或者一个Pipeline代码文件,我们可以使用两个脚本模式去写代码,这两种分类叫:Declarative Pipeline 和 Scripted Pipeline.

​Declarative相对于Scripted有两个优点。

1)、第一个是提供更丰富的语法功能;

2)、第二个是写出来的脚本可读性和维护性更好;​

jenkins是一个非常著名的CI服务器平台,支持很多不同第三方(插件的形式)集成自动化测试。Jenkins UI 配置已经满足不了这么复杂的自动化需求,加入Pipeline功能之后,Jenkins 表现更强大。

​Pipeline主要有一下特点

  • Code代码:Pipeline是用代码去实现,并且支持check in到代码仓库,这样项目团队人员就可以修改,更新Pipeline脚本代码,支持代码迭代。
  • Durable耐用:Pipeline支持在Jenkins master(主节点)上计划之内或计划外的重启下也能使用。
  • Pausable可暂停:Pipeline支持可选的停止和恢复或者等待批准之后再跑Pipeline代码。
  • Versatile丰富功能:Pipeline支持复杂和实时的CD需求,包括循环,拉取代码,和并行执行的能力。
  • Extensible可扩展性:Pipeline支持DSL的自定义插件扩展和支持和其他插件的集成。

jenkins pipline流程图

devops学习笔记-jenkins pipeline流水线发布_docker

​第1步.开发(IDE)提交代码到项目仓库服务器(gitlab);

第2步.jenkins开始执行Pipeline代码文件,开始从(gitlab)仓库git clone代码;

第3步.jenkins启动Pipeline里面第一个stage(阶段);

第4步.图里面第一个Stage从仓库检出(Checkout)代码;

第5步.接着进入第二Stage构建(Build)检出的代码;

第6步.然后进入测试(Test)的阶段,执行各种自动化测试验证;

第7步.然后测试结束,到运维的部署(Deploy)阶段;

第8步.部署结束,输出报告,整个自动化流程工作完成;

等待触发构建,开始重复下一轮1到8步骤。

jenkins pipline概念

  • 流水线pipline

流水线是用户定义的一个CD流水线模型 。流水线的代码定义了整个的构建过程, 他通常包括构建, 测试和交付应用程序的阶段 。

  • 节点(node)

节点是一个机器,它是jenkins环境的一部分。

  • 阶段(stage)

stage 块定义了在整个流水线的执行任务的概念性地不同的的子集(比如 "Build", "Test" 和 "Deploy" 阶段), 它被许多插件用于可视化 或Jenkins流水线目前的 状态/进展.

  • 步骤(step)

step为一个单一任务,它告诉jenkins在待定的时间点要做什么

pipline流水线语句说明

在声明式流水线语法中, pipeline 块定义了整个流水线中完成的所有的工作。

Jenkinsfile (Declarative Pipeline)
pipeline {
agent any //在任何可用的代理上,执行流水线或者它的任何阶段
stages {
stage('Build') { //定义Build阶段
steps {
// 执行Build阶段的相关步骤
}
}
stage('Test') { //定义Test阶段
steps {
// 执行Test阶段的相关步骤
}
}
stage('Deploy') { //定义Deploy阶段
steps {
// 执行deploy阶段的相关步骤
}
}
}
}

关于流水线的具体语法,参考官方手册​ ​https://www.jenkins.io/zh/doc/book/pipeline/syntax/​

jenkins上使用pipeline

在我之前的jenkins上,使用pipeline方式重新建立一个ITEM。

流程如下:

devops学习笔记-jenkins pipeline流水线发布_服务器_02

1 拉取gitlab仓库代码

2 通过mvn构建项目

3 通过sonarqube做代码质量检测,本次实验暂时不涉及。

4 通过docker制作自定义镜像

5 将自定义镜像推送到harbor仓库,此时需要编写一个脚本,来判断镜像容器是否存在

准备jenkinsfile

在gitlab上,新增一个Jenkinsfile,注意大小写,不然jenkins识别不到。也可以通过IDE的VCS版本控制将编写好的Jenkinsfile推送到gitlab中。

devops学习笔记-jenkins pipeline流水线发布_服务器_03
devops学习笔记-jenkins pipeline流水线发布_docker_04

Jenkinsfile准备好的文件内容如下,当前指明步骤,没有填充步骤的详细内容。pipline脚本的语法基本上跟groovy一致。

//所有的脚本命令都放在pipeline中
pipeline {
//指定任务在哪个集群节点中执行
agent any

//申明全局变量,后期使用
environment {
key ='value'
}
stages {
stage('拉取git仓库代码') {
steps {
echo '拉取git仓库代码-SUCCESS'
}
}
stage('通过maven构建项目') {
steps {
echo '通过maven构建项目-SUCCESS'
}
}
stage('通过SonarQube做代码质量检测') {
steps {
echo '通过SonarQube做代码质量检测-SUCCESS'
}
}
stage('通过docker制作自定义镜像') {
steps {
echo '通过docker制作自定义镜像-SUCCESS'
}
}
stage('将自定义镜像推送到Harbor') {
steps {
echo '将自定义镜像推送到Harbor-SUCCESS'
}
}
stage('通过Publish Over SSH 通知目标服务器') {
steps {
echo '通过Publish Over SSH 通知目标服务器-SUCCESS'
}
}
}

}

完成简单Jenkinsfile编写后,在gitlab上保存即可。

jenkins上新建pipeline

在jenkins上新建一个ITEM,名称为mytest3。

devops学习笔记-jenkins pipeline流水线发布_docker_05

job类型选择Pipeline

devops学习笔记-jenkins pipeline流水线发布_docker_06

勾选"This project is parameterized",添加git参数,如下所示:

devops学习笔记-jenkins pipeline流水线发布_git_07

名称为tag,这个参数将作为jenkins的全局参数使用。参数类型为表标签,代表从gitlab使用不同的标签拉取代码。默认值为origin/master,代表默认从gitlab的master分支拉取代码。

配置流水线

找到pipeline选项卡,按照如下填写:

devops学习笔记-jenkins pipeline流水线发布_服务器_08

1.推荐使用 Pipeline script from SCM,代表从gitlab上读取jenkinsfile;

2.需要填写正确的gitlab仓库地址和账号密码,同时要确保gitlab上仓库中的根目录要存在Jenkinsfile

3.指定在gitlab仓库中jenkinsfile的目录路径和文件名称。

点击应用保存,完成流水线配置。

测试流水线

因为的我们的jenkinsfile中虽然写明了构建步骤,但是没有写构建步骤的内容与动作,我们可以先测试下目前流水线是否能够正常构建。

devops学习笔记-jenkins pipeline流水线发布_docker_09

构建完成后,我们等清楚的看到每个流水线步骤执行结果,花费时间等,看能看到每个步骤的日志。

devops学习笔记-jenkins pipeline流水线发布_服务器_10

注意,流水线步骤是串行顺序执行,如果前一个步骤执行报错失败,那么后面的步骤将不会执行。

配置流水线步骤

完成流水线的基本结构的jenkinsfile编写和测试后,需要按照之前的构建步骤填写jenkinsfile中步骤。

由于我们的执行步骤都是在jenkins上或者目标服务器上执行脚本或者使用插件动作,所以我们需要使用jenkins的流水线语法工具,将我们定义的步骤转换为jenkins的流水线步骤语法。

devops学习笔记-jenkins pipeline流水线发布_服务器_11
devops学习笔记-jenkins pipeline流水线发布_服务器_12

定义全局变量

使用environment定义全局变量,这些变量可以给后面的pipeline脚本的调用。

//申明全局变量,后期使用
environment {
user_name='user' //harbor仓库用户名
harbor_password='Harbor12345' //harbor仓库密码
harbor_addr='192.168.85.3:8090' //harbor仓库地址
harbor_repo='test' // harbor仓库名称
container_port='8080' //容器暴露端口
host_port='8092' //宿主机暴露端口
}

拉取git代码

在示例步骤中选择"checkout:Check out from version control",表示jenkins从gitlab拉取代码。

devops学习笔记-jenkins pipeline流水线发布_git_13

填写完成后,点击生成流水线脚本。将生成的流水线脚本,添加补充到我们的jenkinsfile对应的步骤中。

stage('拉取git仓库代码') {
steps {
checkout([$class: 'GitSCM', branches: [[name: '${tag}']], extensions: [], userRemoteConfigs: [[credentialsId: 'fc7dffd0-2911-45da-ba46-7a9f7e00a41a', url: 'http://192.168.85.6/root/mytest.git']]]) //此处为流水线脚本生成
echo '拉取git仓库代码-SUCCESS'
}
}

通过maven构建项目

同样使用流水线语法生成脚本,不过这次使用”sh:Shell Script"方式,表示在jenkins上使用maven构建打包并生成的jar包。

/usr/local/apache-maven-3.8.6/bin/mvn clean package -DskipTest #mvn打包命令
devops学习笔记-jenkins pipeline流水线发布_服务器_14

将生成的流水线语法添加到jenkinsfile中。

stage('通过maven构建项目') {
steps {
sh '/usr/local/apache-maven-3.8.6/bin/mvn clean package -DskipTest'
echo '通过maven构建项目-SUCCESS'
}

通过SonarQube代码检测

本次流水线配置不涉及此处(我没想好。。。。)

通过docker制作自定义镜像

在jenkins上,将maven构建jar包移动到docker目录下,然后使用docker命令构建镜像。

mv target/*.jar ./docker/ #将jenkins中target目录生成的jar包移动到当前docker目录下
docker build -t ${JOB_NAME}:${tag} ./docker/ #docker构建镜像,${JOB_NAME}为jenkins
#全局变量,本次为mytest3
# ${tag}为jenkins自定义git参数,读取gitlab
#仓库中的tag

使用流水线语法生成脚本

devops学习笔记-jenkins pipeline流水线发布_服务器_15

将生成的流水线脚本添加到jenkinsfile中

stage('通过docker制作自定义镜像') {
steps {
sh '''mv target/*.jar ./docker/
docker build -t ${JOB_NAME}:${tag} ./docker/'''
echo '通过docker制作自定义镜像-SUCCESS'
}
}

将自定义镜像推送的到Harbor

采用shell脚本的方式,登录harbor仓库,本地打上镜像标签,将制作的docker镜像推送到harbor仓库

docker login -u ${user_name} -p ${harbor_password} ${harbor_addr} #变量为前面enivronment定义的全局变量
docker tag ${JOB_NAME}:${tag} ${harbor_addr}/${harbor_repo}/${JOB_NAME}:${tag} #${JOB_NAME}为jenkins内置的全局变量
docker push ${harbor_addr}/${harbor_repo}/${JOB_NAME}:${tag} #${tag}为自定义git参数的变量

使用流水线语法生成脚本

devops学习笔记-jenkins pipeline流水线发布_docker_16

将生成的脚本添加到 jenkinsfile中。

stage('将自定义镜像推送到Harbor') {
steps {
sh '''docker login -u ${user_name} -p ${harbor_password} ${harbor_addr}
docker tag ${JOB_NAME}:${tag} ${harbor_addr}/${harbor_repo}/${JOB_NAME}:${tag}
docker push ${harbor_addr}/${harbor_repo}/${JOB_NAME}:${tag}'''
echo '将自定义镜像推送到Harbor-SUCCESS'
}
}

通过publish over ssh通知目标服务器

需要通过jenkins的publish over ssh插件,通知目标服务器从harbor行拉取镜像运行容器。拉取镜像和运行容器,要满足以下逻辑:

  • 告知目标服务器拉取哪个镜像
  • 判断当前服务器是否正在运行容器,有的话需要删除
  • 如果目标服务器已经存在当前镜像,有的话需要删除
  • 目标服务器拉取harbor上的镜像
  • 将拉取下来的镜像运行成容器

编写shell脚本,并将脚本传输到目标服务器上,由于是实验环境,目标服务器和jenkins其实就是一台机器,所以不用将脚本文件传送。

vim deploy.sh

#!/usr/bin/bash
#script_name:deploy.sh
#部署脚本
#1.告知目标服务器拉取哪个镜像
#2.判断当前服务器是否正在运行容器,需要删除
#3.如果目标服务器已经存在当前镜像,需要删除
#4.目标服务器拉取harbor上的镜像
#5.将拉取下来的惊醒运行成容器
#定义部署信息参数

harbor_addr=$1
harbor_repo=$2
project=$3
version=$4
host_port=$5
container_port=$6

#测试部署的信息
ImageName=${harbor_addr}/${harbor_repo}/${project}:${version}
echo ${ImageName}

#判断当前服务器上是否存在docker镜像,存在则停止并删除容器
ContainerId=$(docker ps -a | grep ${project} | awk '{print $1}')
echo ${ContainerId}
ImageId=$(docker images | grep ${harbor_addr}/${harbor_repo}/${project} | awk '{print $3}')

if [ "${ContainerId}" != "" ];then
docker stop ${ContainerId}
docker rm ${ContainerId}
fi


#Image=$( docker images | grep ${harbor_addr}/${harbor_repo}/${project} | awk '{print $1":"$2}')
Tag=$( docker images | grep ${project} | awk '{print $2}')

echo ${Tag}

#判断版本,如果存在当前版本,则删除该版本的镜像
if [[ "${Tag}" =~ "${version}" ]] ;then #判断是否包含版本
docker rmi -f ${ImageId} #如果存在当前版本,则删除镜像
fi

docker login -u user -p Harbor12345 ${harbor_addr} #登录harbor仓库
docker pull ${ImageName} #拉取镜像

#运行镜像
docker run -d -p ${host_port}:${container_port} --name ${project} ${ImageName}

echo "SUCESS!!"

在本地测试脚本,保证脚本运行没有问题。

devops学习笔记-jenkins pipeline流水线发布_docker_17

在流水线语法中,使用”sshPublisher:Send build artifacts over SSH",生成脚本

cd /root/jenkins_shell/ && sh -x deploy.sh ${harbor_addr} ${harbor_repo} ${JOB_NAME} ${tag} ${host_port} ${container_port} #执行脚本,脚本参数使用前面environment定义的全局变量
devops学习笔记-jenkins pipeline流水线发布_服务器_18

以下为生成的脚本:

devops学习笔记-jenkins pipeline流水线发布_docker_19

注意要将生成的脚本中的'''符号改为“, 不然脚本无法通过jenkins去执行

sshPublisher(publishers: [sshPublisherDesc(configName: 'localhost', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: ”cd /root/jenkins_shell/ && sh -x deploy.sh ${harbor_addr} ${harbor_repo} ${JOB_NAME} ${tag} ${host_port} ${container_port}“, execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])

将生成的脚本添加到jenkinsfile中。

stage('通过Publish Over SSH 通知目标服务器') {
steps {
sshPublisher(publishers: [sshPublisherDesc(configName: 'localhost', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "cd /root/jenkins_shell/ && sh -x deploy.sh ${harbor_addr} ${harbor_repo} ${JOB_NAME} ${tag} ${host_port} ${container_port}", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
echo '通过Publish Over SSH 通知目标服务器-SUCCESS'
}
}

最终的jenkinsfile

完成了以上的步骤后,最终的jenkinsfile内容如下:

//所有的脚本命令都放在pipeline中
pipeline {
//指定任务在哪个集群节点中执行
agent any

//申明全局变量,后期使用
environment {
user_name='user'
harbor_password='Harbor12345'
harbor_addr='192.168.85.3:8090'
harbor_repo='test'
container_port='8080'
host_port='8092'
}
stages {
stage('拉取git仓库代码') {
steps {
checkout([$class: 'GitSCM', branches: [[name: '${tag}']], extensions: [], userRemoteConfigs: [[credentialsId: 'fc7dffd0-2911-45da-ba46-7a9f7e00a41a', url: 'http://192.168.85.6/root/mytest.git']]])
echo '拉取git仓库代码-SUCCESS'
}
}
stage('通过maven构建项目') {
steps {
sh '/usr/local/apache-maven-3.8.6/bin/mvn clean package -DskipTest'
echo '通过maven构建项目-SUCCESS'
}
}
stage('通过SonarQube做代码质量检测') {
steps {
//不好弄
echo '通过SonarQube做代码质量检测-SUCCESS'
}
}
stage('通过docker制作自定义镜像') {
steps {
sh '''mv target/*.jar ./docker/
docker build -t ${JOB_NAME}:${tag} ./docker/'''
echo '通过docker制作自定义镜像-SUCCESS'
}
}
stage('将自定义镜像推送到Harbor') {
steps {
sh '''docker login -u ${user_name} -p ${harbor_password} ${harbor_addr}
docker tag ${JOB_NAME}:${tag} ${harbor_addr}/${harbor_repo}/${JOB_NAME}:${tag}
docker push ${harbor_addr}/${harbor_repo}/${JOB_NAME}:${tag}'''
echo '将自定义镜像推送到Harbor-SUCCESS'
}
}
stage('通过Publish Over SSH 通知目标服务器') {
steps {
sshPublisher(publishers: [sshPublisherDesc(configName: 'localhost', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "cd /root/jenkins_shell/ && sh -x deploy.sh ${harbor_addr} ${harbor_repo} ${JOB_NAME} ${tag} ${host_port} ${container_port}", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
echo '通过Publish Over SSH 通知目标服务器-SUCCESS'
}
}
}

}

在gitlab上编写jenkinsfile的时候,有时候它会自动换行,添加不必要的换行符\n,从而导致jenkins读取报错。可以尝试用以下方式避免。

devops学习笔记-jenkins pipeline流水线发布_服务器_20

运行pipeline

完成jenkinsfile的编写后,在jenkins运行构建。如下所示:

devops学习笔记-jenkins pipeline流水线发布_docker_21
devops学习笔记-jenkins pipeline流水线发布_服务器_22
devops学习笔记-jenkins pipeline流水线发布_docker_23

构建输出日志

devops学习笔记-jenkins pipeline流水线发布_docker_24

流水线构建成功

devops学习笔记-jenkins pipeline流水线发布_git_25

harbor上检查效果

检查harbor上是否完成上传了镜像

devops学习笔记-jenkins pipeline流水线发布_服务器_26
devops学习笔记-jenkins pipeline流水线发布_git_27
devops学习笔记-jenkins pipeline流水线发布_docker_28

确认通过流水线,jenkins生成镜像并上传到harbor

目标服务器上检查效果

devops学习笔记-jenkins pipeline流水线发布_服务器_29
devops学习笔记-jenkins pipeline流水线发布_服务器_30

目标服务器上确认了从docker拉取了镜像,并生成了容器运行。

devops学习笔记-jenkins pipeline流水线发布_服务器_31

确认容器业务征程运行。

1 pipeline流水线语法有一定的学习曲线,需要不停参考官方指导才能指导。

2 官方提供了pipeline构建流程参考示例,需要耐心研究。

3 实现生产上jenkins,sonarqube,harbor等最好不要用容器化部署,不太容易与jenkins集成,本次没有配置sonarqube代码检测,也是这个原因


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK