在前一章我们实现了不同版本快速进行交付,但我们如果不选择分支直接构建就会报错了
我们前面构建镜像的时候选择的是以tag标签作为镜像的版本信息,当我们没有选择任何标签时,他会根据我们配置的默认值origin/master 主分支去构建,这样一来我们就要走两条路 master和tag版本,我们在构建镜像和部署/更新的任务中添加条件分支
stage('4、通过jenkins主机构建docker镜像') {
steps() {
echo '通过jenkins主机构建docker镜像 - SUCCESS'
script{
if ("${tag}" == "origin/master" ){
sh '''mv ./target/*.jar docker/
docker build -t "${JOB_NAME}:latest" ./docker/
docker login ${harborAddress} -u${harborUser} -p${harborPasswd}
docker tag ${JOB_NAME}:latest ${harborAddress}/${harborRepo}/${JOB_NAME}:latest
docker push ${harborAddress}/${harborRepo}/${JOB_NAME}:latest'''
}
else{
sh '''mv ./target/*.jar docker/
docker build -t "${JOB_NAME}:${tag}" ./docker/
docker login ${harborAddress} -u${harborUser} -p${harborPasswd}
docker tag ${JOB_NAME}:${tag} ${harborAddress}/${harborRepo}/${JOB_NAME}:${tag}
docker push ${harborAddress}/${harborRepo}/${JOB_NAME}:${tag}'''
}
}
}
}
stage('5、发送Chart包到K8master主机 通过helm部署, 这里多写了个第6步已经删了') {
steps() {
echo '发送Chart包到K8master主机 - SUCCESS'
script{ //这里当我们是master分支时 上传的镜像为latest
if ("${tag}" == "origin/master" ){
sshPublisher(publishers: [sshPublisherDesc(configName: 'test', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "helm upgrade -i ${JOB_NAME} --set containers.image=$harborAddress/$harborRepo/${JOB_NAME}:latest --set name=${JOB_NAME} /usr/local/test/helm/mytest/", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: 'helm/mytest/* helm/mytest/templates/* ')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
}
else {
sshPublisher(publishers: [sshPublisherDesc(configName: 'test', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "helm upgrade -i ${JOB_NAME} --set containers.image=$harborAddress/$harborRepo/${JOB_NAME}:${tag} --set name=${JOB_NAME} /usr/local/test/helm/mytest/", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: 'helm/mytest/* helm/mytest/templates/* ')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
}
}
}
}
我们上面做了两条分支路线,当master时把镜像打成latest标签,并更新为latest,当为其他标签时和之前的步骤一样
构建是能够通过的,但是存在一个问题,当我们多次构建master分支的时候,因为helm识别镜像并没有被修改,所以不会更新,下面我们做个测试
我们这里修改一下输出的值,然后去jenkins构建,如果成功,容器会重启,访问页面会为V6.0.0才对
测试构建
从结果可以看到,我们虽然用最新代码构建了,但是实际部署的容器并没有更新
上面说了我们helm在更新时发现原来更新的镜像都是latest,helm认为并没有发生修改,所以不会去更新pod,我们应该让这个标签流动起来做为一个动态标签,这里我们使用git commithash的值作为最新的标签
cd /apps/devops_setup/data/jenkins/data/workspace/pipeline
//查看
git log
我们每次git写入到仓库都会生成一个commit hash值,可以通过这个值找到对应的操作,我们最新版本的镜像就以这个标签来指定
pipeline {
agent any
environment {
harborUser = 'admin'
harborPasswd = 'Harbor12345'
harborAddress = '101.43.4.210:30007'
harborRepo = 'repo'
GIT_COMMIT_HASH = ""
}
stages {
stage('1、 拉取gitlab上的代码到jenkins主机 ') {
steps() {
echo '拉取git仓库代码 - SUCCESS'
checkout([$class: 'GitSCM', branches: [[name: '$tag']], extensions: [], userRemoteConfigs: [[url: 'http://101.43.4.210:30001/root/mytest.git']]])
}
}
stage('2、通过jenkins本机的maven+jdk来实现编译打包') {
steps() {
echo '通过maven构建项目 - SUCCESS'
sh '/var/jenkins_home/maven/bin/mvn clean package -DskipTests'
}
}
stage('3、通过SonarQube做代码质量检测') {
steps() {
echo '通过SonarQube做代码质量检测 - SUCCESS'
sh '/var/jenkins_home/sonar-scanner/bin/sonar-scanner -Dsoanr.sources=./ -Dsonar.projectname=${JOB_NAME} -Dsonar.projectKey=${JOB_NAME} -Dsonar.java.binaries=./target -Dsonar.login=squ_3005d10215abc1ac559457cc90ba804c6c477c0c' }
}
stage('4、通过jenkins主机构建docker镜像') {
steps() {
script {
GIT_COMMIT_HASH = sh (script: "git log -n 1 --pretty=format:'%H'", returnStdout: true)
if ("${tag}" == "origin/master" ){
echo '通过jenkins主机构建docker镜像 - SUCCESS'
sh """mv ./target/*.jar docker/
docker build -t "${JOB_NAME}:latest" ./docker/
docker build -t "${JOB_NAME}:${GIT_COMMIT_HASH}" ./docker/
docker login ${harborAddress} -u${harborUser} -p${harborPasswd}
docker tag ${JOB_NAME}:latest ${harborAddress}/${harborRepo}/${JOB_NAME}:${GIT_COMMIT_HASH}
docker tag ${JOB_NAME}:latest ${harborAddress}/${harborRepo}/${JOB_NAME}:latest
docker push ${harborAddress}/${harborRepo}/${JOB_NAME}:${GIT_COMMIT_HASH}
docker push ${harborAddress}/${harborRepo}/${JOB_NAME}:latest
"""
}
else {
sh '''mv ./target/*.jar docker/
docker build -t "${JOB_NAME}:${tag}" ./docker/
docker login ${harborAddress} -u${harborUser} -p${harborPasswd}
docker tag ${JOB_NAME}:${tag} ${harborAddress}/${harborRepo}/${JOB_NAME}:${tag}
docker push ${harborAddress}/${harborRepo}/${JOB_NAME}:${tag}'''
}
}
}
}
stage('5、发送Chart包到K8master主机 通过helm部署, 这里多写了个第6步已经删了') {
steps() {
echo '发送Chart包到K8master主机 - SUCCESS'
echo "${GIT_COMMIT_HASH}"
script{
if ("${tag}" == "origin/master"){
echo "${tag}"
sshPublisher(publishers: [sshPublisherDesc(configName: 'test', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "helm upgrade -i ${JOB_NAME} --set containers.image=$harborAddress/$harborRepo/${JOB_NAME}:${GIT_COMMIT_HASH} --set name=${JOB_NAME} /usr/local/test/helm/mytest/", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: 'helm/mytest/* helm/mytest/templates/* ')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
}
else {
echo "${tag}"
sshPublisher(publishers: [sshPublisherDesc(configName: 'test', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "helm upgrade -i ${JOB_NAME} --set containers.image=$harborAddress/$harborRepo/${JOB_NAME}:${tag} --set name=${JOB_NAME} /usr/local/test/helm/mytest/", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: 'helm/mytest/* helm/mytest/templates/* ')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
}
}
}
}
}
}
说明
1、 添加全局变量 GIT_COMMIT_HASH = "" 当分支为master时将git commit hash写入全局变量
2、 镜像构建那部分, 当为master分支时我们把git_commithash 作为标签打镜像
//mytest:latest 后续单独拉取时的最新镜像
//mytest:${git_commithash} 每次helm更新部署时所用的镜像
3、 在helm部署部分,当我们操作的是master分支时,helm --set 更新的镜像名称的标签就是全局变量的GIT_COMMIT_HASH值
我现在部署的版本是V5,我们下面的操作中会更新代码中输出的值为V7,作为master分支进行推送,通过jenkins构建后可以看到我们实际运行中使用的镜像是git_commithash的值
这样一来,我们就每次上传代码去jenkins构建就能得到最新的版本部署了
语法参考
// 获取shell命令的标准输出或者状态
https://blog.csdn.net/liurizhou/article/details/86670092?spm=1001.2101.3001.6650.2&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-2-86670092-blog-81546477.pc_relevant_vip_default&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-2-86670092-blog-81546477.pc_relevant_vip_default&utm_relevant_index=3
上面实现了master主分支的自动化构建部署,但master分支会一直迭代版本的,下面我们将实现一个在推送代码后,自动去触发jenkins构建的一个触发器
//插件列表
Generic Webhook Trigger
gitlab
http://101.43.4.210:30004/project/pipeline
如上我们去测试勾子后会自动触发jenkins流程构建,下面我们更新下代码试试
这样一来每次我们上传代码都会自动帮忙部署,当我们需要使用指定版本时也可以选择标签去部署,持续部署完成~( •̀ ω •́ )y
持续集成:指程序员在代码的开发工程中,可以频繁的将代码部署到主干上,并进行自动化测试
持续交付:指在持续集成的基础之上,将代码部署到线上测试环境
持续部署:指在持续交付的基础之上,将要部署的代码实现自动部署
Dingtalk
//获取到的webhook
https://oapi.dingtalk.com/robot/send?access_token=d677b287ca50a1ed3ab23eaf0c78b8b01c76c0826ce2f3741ae4df6ab41fc8a5
post{
success{
dingtalk(
robot: 'jenkins',
type: 'MARKDOWN',
title: "success: ${JOB_NAME}",
text: ["- 成功构建: ${JOB_NAME}! \n- 版本: ${tag} \n- 持续时间: ${currentBuild.durationString} "]
)
}
failure {
dingtalk(
robot: 'jenkins',
type: 'MARKDOWN',
title: "success: ${JOB_NAME}",
text: ["- 构建失败: ${JOB_NAME}! \n- 版本: ${tag} \n- 持续时间: ${currentBuild.durationString} "]
)
}
}
配置说明
post{
success{ //success 当构建成功时发送
dingtalk( //钉钉
robot: 'jenkins', // 指定全局配置中钉钉机器人对应配置的id号,通过id号来识别不同的钉钉机器人
type: 'MARKDOWN', //输出的格式
title: "success: ${JOB_NAME}", //输出的标题信息
text: ["- 成功构建: ${JOB_NAME}! \n- 版本: ${tag} \n- 持续时间: ${currentBuild.durationString} "] //输出的文本信息 这里有一些是直接取jenkins全局变量的值${currentBuild.durationString}
)
}
failure { //当构建失败后的通知信息
dingtalk(
robot: 'jenkins',
type: 'MARKDOWN',
title: "success: ${JOB_NAME}",
text: ["- 构建失败: ${JOB_NAME}! \n- 版本: ${tag} \n- 持续时间: ${currentBuild.durationString} "]
)
}
}
后续如果想要其他全局变量的信息,可以在jenkins流水线语法处查看
pipeline {
agent any
environment {
harborUser = 'admin'
harborPasswd = 'Harbor12345'
harborAddress = '101.43.4.210:30007'
harborRepo = 'repo'
GIT_COMMIT_HASH = ""
}
stages {
stage('1、 拉取gitlab上的代码到jenkins主机 ') {
steps() {
echo '拉取git仓库代码 - SUCCESS'
checkout([$class: 'GitSCM', branches: [[name: '$tag']], extensions: [], userRemoteConfigs: [[url: 'http://101.43.4.210:30001/root/mytest.git']]])
}
}
stage('2、通过jenkins本机的maven+jdk来实现编译打包') {
steps() {
echo '通过maven构建项目 - SUCCESS'
sh '/var/jenkins_home/maven/bin/mvn clean package -DskipTests'
}
}
stage('3、通过SonarQube做代码质量检测') {
steps() {
echo '通过SonarQube做代码质量检测 - SUCCESS'
sh '/var/jenkins_home/sonar-scanner/bin/sonar-scanner -Dsoanr.sources=./ -Dsonar.projectname=${JOB_NAME} -Dsonar.projectKey=${JOB_NAME} -Dsonar.java.binaries=./target -Dsonar.login=squ_3005d10215abc1ac559457cc90ba804c6c477c0c' }
}
stage('4、通过jenkins主机构建docker镜像') {
steps() {
script {
GIT_COMMIT_HASH = sh (script: "git log -n 1 --pretty=format:'%H'", returnStdout: true)
if ("${tag}" == "origin/master" ){
echo '通过jenkins主机构建docker镜像 - SUCCESS'
sh """mv ./target/*.jar docker/
docker build -t "${JOB_NAME}:latest" ./docker/
docker build -t "${JOB_NAME}:${GIT_COMMIT_HASH}" ./docker/
docker login ${harborAddress} -u${harborUser} -p${harborPasswd}
docker tag ${JOB_NAME}:latest ${harborAddress}/${harborRepo}/${JOB_NAME}:${GIT_COMMIT_HASH}
docker tag ${JOB_NAME}:latest ${harborAddress}/${harborRepo}/${JOB_NAME}:latest
docker push ${harborAddress}/${harborRepo}/${JOB_NAME}:${GIT_COMMIT_HASH}
docker push ${harborAddress}/${harborRepo}/${JOB_NAME}:latest
"""
}
else {
sh '''mv ./target/*.jar docker/
docker build -t "${JOB_NAME}:${tag}" ./docker/
docker login ${harborAddress} -u${harborUser} -p${harborPasswd}
docker tag ${JOB_NAME}:${tag} ${harborAddress}/${harborRepo}/${JOB_NAME}:${tag}
docker push ${harborAddress}/${harborRepo}/${JOB_NAME}:${tag}'''
}
}
}
}
stage('5、发送Chart包到K8master主机 通过helm部署, 这里多写了个第6步已经删了') {
steps() {
echo '发送Chart包到K8master主机 - SUCCESS'
echo "${GIT_COMMIT_HASH}"
script{
if ("${tag}" == "origin/master"){
echo "${tag}"
sshPublisher(publishers: [sshPublisherDesc(configName: 'test', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "helm upgrade -i ${JOB_NAME} --set containers.image=$harborAddress/$harborRepo/${JOB_NAME}:${GIT_COMMIT_HASH} --set name=${JOB_NAME} /usr/local/test/helm/mytest/", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: 'helm/mytest/* helm/mytest/templates/* ')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
}
else {
echo "${tag}"
sshPublisher(publishers: [sshPublisherDesc(configName: 'test', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "helm upgrade -i ${JOB_NAME} --set containers.image=$harborAddress/$harborRepo/${JOB_NAME}:${tag} --set name=${JOB_NAME} /usr/local/test/helm/mytest/", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: 'helm/mytest/* helm/mytest/templates/* ')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
}
}
}
}
}
post{
success{
dingtalk(
robot: 'jenkins',
type: 'MARKDOWN',
title: "success: ${JOB_NAME}",
text: ["- 成功构建: ${JOB_NAME}! \n- 版本: ${tag} \n- 持续时间: ${currentBuild.durationString} "]
)
}
failure {
dingtalk(
robot: 'jenkins',
type: 'MARKDOWN',
title: "success: ${JOB_NAME}",
text: ["- 构建失败: ${JOB_NAME}! \n- 版本: ${tag} \n- 持续时间: ${currentBuild.durationString} "]
)
}
}
}