本文我们将基于Jenkins和Kubernetes流水线过程实现自动化构建Java应用,即把流水线的过程转换为pipeline语法,实现应用的自动发版。

一、 创建Java测试用例

本书为读者准备了一个简单的Java测试用例,用于读者的学习,可以从 https://github.com/andanyoung/springboot-hello.git 找到该项目(也可以使用公司的Java项目)。

接下来将该项目导入自己的GitLab中。首先找到之前创建的Kubernetes组,然后单击New project,如图1所示。

图1 创建测试项目

选择Import project,如图2所示。

图2 导入项目

单击Repo by URL

图3 导入Java测试项目

在Git repository URL中输入示例地址,然后单击Create project,如图4所示。

图4 创建Project

导入后,结果如图5所示。

图5 查看导入的项目

二、定义Jenkinsfile

Jenkinsfile定义流水线的步骤包括拉取代码、执行构建、生成镜像、更新Kubernetes资源等。本书将Jenkinsfile放置于项目源代码一并管理,也可以单独放置于一个Git仓库进行管理。

接下来在GitLab的源代码中添加Jenkinsfile。首先单击代码首页的“+”,然后单击New file,如图6所示。

图6 添加文件

在窗口中添加如下内容(完整内容见本书代码):

pipeline {...parameters {gitParameter(branch: '', branchFilter: 'origin/(.*)', defaultValue: '', description: 'Branch for build and deploy', name: 'BRANCH', quickFilterEnabled: false, selectedValue: 'NONE', sortMode: 'NONE', tagFilter: '*', type: 'PT_BRANCH')}}

这个Jenkinsfile比较长,接下来我们分别解析一下。

三、 Jenkinsfile详解

首先是顶层的agent,定义Kubernetes的Pod作为Jenkins的Slave:

agent {# 定义使用Kubernetes作为agentkubernetes {选择的云为之前配置的名字cloud 'kubernetes-study'slaveConnectTimeout 1200#将workspace改成hostPath,因为该Slave会固定节点创建,如果有存储可用,可以改成PVC的模式workspaceVolume hostPathWorkspaceVolume(hostPath: "/opt/workspace", readOnly: false)yaml '''apiVersion: v1kind: Podspec:containers:# jnlp容器,和Jenkins主节点通信- args: ['$(JENKINS_SECRET)', '$(JENKINS_NAME)']image: 'registry.cn-beijing.aliyuncs.com/citools/jnlp:alpine'name: jnlpimagePullPolicy: IfNotPresentvolumeMounts:​    - mountPath: "/etc/localtime"​     name: "localtime"​     readOnly: false # build容器,包含执行构建的命令,比如Java的需要mvn构建,就可以用一个maven的镜像 - command:​    - "cat"env:​    - name: "LANGUAGE"​     value: "en_US:en"​    - name: "LC_ALL"​     value: "en_US.UTF-8"​    - name: "LANG"​     value: "en_US.UTF-8"# 使用Maven镜像,包含mvn工具。NodeJS可以用node的镜像image: "registry.cn-beijing.aliyuncs.com/citools/maven:3.5.3"imagePullPolicy: "IfNotPresent"# 容器的名字,流水线的stage可以直接使用该名字name: "build"tty: truevolumeMounts:​    - mountPath: "/etc/localtime"​     name: "localtime"​    # Pod单独创建了一个缓存的volume,将其挂载到了maven插件的缓存目录,默认是/root/.m2​    - mountPath: "/root/.m2/"​     name: "cachedir"​     readOnly: false# 发版容器,因为最终是发版至Kubernetes的,所以需要有一个kubectl命令- command:​    - "cat"env:​    - name: "LANGUAGE"​     value: "en_US:en"​    - name: "LC_ALL"​     value: "en_US.UTF-8"​    - name: "LANG"​     value: "en_US.UTF-8"# 镜像的版本可以替换为其他的版本,也可以不替换,因为只执行set命令,所以版本是兼容的image: "registry.cn-beijing.aliyuncs.com/citools/kubectl:self-1.17"imagePullPolicy: "IfNotPresent"name: "kubectl"tty: truevolumeMounts:​    - mountPath: "/etc/localtime"​     name: "localtime"​     readOnly: false# 用于生成镜像的容器,需要包含docker命令- command:​    - "cat"env:​    - name: "LANGUAGE"​     value: "en_US:en"​    - name: "LC_ALL"​     value: "en_US.UTF-8"​    - name: "LANG"​     value: "en_US.UTF-8"image: "registry.cn-beijing.aliyuncs.com/citools/docker:20.10.9-git"imagePullPolicy: "IfNotPresent"name: "docker"tty: truevolumeMounts:​    - mountPath: "/etc/localtime"​     name: "localtime"​     readOnly: false​    # 由于容器没有启动docker服务,因此将宿主机的docker直接挂载至容器即可​    - mountPath: "/var/run/docker.sock"​     name: "dockersock"​     readOnly: falserestartPolicy: "Never"# 固定节点部署nodeSelector:build: "true"securityContext: {}volumes:# Docker socket volume- hostPath:​    path: "/var/run/docker.sock"name: "dockersock"- hostPath:​    path: "/usr/share/zoneinfo/Asia/Shanghai"name: "localtime"# 缓存目录- name: "cachedir"hostPath:​    path: "/opt/m2"'''}

之后看一下Jenkinsfile最后的环境变量和parameters的配置:

# 定义一些全局的环境变量environment {COMMIT_ID = ""HARBOR_ADDRESS = "10.0.0.204" # Harbor地址REGISTRY_DIR = "kubernetes"  # Harbor的项目目录IMAGE_NAME = "spring-boot-project" # 镜像的名称NAMESPACE = "kubernetes" # 该应用在Kubernetes中的命名空间TAG = "" # 镜像的Tag,在此用BUILD_TAG+COMMIT_ID组成}parameters {# 之前讲过一些choice、input类型的参数,本次使用的是GitParameter插件# 该字段会在Jenkins页面生成一个选择分支的选项gitParameter(branch: '', branchFilter: 'origin/(.*)', defaultValue: '', description: 'Branch for build and deploy', name: 'BRANCH', quickFilterEnabled: false, selectedValue: 'NONE', sortMode: 'NONE', tagFilter: '*', type: 'PT_BRANCH')}

接下来是拉取代码的stage,这个stage是一个并行的stage,因为考虑了该流水线是手动触发还是自动触发:

stage('Pulling Code') {parallel {​    stage('Pulling Code by Jenkins') {​     when {​      expression {​      # 若env.gitlabBranch为空,则该流水线为手动触发,执行该stage;若不为空,则会执行同级的另一个stage​       env.gitlabBranch == null​      }​     }​     steps {​      # 这里使用git插件拉取代码,BRANCH变量取自前面介绍的parameters配置​      # git@xxxxxx:root/spring-boot-project.git代码地址​      # credentialsId: 'gitlab-key',之前创建的拉取代码的key​      git(changelog: true, poll: true, url: 'git@xxxxxx:root/ spring-boot-project.git', branch: "${BRANCH}", credentialsId: 'gitlab-key')​      script {​      # 定义一些变量用于生成镜像的Tag​      # 获取最近一次提交的Commit ID​       COMMIT_ID = sh(returnStdout: true, script: "git log -n 1 --pretty=format:'%h'").trim()​      # 赋值给TAG变量,后面的docker build可以取到该TAG的值​       TAG = BUILD_TAG + '-' + COMMIT_ID​       println "Current branch is ${BRANCH}, Commit ID is ${COMMIT_ID}, Image TAG is ${TAG}"​      }​     }​    }​    stage('Pulling Code by trigger') {​     when {​      expression {​      # 如果env.gitlabBranch不为空,说明该流水线是通过webhook触发的,则此时执行该stage,上述的stage不再执行。此时BRANCH变量为空​       env.gitlabBranch != null​      }​     }​     steps {​      # 以下配置和前面一致,只是此时branch: env.gitlabBranch取的值为env.gitlabBranch​      git(url: 'git@xxxxxxxxxxx:root/spring-boot-project.git', branch: env.gitlabBranch, changelog: true, poll: true, credentialsId: 'gitlab-key')​      script {​       COMMIT_ID = sh(returnStdout: true, script: "git log -n 1 --pretty=format:'%h'").trim()​       TAG = BUILD_TAG + '-' + COMMIT_ID​       println "Current branch is ${env.gitlabBranch}, Commit ID is ${COMMIT_ID}, Image TAG is ${TAG}"​      }​     }​    }}}

代码拉下来后,就可以执行构建命令,由于本次实验是Java示例,因此需要使用mvn命令进行构建:

stage('Building') {steps {​    # 使用Pod模板里面的build容器进行构建​    container(name: 'build') {​      sh """​      # 编译命令,需要根据自己项目的实际情况进行修改,可能会不一致​       mvn clean install -DskipTests​      # 构建完成后,一般情况下会在target目录下生成jar包​       ls target/*​      """​    }}}

生成编译产物后,需要根据该产物生成对应的镜像,此时可以使用Pod模板的docker容器:

stage('Docker build for creating image') {# 首先取出HARBOR的账号和密码environment {​    HARBOR_USER   = credentials('HARBOR_ACCOUNT')}steps {​    # 指定使用docker容器​    container(name: 'docker') {​     sh """​     # 执行build命令,Dockerfile会在下一小节创建,也是放在代码仓库,和Jenkinsfile同级​     docker build -t ${HARBOR_ADDRESS}/${REGISTRY_DIR}/${IMAGE_NAME}:${TAG} .​     # 登录Harbor,HARBOR_USER_USR和HARBOR_USER_PSW由上述environment生成​     docker login -u ${HARBOR_USER_USR} -p ${HARBOR_USER_PSW} ${HARBOR_ADDRESS}​     # 将镜像推送至镜像仓库​     docker push ${HARBOR_ADDRESS}/${REGISTRY_DIR}/${IMAGE_NAME}:${TAG}​     """​    }}}最后一步就是将该镜像发版至Kubernetes集群中,此时使用的是包含kubectl命令的容器:stage('Deploying to k8s') {# 获取连接Kubernetes集群证书 environment {​    MY_KUBECONFIG = credentials('study-k8s-kubeconfig')}steps {​    # 指定使用kubectl容器​    container(name: 'kubectl'){​      sh """​     # 直接set更改Deployment的镜像即可​      /usr/local/bin/kubectl --kubeconfig $MY_KUBECONFIG set image deploy -l app=${IMAGE_NAME} ${IMAGE_NAME}=${HARBOR_ADDRESS}/${REGISTRY_DIR}/${IMAGE_NAME}:${TAG} -n $NAMESPACE​      """​    }}}}

注意
本例发版的命令为/usr/local/bin/kubectl --kubeconfig MYKUBECONFIGsetimagedeploy−lapp=MY_KUBECONFIG set image deploy -l app=MYK​UBECONFIGsetimagedeploy−lapp={IMAGE_NAME} IMAGENAME={IMAGE_NAME}=IMAGEN​AME={HARBOR_ADDRESS}/REGISTRYDIR/{REGISTRY_DIR} /REGISTRYD​IR/{IMAGE_NAME}

基于Jenkins和Kubernetes流水线实现应用的自动发版相关推荐

  1. 基于 Jenkins 和 Kubernetes 的持续集成测试实践了解一下!

    作者 | 刘春明,责编 | Carol 出品 | CSDN 云计算(ID:CSDNcloud) 封图 | CSDN下载于视觉中国 目前公司为了降低机器使用成本,对所有的AWS虚拟机进行了盘点,发现利用 ...

  2. 【有容云案例系列】基于Jenkins和Kubernetes的CI工作流

    嘉宾介绍 黄文俊 有容云资深系统架构师 主要负责容器云平台产品架构及设计. 8年工作经验, 有着企业级存储, 云计算解决方案相关理解. 关注于微服务设计思考, 开发流程优化, docker及kuber ...

  3. git连接jenkins_基于 Jenkins 和 Kubernetes 的持续集成测试实践了解一下!

    作者 | 刘春明 责编 | Carol 出品 | CSDN 云计算(ID:CSDNcloud) 封图| CSDN下载于视觉中国 目前公司为了降低机器使用成本,对所有的AWS虚拟机进行了盘点,发现利用率 ...

  4. 你公司的虚拟机还闲着?基于 Jenkins 和 Kubernetes 的持续集成测试实践了解一下!...

    作者 | 刘春明 责编 | Carol 出品 | CSDN 云计算(ID:CSDNcloud) 封图| CSDN下载于视觉中国 目前公司为了降低机器使用成本,对所有的AWS虚拟机进行了盘点,发现利用率 ...

  5. 基于Jenkins的DevOps流水线实践教程

    讲师介绍 课程寄语 我认为Jenkins是对我这些年运维经验的总结,起初我们运维同学都是编写脚本完成一些自动化的操作.而有了Jenkins我们可以将我们的运维经验与Jenkins设计理念融合完成自动化 ...

  6. 基于Jenkins的DevOps流水线实践教程|2020全新制作|端到端研发效能提升

    讲师介绍 课程寄语 我认为Jenkins是对我这些年运维经验的总结,起初我们运维同学都是编写脚本完成一些自动化的操作.而有了Jenkins我们可以将我们的运维经验与Jenkins设计理念融合完成自动化 ...

  7. 基于Jenkins的DevOps流水线实践教程|2020全新制作|端到到研发效能提升

    讲师介绍 课程寄语 我认为Jenkins是对我这些年运维经验的总结,起初我们运维同学都是编写脚本完成一些自动化的操作.而有了Jenkins我们可以将我们的运维经验与Jenkins设计理念融合完成自动化 ...

  8. Jenkins 流水线 获取git 分支列表_基于Jenkins的DevOps流水线实践课程

    讲师介绍 课程寄语 我认为Jenkins是对我这些年运维经验的总结,起初我们运维同学都是编写脚本完成一些自动化的操作.而有了Jenkins我们可以将我们的运维经验与Jenkins设计理念融合完成自动化 ...

  9. Jenkins 流水线 获取git 分支列表_基于Jenkins的DevOps流水线实践

    讲师介绍 课程寄语 我认为Jenkins是对我这些年运维经验的总结,起初我们运维同学都是编写脚本完成一些自动化的操作.而有了Jenkins我们可以将我们的运维经验与Jenkins设计理念融合完成自动化 ...

最新文章

  1. PNAS: 儿童生长发育迟缓 = 长期饥饿?
  2. Uber发布了Ludwig,一款不使用代码的人工智能开发工具
  3. 2.登录linun 输入密码登录不进去 进入单用户模式 修改 然后reboot
  4. 慕课网 javascript深入浅出编程练习
  5. tomcat运行报错Failed to start component [StandardEngine[Catalina].StandardHost[localhost].
  6. 如何使 highchart图表标题文字可选择复制
  7. mysql switch binlog_如何使用 Golang 处理 MySQL 的 binlog
  8. ERP failure: Error when opening an RFC connection
  9. nginx php iconv,Nginx +PHP部署一
  10. tiny4412u-boot烧写及根文件系统制作(不进入终端问题)
  11. P5707 【深基2.例12】上学迟到(python3实现)
  12. local lua 多个_Lua 级别 CPU 火焰图介绍
  13. Objective-C基础3:内存管理续
  14. 2021级C语言大作业 - 涂鸦跳跃
  15. ❤️《AOP》(Spring必备技能)
  16. 聊聊、Integer 封装特性
  17. 在myeclipse上设置 SVN过滤上传的文件类型
  18. OpenPose学习笔记
  19. js获取当前日期yyyymmdd
  20. 如何解决 Win10 卡顿的问题

热门文章

  1. Python鼠标点击图片,获取点击点的像素坐标/像素值
  2. 使用Python统计历年来各种英语高考题中单词的出现频数
  3. Win10 22H2更新时间 Win10 22H2怎么更新
  4. python自动录音程序
  5. 安卓APP测试要怎么测,测试流程和重点有哪些?我来告诉你
  6. PySide6 Widgets基本小部件类--QWidget
  7. 【Qbot】1.ChatGPT简介与Q群机器人部署教程
  8. 电脑怎么用c语言写丘比特,C语言丘比特#includebr/#includebr/ 爱问知识人
  9. github上实用、常用的插件和库
  10. 清华计算机系出了哪些牛人,清华大学16位学霸PK 简历吓坏网友