为什么要持续集成与持续部署
DevOps、持续集成、持续交付、持续部署、敏捷等词语大家应该都耳熟能详了,说到底就是快速交付价值,从工程上、管理上、组织上、工具上来提高效率,打造可靠的、快速的产品(项目)交付过程。本书将围绕项目管理、自动化部署、自动化发布、自动化测试、容器云来实现持续集成、持续交付及持续部署,因为它不是一本理论图书,不打算大谈道理,我们将直接谈论持续集成、持续交付、持续部署的价值,抛出问题,说思路,讲方案,讲实际操作。希望能够帮助广大读者快速在企业落地持续集成、持续交付与持续部署。
1.1CI&CD 的价值
持续集成(Continuous Integration,CI)是一种软件开发实践。在持续集成中,团队成员频繁集成他们的工作成果,一般每人每天至少集成一次,也可以多次。每次集成会经过自动构建(包括静态扫描、安全扫描、自动测试等过程)的检验,以尽快发现集成错误。许多团队发现这种方法可以显著减少集成引起的问题,并可以加快团队合作软件开发的速度(以上引用自Martin Fowler 对持续集成的定义)。
持续交付(Continuous Delivery)是指频繁地将软件的新版本交付给质量团队或者用户,以供评审,如果评审通过,代码就进入生产阶段。
持续部署(Continuous Deployment)是持续交付的下一步,指的是代码通过评审以后,自动部署到生产环境中。
通过上面的定义我们不难发现,持续突出的就是一个快字,商业软件的快速落地需求推动了软件工程的发展。可持续的、快速迭代的软件过程是当今主流开发规约。尤其在互联网行业,快速响应即是生命线。从一个想法到产品落地都处在冲锋的过程中,机会稍纵即逝。响应用户反馈也是万分敏捷,早晨的反馈在当天就会上线发布,快得让用户感觉倍受重视。“快”已经成为商业竞争力。这一切都要求企业具备快速响应的能力,这正是推动持续集成、持续交付、持续部署的动力。
产品或者项目的参与者应该能够深刻体会到团队协作时,工作交接(系统集成)部分最容易出问题,会消耗大量的沟通成本与时间成本,直接拖慢进度。所以,一个行之有效的项目管理过程(包括沟通管理、流程管理)在大型项目中效果明显。当前敏捷开发是主流,持续集成、持续交付与持续部署正好能够帮助高效地实施敏捷过程,促进开发、运维和质量保障(QA)部门之间的沟通、协作与整合。
1.2 CI&CD 带来的变化
通常把开发工作过程分为编码、构建、集成、测试、交付、部署几个阶段(见图1-1),持续集成、持续交付、持续部署刚好覆盖这些阶段。从提高效率上来讲,对每个阶段的优化都可以缩短软件交付时间。持续集成、持续交付及持续部署的过程即是一个软件开发优化过程。
墨菲定律大家都不陌生,越是担心什么就越会发生什么;在多团队协作时,比如系统对接时,我们都会担心对接是否顺利,往往也不枉我们担心,时常我们会被集成折磨得焦头烂额。有很多团队只是担心,并没有拿出有效的措施去避免这种事情发生,以至于延长了交付时间。既然担心,我们何不及早集成,把问题先暴露出来?
目前多数公司都已经使用了版本管理工具来管理源码,比如GitLab、SVN 等版本管理工具。在版本管理这一块,公司会根据自己的实际情况来制订版本管理办法。对于持续集成来说,业内建议只维护一个源码仓库,降低版本管理的复杂度。开发人员持续提交自己的修改,自动触发编译,自动集成,自动进行自动化的测试,及早反馈集成过程中的问题,就能更好地防止出现平时不集成、集成就出问题的现象。
通过自动化的持续集成,把管理流程固化;保证集成的有序性、可靠性;减少版本发布的不合规性(开发或者测试手动打包,可能一天打多个包,更新多次,测试不充分),保证版本可控,问题可追溯(至于哪个版本出现的问题,可以回溯)。
一旦把这种持续集成的过程固定下来,形成一个自动化过程,就具备了持续集成的能力,软件交付的可靠性就大大增强,这无形也是一种竞争力。这种竞争力保证了集成的有序性、可靠性。过程的自动化抛弃了人工,降低了出错率,提高了速度,自然会节省成本。
1.3 CI&CD 实施现状
在日常生活中处处都体现着一个“快”字,互联网更是对快追求到极致。持续集成、持续交付、持续部署在互联网行业更为广泛。作者没有统计哪些公司在用,只是圈子中朋友公司都实施了持续集成,具备持续交付能力。至于持续部署就没这么广泛了,毕竟持续部署不仅仅是技术问题,还涉及管理、营运等问题。尤其是一些金融企业、大型国企,开发团队外包,测试外包,运营半外包,安全要求高,很难快速实施。多数能够在测试环境中建立起CI&CD就已经很不错了。
阿里云、腾讯云、网易蜂巢等国内云,都提供了从GitLab 下拉代码、编译打包、单元测试、镜像制作、容器发布的功能。这个过程实际上就是持续集成、持续交付的过程,同时具有持续部署的能力。基本上,持续集成、持续交付、持续部署是一种服务能力,是云平台必须具备的能力。
下面引自2017 年DevOps 现状调查报告。
统计资料显示,DevOps 正在各个行业、各种规模的企业中落地。DevOps 团队的比例在2014 年是16%,在2015 年是19%,在2016 年是22%,在2017 年已经增长到27%,越来越多的企业和团队开始拥抱DevOps。图1-2 是2017 年DevOps 现状调查报告统计的从业分布情况。
完整的报告可以从qcloudimg 网站下载。
在本书撰写过程中2018 年DevOps 现状调查报告也已经出来,图1-3 是精英级执行团队使用DevOps 后的效率。精英级执行团队在以下几个方面有着突出的表现。
1)代码发布频率高46 倍。
2)代码从提交至发布的速度快2555 倍。
3)故障变更率降低1/7。
4)事故恢复时间快2604 倍。
另外,云计算持续增长(见图1-4)。有17%的调查者仍然没有使用云厂商的服务。AWS最受欢迎,占比为52%,Azure 屈居次席,占比为34%。
1.4 CI&CD 技术栈
目前持续集成、持续交付、持续部署在开源社区都是热点,用户可以方便地利用这些开源组件来构建自己企业的持续集成、持续交付及持续部署平台。
持续集成工具中以Jenkins 使用最为广泛,由Jenkins 来作业化持续集成过程;利用GitLab来管理程序版本;利用Gerrit 来做代码审核;利用Sonar 进行代码质量扫描;利用JUnit 进行单元测试;利用Docker compose 来构建镜像;利用Docker 来部署容器;利用Kubernetes、Rancher 等进行服务编排。图1-5 显示了常见的CI&CD 技术栈。
后续讲解CI&CD 落地时会运用到其中的一些技术与工具。当然,基本上都运用开源工具,这也有助于企业在落地时节省费用。
1.5 大规模部署的烦恼
对于同样的功能,在用户量不同的系统中,工作量是完全不同的,后台为性能考虑而设计的架构完全不一样。对于CI&CD 也是如此,小规模的很容易,配几个作业就可以完成工作,但对于大规模的CI&CD,一旦系统数量、实例数量上去后各种问题就都来了。下面列举几个主要的问题。
1)更新问题。更新一次要耗费大量精力,很多企业都是晚上更新,员工得通宵加班,还不能保证更新没问题,不具备快速大批量部署的能力。
2)部署包(jar 包、war 包、ear 包等)的管理问题。为了保证版本可追溯,出错后能够回滚,我们需要保存各个历史版本,而且方便下载。
3)版本的安全性。传统上以Java 语言开发的系统多数以jar 包、war 包、ear 包的方式发布,容易被篡改(人为修改,传输过程不完整);通常我们用md5 来验证完整性,但包与md5 对应关系的管理并没有系统化,往往在出问题后人工进行md5 验证。
4)主机管理问题。系统部署到哪些机器上需要进行主机管理?在部署时人工选择部署到哪台主机显然不是一种明智的方式,能否自动进行调度?同时,不会产生有些主机性能堪忧、有些主机空闲导致的负载不均情况。
5)端口管理问题,在部署Java 项目时我们并不建议设置太多的JVM 内存,因此一台主机上往往能够部署多个应用实例,同一台机器上多个实例的开放端口就必须不一致,于是端口又成了需要管理的资源。有人会说可以选用虚拟机,一台虚拟机上只部署一个实例。当然,这也是可以的。实际上,多数企业也是这么做的。这种做法也有弊端,虚拟机虽然帮助做了隔离,但会损失一些主机性能;虚拟机要使用内网IP,这样IP 又成了稀有资源,当部署多个实例时IP 会不够用。
6)负载均衡管理问题。不管是在主机上部署多个实例,还是利用虚拟机来部署多个实例,在做集群时,都会通过代理(Nginx、Apache、LVS……)软件来做负载均衡,因此我们需要把各实例的访问地址配置到负载器的配置文件中。实例数少的时候手工配置还可以接受,多了就没法手工配置了。当然,方法也会有,比如用Etcd+Confd+Nginx(HAProxy)来做服务发现,我们需要自己部署一套工具,并进行维护,复杂的框架提高了对运维人员的要求。
7)服务伸缩问题。当服务访问量上去后,要能够具备快速扩充的能力;当访问量下去后,要能够具备缩小服务规模的能力,收放自如。这种弹性的服务能力显然是通过工具来完成的,手动完成是不可能的。
8)IP 管理问题。当大规模部署后,IP 资源会成为稀有资源,如何用更少的IP 来部署更多的服务?IP 的分配及管理显然不能人工完成,那样效率太过低下,这就需要一个IP 管理工具。
如果有一个系统能够一站式解决以上问题,那真是太完美了。因为没有这样的系统,所以很多公司开发了他们的运维平台,专门用来解决大规模部署问题。但对于中小公司来说,技术与人力投入往往受限,没有这个能力、精力或者财力去建立一个智能的运维平台。但是我们可以利用开源工具、开源技术来搭建一个相对完善的持续集成、持续部署体系。
1.6 实施云平台化
虚拟化、云平台化为大规模部署提供了方便,尤其是在硬件资源管理及网络管理方面。互联网的火热更是推动了云的快速发展,基本上各大互联网企业都已经完成了云平台化,生产力也在不断提升。以Docker 为代表的容器化技术出现后,云变得更灵活,容器化已经成为大潮,Docker 也占据了容器市场的绝对份额。容器部署方式能够满足快速大批量部署的要求,充分利用物理机器资源。以Docker 为例,Docker 容器技术让应用一次构建,到处(物理机、虚拟机、公有云、私有云、Windows 系统、Linux 系统等)可运行,加快了本地开发和构建,实现了快速交付和部署;同时还可以在操作系统层面提供资源隔离服务。
为了提高服务水平,企业服务需要能够快速水平扩展,在系统设计层面也大举采用SOA框架,这种框架天生适合使用容器大规模部署。当然,也存在一些问题,比如管理大量的服务实例成为一个挑战,运维、监控、问题分析等变得复杂。那么如何管理这些容器呢?于是就产生了大量的容器管理工具,支持Docker 容器管理的工具使用得比较广的有Swarm、Mesos、Kubernetes、Rancher 等工具。这些工具能够帮我们方便管理容器,虽然有一些问题的解决方式并不完美,但这也给运维开发、测试开发提供了更多的想象空间与工作机会。目前容器管理工具Kubernetes 影响最大,但Kubernetes 的学习与运维成本相对较高,需要专业人士的支持。目前国内大型互联网公司基本都基于Kubernetes 来管理大量容器,包括BAT、京东等企业。腾讯的蓝鲸(DevOps)也基于Kubernetes,已经开始市场化;淘宝的云效也是与蓝鲸同类型的产品。
对于中小型企业来说,上Kubernetes 显得有点操之过急,需要有技术储备与维护团队,学习成本相对也会高一点,因此应该选择简单的、快速能够落地的、能够满足企业要求的、有一定市场的工具。当然,最好还是开源的,社区也支持的。所以我们选择Rancher,据说早期云效也是整合Rancher 的,作者也在基于Rancher 做整合,利用Rancher 实现容器的管理,利用Jenkins 构建,利用GitLab 实现源码管理,再加上静态扫描、自动化测试、性能测试、日志管理等功能,整合成DevOps,足够运行、管理上千个实例级别的容器实例。实际上,拥有DevOps 并且已经容器化,就相当于已经拥有一个相对智能化的私有云平台(不是真正意义上的云,并没有对物理资源进行管理,抽象成服务)。图1-6 是作者早期开发的DevOps静态架构。
此平台类似于一个私有云平台,基本涵盖了系统的生命周期:编译、打包、发布、测试、上线、运维、下线。同时把硬件资源管理起来,这些硬件对用户透明。平台主要分3 层。
• 基础组件层,提供了存储、网络与运算功能。对于上层来说,硬件只是一个服务而已。
• 服务组件层,提供了运维与监控功能。对于大规模系统营运来说,系统监控、问题诊断分析变得复杂,必须在系统层面给予帮助,结合平台能力,让用户分析问题变得简单。那种从服务器上看日志的老旧方式一去不复返了。
• DevOps 用户层,直接面向运维人员,做到持续集成、持续交付、持续部署,在平台中完成各种测试。支持多种形式的发布,减少上线风险。
图1-7 是上述平台用到的技术栈。下面对用到的部分工具进行简单说明。
• Rancher:一个开源的企业级容器管理平台。通过Rancher,企业再也不必自己使用一系列的开源软件去从头搭建容器服务平台。Rancher 提供了在生产环境中使用的管理Docker 和Kubernetes 的全栈化容器部署与管理平台。
• Jenkins:用于构建管理,定义管理工作过程。
• Docker compose:一种定义编排容器的工具,以YAML 或者XML 的格式展示编排内容。
• Maven:源码编译工具。
• GitLab:源码管理工具。
• Gerrit:代码审核工具。
• Sonar:代码静态扫描工具。
• robot:自动化测试工具。
• Ceph:分布式存储产品。
• Spring Boot:DevOps 集成开发技术框架。
• React:门户开发框架。
• Redux:门户开发框架。
• MySQL:数据库。
• MyBatis:ORM 框架。
• Kibana、Logstash、Elastic:用于统一进行日志管理、日志存储、日志分析。
本书讲到的CI&CD刚好是这个DevOps 的一个子集,我们将围绕上述架构及技术栈展开,
本书不仅讲解如何实现,还会结合实例展示如何落地。这些对于大多数中小型企业来说已经足够支撑业务。企业给CI&CD 加上Web 版本的门户、集中的账户管理体系以及运维监控体系,即可打造一个智能的DevOps 平台。
图1-8 是CI&CD 流程,后面的实例也将围绕这个流程。
下面先简单介绍该流程。
1)程序员提交代码。
2)Gerrit 做代码审核,通过提交到GitLab,能通过邮件通知相关人员。
3)Sonar 做代码静态扫描,并把结果通知相关人员。
4)在GitLab 中贴标签(通过WebHook 触发Jenkins 作业)或者手动在Jenkins 中触发作业,Maven 开始下拉代码进行编译,然后进行单元测试和打包。
5)打包完成后利用Docker cli 构建镜像。
6)把镜像上传到镜像仓库中。
7)Jenkins 作业触发Rancher 在测试环境中启动容器,首先下拉镜像,然后根据配置启动容器。
8)Rancher 自动或者按规则调度容器在哪台机器上运行。
9)Rancher 负责容器生命周期管理(启动、监控、健康检查、扩展等)。
10)进行自动化测试。
11)测试通过后,Jenkins 触发Rancher 在生产环境中启动或者更新测试通过的服务,当然,也可以手动在Rancher 中进行发布,当实例增加时只需要填写实例数量即可快速扩展,在发布时可以支持灰度发布、蓝绿发布等个性化的发布需求。
注意:
1)我们一直不加上云平台这个名称,是因为云平台的定义太广,我们并没有产品接入功能,比如提供数据存储服务、缓存服务,以及提供大数据运算能力。
2)当然,我们也具备云要提供的很多服务,所以在把下面要讲的一套东西落地后,也可以冠以云平台之名,其他的功能可以慢慢补上来。“欲立新功,行之有名;立人之先,憨享其成。”
由于要用的工具比较多,这些工具多由外国人开发,译过来叫法比较多,因此为了方便讲述,下面介绍术语。
• 服务:完成某一功能的程序。
• 服务实例:程序部署单元,比如一个订单程序由Tomcat 启动,一个这样的部署单元(一个JVM 实例)称为一个服务实例。
• 容器:如Docker 容器。
• 容器实例:镜像的运行态叫容器实例,如果运行一个Nginx 镜像,那么这就是一个容器实例,我们利用镜像运行两个Nginx,那么实例数为2;这些实例称为容器实例,一定语境下直接称为实例。
1.7 本章小结
本章简单叙述了进行CI&CD 的价值,以及通过CI&CD 的实施能够帮我们解决什么问题。结合当前的CI&CD 技术栈,我们知道要朝哪个方向去发力建立自己的私有云平台。利用当前的开源技术实现CI&CD,运行自己的私有云平台,加速企业的系统集成效率,缩短部署时间,提高成功率。
本文摘自《持续集成与持续部署实践》
作者:陈志勇 钱琪 孙金飞 李诚诚
腾讯、阿里、滴滴等公司众多专家推荐
讲述如何用Docker构建集成容器、镜像仓库规划及管理
一书在手,持续集成无忧。
本书来自一线的实践经验,深入呈现技术细节;详实的实操示例,即学即用的实战技术。
讲解了持续集成中引人入胜的内容:CI/CD到底要解决什么问题?它与DevOps之间的关系是怎样的?程序员如何用工具化的系统持续进行代码的版本管理、构建、打包、集成、测试和部署?利用云平台和容器技术实现弹性伸缩价值等。