7 月 6 日上午,在 ArchSummit 2018 深圳站 | 全球架构师峰会上,七牛云工程效率部技术专家宫静分享了《基于容器和大数据平台的持续交付平台》为题的演讲。本文是对演讲内容的整理。
本次分享的主要内容是基于容器和大数据平台去构建的持续交付系统,是七牛云工程效率部在持续交付、容器化方面去做的技术实践。将从以下两个方向展开:一个是容器化方向,一个是持续交付的平台。主要会结合在七牛云的实践来介绍这个持续集成、持续部署在容器化方向的探索和思考,以及未来方向的考虑。
01 业务场景的介绍
七牛云业务场景:
上图的数字其实是七牛云的业务场景的缩影,七牛云现在有六大产品线,围绕这六大核心业务,我们有 500 多个组件和服务,这个数字可能还在持续地变化,不断地上升,不断地发展。我们外部的业务需求是这样的,因为市场在快速变化,它对我们业务需求要求是有一个快速迭代的能力,快速发布的能力。工程效率部的目标是在保证质量的前提下来做到一个快速的验证和有效的发布的能力。而产品研发人员和工程效率这边是这样的一个人员比,在这样的一个人员比下,我们会遇到哪些问题呢?
02 研发团队在质量、工程效率所面临的问题总结
以下是我们研发团队面临的一个真实的问题的总结。当一个团队中的开发人员面对的是怎么样一个开发场景,开发人员要面对的是多样化的编译运行环境,要保证从代码开发到编译到运行到调试自测这样一个完整的路径覆盖,当他完成这个路径过长的时候,就会影响他的开发效率。覆盖这样一个完整的路径目前有一个什么样的挑战呢?
第一部分是我们的服务比较多的,产品结构是比较复杂的,在各种情况下调试自测的难度是增加的。首先我们开发人员并不是去独立开发,通常情况下是一个很大的团队,需要一个团队合作,这个团队中可能有多个人在并行进行开发,然后如何去有效把这些并行的开发高效的集成在一起,做到一个快速的迭代,同时合并不会对主干代码的稳定性和质量造成一个不稳定的风险。
第二部分是质量方面的问题。质量的同学面对的是复杂的测试场景,对业务产品在不同的测试环境下做多样的验证,保证我们的产品能在各种各样的复杂场景下都能正确稳定的运行。第二点,通常情况下测试资源是有限的,我们要合理地做一个规划,用有限的资源应对集成测试、性能测试等各种情况的验证需求。第三点是在面对这么复杂的场景,这么多样的业务,然后我们又怎么去把我们验证效率做提升,来满足我们快速迭代,快速发布的需求。第四点是我们现在经常提到的一点,我们如何在产品研发的整个流程,对代码状态做有效追踪,这是我们要回答的问题,也是我们日常的工作一个重要组成部分。
第三部分是微服务带来的新挑战。我们也观察到说,比如说像刚刚的服务数量的量级是因为微服务模式的实施,微服务架构给我们带来一些好处,但任何事情都是有两面性的,不能先看到它所有带来的好处,而要看到另外一面。
首先是服务拆分之后带来的架构复杂度,服务拆分以后,开发人员可能只需要去关注拆分后的服务,这部分服务它的部署运行,它的功能。但是这个服务它是服务于整个产品的,我们产品的整体由于服务拆分,它的架构变得更复杂了。我们是不是需要有一个架构人员或者是技术人员做整体的把控?当产品在做微服务模式实施的时候,我的架构复杂度不能有一个线性的或者指数性的提升。
第二点就是说,当服务拆分以后,给开发人员带来了一些便利,但是微服务模式它是否是面对整个运维部署的流程的?我们的产品虽然服务拆分了,但仍然要作为一个整体去部署运维。对于测试人员来说,我们要面对的是这样的一个整体的方面,所以我们要考虑的是产品去整体部署运维的难度。
接下来是七牛云工程效率部,在解决这些问题方面,提出的一些方向和思路。
第一个是比较容易考虑到的一点,就是要去保证我们的工具链是完备的,当开发人员从第一行代码开始,就有一个完备的工具链去支持他完成开发,完成整个的调试自测。而研发团队的一些其它角色,比如说测试人员或者运维人员,会遇到其他各种各样的需求,这都需要工具链的支持。
第二个是容器化方向,因为在这样的主题下,容器化方向是大家都在考虑的,它能给我们带来什么好处,首先我们的资源可以大幅提升它的有效利用率。第二点可以做到环境的隔离,然后保证从代码开始就在一致的环境上编译运行,它的可移植性是增强的。
第三点是主要在质量效率上要保证有持续演进的 CICD 系统,这个系统保证我们做快速的迭代,有效的验证。
第四、第五点其实是我们现在一直考虑的问题,如何把一个产品从代码开始,到最终上线去做一个有效的追踪和分析,在不同的开发流程环节中,都需要去追踪,这个功能在开发的时候,它的整体实现是什么样的、它的代码质量什么样的,不同的人有不同的代码实现质量,有的人做了有效的单测覆盖、有的人可能没有单测。对整个研发流程都需要去做打点、追踪、分析,全流程去保证作为一个团队的研发阶段到最终交付的内容是符合我们效率上、质量上的要求。
03 持续交付平台 SPOCK 介绍
下面是对前三点的实践做主要的介绍,也就是持续交付系统 SPOCK 平台。
SPOCK 平台的定位是基于容器和大数据平台的持续交付系统。
第一点是容器化方向的实施,SPOCK 平台可以做到什么。它可以做到的我们容器化测试环境的管理,当用户对测试环境有任何需求的时候可以一键部署,这个一键部署听起来是比较容易的,但是实际上我们有很多的开发维护的细节。
第二点是把容器化服务做到了模板化,它可以自由编排,当我面对的是复杂产品的结构的时候,自由编排会保证创建产品环境的灵活性。
第三点是工作流模块化,不同角色对集成的需求是不一样的,应对这样不同的需求,把工作流各个环节做到了模块化,也就是说研发人员和测试人员,他可以根据他的需求来定制他的工作流,扩展他的工作流,用户可以通过配置来按照需要对这个工作流路径做扩展。
第四点是持续交付及系统的基本,也就是说我们需要跟研发流程中所涉及到的各个系统,比如 jira 系统、github 系统发布系统集成起来,达到代码的持续集成持续发布的目的。
第五点是统一日志服务,它是基于大数据平台构建的。
最后一点就是在持续交付流程的各个环节,我们做数据的打点和收集。这样做是为了去构建持续交付流程上的质量效率体系,数据是可以收集,可以度量的,这些收集和度量可以帮助去优化和改进研发流程,去对质量效率提出下一步的发展空间。
上图现在的持续交付流程示意图,在这个里面可以看到,我们的研发团队的不同角色,都可以去使用 SPOCK 平台,去进行它的持续集成。开发人员可能的使用流程是这样的,当开发完成一部分功能的开发,可以去手动地触发的工作流,这个工作流是在 SPOCK 平台中管理的,它可以做到基于容器化的统一构建,SPOCK 平台可以把构建镜像自动部署到容器云环境中,提供给开发同学进行调试和自测。当代码开发调试自测完成迭代之后,代码提交到代码仓库中去进行管理。在这个提交之后,我们会进入测试环节,测试人员是怎么用这个环境的呢?首先是我们的自动持续集成能力,也就是说我们这个平台集成各种系统,做到代码的自动集成和部署。
测试人员需要对整个产品或者是几个服务做一个集成的测试或者是联调的测试的时候,可以根据自己的需求,对他所维护的集成环境进行一键部署,然后通过工作流来进行集成测试的自动回归验证。在验证通过之后,就可以走到一个持续发布的流程,发布到我们的预上线系统环境。
这是 SPOCK 架构的示意图,SPOCK 平台的两个特性,第一个是容器环境的管理,第二个是在容器环境之上,做到的持续交付的实现,从右边来讲,是容器化方向的实现。SPOCK 平台中把产品抽象成产品模板进行管理,基于这些模板,可以去部署产品实例。这些部署和模板是通过我们的 K8S CTL 模块去实施的,从而在容器集群中去生效,底层就是七牛的容器云服务平台 Kirk Cluster。
上文提到,基于模块化的工作流配置做到了可定制化的交付流程,Reaper 模块执行统一的容器化构建,Warpdrive 对工作流各模块做实际的任务执行。底层还有 SPOCK 涉及到的一些其它服务,比如我们的镜像仓库和对象存储,基于这些基础服务对整个持续交付过程都做到了的软件管理,所以对整个过程都是可追踪的,任何构建的交付对象都在我们的对象存储中去进行跟踪、存储和管理。中间的 Pandora 服务是七牛大数据平台,基于大数据平台对我们整个持续交付流程和测试环境集群做数据的统一收集和分析,最终可以在 Pandora 大数据平台上进行数据分析。
04 产品实施
下面介绍测试环境容器化具体的实施,换句话就是怎么对测试环境做到一键部署。
当我去问一个技术人员说,你怎么把你的服务容器化的时候,技术人员可能他的回答是比较简单的:写一个 Dockerfile 为服务编译容器镜像,底层是 kubernetes 容器编排系统,写一个 yml 文件,描述这个容器怎么在我的集群里面去部署、如何启动运行、服务的伸缩、服务的更新、服务的维护、它的策略是什么样的。并且我去声明服务在这个容器集群里面需要的资源,它的网络和存储。然后通过工具脚本来自动创建,自动更新维护。
当一个服务,或者是几个服务的时候,事情好像就是这么简单,但是当要面临的是几十个服务、上百个服务的时候,事情就变得不那么简单了。我要面对的不仅是服务量级上的变化,我的服务在不同的环境下,不同的场景下,它的配置可能是不一样的,它的运行环境可能是不一样的,它所需要的资源也不一样,比如说我的存储声明在测试环境和在生产环境下是不一样的,同时不同的研发人员需要部署产品结构也是不一样的。要怎么把这些差异在我们平台中去有效地管理和维护起来呢?这个就是 SPOCK 在容器化方向做的一些探索。
首先可以看到的是这个场景,这些小的圆圈圈可能是一个容器服务,或者是我们比较熟悉 K8S 的,认为它是一个服务的最小单元 POD,单个服务就是一个容器镜像加一个部署描述 yml 文件,再加一些配置文件。我们怎么把这些零散的服务把它给组织起来,做到根据需求的差异化部署,提供给开发人员呢?不同的开发人员对环境的要求差异很大,开发只需要关注他负责开发的那一块就够了。它可能有共同的依赖或者是类似的服务需求,又要部署自己正在开发调试的服务。
第二个场景,我们可能看到的是产品结构层级上更复杂一点,要部署的服务之间,有先后启动顺序关系,有服务的依赖,最终作为一个整体的产品去运维和部署。这个主要是在调研的时候,发现的是测试人员的集成测试环境,它对这样的需求会比较多一些。
应对这样的不同环境,我们是怎么去实施的呢?
首先我们把这些单个的服务,给抽取出来,定义一个服务的模板。一个服务的模板包括的是描述这个服务的模板文件,以及这个服务它自身所需要的一些配置文件。简单来说就是一个 YAML 文件,加一些 Config 文件,服务可以按照业务逻辑进行组织成服务组,一个服务组里面的服务,它是没有先后启动顺序的,它是并行的,只是把一个服务放到了一个服务组单元,我们可以对同一个单元下的服务做统一管理。但是当我有层级关系,依赖关系的时候,有先后启动顺序的时候,在服务组织上又有个整体的产品结构概念,这个产品结构把不同的服务组做一个层级的管理。比如说我先起第一级别的服务组,再起第二级别的服务组,再起第三层级的服务组,服务组之间是按照顺序去先后启动,它是有一个依赖关系的。
对应到我们真正的产品上,现实是什么样的呢?一个实际案例是要去部署一个带数据库服务的架构的时候。首先我可能要去定义这个产品结构,我把产品中的服务做一个抽象,做一个隔离,做了一个拆分。抽象出前端的服务、后端服务、数据库服务,我们把这些前端服务、后端服务、数据库服务都模块化,作为服务模块去管理。
编排的时候把服务按照逻辑编排到服务组,服务组内部都是平行的,同一服务组没有先后的启动顺序。但是当我要整体的去部署这个产品的时候,我可能先去部署数据库服务组,然后再去部署我的后端服务组,最后再去部署我的前端服务组,当我的所有服务组都部署完成之后,我们整个产品就可以对外提供一个可访问域名,然后作为一个整体去运行起来。
另外是我们在实施中发现可能还会遇到一些实际问题,比我们想象的更要复杂,是不是所有的服务都在容器化的环境下去运行。我们首先要明确一点,我们把服务做容器化的时候,前面描述的是服务怎么去运行,怎么去部署,但是实际我们在做容器化方案的时候,我们要考虑的一点就是容器化不等于把一个服务从物理级直接迁移容器上面去部署运行,因为我们在物理级部署和容器部署这两个不同的部署架构上,其实在服务场景是有差异化的。
什么样的服务适合在物理级上部署,什么样的服务适合在容器化的环境下部署,在目前的这个容器服务上或者是现有的解决方案上,一些特殊服务是不是还不能做到在容器环境中提供等同的服务支持。所以我们在实际做这个容器化方案的时候,我们需要去做一个整体的评估和审核,拿到一个产品去做容器化的时候,要去进行设计,我这个容器化环境提供的是什么样的业务场景、提供的是什么样的服务能力、它是否是跟我们物理级部署提供的一样的目的和一样的场景支持。同时我们要对容器化的范围也做一个界定,什么样的服务做容器化,什么样的服务不做容器化,这个是要根据我们实践和方案评估来确定的。
在实践中遇到了这样的情况,也就是说一些服务我们判断它在现有的方案下不适合做容器化,那么怎么做到说,去提供一个可以一键部署的测试环境呢,这里是 SPOCK 的解决方案,我们把物理级部署和容器部署做一个打通,也就是说在 SPOCK 去进行一键部署的时候,物理机部署和容器服务部署同时支持的,服务之间可能有物理级部署和服务部署两部分,然后它们之间可以互相依赖,这样的方案有一个前提,然后也有很多的技术细节。首先 SPOCK 平台需要把已有的物理级部署方式在平台上实现,并且对接。然后我们需要去梳理我们的服务依赖关系,通过统一的配置管理和统一的规划来进行部署实施。
接下来就是我们实施中遇到的一个日志方面的实际问题,比如说当我的容器服务去重启伸缩的时候,它的日志,到底是怎么管理去收集的,这个我们现在的实施是基于大数据平台做一个统一的日志收集和分析的服务,也就是说我跑在这个容器集群上面的所有测试环境,我都基于这个大数据平台它的数据源收集的组件去进行数据收集,数据收集之后,我们的日志数据其实不是存储在容器集群的存储当中的,我们现在把它统一放在数据平台上做日志管理,通过这个日志管理我们也发现可以有一些新的创新点,当日志统一收集起来之后,它可以做到的是,它可以做更高效的分析,可以定制化的搜索,业务报警,这是我们现在发现,通过这个解决方案给我们带来的一些好处。
这个大数据平台也不只是去收集我们的统一日志服务,前面可以看到我们的系统定位是一个持续交付的系统,持续交付也就是在代码的初始阶段就进入了这个系统,但是在这个流程持续运行的时候,各个环节它的代码质量到底是什么样的,我们需要去观察、去收集、去度量,也就是说在代码进入到持续交付系统之后,就对每个环节做一个数据收集,在代码的构建阶段、单测阶段、部署阶段、集成测试、分发阶段,都去收集各种有效数据,去把它给放到我们数据平台。
这个数据做什么用呢?这个数据作为我们一个质量效率体系的数据基础,这个数据基础可以去有效度量代码在进入持续交付、持续迭代的流程中,它到底是处于一个什么状态的,是否在某一个环节,或者是某几个环节,有一个比较好的可改进的空间。
这里给了一个图,是我们持续交付流程中收集的系统测试的覆盖率。我们能评估到每一次开发提交代码,系统测试是否有效覆盖到了代码,它有一个整体的评估。代码提交后自动触发这些自动进行持续集成和持续构建的流程,在这个过程中,这些数据就自动进入我们的质量效率体系,生成度量指标用于评估。
05 关于未来的挑战和思考
最后介绍的是我们未来考虑的一个方向。
这个方向比较大,就是我们希望把测试服务化,对研发团队进行开放。现在做到的是测试环境,作为一个一键部署的服务去提供开放,之后希望把所有的这些持续交付的流程环节都把它给模块化、服务化,作为测试服务提供出去。这样所有开发人员都是可以通过服务化的方式,去使用我们的测试体系、质量体系。
以上是今天全部的内容分享。
关注公众号【七牛云】,了解更多信息哦~