一、持续集成
1.1 软件开发生命周期
软件开发生命周期又叫做SDLC(Software Development Life Cycle),它是集合了计划、开发、测试和部署过程的集合,如下图所示:
1.1.1 需求分析
这是生命周期的第一阶段,根据项目需求,团队执行一个可行性计划的分析。项目需求可能是公司内部或者客户提出的。这阶段主要是对信息的收集,也有可能是对现有项目的改善和重新做一个新项目。还要分析项目的预算多长,可以从哪方面受益及布局,这也是项目创建的目标。
1.1.2 设计
第二阶段就是设计阶段,系统架构和满意状态(就是要做成什么样子,有什么功能)。创建一个项目计划,计划可以使用图表,布局设计或者文字的方式呈现。
1.1.3 实现
第三阶段就是实现阶段,项目经理创建和分配工作给开发者,开发者根据任务和在设计阶段定义的目标进行开发代码。依据项目的大小和复杂度,可以需要数月或更长的时间才能完成。
1.1.4 测试
测试人员进行代码测试,包括功能测试、代码测试、压力测试等。
1.1.5 进化
最后阶段就是对产品不断的进行改进和维护阶段,根据用户的使用情况,可能需要对某功能进行修改,bug修复,功能增加等。
1.2 软件开发瀑布模型
瀑布模型是最著名和最常使用的软件开发模型。瀑布模型就是一系列的软件开发过程。它是由制造业繁衍出来的。一个高度化的结构流程在一个方向上流动(不可逆),有点像生产线一样。在瀑布模型创建之初,没有其他开发的模型,有很多东西全靠开发人员去猜测,去开发。这样的模型仅适用于那些简单的软件开发,但是已经不适合现在的开发了。下图对软件开发瀑布模型的一个阐述:
1.3 软件的敏捷开发
1.3.1 什么是敏捷开发
敏捷开发(Agile Development)的核心是迭代开发(Iterative Development)与增量开发(Incremental Development)。
1.3.2 何为迭代开发
对于大型软件项目,传统的开发方式是采用一个大周期(比如一年)进行开发,整个过程就是一次大开发。迭代开发的方式则不一样,它将开发过程拆分成多个小周期,即一次大开发变成很多次小开发,每次小开发都是同样的流程,所以看上去就好像重复在做同样的步骤。
1.3.3 何为增量开发
软件的每个版本,都会新增一个用户可以感知的完整功能。也就是说,按照新增功能来划分迭代。
举例来说,房产公司开发一个10栋楼的小区。如果采用增量式开发的模式,该公司第一个迭代就是交付一号楼,第二个迭代交付二号楼……每个迭代都是完成一栋完整的楼。而不是一个迭代挖好10栋楼的地基,第二个迭代建好每栋楼的骨架,第三个迭代架设屋顶……
1.3.4 敏捷开发如何迭代
虽然敏捷开发将软件开发分成多个迭代,但是也要求,每次迭代都是一个完整的软件开发周期,必须按照软件工程的方法论,进行正规的流程管理。
1.3.5 敏捷开发有什么好处
- 早期交付:敏捷开发的第一个好处,就是早期交付,从而大大降低成本。
还是以上面房产公司为例,如果按照传统的瀑布开发模式,先挖10栋楼的地基,再盖骨架,然后架设屋顶,每个阶段都等到前一个阶段完成后开始,可能需要两年才能一次性交付10栋楼。也就是说,如果不考虑预售,该项目必须等到两年后才能回款。敏捷开发是六个月后交付一号楼,后面每两个月交付一栋楼。因此,半年就能回款10%,后面每个月都会有现金流,资金压力就大大减轻了。
- 降低风险:敏捷开发的第二个好处是,及时了解市场需求,降低产品不适用的风险。请想一想,哪一种情况损失比较小:10栋楼都造好以后,才发现卖不出去,还是造好第一栋楼,就发现卖不出去,从而改进或停建后面9栋楼。
1.4 持续集成
1.4.1 什么是持续集成
持续集成(Continuous integration,简称CI)指的是,频繁地(一天多次)将代码集成到主干。继续集成的目的,就是让产品可以快速迭代,同时还能保持高质量。它的核心措施是,代码集成到主干之前,必须通过自动化测试。只要有一个测试用例失败,就不能集成。
通过持续集成,团队可以快速的从一个功能到另一个功能,简而言之,敏捷软件开发很大一部分都要归功于持续集成。
1.4.2 持续集成的流程
根据持续集成的设计,代码从提交到生产,整个过程有以下几步。
提交:流程的第一步,是开发者向代码仓库提交代码,所有后面的步骤都始于本地代码的一次提交(commit)。
测试(第一轮):代码仓库对commit操作配置了钩子(hook),只要提交代码或者合并进主干,就会跑自动化测试。
构建:通过第一轮测试,代码就可以合并进主干,就算可以交付了。交付后,就先进行构建(build),再进入第二轮测试。所谓构建,指的是将源码转换为可以运行的实际代码,比如安装依赖,配置各种资源(样式表、JS脚本、图片)等等。
测试(第二轮):构建完成,就要进行第二轮测试。如果第一轮已经涵盖了所有测试内容,第二轮可以省略,当然,这时构建步骤也要移动到第一轮测试前面。
部署:过了第二轮测试,当前代码就是一个可以直接部署的版本(artifact)。将这个版本的所有文件打包存档,发到生产服务器。
回滚:一旦当前版本发生问题,就要回滚到上一个版本的构建结果。最简单的做法就是修改一下符号链接,指向上一个版本的目录。
1.4.3 持续集成的组成要素
1、一个自动构建过程,从检出代码、编译构建、运行测试、结果记录、测试统计等都是自动完成的,无需人工干预。
2、一个代码存储库,即需要版本控制软件来保障代码的可维护性,同时作为构建过程的素材库,一般使用SVN或Git。
3、一个持续集成服务器,Jenkins就是一个配置简单和使用方便的持续集成服务器。
1.4.4 持续集成的好处
降低风险,由于持续集成不断去构建,编译和测试,可以很早期发现问题,所以修复的代价就少。
对系统健康持续检查,减少发布风险带来的问题。
减少重复性工作。
持续部署,提供可部署单元包。
持续交付可供使用的版本。
增强团队信心。
二、GitLab
2.1 GitLab安装
2.2 GitLab项目组&权限
2.2.1 项目组
使用管理员root创建组,一个组里可以有多个项目分支,可以将开发添加到组里进行设置权限,不同的组就是公司不同的开发项目或者服务模块,不同的组添加不同的开发即可实现对开发设置权限的管理。
2.2.2 权限
GitLab用户在组里面有5种不同权限
Guest:可以创建issue、发表评论、不能读写版本库
Report:可以克隆代码、不能提交,QA、PM可以赋予这个权限
Developer:可以克隆代码、开发、提交、push,普通开发可以赋予这个权限
Maintainer:可以创建项目、添加tag、保护分支、添加项目成员、编辑项目,核心开发可以赋予这个权限
Owner:可以设置项目访问权限、Visibility Level、删除项目、迁移项目、管理组成员、开发组组长可以赋予这个权限
三、Jenkins
3.1 Jenkins介绍
Jenkins是一款流行的开源持续集成(Continuous Integration)工具,广泛用于项目开发,具有自动化构建、测试和部署等功能。
Jenkins的特征:
开源的Java语言开发持续集成工具,支持持续集成,持续部署。
易于安装部署配置:可通过yum安装或下载war包以及通过docker容器等快速实现安装部署,可方便web界面配置管理。
消息通知及测试报告:集成RSS/E-mail通过RSS发布构建结果或当构建完成时通过e-mail通知,生成JUnit/TestNG测试报告。
分布式构建:支持Jenkins能够让多台计算机一起构建/测试。
文件识别:Jenkins能够跟踪哪次构建生成哪些jar,哪次构建使用哪个版本的jar等。
丰富的插件支持:支持扩展插件,你可以开发适合自己团队的工具,如git、svn、maven、docker等。
3.2 Jenkins安装
3.3 Jenkins插件管理
Jenkins本身不提供很多功能,我们可以通过使用插件来满足我们的使用,例如从GitLab拉取代码,使用Maven构建项目等功能需要依靠插件完成。
Jenkins国外官方插件地址下载速度非常慢,所以我们一般将地址修改为国内插件地址。
3.4 重启Jenkins
一般我们安装完插件后需要重启Jenkins,我们可以在Jenkis访问地址后加restart
进行重启,http://192.168.1.1:8666/restart
3.5 Jenkins用户权限管理
我们可以利用Role-base Authorization Strategy
插件来管理Jenkins用户权限。
3.5.1 安装插件
3.5.2 开启Role-base Strategy
3.5.3 角色管理
3.5.4 用户管理
3.5.5 分配角色
3.6 Jenkins凭证管理
凭证可以用来存储需要密文保护的数据库密码、GitLab密码信息、Docker私有仓库密码等,以便Jenkins可以和这些第三方的应用进行交互。
3.6.1 安装Credentials Binding插件
要在Jenkins使用凭证管理功能,需要安装Credentials Binding
插件。
3.6.2 Jenkins管理GitLab凭证
前提:已安装Git插件和功能
3.6.2.1 用户密码类型
创建凭证:Jenkins->凭证->系统->全局凭证->添加凭证
3.6.2.2 SSH密码类型
SSH免密登录示意图
1、使用root用户生成公钥和私钥
ssh-keygen -t rsa
- id_rsa:私钥文件
- id_rsa.pub:公钥文件
2、把生成的公钥在GitLab中进行设置
3、把生成的私钥在Jenkins中进行设置
3.7、Maven
在Jenkins集成服务器上,我们需要安装Maven来编译和打包项目
3.7.1 Jenkins构建Maven项目类型
Jenkins中自动构建项目的类型有很多,常用的有以下三种:
- 自由风格软件项目(FreeStyle Project)
- Maven项目(Maven Project)
- 流水线项目(Pipeline Project)
每种类型的构建其实都可以完成一样的构建过程与结果,只是在操作方式、灵活度等方面有所区别,在实际开发中可以根据自己的需求和习惯来选择。
3.8 流水线项目(Pipeline Project)
3.8.1 Pipeline简介
3.8.1.1 概念
Pipeline,简单来说,就是一套运行在Jenkins上的工作流框架,将原来独立运行于单个或者多个节点的任务连接起来,实现单个任务难以完成的复杂流程编排和可视化的工作。
3.8.1.2 使用Pipeline的好处(翻译官方)
代码:Pipeline以代码的形式实现,通常被检如源代码控制,使团队能够编辑,审查和迭代其传送流程。
持久:无论是计划内的还是计划外的服务器重启,Pipeline都是可恢复的。
可停止:Pipeline可接收交互式输入,以确定是否继续执行Pipeline。
多功能:Pipeline支持现实世界中复杂的持续交付要求。它支持fork/join、循环执行,并行执行任务的功能。
可扩展:Pipeline插件支持其DSL的自定义扩展,以及与其他插件集成的多个选项。
3.8.1.3 如何创建Jenkins Pipeline?
Pipeline脚本是由Groovy语言实现的,但是我们没必要单独去学习Groovy
Pipeline支持两种语法:Declarative(声明式)和Scripted Pipeline(脚本式)语法
Pipeline也有两种创建方式:可以直接在Jenkins的Web UI界面中输入脚本;也可以通过创建一个Jenkinsfile脚本文件放入项目源码库中(推荐)。
3.8.2 安装Pipeline插件
3.8.3 Pipeline-声明式
3.8.4 Pipeline-脚本式
3.9 Jenkins常用的构建触发器
Jenkins内置4种构建触发器
- 触发远程构建
- 其他工程构建后触发(Build after other projects are build)
- 定时构建(Build periodically)
- 轮询SCM(Poll SCM)
3.9.1 触发远程构建
访问地址:http://192.168.66.101:8888/job/web_demo_pipeline/build?token=6666
远程触发自动构建
3.9.2 其他工程构建后触发
3.9.3 定时构建
定时字符串从坐往右分别为:分 时 日 月 周。一些定时表达式的例子:
1、每30分钟构建一次:H代表形参
H/30 * * * *
10:02 10:32
2、每2个小时构建一次
H H/2 * * *
3、每天的8点、12点、22点构建一次,天构建3次(多个时间点中间用逗号隔开)
0 8,12,22 * * *
4、每天中午12点定时构建一次
H 12 * * *
3.9.4 轮询SCM
轮询SCM是指定时扫描本地代码仓库的代码是否有变更,如果代码有变更就触发项目构建。注意:这种构建触发器,Jenkins会定时扫描本地整个项目的代码,增大系统的开销,不建议使用。
3.10 Jenkins Git hook自动触发构建
Jenkins的内置构建触发器中,轮询SCM可以实现GitLab代码更新,项目自动构建,但是该方案的性能不佳,那是否有更好的方案呢?有的,就是利用GitLab的webhook实现代码push到仓库,立即触发项目自动构建。
3.10.1 安装GitLab Hook插件
需要安装两个插件:GitLab Hook和GitLab
3.10.2 设置自动构建
3.11 Jenkins的参数化构建
有时在项目构建的过程中,我们需要根据用户的输入动态传入的一些参数,从而影响整个构建结果,这时我们可以使用参数化构建。
3.12 Jenkins配置邮箱服务器发送构建结果
3.12.1 安装Email Extension插件
3.12.2 配置
3.13 Jenkins+SonarQube代码审查
SonarQube是一个用于管理代码质量的开放平台,可以快速的定位代码中潜在的或者明显的错误。目前支持Java等二十几种编程语言的代码质量管理与检测。官网:https://www.sonarqube.org
四、Jenkins+Docker+SpringCloud微服务持续集成
4.1 持续集成流程说明
4.2 Docker
4.3 Harbor镜像仓库
Harbor(港口,港湾)是一个用于存储和分发Docker镜像的企业级Registry服务器。除了Harbor这个私有镜像仓库之外,还有Docker官方提供Registry。相对Registry,Harbor具有很多优势:
提供分层传输机制,优化网络传输:Docker镜像是分层的,而如果每次传输都使用全量文件(所以用FTP的方式并不合适),显然不经济。必须提供识别分层传输的机制,以层的UUID为标识,确定传输的对象。
提供WEB界面,优化用户体验:只用镜像的名字来进行上传下载显然很不方便,需要有一个用户界面可以支持登录、搜索功能,包括区分公有、私有镜像。
支持水平扩展集群:当有用户对镜像的上传下载操作集中在某服务器,需要对相应的访问压力做分解。
良好的安全机制:企业中的开发团队有很多不同的职位,对于不同的职位人员,分配不同的权限,具有更好的安全性。
4.3.1 Harbor项目
Harbor的项目分为公开和私有的
公开项目:所有用户都可以访问,通常存放公共的镜像,默认有一个library公开项目。
私有项目:只有授权用户才可以访问,通常存放项目本身的镜像。
五、Kubernetes实现Master-Slave分布式构建方案
5.1 传统Jenkins的Master-Slave方案的缺陷
Master节点发生单点故障时,整个流程都不可用了。
每个Slave节点的配置环境不一样,来完成不同语言的编译打包等操作,但是这些差异化的配置导致管理起来非常不方便,维护起来也是比较费劲。
资源分配不均衡,有的Slave节点要运行的job出现排队等待,而有的Slave节点处于空闲状态。
资源浪费,每台Slave节点可能是实体机或者VM,当Slave节点处于空闲状态时,也不会完全释放掉资源。
以上种种问题,我们可以引入Kubernetes来解决。
5.2 Kubernetes简介
Kubernetes(简称K8S)是Google开源的容器集群管理系统,在Docker技术的基础上,为容器化的应用提供部署运行、资源调度、服务发现和动态伸缩等一系列完整功能,提高了大规模容器集群管理的便捷性。其主要功能如下:
使用Docker对应用程序包(package)、实例化(instantiate)、运行(run)。
以集群的方式运行、管理跨机器的容器。
解决Docker跨机器容器之间的通讯问题。
Kubernetes的自我修复机制使得容器集群总数运行在用户期望的状态。
5.3 Kubernetes+Docker+Jenkins架构图
5.4 Kubernetes+Docker+Jenkins持续集成方案好处
服务高可用:当Jenkins Master出现故障时,Kubernetes会自动创建一个新的Jenkins Master容器,并且将Volume分配给新创建的容器,保证数据不丢失,从而达到集群服务高可用。
动态伸缩,合理使用资源:每次运行Job时,会自动创建一个Jenkins Slave,Job完成后,Slave自动注销并删除容器,资源自动释放,而且Kubernetes会根据每个资源的使用情况,动态分配Slave到空闲的节点上创建,降低出现因某节点资源利用率高,还排队等待在该节点的情况。
扩展性好:当Kubernetes集群的资源严重不足而导致Job排队等待时,可以很容易地添加一个Kubernetes Node到集群中,从而实现扩展。
5.5 Kubernetes架构
API Server:用于暴露Kubernetes API,任何资源的请求的调用操作都是通过kube-aipserver提供的接口进行的。
Etcd:是Kubernetes提供默认的存储系统,保存所有集群数据,使用时需要为etcd数据提供备份计划。
Controller-Manager:作为集群内部的管理控制中心,负责集群内的Node、Pod副本、服务端点(Endpoint)、命名空间(Namespace)、服务账号(ServiceAccount)、资源定额(ResourceQuota)的管理,当某个Node意外宕机时,Controller Manager会及时发现并执行自动化修复流程,确保集群始终处于预期的工作状态。
Scheduler:监视新创建没有分配到Node的Pod,为Pod选择一个Node。
Kubelet:负责维护容器的生命周期,同时负责Volume和网络的管理
Kube proxy:是Kubernetes的核心组件,部署在每个Node节点上,它是实现Kubernetes-Service的通信与负载均衡机制的重要组件。