Jenkins+GitLab+SonnarQube搭建CI/CD全流程
1. CI/CD
1.1 CI - 持续集成
持续集成( Continuous integration , 简称 CI )指的是,频繁地(一天多次)将代码集成到主干。持续集成的目的就是让产品可以快速迭代,同时还能保持高质量。它的核心措施是代码集成到主干之前,必须通过自动化测试。只要有一个测试用例失败,就不能集成。通过持续集成团队可以快速的从一个功能到另一个功能,简而言之,敏捷软件开发很大一部分都要归功于持续集成。
持续集成的组成要素
-
一个自动构建过程, 从检出代码、 编译构建、 运行测试、 结果记录、 测试统计等都是自动完成的, 无需人工干预。
-
一个代码存储库,即需要版本控制软件来保障代码的可维护性,同时作为构建过程的素材库,一般使用SVN或Git。
-
一个持续集成服务器, Jenkins 就是一个配置简单和使用方便的持续集成服务器。
1.2 CD - 持续部署
持续部署则是在持续集成的基础上,把部署到生产环境的过程自动化。
2. 整体架构说明
单体项目 / 前后端分离项目 解决方案(已实现)
微服务项目 解决方案
3. GitLab代码管理私服
3.1 理解
GitLab和GitHub一样属于第三方基于Git开发的作品,免费且开源(基于MIT协议),与Github类似,可以注册用户,任意提交你的代码,添加SSHKey等等。不同的是GitLab是可以部署到自己的服务器上,数据库等一切信息都掌握在自己手上,适合团队内部协作开发,你总不可能把团队内部的智慧总放在别人的服务器上吧?简单来说可把GitLab看作个人版的GitHub。
3.2 安装(CentOS7)
这里我使用的是Docker-compose安装,基于twang2218/gitlab-ce-zh汉化版镜像
3.3 相关配置
3.4 页面配置
- 管理员账号
- 添加组
使用管理员 root 创建组,一个组里面可以有多个项目分支,可以将开发添加到组里面进行设置权限,不同的组就是公司不同的开发项目或者服务模块,不同的组添加不同的开发即可实现对开发设置权限的管理。
- 创建用户
- 将用户添加到组中
Gitlab用户在组里面有5种不同权限:
Guest:可以创建issue、发表评论,不能读写版本库
Reporter:可以克隆代码,不能提交,QA、PM可以赋予这个权限
Developer:可以克隆代码、开发、提交、push,普通开发可以赋予这个权限
Maintainer:可以创建项目、添加tag、保护分支、添加项目成员、编辑项目,核心开发可以赋予这个权限
Owner:可以设置项目访问权限 - Visibility Level、删除项目、迁移项目、管理组成员,开发组组长可以赋予这个权限
-
组中创建项目
-
源码上传到Gitlab仓库(这里我们通过SSH的方式)
-
登录GitLab私服地址:192.168.0.200:8089
-
配置SSH免密登录,以SSH方式push,pull代码
- 下载安装Git客户端
- 打开Git Bash
- 然后打开
~/.ssh/id_rsa.pub
文件(~表示用户目录,比如我的windows就是C:\Users\Administrator),复制其中的内容 - 打开gitlab,搜索SSH Key,并把上一步中复制的内容粘贴到Key所对应的文本框,在Title对应的文本框中给这个sshkey设置一个名字,点击Add key按钮
- 尝试拉取代码和提交代码,此时已不需要输入密码了
4. Jenkins环境搭建
4.1 安装环境(CentOS7)
名称 | 安装包 | 版本号 |
---|---|---|
Jenkins | jenkins-2.190.3-1.1.noarch.rpm | 2.190.3 |
JDK | 1.8 | |
Maven | 3.6.2 |
4.2 Jenkins安装与配置
4.3 页面配置
- 第一次进入需要输入admin账户密码
-
选择插件来安装 => 选择无 => 安装。 以此来跳过插件安装,因为Jenkins插件需要连接默认官网下载,速度非常慢而且经过会失败,所以我们暂时先跳过插件安装
-
添加一个管理员账户,并进入Jenkins后台
- JenKins URL默认即可
4.4 Jenkins插件下载加速
- Jenkins本身没有提供多少功能,我们可以通过使用插件来满足我们的使用。例如从Gitlab拉取代码,使用Maven构建项目等功能需要依靠插件完成。接下来演示如何下载插件。
- 修改Jenkins插件下载地址,Jenkins国外官方插件地址下载速度非常慢,所以可以修改为国内插件地址。
enkins->Manage Jenkins->Manage Plugins,点击可选插件待其加载完成。这样做是为了把Jenkins官方的插件列表下载到本地,接着修改地址文件替换为国内插件地址。
最后,Manage Plugins点击Advanced,把Update Site改为国内插件下载地址
https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json
Submit后,在浏览器输入: http://192.168.66.101:8888/restart ,重启Jenkins。
4.5 Jenkins用户权限管理
我们可以利用Role-based Authorization Strategy 插件来管理Jenkins用户权限
- Role-based Authorization Strategy插件
- 开启权限全局安全配置
Manage Jenkins -> Configure Global Security
- 创建角色
Manage Jenkins -> Manage and Assign Roles -> Manage Roles
Global roles(全局角色):管理员等高级用户可以创建基于全局的角色
Project roles(项目角色):针对某个或者某些项目的角色
Node roles(节点角色):节点相关的权限
- 我们添加以下三个角色
- baseRole:该角色为全局角色。这个角色需要绑定Overall下面的Read权限,是为了给所有用户绑定最基本的Jenkins访问权限。注意:如果不给后续用户绑定这个角色会报错误:"用户名 ismissing the Overall/Read permission"
-
role1:该角色为项目角色。使用正则表达式绑定"jp.*",意思是只能操作jp开头的项目。
-
role2:该角色也为项目角色。绑定"web.*",意思是只能操作web开头的项目。
- 创建用户
Manage Jenkins -> Manage Users -> 新建两个用户如xixi / haha
- 给用户分配角色
Manage Jenkins -> Manage and Assign Roles -> Assign Roles
绑定规则如下:
xixi用户绑定baseRole和role1角色,haha绑定baseRole和role2角色
创建项目测试权限!
4.6 Jenkins凭证管理
- 凭据可以用来存储需要密文保护的数据库密码、Gitlab密码信息、Docker私有仓库密码等,以便Jenkins可以和这些第三方的应用进行交互。
- 安装
Credentials Binding
插件,要在Jenkins使用凭证管理功能,安装后Manage Jenkins出现如下菜单
- 五种凭据类型
- Jenkins管理Gitlab凭证 - 用户密码类型
- 安装Git插件。为了让Jenkins支持从Gitlab拉取源码,需要安装Git插件
- 安装Git工具,为了让Jenkins支持从Gitlab拉取源码,需要在CentOS7上安装Git工具
- 创建用户密码类型凭证
Manage Jenkins -> Manage Credentials -> 添加凭据
- 测试凭证是否可用
创建一个自由风格的项目,找到"源码管理"->"Git",在Repository URL复制Gitlab中的项目URL。
查看/var/lib/jenkins/workspace/目录,发现已经从Gitlab成功拉取了代码到Jenkins中。
- Jenkins管理Gitlab凭证 - SSH类型
- 把生成的公钥放在Gitlab中。
以root账户登录->点击头像->Settings->SSH Keys。复制刚才id_rsa.pub文件的内容到这里,点击"Add Key"
- 在Jenkins中添加凭证,配置私钥
在Jenkins添加一个新的凭证,类型为"SSH Username with private key",把刚才生成私有文件内容复制过来
4.7 Maven安装和配置
在Jenkins集成服务器上,我们需要安装Maven来编译和打包项目。
-
安装Maven
-
配置环境变量
- 全局工具配置关联JDK和Maven
Jenkins -> Global Tool Confifiguration -> JDK->新增JDK
Jenkins->Global Tool Confifiguration->Maven->新增Maven
- 添加Jenkins全局变量
Manage Jenkins->Confifigure System->Global Properties ,添加三个全局变量
- 修改Maven的settings.xml
- 测试Maven是否配置成功
- 使用之前的测试项目,修改配置
- 构建 -> 增加构建步骤 -> Execute Shell
- 再次构建,如果可以把项目打成war包,代表maven环境配置成功!
4.8 Tomcat安装与配置
这里使用的是window服务器。配置与Linux服务器并无差异
- 安装Tomcat8.5
- 配置Tomcat用户角色权限
默认情况下Tomcat是没有配置用户角色权限的。但是,后续Jenkins部署项目到Tomcat服务器,需要用到Tomcat的用户,所以修改tomcat以下配置,添加用户及权限。
- 重启Tomcat,访问测试
- Tomcat调优,调整Jvm内存大小(解决后端项目无端部署失败的bug)
由于公司项目体积较大,我多次使用Jenkins自动部署项目都失败了,但是代码并无明显错误。后来发现是tomcat的jvm设置太小容易内存溢出,可以适当调整jvm内存大下,重启下即可。
- 使用刚才创建的角色进入manager应用,点击Server Status查看JVM状态
- 修改JVM内存大小
修改方式:打开Tomcat的bin/catalina.bat文件进行修改
注意:内存不宜设置太大,根据服务器内存大小适当配置
增大堆内存
增大非堆内存
5. Jenkins各种类型项目构建
5.1 自动构建项目类型
Jenkins中自动构建项目的类型有很多,常用的有以下三种:
- 自由风格软件项目(FreeStyle Project)
- Maven项目(Maven Project)
- 流水线项目(Pipeline Project)
每种类型的构建其实都可以完成一样的构建过程与结果,只是在操作方式、灵活度等方面有所区别,在实际开发中可以根据自己的需求和习惯来选择。(PS:个人推荐使用流水线类型,因为灵活度非常高)
5.2 自由风格项目搭建
演示集成过程:拉取代码 -> 编译 -> 打包 -> 部署
- 创建自由风格项目web_test2
- 配置源码管理,从GitLab拉取代码
- 编译打包
- 部署
把项目部署到远程的Tomcat里面
- 安装
Deploy to container
插件。Jenkins本身无法实现远程部署到Tomcat的功能,需要安装Deploy to container插件实现
- 添加Tomcat用户凭证
- 添加构建后操作
- 点击Build Now,开始构建过程
- 之后改动代码再push到GitLab,在Jenkins中对项目进行重新构建部署即可
5.3 Maven项目搭建
- 安装Maven Integration插件
- 创建Maven项目web_test2_maven
- 配置项目
拉取代码和远程部署的过程和自由风格项目一样,只是"构建"部分不同
5.4 流水线项目搭建
- Pipeline简介
Pipeline,简单来说就是一套运行在 Jenkins 上的工作流框架,将原来独立运行于单个或者多个节点的任务连接起来,实现单个任务难以完成的复杂流程编排和可视化的工作。
使用Pipeline有以下好处:
-
代码:Pipeline以代码的形式实现,通常被检入源代码控制,使团队能够编辑,审查和迭代其传送流程。
-
持久:无论是计划内的还是计划外的服务器重启,Pipeline都是可恢复的。
-
可停止:Pipeline可接收交互式输入,以确定是否继续执行Pipeline。
-
多功能:Pipeline支持现实世界中复杂的持续交付要求。它支持fork/join、循环执行,并行执行任务的功能。
-
可扩展:Pipeline插件支持其DSL的自定义扩展 ,以及与其他插件集成的多个选项。
如何创建 Jenkins Pipeline?
-
Pipeline 脚本是由 Groovy 语言实现的,但是我们没必要单独去学习 Groovy
-
Pipeline 支持两种语法:Declarative(声明式)和 Scripted Pipeline(脚本式)语法
-
Pipeline 也有两种创建方法:可以直接在 Jenkins 的 Web UI 界面中输入脚本;也可以通过创建一个 Jenkinsfifile 脚本文件放入项目源码库中(一般都推荐在 Jenkins 中直接从源代码控制(SCM)中直接载入 Jenkinsfifile Pipeline 这种方法)
- 安装Pipeline插件
- 安装插件后,创建项目的时候多了“流水线”类型
- Pipeline语法快速入门
- Declarative声明式-Pipeline
流水线->选择HelloWorld模板
生成内容如下
stages:代表整个流水线的所有执行阶段。通常stages只有1个,里面包含多个stage
stage:代表流水线中的某个阶段,可能出现n个。一般分为拉取代码,编译构建,部署等阶段。
steps:代表一个阶段内需要执行的逻辑。steps里面是shell脚本,git拉取代码,ssh远程发布等任意内容。
编写一个简单声明式的Pipeline
点击构建,可以看到整个构建过程
- Scripted Pipeline脚本式-Pipeline
流水线->选择Scripted Pipeline
生成内容如下
Node:节点,一个 Node 就是一个 Jenkins 节点,Master 或者 Agent,是执行 Step 的具体运行环境,后续讲到Jenkins的Master-Slave架构的时候用到。
Stage:阶段,一个 Pipeline 可以划分为若干个 Stage,每个 Stage 代表一组操作,比如:Build、Test、Deploy,Stage 是一个逻辑分组的概念。
Step:步骤,Step 是最基本的操作单元,可以是打印一句话,也可以是构建一个 Docker 镜像,由各类 Jenkins 插件提供,比如命令:sh ‘make’,就相当于我们平时 shell 终端中执行 make 命令
一样
- 我们可以通过左下侧流水线语法快速生成pipeline代码
以拉取代码为例,选择片段生成器模板
- Pipeline Script from SCM
刚才我们都是直接在Jenkins的UI界面编写Pipeline代码,这样不方便脚本维护,建议把Pipeline脚本放在项目中(一起进行版本控制),在项目根目录建立Jenkinsfifile文件,把脚本内容复制到该文件中即可
6. Jenkins构建触发器
6.1 Jenkins内置4种构建触发器
-
触发远程构建
-
其他工程构建后触发(Build after other projects are build)
-
定时构建(Build periodically)
-
轮询SCM(Poll SCM)
6.2 触发远程构建演示
触发构建url:http://192.168.0.200:8888/job/web_test2/build?token=123456
6.3 其他工程构建后触发
6.4 定时构建
- 定时字符串从左往右分别为: 分 时 日 月 周
- 一些定时表达式的例子:
每30分钟构建一次:H代表形参 H/30 * * * * 10:02 10:32
每2个小时构建一次: H H/2 * * *
每天的8点, 12点, 22点,一天构建3次: (多个时间点中间用逗号隔开) 0 8,12,22 * * *
每天中午12点定时构建一次 H 12 * * *
每天下午18点定时构建一次 H 18 * * *
在每个小时的前半个小时内的每10分钟 H(0-29)/10 * * * *
每两小时一次,每个工作日上午9点到下午5点(也许是上午10:38,下午12:38,下午2:38,下午4:38) H H(9-16)/2 * * 1-5
6.5 轮询SCM
轮询SCM,是指定时扫描本地代码仓库的代码是否有变更,如果代码有变更就触发项目构建。
注意:这次构建触发器,Jenkins会定时扫描本地整个项目的代码,增大系统的开销,不建议使用。
6.6 Git hook自动触发构建插件
- 刚才我们看到在Jenkins的内置构建触发器中,轮询SCM可以实现Gitlab代码更新,项目自动构建,但是该方案的性能不佳。那有没有更好的方案呢? 有的。就是利用Gitlab的webhook实现代码push到仓库,立即触发项目自动构建。
- 安装GitLab Hook插件:Gitlab Hook 与 GitLab两个插件
- Jenkins设置自动构建
- GitLab配置webhook
- 开启webhook功能
使用root账户登录到后台,点击Admin Area -> Settings
勾选"允许钩子和服务访问本地网络"
- 在项目中添加webhook
- 注意:以下设置必须完成,否则会报错!
7. Jenkins参数化构建
7.1 理解
有时在项目构建的过程中,我们需要根据用户的输入动态传入一些参数,从而影响整个构建结果,这时我们可以使用参数化构建。
Jenkins支持非常丰富的参数类型。
7.2 演示通过分支名称来部署不同分支项目
流水线项目作为演示
- 项目创建分支,并推送到Gitlab上
- 在Jenkins项目配置中添加字符串类型参数
- 修改pipeline流水线拉取步骤的代码
- 点击Build with Parameters
输入分支名称构建即可!构建完成后访问Tomcat查看结果
8. Jenkins配置邮箱服务器发送构建结果
8.1 安装Email Extension Plugin插件
8.2 Jenkins设置邮箱相关参数
Manage Jenkins -> Confifigure System
- 设置管理员邮箱
- 设置邮件参数
- 设置Jenkins默认邮箱信息
- 准备邮件内容(模板)
在项目根目录编写email.html,并把文件推送到Gitlab,内容如下: