传统持续集成跟容器化持续集成的区别

两万余字的系列干货长文攻下歭续集成与持续部署!


通过前两篇文章《持续集成与持续部署宝典Part 1:将构建环境容器化》和《持续集成与持续部署宝典Part 2:创建持续集成流沝线》,我们使用Docker创建了一个集中管理的构建环境它可以应用到任意数量的机器上。接着我们将环境设置到了Jenkins CI上,自动化处理了源代碼的持续构建、打包和测试在本章中,我们将进一步对流水线进行研究(如下所示)了解如何将项目持续部署到一个长时间运行的测試环境中。除了自动验收测试外它还将允许人工测试代码。有了这样的环境你就可以在产品投入生产之前让你的客户或者QA(质量管理員)看到最新的变化。此外它还是一个构建和部署到生产环境的好方法,我们将这一章中进行介绍

在我们构建并且测试了应用程序后,可以将它部署到一个长期运行的、潜在面向外部的环境中这种环境要允许客户或者QA在产品投入生产前查看和测试最新的更改,它也是苼产过程中一个重要步骤有了它,我们能够发现在自动化集成测试中会隐藏起来、只有在真实环境才能发现的bug我们通常把这样的环境稱为QA或集成环境,当然你也可以自己命名我们将通过以下步骤来创建集成环境:

  1. 在Rancher中创建一个集成环境
  2. 用Rancher创建应用程序堆栈
  3. 添加对HTTPS的支歭

在Rancher中创建一个集成环境

在Rancher UI中,在左上角选择Manage Environments 以及 Add Environment会出现下面屏幕显示的内容,添加Name(Integration)给每个环境添加一定的描述。你还需要选择囿权访问环境的用户和组织清单

在环境设置好后,在屏幕左上角的下拉菜单中选择Integration(集成)环境现在我们可以为集成环境创建应用程序堆栈了。在这之前我们先了解一下Rancher部署的API密钥。从顶部菜单中选择API > Key接着Add Account API Key。会出现一个弹出式屏幕在这里你可以创建一个命名的API密鑰对。在后续步骤中我们需要使用到Rancher Compose创建测试环境我们将创建名为JenkinsKey的密钥对,由Jenkins实例运行Rancher Compose记得要留下密钥(access key)和密码(secret key)以备后用,の后不会再显示这些值了请注意,API密钥匙是针对于特定环境的因此需要为每个环境创建一个新密钥。

Key和Secret Key之后我们还会使用到。在用戶创建后你需要将AmazonRoute53FullAccess策略添加到用户中,这样它就可以对route53进行更新

现在我们已经有了Hosted Zone以及IAMs用户设置,我们可以将Route53集成添加到我们的 Rancher Server(rancher服務器)有关如何操作的详细说明可以在这里找到: 。简而言之你需要在rancher服务器上浏览Catalog >

该服务会监听Rancher事件,捕获任何任何负载均衡器实唎的启动和终止有了这些信息,它将自动为所有运行负载均衡器容器的主机创建DNS条目DNS条目的格式是[Loadbalancer].[stack].[env].[domain],比如:

随着越来越多的容器在各個Rancher计算节点上启动与关闭Route53服务将保持DNS记录的一致性。这对我们的集成测试环境来说至关重要我们稍后就会看到它的重要性。我们需要偅新启动环境容器来以便将更新作为持续部署的一部分。通过使用Route53 DNS集成我们不必再为给我们的客户和测试人员获取最新主机名而担心叻。

在为我们的环境创建DNS记录后让它支持HTTPS协议会是一个不错的选择。首先我们需要拿到我们域名的SSL证书。你可以从很多可信任的证书頒发机构中选择一个购买域名的SSL证书如果你没有证书,可以生成自签名(self-signed)证书来完成设置在一段时间后把它更换成可信任的证书。洎签名证书的含义是:任何用户都会在浏览器中看到“此连接不可信”的警告但通信仍然是加密的。那么要生成自签名证书首先需要苼成ssl密钥,它可以由openssl的genrsa命令实现然后你可以用这个密钥文件,使用req命令生成证书下面列出了这一步骤。你也可以将证书的sha256指纹打印并儲存下来这样就手动地保证了在发出HTTPS请求时向你显示相同的证书。在缺少可信证书的情况下手动匹配指纹是避免中间人攻击的唯一方法。

File从文件读取)在完成了表单后,点击保存等待片刻证书便生效了。

证书激活之后我们可以将HTTPS端点添加到我们的环境中。想要做箌这一点我们必须修改rancher-compose文件,让它包含SSL端口配置我们将第二个端口(9001)添加到ports部分,让我们的环境可以在负载均衡器之外访问并且使用io.rancher.loadbalancer.ssl.ports标签指定'9001'是具有SSL终止的公共负载均衡器端口。

此外因为我们在负载均衡器处终止了SSL,我们可以使用原9000端口上的常规HTTP将请求发送到我們的实际服务容器中我们使用了io.rancher.loadbalancer.target.auth-service标签来指定从9001到9000的映射。

我们还需要更新rancher-compose文件指定SSL证书该证书是我们在负载均衡器服务中针对SSL终止要使用的。将我们之前上传的证书名称添加到default_cert上有了这些更改,你还需要删除并重新创建堆栈这是因为目前还没有办法将这些属性添加箌已有的堆栈上。

现在可以使用curl命令确保一切正常了当你使用https协议说明符和9001端口尝试相同的命令时,应该会看到一个failure说你使用了一个鈈受信任的证书。你可以使用--insecure开关关闭可信证书检查并且在没有证书的情况下使用https。

在本文中我们开始了持续部署流水线的创建,并苴完成了第一部分的重要工作——创建应用程序环境内容包含在Rancher中创建一个集成环境、定义Compose模板、用Rancher CLI创建一个应用程序堆栈、管理DNS记录、启用HTTPS。

下篇文章将是本系列文章的最后一篇完成创建持续部署流水线的最后工作,敬请期待!

以业务为核心的云原生体系建设

偠做好整个企业的云原生体系建设需要有个总体的视角,不谋全局者不足以谋一域。我们将企业的架构进行全方面的梳理并给出云原生体系建设总图,这个图当然不是一蹴而就就能建设完毕的而是根据业务需求不断迭代演进出来的,但是我们要知道目标在哪里

1、企业架构的五个方面

企业架构不仅仅是技术问题,还有流程问题和组织问题总得来说分为五个方面,业务架构、技术架构、数据架构、研发流程和组织架构

第一个是业务架构,里面承载了企业所从事的业务的核心逻辑目前大部分企业因为系统多是外采的,或者因为原來对于IT投入不够重视处于单体架构的阶段。也有部分比较先进的企业为了应对市场的快速变化,而采用了服务化的架构构建了中台體系。而互联网公司因为要应对高并发流量已经将服务拆分得更加细,实现了微服务架构

第二个是技术架构,为了支撑业务代码的运荇而建设的IT基础实施最初企业多会采购物理机的方式运行业务代码,因为资源使用效率和灵活度的问题很多企业采用了虚拟化平台。從虚拟化平台到云平台的变化不在于技术而在于使用模式,主要是三点统一接口,抽象概念租户自助,说白了就是让业务方不需要特别专业的底层技术能力就能实现应用的部署,同时将运维人员从应对越来越多的业务方的噩梦中解放出来这一点很多企业出现了问題,一些采购了公有云或者OpenStack仍然将所有的操作权限都放在运维那里,把云当成了虚拟化软件在用容器进一步让应用从代码到运行无缝嘚连接起来,并且可以实现跨云的迁移Service Mesh将微服务的治理放到统一的平台上来做,进一步解放业务方

第三个是数据架构,在业务运行的過程中会积累很多的数据。最初企业的系统多只做数据记录的作用并没有发挥太多的价值,数据是散落在各个系统的数据库之中的洳果想进行分析,查看当前业务的运行情况需要一个分析师将数据导出来,做成表格和报告给领导看,这样时效性就会很差后来很哆企业开始做数据的梳理,建设数据仓库并且建设BI大屏,领导驾驶舱支撑战略决策。当然这种方式没有办法和业务直接结合于是才囿的后来的数据运营驱动业务创新,我们在电商和社交APP上感受到的千人千面智能推荐,都是例子

第四个是研发流程,也即代码是如何發布上线的最初企业的发布上线都是手工化的,后来随着服务数目增多开始脚本化。脚本难以维护容易出错,后来就有了统一的发咘平台和云平台相结合,进行自动化的发布流程管理有了容器之后,发布模式有了一定的改变强调开发和运维合作保障在线业务的SLA,而非仅仅运维保障从而发布平台也要DevOps化。

第五个是组织架构根据康威定律,组织架构和技术架构往往是相互影响的如果仅仅调整技术架构,不调整组织架构则不能发挥新技术的优势。最初企业往往是开发和运维完全隔离的甚至是两个老大进行领导,因而不能融匼迭代速度慢,线上高可用无法保证要改变这种方式,除了配备上面的技术平台之外还需要成立中台组或者架构师组,来衔接开发囷运维最终实现开发和运维的融合,共同基于DevOps平台保障线上系统的可用性

2、云原生体系建设总图

根据上面的梳理,我们会发现云原苼体系建设还是非常复杂的,最终会建成一个什么样呢需要有一个目标的总体架构,只有有了目标就可以根据业务的发展阶段,逐步姠这个方向进行靠拢

所以我这里画了一张云原生体系建设总图。

这张图左面是组织架构的部分右面是技术架构的部分。左面和右面相哃颜色的部分就是相应的团队负责相应的技术架构的部分。

我们先看右面技术架构的部分

最底层是数据中心的物理网络,对于数据中惢的基本原理《趣谈网络协议》中有一节专门描述。但是这里的数据中心是云数据中心所以其设计会要求更高,在这个课程会更加详細的描述

在物理网络之上是虚拟网络,最好整个数据中心有一个统一的SDN控制器可以方便不同的环境之间的网络打通,例如物理机Vmware虚擬机,OpenStack虚拟机容器网络,都可以被统一的管理SDN可以是使用硬件的,也可以使用软件的

接着是OpenStack云平台,可以纳管物理机Vmware虚拟机,KVM虚擬机向上提供统一的接口。当然也可以不基于OpenStack创建云平台而用云管平台。OpenStack的好处就是接口统一业内和他配合的工具链比较丰富,有佷多的运维工具可以直接基于OpenStack接口创建虚拟机因而持续集成平台和OpenStack对接会轻松很多,实现基于云接口的应用编排无论是用OpenStack或者其他的雲管平台,作为“云”除了统一接口之外,还要有相应的租户管理体系租户和用户要分层分权限,让平台管理员可以分配给业务方一萣的权限例如Quota,QoS等可以让业务方对于应用部署有一定的自助能力。另外云还要提供一层对于底层技术的抽象例如flavor作为CPU和内存的抽象,VPC作为网络的抽象安全组作为防火墙的抽象等,这样业务不需要特别懂底层技术就能有应用的部署能力。

基于OpenStack云平台可以实现基于虛拟机镜像的运行环境,容器有镜像虚拟机也有,在有容器之前我们就可以对接持续集成平台,基于虚拟机的镜像实现应用的编排將主流的运行环境全部打成镜像,并可以基于虚拟机镜像实现弹性伸缩

基于OpenStack云平台以及虚拟机镜像,可以构建基于虚拟机的PaaS平台也即數据库,消息队列缓存等,都可以变成托管服务让业务方点即可得,不用自己搭建也不用考虑高可用如何配置,主备如何切换PaaS如哬扩容等等,这些全部由虚拟机镜像中的脚本自动化搞定

在此之上是Kubernetes容器平台,他作为统一的编排层可以将Vmware创建出来的虚拟机,KVM创建絀来的虚拟机以及物理机统一的纳管进来,还可以通过多Kubernetes管理纳管公有云上的资源。Kubernetes里面的概念更贴近应用层所以可以看成从资源層到应用层过渡的桥梁,将底层不同的资源全部屏蔽起来对上提供统一的应用编排。Kubernetes的编排能力比OpenStack强很多对概念的抽象也更加对应用伖好,因而持续集成平台可以从对接OpenStack慢慢切换称为对接Kubernetes,可以实现跨云编排迁移,与弹性伸缩

有了Kubernetes,就不用使用虚拟机镜像做应用運行环境了Docker镜像就是天然的运行环境,而且更加的标准化可以跨云迁移。另外有了Kubernetes Operator可以基于容器实现PaaS平台,也即数据库缓存,消息队列的编排

在网上就是应用层了,这里以电商业务为例子业务层已经实现了微服务化,封为两层下层为中台层,也即可复用的能仂强调资源整合和能力沉淀,包括第三方商家供应链,决策用户,商品社交,交易等基础服务上层为业务应用,强调贴近用户快速应对市场变化,包含的系统非常多当然不是任何一个业务都是要一下子拆这么细的,而是逐渐拆分的如何逐步拆分成这样,也昰本课程的重点

为了支撑如此复杂的微服务架构,需要配备相应的工具链例如API网关,微服务管理与治理平台APM性能管理平台,日志中惢配置中心,分布式事务等当然这些工具链也不是一下子都用起来,也是随着微服务的不断拆分逐渐的使用。

这些工具的采用都多尐对于应用有侵入性如果想让微服务的治理能力下层到基础设施层,Service Mesh是一个好的选择

另外还要有端到端统一的监控中心,要下能够监控基础设施上能够监控应用的运行,这样在定位问题的时候才能够互相印证。

我们再来看左面的组织架构

为了讲右面的技术架构运荇起来,要改变原来CIO下面一个技术总监一个运维总监的情况。由于整个技术体系比较复杂需要整个团队基于统一的流程和规范,才能方便管理而如何保证整个系统的运行符合这个流程和规范,仅仅CIO一个人的精力不够需要有一个架构委员会,这里面有专职的架构师包括云的,运维的微服务的,QA的项目管理的,另外架构委员会里面还应该有各个组架构师代表架构委员会对于整个架构的运行,流程和规范的落地负责并像CIO汇报。而且架构委员会会融合各个角色不会出现开发和运维隔离的情况。架构委员会制定流程和规范并要求各个开发和运维组执行。

开发组分成业务开发和中台开发组业务开发组用于快速响应客户的需求,中台开发组不直接面向客户每天想的事情就是能力如何复用,如何锻炼腰部力量只有有一拨人专门考虑这个问题,才有可能积累称为中台

业务开发和中台开发到底是否执行架构委员会制定的流程和规范,需要有一定的工具链的配合因而就需要技术底座组,包括云大数据,容器微服务,已经相应嘚流程管理规范管理,绩效看板等可以让架构委员会通过工具链,实时审核架构当前的运行情况并对不符合流程和规范的接口,测試文档等及时纠正,并计入绩效看板

看完了这些,你可能觉得哇,云原生如此的复杂直接放弃吧。

其实不是的从来没有一种说法是一下子就达到这个状态,而且也不可能通过采购一个大平台公司一下子就形成了云原生架构,这都需要迭代的进行这正是要解决嘚问题。

接下来我会逐层剖丝剥茧的解析这个迭代过程,主要的思路为:

遇到什么样的问题应该采取什么样的技术解决这个问题?如哬解决这个问题的这个技术的实现有很多种,应该如何选型使用这个技术有没有最佳实践,能不能形成企业的相关规范

3、云原生体系演进阶段一:拉通信息系统,重塑组织协同

我们来看第一个阶段拉通信息系统,重塑组织协同

我们分别从企业架构的五个方面依次闡述。

3.1.1、业务架构:单体应用企业消息总线集成

我们还是从业务架构入手分析,大部分企业的信息系统并没有做到这一点——拉通信息系统重塑组织协同,因为大部分系统都是外部采购或者外包公司开发,由不同的团队进行维护这些都是烟囱系统,信息零散格式鈈一致,无法拉通无法协同。

以制造业为例子如图所示,企业外采了CRMMES,ERPHR,PLMSCM等系统,但是各自独立各有各数据库,各有各的权限管理

这样的架构使得企业的各个部门无法协同,例如公司生产两种工业品A和B其中A需要原材料A1和A2,B需要原材料B1和B2突然有一天,销售囚员发现市场情况有所变化原来客户喜欢A和B是1:1的比例,现在突然B的需求量大了起来变成了1:2的关系,这些信息销售人员都将一个个客戶的需求登记到CRM里面,可是工厂并不知道这件事情于是还是按照1:1的来生产,这样A就会滞销B就会脱销,这就需要销售部门的老大根据报告看到这种情况,给生产部门老大说改变生产的比例,但是这又牵扯到原料如果A1和A2,B1和B2还按照原来的数量采购那没有原料,A和B也苼产不出来所以生产部门的老大要同供应链的老大去说。另外还有不同车间的人员比例明显生产B所需要的人才要多了,而且生产B的人偠配备相应的绩效这些HR都不知道,所以要有人告诉HR另外市场发生变化之后,对于公司的收入和利润有什么影响这也是两眼一抹黑。等这些都理清楚那几个月都过去了,市场可能又发生变化了

为了解决这个问题,在多年之前很多企业就采购了企业服务总线ESB和数据茭换工具,将不同的流程打通做到信息拉通,数据集成协同管理。

企业消息总线可以实现不同系统之间不同接口的调用哪怕这些接ロ格式,协议都不一样有的是SOAP,有的是Restful有的是RPC,有的是私有协议他可以做协议的转换。使得一个系统发生的事情另一个系统可以通过接口调用得到结果。也有的功能没有暴露接口那可以通过数据交换工具,将一个系统的数据库里面的数据定时的导出来放到另一個系统里面去,也实现了数据的拉通

虽然这个体系结构比较原来的架构有了改进,但是仍然有问题就是无法支撑业务快速创新。

3.1.2、技術架构:物理机及虚拟化

在第一阶段在传统架构下,基础设施层往往采取物理机或者虚拟化进行部署为了不同的应用之间方便相互访問,多采取桥接扁平二层机房网络也即所有的机器的IP地址都是可以相互访问的,不想互相访问的多采用防火墙进行隔离。

无论是使用粅理机还是虚拟化,配置是相对复杂的不是做过多年运维的人员,难以独立的创建一台机器而且网络规划也需要非常小心,分配给鈈同业务部门的机器网段不能冲突。例如使用Vmware可能需要考一个特别有含金量的证书,才能很好的配置他所有这一切,都需要运维部門统一进行管理一般的IT人员或者开发人员既没有专业性,也不可能给他们权限进行操作要申请机器怎么办,走个工单审批一下,过┅段时间机器就能创建出来。

传统架构数据库层由于系统由外包公司独立开发,或者不同开发部门独立开发不同业务使用不同的数據库,有用Oracle的有用SQL Server的,有用Mysql的有用MongoDB的,各不相同

传统架构的中间件层,每个团队独立选型中间件可能会多种多样。

这个阶段没有所谓的数据架构由于业务是离散的,业务数据库里面的数据也是离散的没有统一标准,虽然有了数据交换工具会使得同一个数据很哆份,各自分析当然公司的领导和部门的领导都想看到当前企业的运行情况的,往往会有一个分析师的团队从业务系统里面导出数据來,形成excel然后利用自己对于流程和行业的理解进行分析,做出各种表格图形,变成报告交给公司领导或者部门领导看,领导肯定会根据报告进行讨论然后根据运行情况调整战略和策略。

研发流程:测试与发布手工化及脚本化

在物理机上部署由于机器数目比较小,鈳以使用手动测试和发布的方法无非是丢上去一个安装包,然后重启一下Tomcat发布就结束了。

后来上了虚拟化机器的数目多了起来,服務数目也多了再手动的一个个部署,工作量就比较大了这个时候多采取脚本化的部署方法,写shell或者写Ansible脚本等,进行自动化的发布与仩线

当然脚本比较难维护,专业性强所以上线还是由写脚本的运维统一完成。

3.1.4、组织架构:研发与运维隔离

运维部和开放部是天然分開的谁也不想管对方,两边的老大也是评级的本相安无事。

统一的运维组管理物理机,物理网络Vmware虚拟化等资源,同时部署上线由運维部负责

开发组每个业务都是独立的,负责写代码不同的业务沟通不多,开发除了做自己的系统外还需要维护外包公司开发的系統,由于不同的外包公司技术选型差异较大因而处于烟囱式的架构状态。

机房当然只能运维人员能碰这里面有安全的问题,专业性的問题线上系统严肃的问题。如果交给没有那么专业的开发去部署环境一旦系统由漏洞,谁能担责任一旦线上系统挂了,又是谁的责任这个问题问出来,能够让任何争论鸦雀无声

阶段一有问题吗?这要从业务角度出发其实也本没有什么问题。

中间件服务层,前端全部由外包商或者乙方搞定,端到端维护要改什么招手即来,而且每个系统都是完整的一套部署方便,运维方便

数据库无论使鼡Oracle, DB2,还是SQL Server都没有问题只要公司有足够的预算,而且性能也的确杠杠的里面存储了大量存储过程,会使得应用开发简单很多而且有专業的乙方帮忙运维,数据库如此关键如果替换称为Mysql,一旦抗不出挂了或者开源的没人维护,线上出了事情谁来负责?

如果一起安好其实没有任何问题,这个时候上容器或者上微服务的确自找麻烦。

那什么时候才会觉得阶段一有问题呢?还是从业务角度出发当伱的系统需要灵活的响应业务变化的时候,才会感觉到痛

例如本来你经营着一家超市,原来主要通过线下进行销售此次冠状病毒突然使得大家都不能逛超市了,这个时候就需要能够线上下单线上销售,但是由于疫情事发突然你外采的供应链管理,ERP等系统根本没办法修改加入自己的业务逻辑,你让外包公司开发的系统也不能随便修改,因为这需要重新招标瀑布式的开发,交付上线。你根本来鈈及

再如你是一个汽车厂商,原来主要通过4S店进行销售突然国家出台了一项激励新能源车的政策,使得你想借此机会促进一下销售泹是你发现外采的和外包的系统同样不能修改,等你改完了风口早就过去了。

没有办法快速迭代上线是阶段一的主要问题,我们还是汾别从企业架构的五个方面依次阐述

3.2.1、业务架构:架构耦合问题,架构腐化问题技术债务问题

外采的程序和外包的程序,为了交付方便往往开发成为单体应用。你可能会说如果变成我自己开发和维护,是不是就能够解决这个问题了而且我有企业服务总线,可以灵活的对于多个单体应用接口做集成那是不是也能够解决,快速迭代上线的问题呢

自然,自己开发和维护灵活性确实要强的多。但是洳果你依然采取单体的架构你将来仍然会存在因为耦合问题导致无法快速响应业务变化情况。

因为任何混合在一起的架构都会不断地腐化,即便你花时间和精力重构了一遍还会再腐化,再重构再腐化。这是架构的天然宿命也是人性而导致的。他不能避免但是可鉯不断地修正。所以架构设计并不能避免架构腐化的问题但是能够解决及时发现及时修正的问题。

如果你不相信这一点那我们就举一個例子,看是不是天天发生在你的身边

就像图中显示的一样,左边是你的领导认为一个单体应用的内部架构里面的几个模块,界限清楚调用分明。而右面可能是实际的内部架构界限已经十分模糊,很多逻辑都糅合在了一起

为什么会出现这种现象呢?第一个原因就昰没时间搞对单体应用内部的界限是不可观测的。我们都知道领导都非常重视功能和bug,因为功能和bug都是可以观测的而且是会影响用戶的体验的。而架构往往不受重视是因为单体运用内部的架构,领导是看不到的他看不到,他就不会给你留时间在开发功能的时候,不断的去调整架构第二个原因,就是没动力搞一旦代码的很多逻辑糅合在一起,那代码的可理解性就会非常的差这个时候重构往往就更加的费时间。而领导又不肯留时间那这时候开发人员就会想,反正领导也不重视代码可理解性差呢,Code Review也Review不出啥来那索性就头痛医头脚痛医脚好了。第三个原因就是没胆量搞。哪怕这时候有一个有技术洁癖技术理想的人想搞这个事情但是他会发现,代码复杂耦合性强,越是核心的逻辑越是不敢动,因为线上出了问题谁改谁负责,所以只好层层封装。

以上的三点都是不可避免的人性。作为管理者和架构设计者不能要求我们的程序员是圣人也不能不考虑人性去解决这些问题。

所以由于以上三点我们就观察到了非常瑺见的两个现象。第一个就是迭代速度慢因为架构的耦合,往往A上线明明不关B的事情,需要B配合B上线明明不关C的事情,需要C配合朂后问了一圈,只好10个功能一起弄完一起上线那上线周期以月为周期。第二个就是可复用性差如果你是一个领导,你会经常问这样的問题明明你记得某个模块里面有某个功能,当另外一个模块需要的时候拿不出来,需要另外开发

最终就形成了技术债务,就像咱们借P2P借了一万,一个月后发现要还两万同理,当领导一年前问你某个功能开发需要多长时间你半天就搞定了,一年后你说要一个星期,领导很困惑以为你开始学会偷懒了,变成老油条了其实领导已经不知道单体应用里面已经一团浆糊了。

3.2.2、技术架构:资源申请慢复用性差,高可用性差

从技术架构的角度来看基于虚拟机技术,资源申请非常的慢因为虚拟机大量地依赖于人工的调度,需要运维囚员非常清楚要部署在什么地方,往往需要通过excel进行维护另外VMware还有一个问题,它使用共享存储会限制整个集群的规模,因为此时的應用不多这个程度的规模还可以接受。

另外网络、虚拟化、存储等基础设施没有抽象化的概念,复杂度非常高开发接不了这个工作,必须依赖运维就要审批。由统一的一帮人来做而且他们要考证书,比如网络要有思科的证书,虚拟化要有VMware的证书要特别专业才能做这件事情,因此会极大地降低迭代速度业务方无论做什么事,都要走审批运维部的人根本忙不过来,就会降低资源的申请速度

所以我们经常观察到这样的现象,业务部门要部署应用本来需要80台机器,却要申请100台因为流程比较慢,万一不够就要重新申请,一旦申请的就不愿意归还运维部,因为说不定什么时候要用上这样资源利用率大大降低。另外部署应用的时候如果基于脚本部署,应該是环境越干净越一致脚本部署的越顺畅,所以本来应该每次部署都是新创建的虚拟机而且一旦一个系统被安装坏了,不必修复这个系统重新创建一个虚拟机是最方便的。本来挺好的虚拟机的特性被审批流程给破坏了,业务部门发现虚拟机坏了想想重新申请太慢叻,于是就忍忍自己在虚拟机里面进行修复,十分浪费时间

多种多样的中间件,每个团队独立选型中间件没有统一的维护,没有统┅的知识积累无法统一保障SLA。一旦使用的消息队列缓存,框架出了问题整个团队没有人能够搞定这个事情,因为大家都忙于业务开發没人有时间深入的去研究这些中间件的背后原理,常见的问题如何调优等等。

3.2.3、数据架构:数据分散质量差单一维度统计分析,囚为报告反馈链长

这个时候的数据是非常分散的不同的数据存在不同的业务系统中,如上面说的单体应用客户管理系统、生产系统、销售系统、采购系统、订单系统、仓储系统和财务系统等或者同一个业务系统但由不同的机器在采集,这都导致了数据没有统一的标准洏是以割裂的形态存在,也就是数据孤岛

但是业务的领导和部门的主管想了解业务的运行情况,就需要有人统计分析这就是分析师,泹是分析师因为生产流程太多了数据太分散了,设备、系统、测量数据一堆每个特性最少N个数据,一方面需要到处找人一方面N多数據接口、N多数据格式,各自为战数据对接不上。所以报告一般以周为单位给出然后层层汇报,领导根据汇报才能调整策略,然后再根据运行情况再出报告,这个反馈链太长要以月为单位了,不能适应市场的快速变化

3.2.4、研发流程:上线依赖人,部署风险高脚本難维护

上线依赖于人工和脚本,人是最不靠谱的很容易犯错误,造成发布事故而发布脚本、逻辑相对复杂,时间长了以后逻辑是难鉯掌握的。而且如果你想把一个脚本交给另外一个人,也很难交代清楚

另外,并且脚本多样不成体系,难以维护线上系统会有Bug,其实发布脚本也会有Bug

所以如果你上线的时候,发现运维人员对着一百项配置和Checklist看半天,或者对着发布脚本多次审核都不敢运行他,僦说明出了问题

3.2.5、组织架构:研发运维标准不一,难保障端到端高可用

线上的高可用性业务层的开发人员不会做任何事情,他认为是線上一旦出事应该由运维集中处理,迫使运维服务的发布人员依赖虚拟化机制来提供高可用机制。我们都知道VMware有非常著名的简化运维嘚高可用机制比如FT、HA、DR等类似的机制。如果我们是从IT层来做高可用有一个缺点,作为基础设施层来讲它看上层没有任何的区别,所鉯没有办法区分业务优先级比如说FT的模式,跑CPU指令它不知道这是最核心支付的指令、还是日志的指令,再如数据中心之间的同步存儲层是无法区分交易数据和日志数据的。这样就会造成一方面该同步的没有同步不该同步的同步了很多,使得线上业务SLA降低了另一方媔浪费了存储和带宽的资源。而且一个服务到底是不是正常需要应用层开放一个health接口来返回,如果应用层不做这件事情基础设施只能通过看进程是否存在,端口是否监听等判断很可能出现进程在,但是服务不可用的情况也会降低SLA。

至此我们看到了阶段一的问题,那应该如何解决这些问题呢我们下一节详细解读。

4、云原生体系演进阶段二:构建中台体系加速业务创新

上一节,我们讲了阶段一的佷多问题其实这些问题归根结底是一个字——散。系统散数据散,流程散组织散,而当前的市场竞争条件下业务创新要争分夺秒,如此“散”的架构没有办法拧成一股绳应对业务的快速变化,就像集团军作战各个部队分兵作战,就不能形成合力

因而要将这些系统,数据流程,组织重新组合形成公司的“腰部力量”,强调能力的沉淀强调融合与复用。只有有了“腰部力量”才能灵活应對业务的快速变化,这就像打篮球“腰部力量”是最重要的,无论是投三分球还是在空中做花哨的投篮动作,看起来是在手腕其实嫃正的能力在腰部。

这就是我们常说的中台中台这个词很火,有的人觉得很好有的人觉得太虚,但是名字无所谓其实就是构建公司嘚可复用能力。

这里给中台下一个相对完整而准确的定义

这个概念需要解读一下。中台是为了体现IT技术IT系统,IT部门的业务价值而诞生嘚概念这一点如果作为一个纯技术,很难感受到这一点感觉中台就是忽悠,如果在一家技术为主导的公司也很难感受到这一点觉得技术的价值马老板都清清楚楚,还需要“体现”吗

但是在传统企业,可不像互联网公司这样重视技术业务部门的老大在中国的市场经濟搏杀了几十年,最后混出来靠的一个是中国过去几十年的快速发展及人口的红利二是老板们对于市场,营销供应链的把控。当然这種野蛮生长的过程并没有对IT技术和IT系统有什么感觉,所以往往会重业务而轻技术重硬件而轻软件。当然低成本人口红利的野蛮生长阶段已经过去老板们也发现过去的这一套有点玩不转了,差异化客户体验驱动产品创新阶段已经到了他们开始眼红互联网公司的兴起了,于是开始设立了CIO这个职责只不过大部分公司的情况是,CIO作为高管在业务老大那里话语权还不高,毕竟钱是业务部门赚的真正IT预算嘟是业务老大要批的,所以在传统企业能够体现业务价值非常重要,这是中台这个词的核心也即定义中的“面向业务场景”以及“支撐业务快速迭代”所强调的,CIO要让CEO业务部门理解IT部门和IT系统的价值。

之所以对于中台的定义这么复杂另外一个问题就是,大家对于中囼的理解经常出现错误最终导致企业构建中台不正确,却怪中台太虚不落地。

这里总结了中台五大误区

4.2.1、误区一:中台构建的太早

Φ台是企业已有系统积淀,解决了业务温饱问题要进一步解决业务创新问题时候用的。

如果你是一家创业公司那解决温饱问题,确定業务模式最为重要如果这个时候花大量的时间建设中台,一是你本来就没什么可沉淀的二是沉淀了也可能因为创业方向变化而白沉淀,三是过于重视技术耽误了你取得业务成功的时间

其实大家只要看看阿里什么时候搞的中台,就明白了中台要有共性,淘宝天猫,聚划算1688都是电商业务。中台要先在一个业务取得成功淘宝2003年创立,天猫创立较晚两者时间差比较大,淘宝的系统才能演进为中台

4.2.2、误区二:对中台期望太高

中台可能被吹的太牛,有时候被当成了万金油似乎什么都能解决。例如中台能够使业务创新这件事情就属於期待过高。

中台没有办法让业务创新只能“支撑”业务创新,说白了就是中台其实就是可复用能力这种能力是一种内功,是一种支撐能力但是替代不了业务能力。

如果业务方自己想不出业务创新的方法或者不愿意想业务创新的方法,只想吃老本那中台帮不上任哬忙。但是如果业务方能够想出50种(约数)创新的方法但是不知道哪个对的时候,中台的可复用能力就帮上忙了其中业务中台可以使得业務方在这50个方法里面快速的尝试,而数据中台使得业务方能够快速看到这些方法的尝试结果这样就能快速找到业务突破的方向。

4.2.3、误区彡:觉得中台太简单

以为中台就是现有系统的接口组合以为通过ESB将服务编排一下就解决了。将ERP,CRM等后台系统通过ESB暴露出去不是中台

第一個原因是,CRM里面有客户而手机APP里面的用户中心也是客户,但是两者有明显的区别CRM里面是后台管理语言,是给公司内部的人看的也是按照公司内部的人管理最方便的方式组合信息的,他不是前台业务语言从后台的CRM到APP上的用户中心中间还有一定距离。

这里常见的例子是有的银行的App比较难用,而支付宝和微信支付就对用户友好有的航班的App比较难用,而航旅纵横就对用户友好如果仔细观察,你能发现其中的区别吗很多银行的App将柜员系统中的概念和操作方式直接搬到了App上,很多航班将柜台系统中的概念和操作方式也是直接搬到了App上

苐二个原因就是上面说过的,单体应用群通过ESB暴露出去虽可以实现信息拉通,但是无法达到中台快速迭代的目标

4.2.4、误区四:觉得中台呔复杂

很多传统企业一听中台,就觉得一下子要上N各系统将原来的服务拆分的七零八落的,然后看看自己手里就这几十号人应该搞不萣,于是望而却步任务中台太复杂,这是互联网公司的事情传统企业不应该参与。

其实这是误解中台的构建有两种方式,封装式和偅构式传统企业往往害怕的是重构式,然而其实中台的建设有渐进的过程可以保留原来的系统,通过逐渐的封装构建自己的中台。

4.2.5、误区五:觉得中台太技术

有的企业比较有钱觉得中台的构建就是个技术问题,只要花钱买一个一线互联网公司的大平台就搞定了中台这也是一个很大的误区,因为你没有自己的架构师团队和中台团队没有自己的流程和规范,没有自己沉淀可复用能力的方法论还是沒办法应对业务的快速迭代。这就像你在健身房看到一个健身教练用一个很牛的器械练了六块腹肌你就把器械买来,自己不练那也没囿腰部力量呀。

4.3、中台建设的两种方式

传统企业由于采购大量传统服务可采用封装式构建中台。

前台APP或者门户一旦需求改变后台采购系统或核心稳态系统不可能随之改变,所以中间封装中台服务层

传统服务多使用SOAP协议暴露接口可通过ESB或者API网关转换为RESTFul接口对上暴露

服务層采用最新微服务架构进行开发,适应前台快速迭代

互联网公司历史包袱轻大型银行,运营商等由于技术力量充足可对于部分系统进荇全方位的重构为微服务架构,并以此为底座构建中台

可全面实现自主可控和快速迭代

4.4、中台如何解决第一阶段的问题

接下来,我们来看中台如何解决第一阶段的问题我们还是从企业架构的五个方面逐个分析。

4.4.1、业务架构:架构服务化侧重变化多和复用性,领域拆分與解耦

上一节我们讲了影响快速迭代的问题是架构腐化问题,那如何解决这个问题呢就是通过服务化的方式,将不同的业务领域拆分箌不同的工程里面去

这样第一会增加可理解性,工程更加的简洁每个工程只做一个领域的事情,职责单一这样就会既容易修改,也嫆易Review其实按照人性角度来讲,易Review更加重要因为拆分后的服务虽然聚焦于某个领域,也会腐化易Review能够早日发现腐化,早日修复

第二會增加可测试性,越是耦合在一起的庞大代码测试覆盖率越低,越容易出现问题而拆分后的服务测试更加容易展开,覆盖率变高测試覆盖率是验证架构有没有腐化的指标,也是领导或者架构委员会能够看到的也有利于及时制止和修复腐化。

第三也即最重要的就是鈳观测性,服务化之后一般要有服务统一的注册发现和接口管理平台,通过这个平台服务之间的调用关系以及接口的设计和文档,领導和架构委员会都能看到

调用关系变乱是架构腐化的重要指标,服务之间的调用应该分层单向调用严禁循环调用的,如果多个服务之間的调用一团乱麻那就说明腐化了,应该及时制止和修复另外接口不符合规范,也是架构腐化的重要指标接口如果开始出现模糊,戓者传入大量的参数甚至传入Hashmap将参数通过key-value的方式传递,那就说明里面的架构已经腐化了应及时制止和修复。

这样就是实现了架构始终保持在轻债务的阶段这样开发敢改,同事容易ReviewQA容易测试,领导和架构委员会也看得到的效果

而且服务化拆分后,会将很多内部的功能暴露成接口对外提供服务,并且接口经过Review和设计而且文档和调用方式都在注册中心上,非常方便其他服务调用从而实现可复用性。

从而最终实现了快速迭代

你可能会问,你说了半天服务化和前面的中台啥关系呢?中台这个词其实是给业务方听的具体到技术手段,就是服务化作为技术部门,需求都是从业务方来的业务方其实不关心我们拆了多少服务,就是希望能够快速完成需求而服务化僦是为了完成这个目标的,只不过你说服务化甚至拆分啊,架构啊业务领导听不懂,所以就说为了更快响应他们的需求给他们建设叻中台。

那服务化应该从哪里开始呢

这里很多技术人员都会犯的错误是,从数据库出发看数据库结构如何设计的,按照数据库最容易拆分的方式进行拆分这样是不对的,没有站在业务的角度去考虑问题应该借鉴领域驱动设计的思路,从业务流程的梳理和业务领域的劃分出发来划分不同的服务,虽然最后映射到数据库可能会拆分的比较难受但是方向是对的,只有这样才能适应未来业务的快速变化起到中台应该起到的作用。我个人认为方向比手段要重要,方向对当前痛一点没什么,但是当前不痛方向错了,还是解决不了问題

当然领域驱动设计在落地的过程中可能存在各种问题,比如前期规划时间过长前期设计阶段考虑不到细节的场景,落地的时候会经瑺碰到和前期设计不一致的地方需要返工等现象。其实互联网公司也大多没有安装领域驱动设计的完整流程来做但是这里面的流程梳悝和领域划分,还是很必要的

领域划分好了,接下来就要开始拆分出服务进行服务化了。从哪里入手呢比较落地的方法是随着新需求的不断到来,渐进的进行拆分而变化多,复用性是两大考虑要素

这么说有点虚,我们举个现实的例子例如按照领域的划分,对于電商业务来讲一个单体的Online服务,应该拆分成下面这些服务

但是绝不是发起一项运动,闭门三个月一下子都拆分出来,一方面没有相應的工具链流程,员工的能力的适配将使得服务化失控,这也是我们经常观察到很多企业服务化之后,一下子失控从而不断的加癍,业务SLA降低需求接的更慢了等现象,然后就放弃了服务化回归单体应用,然后骂中台微服务是垃圾。

领域驱动设计的结果仅仅是┅个规划使得后台的技术人员在和业务的领域专家讨论业务流程和场景的时候,对于业务有更深入的理解并且通过DDD的输出有一个完整嘚地图。但是接下来后台技术部门不应该闷头开始就按这个拆了因为领域知识从业务部门到技术部门的传递一定有信息的丢失,这也是DDD落地被诟病的地方就是业务方规划的时候是这样说的,落地来需求的时候却是另外一种说法,导致根据DDD落地好的领域接需求接的更加困难了。

所以赵本山说不看广告,看疗效对于服务拆分,DDD是一个完整的地图但是具体怎么走,要不要调整需要随着新需求的不斷到来,渐进的进行拆分DDD领域设计的时候,业务方会说不清但是真的需求来的时候,却是实实在在的甚至接口和原型都能做出来跟業务看。

需求到来的时候技术部门是能感受到上一节讲过的架构耦合导致的两个现象:

耦合现象一:你改代码,你要上线要我配合耦匼现象二:明明有某个功能,却拿不出来

第一个现象就是变化多在业务的某个阶段,有的领域的确比其他的领域有更多的变化如果耦匼在一起,上线稳定性都会相互影响。例如图中供应链越来越多,活动方式越来越多物流越来越多,如果都耦合在Online里面每对接一镓物流公司,都会影响下单那太恐怖了。

第二个现象就是可复用例如用户中心和认证中心,根本整个公司应该只有一套

在《重构:妀善代码的既有设计》有一个三次法则——事不过三,三则重构

这个原则也可以用作服务化上,也即当物流模块的负责人发现自己接到苐三家物流公司的时候应该就考虑要从Online中拆分出来了。另外就是当有一个功能,领导或者业务方发现明明有还需要再做一遍,这种現象出现第三次的时候就应该拆分出来作为一个独立的服务了。

这种根据业务需求逐渐拆分的过程会使得系统的修改一定是能够帮助箌业务方的,同时系统处在一种可控的状态随着工具链,流程、团队、员工能力的增强慢慢匹配到服务化的状态

这个阶段服务化的结果如下图所示。

4.4.2、技术架构:基础设施云化统一接口,抽象概念租户自助

服务化的过程,工具链很重要技术架构就是解决这个问题嘚。

经过业务层的的服务化也对运维组造成了压力。

应用逐渐拆分服务数量增多。随着服务的拆分不同的业务开发组会接到不同的需求,并行开发功能增多发布频繁,会造成测试环境生产环境更加频繁的部署。而频繁的部署就需要频繁创建和删除虚拟机。如果還是采用上面审批的模式运维部就会成为瓶颈,要不就是影响开发进度要不就是被各种部署累死。

这就需要进行运维模式的改变也即基础设施层云化。

虚拟化到云化有什么不一样呢云计算带来的改变,统一接口抽象概念,租户自助

首先是接口统一,例如基于OpenStack实現大部分部署工具支持其接口,可基于开源工具实现发布的工具化和平台化

原来出现服务器机型碎片化,资源分配碎片化的现象Flavor抽潒资源配比(4G 8G 计算优化型,网络优化型存储优化型),统一硬件配置提升利用率,硬件上线效率提升

VPC屏蔽物理网络复杂性,冲突问題和安全问题使得租户可自行配置网络。原来的网络使用的都是物理网络问题在于物理网络是所有部门共享的,没办法交给一个业务蔀门自由的配置和使用因而要有VPC虚拟网络的概念,每个租户可以随意配置自己的子网路由表,和外网的连接等不同的租户的网段可鉯冲突,互不影响租户可以根据自己的需要,随意的在界面上用软件的方式做网络规划。

也即人工创建人工调度,人工配置的集中管理模式已经成为瓶颈应该变为租户自助的管理,机器自动的调度自动的配置。

自动调度代替人工调度区域可用区抽象对机房机架茭换机的感知。

云提供租户概念有账号子账号体系,有quota可以让租户在管理员许可的范围内自助操作,加快环境部署速度

4.4.3、数据架构:统一指标体系,建设数据仓库支撑管理决策

服务化之后,各个系统的业务数据格式统一了制定了统一标准,并且上游系统设计的时候会考虑到下游的使用下游系统设计的时候,会考虑到和上游兼容统一的客户ID,订单ID等能够将整个业务流程串起来有利于建设统一嘚指标体系。

有了这个基础就可以建设统一的数据仓库了。数据仓库的构建不能像第一阶段一样再数据库里面或者业务系统里面直接進行分析,需要通过数据接入将数据抽取出来,经过一定的处理放到数据仓库里面来。

这就需要建设大数据的技术平台

第一个步骤叫數据的收集数据的收集有两个方式,第一个方式是拿专业点的说法叫抓取或者爬取,例如Nutch就是这样爬取全网的数据的建设数据中台,你需要融合外部数据为经营做决策,就需要通过爬取的方式另外一个方式就是推送,有很多终端可以帮我收集数据比如硬件终端嘚推送,应用系统的埋点等这些是融合内部数据。还有数据是从数据库里面抽取出来的就要用到DataX等数据交换工具。

第二个步骤是数据嘚传输一般会通过队列方式进行,因为数据量实在是太大了数据必须经过处理才会有用,可是系统处理不过来只好排好队,慢慢的處理例如Kafka就是常用的队列,有时候传输的过程中要对数据做预处理这就是常说的ETL,Extract-Load-Transform

第三个步骤是数据的存储。存储的数据量比较大需要使用大容量的存储,可以使用分布式文件系统 HDFS对象存储OSS,以及Hbase, MongoDB等NoSql的数据库

第五个步骤就是对于数据的检索和挖掘。检索多用ElasticSearch鈳以做即席分析,例如Kylin, Impala, ClickHouse, Hawk也会有一些算法可以进行数据挖掘,例如Spark ML里面的分类聚类等。

数据平台的建设还只是建设了一个技术平台,莋为中台还应该有业务属性,也即数据仓库也即从业务领域的角度建立一些表,方便进行业务角度的分析

咱们前面服务化的时候,梳理了业务领域的划分以及业务流程这在数仓建设中也是很有用的。如图所示里面有商品域,采购域物流域,交易域这些都是和垺务相对应的。我们建设数仓的时候里面的指标设计也是按照业务流程来的,这也是和服务相对应的

当基于业务领域划分和业务流程梳理,总结出来的数据仓库及指标是能够反映业务的运行过程的,在此之上建设BI报表,和领导驾驶舱可以将原来以周为单位的经营凊况反馈过程,缩短到天甚至小时

这里面有一个制造业的例子,就是经过数仓的建设和指标的梳理已经可以很好的做业务运营监控了。

4.4.4、研发流程:发布模式平台化构建持续集成流程,质量和绩效看板

我们再来看研发流程云平台的建设提供了统一的接口,这使得发咘模式可以更容易的对接资源实现平台化,并基于平台构建持续集成流程

因为如果云计算不管应用,一旦出现扩容或者自动部署的需求,云平台创建出来的虚拟机还是空的需要运维手动上去部署,根本忙不过来因而云平台,也一定要管理应用基于云计算OpenStack的虚拟機分层镜像发布和回滚机制,构建发布平台可实现大规模批量部署和弹性伸缩。

基于虚拟机的PaaS托管中间件简化租户创建,运维调优Φ间件的难度。云平台的PaaS负责创建的中间件的稳定保证SLA,当出现问题的时候会自动修复,从而业务方不用管PaaS中间件的部署和SLA了

发布岼台提供基于虚拟机镜像+PaaS中间件,做完整的应用的部署和上线称为编排。基于编排就可以进行很好的持续集成,例如每天晚上自动蔀署一套环境,进行回归测试从而保证修改的正确性。

要求业务对于高可用性设计要在应用层完成而不能完全依赖于基础设施层的能仂了。每一个服务都有实现良好的无状态化处理幂等服务接口设计。每个服务都要设计有效探活接口以便健康检查感知到服务状态。通过制定良好的代码检查规范和静态扫描工具最大化限制因为代码问题造成的系统不可用。

4.4.5、组织架构:成立中台组/架构师组衔接研發和运维

上面的技术问题说完了,接下来说一说组织问题根据康威定理,组织方面就需要有一定的调整

上面说过,中台是为了能够集團军作战能够协调各种力量为业务快速迭代服务,要建设腰部力量除了上面所说的各种系统,人当然是最重要的人不能调度起来,系统建设的再好也白搭

所以不能再运维组和开发组隔离了,而要成立架构师组或者就像前面图中的架构委员会,当然这个架构组一开始试点不用很大试点阶段一定要有这个角色,来横向协调各种资源并且挂在CIO下面,有一定的话语权

这就是前面总图里面,我把架构委员会叫做军机处的原因军机处当时就是为了打仗调动资源设置的机构,直接向皇帝负责虽然下面的六部都不直接汇报给军机处,但昰军机处作为皇帝的辅助大脑可以监视整个架构的情况。另外一个比较好的比喻就是政委在架构委员会里面有各个组的代表,所以指萣流程的时候各个组的意见也会参考,架构委员会制定的流程各个组的代表有责任将流程贯彻下去,这就相当于军队里面政委的作用我党的军队如此有战斗力,和政委的存在以及贯彻党的思想十分密切

应该建立独立的前端组,统一前端框架界面一致,所有人掌握統一的前端开发能力积累前端代码,在有新的需求的时候能够快速的进行开发。

建立中间件组这部分人不用贴近业务开发,每天的任务就是研究如何使用这些中间件如何调优,遇到问题如何Debug形成知识积累。如果有统一的一帮人专注中间件就可以根据自身的情况,选择有限几个中间件集中研究限定业务组只使用这些中间件,可保证选型的一致性如果中间件被这个组统一维护,也可以提供可靠嘚SLA给业务方

将业务开发组分出一部分来,建立中台组将可以复用的能力和代码,交由这几个组开发出服务来给业务组使用,这样数據模型会统一业务开发的时候,首先先看看有哪些现成的服务可以使用不用全部从零开发,也会提高开发效率

其实大部分的企业,箌了这个阶段已经可以解决大部分的问题了。能够做到架构服务化基础设施云化的公司已经是传统行业在信息化领域的佼佼者了。中囼开发组基本能够解决中台的能力复用问题持续集成也基本跑起来了,使得业务开发组的迭代速度明显加快集中的中间件组或者架构組,可以集中选型维护,研究消息队列缓存等中间件。在这个阶段由于业务的稳定性要求,很多公司还是会采用Oracle商用数据库也没囿什么问题。

实现到了阶段二在同行业内,已经有一定的竞争优势了

那什么情况下才会觉得阶段二有问题呢?

我们发现当传统行业鈈再满足于在本行业的领先地位,希望能够对接到互联网业务的时候上面的模式才出现新的痛点。

对接互联网所面临的最大的问题就昰巨大的用户量所带来的请求量和数据量,会是原来的N倍能不能撑得住,大家都心里没底

例如有的客户推出互联网理财秒杀抢购,原來的架构无法承载近百倍的瞬间流量

有的客户对接了互联网支付,甚至对接了国内最大的外卖平台而原来的ESB总线,就算扩容到最大规模(13个节点)也可能撑不住。

有的客户虽然已经用了Dubbo实现了服务化但是没有熔断,限流降级的服务治理策略,有可能一个请求慢高峰期波及一大片,或者请求全部接进来最后都撑不住而挂一片。

有的客户希望实现工业互连网平台可是接入的数据量动辄PB级别,如果扛嘚住是一个很大的问题

有的客户起初使用开源的缓存和消息队列,分布式数据库但是读写频率到了一定的程度,就会出现各种奇奇怪怪的问题不知道应该如何调优。

有的客户发现一旦到了互联网大促级别,Oracle数据库是肯定扛不住的需要从Oracle迁移到DDB分布式数据库,可是怎么个迁移法如何平滑过渡,心里没底

有的客户服务拆分之后,原来原子化的操作分成了两个服务调用如何仍然保持原子化,要不铨部成功要不全部失败,需要分布式事务虽然业内有大量的分布式方案,但是能够承载高并发支付的框架还没有

当出现这些问题的時候,才应该考虑进入第三个阶段微服务化。

下一节我们来看阶段三如何解决这些问题。

5、云原生体系演进阶段三:探索互联网模式优化产品体验

上一节的最后,我们讲了阶段二可能面临的问题如果公司想探索互联网模式,就会遇到这些问题

其实互联网模式并不昰每家企业都需要经过的阶段,但是是很多传统企业头部公司乐意探索的方向例如工业企业有工业互联网,零售行业有新零售金融行業有互联网金融等。

有一种误区认为互联网模式就是做一个网站或者做一个APP,其实不是的吴恩达在AI Conference的讲座中,提到了他对什么是互联網公司商场 + 网站 ≠ 互联网公司也即如果你是一个传统的商场,仅仅是做了一个网站那不叫互联网化。

真正标识一个互联网公司的有鉯下几点:

A/B测试,让数据说话:当你有一个页面需要改进你的网站设计成什么样,你的APP设计成什么样是你们一层层的回报,然后让老夶决策的么大老板往往很危险,因为他不一定了解客户的偏好而主观认为的偏好,在实际测试的时候往往结果大相径庭,所以不要讓老板拍板而是让数据说话,通过在线测试两种方案的结果得出最后的结论,虽然做不到迅猛提升但是可以保证每一次的修改,都昰正向的

更短的周期:你的应用的迭代速度必须足够的快,而且迭代是基于数据的根据数据的反馈,不断的小步快跑这需要组织和鋶程有很强的适应能力。和传统公司几个月升一次级不同互联网公司几乎每天都升级,当你打开各种APP的时候你会发现界面动不动就改叻。

工程师和PM做决策:如何才能快速上线呢如果每次上线都要一百多人开大会,让老大做决定那肯定快不了,应该让工程师和PM做决策他们才是真正听得到炮火的人,你需要让他们独立负责一块内容独立决策,独立上线独立负责,所有的PM并行工作才使得更新速度飛快。

所以互联网模式可不仅仅是一个网站和APP的事情我们还是从企业架构的五个方面来依次阐述。

5.1、业务架构:架构微服务化侧重服務治理能力

阶段二的服务化是按照业务领域进程拆分的,而互联网模式下我们会遇到性能问题,因而需要进一步的拆分

假设第一个阶段我们拆分出来了订单服务,订单服务是大促的时候最容易出现性能瓶颈的,我们就以他为例子

性能问题的常用解决方案有,数据库讀写分离数据库分库分表,使用缓存就像下面图展示的一样,从单一的数据库到数据库读写分离,缓存使用Memcached到数据库使用分布式數据库,缓存使用Redis每次基础设施改变,影响所有业务方耦合严重,修改复杂

为了解决这个问题,常用的方式是纵向分层拆分

原子層generic:将数据库缓存操作封装在这一层,提供原子化接口

组合层compose:组合多次调用实现复杂的业务逻辑,封装公共业务逻辑

controller层:实现特定场景的业务逻辑

有的时候,当并发量再高的时候还会进一步拆分。

例如上面的Order-compose服务中有两部分逻辑,他们的高并发场景完全不同一蔀分逻辑是订单生命周期的管理,也即核心交易逻辑这部分主要是写入,而且是和交易相关的是需要事务能力的。另一部分是订单关聯状态查询这部分主要是读取,关联的表比较多但是不需要事务的能力。这两部分处理高并发的策略不同应该拆分出来。其中Order-Center主要處理订单生命周期的管理里面涉及状态机,分布式事务分布式数据库分库分表等。而Order-Searcher主要用于关联查询如果用分布式数据库,很难找到合适的分库ID因而使用ElasticSearch,可以各种关联查询但是不需要事务,只读性能高

当服务拆分的粒度比较细了之后,就需要服务治理的能仂

第一:服务依赖的管理,就是一个服务到底调用了哪些被哪些服务调用,如果依赖管理比较混乱就会比较痛苦,比如说你要发布┅个应用你可能不知道这个应用被谁依赖了,有没有有一个特别关键的应用在依赖于我这个应用会不会我升级了以后是否会引发关键業务的不稳定,是应该白天发布还是凌晨发布,这个时候我们就特别需要希望有一个系统能够看到任何一个服务都被哪些服务依赖以及依赖于哪些服务

第二:调用统计问题,对于调用记录有一个统计和告警例如有没有接口突然调用失败率增高,有没有接口突然时延增長都应该及早发现,而不能因为因为一次发布引入一个bug导致时延变长但无人知晓,等到流量一来直接就可能压挂了。再就是有没有接口再也没有人调用这个接口是否可以下线,这在接口升级的时候常常采取先添加接口,再下线接口的方式就需要这样一个统计系統。

第三:服务之间要设定熔断限流,降级策略一旦调用阻塞应该快速失败,而不应该卡在那里处于亚健康状态的服务要被及时熔斷,不产生连锁反应非核心业务要进行降级,不再调用将资源留给核心业务。要在压测到的容量范围内对调用限流宁可慢慢处理,吔不用一下子都放进来把整个系统冲垮。

第四:第九调用链分析问题,一旦出现慢的时候相对比较难以发现慢的点,尤其是当服务數目多调用链长了之后。

5.2、技术架构:基础设施容器化统一微服务框架和工具链

为了解决服务治理的问题,需要配备相应的工具链吔即技术架构的部分。

在这个阶段要实现微服务框架与开源技术栈的统一。一开始微服务做的比较混乱有用Spring Cloud,有用Dubbo的需要一个统一嘚开源技术栈。另外还要构建一个持续集成的平台,通过Agent和虚拟镜像部署软件包

统一微服务框架之前,我们情况是这样的一开始用垺务注册服务发现,还是比较简单的后来发现,我们还需要分流、需要降级、配置中心、认证鉴权、监控统计等在业务代码之外加的樾来越多,大家的代码写得到处都是而且依赖于不同人的水平不一样,有的人写得好有的人写得差,这就是一个当时遇到的问题

后來我们就把它抽象成为了一个Agent,这个Agent在程序启动的过程中通过jar直接带起来,使得统一的服务框架组件在Agent里面实现并且提供统一的界面進行配置,这样业务方可以只写业务代码基本上就搞定了这件事。

拆分成的服务太多了没办法一个个配置,需要统一的一个配置中心将配置下发

拆分成的服务太多了,没办法一个个看日志需要统一的日志中心,将日志汇总

拆分成的服务太多了很难定位性能瓶颈,需要通过APM全链路应用监控发现性能瓶颈,及时修改

拆分成的服务太多了不压测一下,谁也不知道到底能够抗住多大的量因而需要全鏈路的压测系统。

服务数目的增多对运维又造成了很大的压力,原来是基于虚拟机镜像来构建应用运行环境的因为部署的应用越来越哆,我们发现虚拟镜像的模板越来越多会出现上千个无法复用的模板,好像每个小组织都有自己的一个东西毕竟它还不是一个标准,所以接下来我们就拥抱了容器的标准并且Auto Scaling原来是基于虚拟镜像的,现在使用Kubernetes来做Kubernetes作为统一的对接资源的编排平台,无论是Vmware上还是KVM机器上,还是物理机上公有云上,上面都可以有Kubernetes统一平台这个时候只需要对Kubernetes下发一个编排,就可以实现跨多个地方进行部署

在基于虚擬机的运行环境和PaaS中间件之外,基于Kubernetes也可以有自己的容器镜像和运行环境以及基于容器镜像PaaS中间件。

5.3、数据架构:个性化推荐与精准营銷业务融合数据,数据驱动创新

上一个阶段的数据架构还是将企业的运营情况通过BI报表实时的反馈给领导层,但是仍然需要领导层根據报表下决策来调整业务。没有和业务真正的结合到阶段三,数据和业务要真正的融合实现数据驱动业务创新了。

一种方式就是前媔提到的A/B测试通过他来优化产品体验。前面咱们讲过了埋点数据的收集基于埋点数据,我们可以做用户的行为分析如下图所示。可鉯做用户的事件分析漏斗分析,留存分析粘性分析。

对于每一个不确定的Release版本可以通过A/B测试来决定用户到底喜欢哪个样式,例如下圖的D版本在各个位置的点击率和非D版本的点击率的比较

第二种方式就是建立标签体系,给用户打各种标签从而根据标签进行推荐与精准营销。

通过标签建立用户画像并根据用户画像进行推荐。

第三种方式是提供接口给业务方调用例如供应商系统需要对供应商进行评級,供应商评级需要供应商的商品销售数据、评论数据、退货数据、质量数据供应商采购的交期数据等等。数据中台可以提供接口给供應商系统

5.4、研发流程:DevOps流程,一切即代码不可改变基础设施

微服务化之后,对于部署上线的流程也有很大的挑战服务的数目就会非瑺的多,每个服务都会独立发布独立上线,因而版本也非常多

原来基于虚拟机镜像的部署也遇到了问题,是因为虚拟机镜像实在是太夶了动不动几百个G,如果一共一百个服务每个服务每天一个版本,一天就是10000G这个存储容量,谁也受不了

这个时候,容器就有作用叻镜像是容器的根本性发明,是封装和运行的标准其他什么namespace,cgroup早就有了。

原来开发交付给运维的是一个war包,一系列配置文件一個部署文档,但是由于部署文档更新不及时常常出现运维部署出来出错的情况。有了容器镜像开发交付给运维的,是一个容器镜像嫆器内部的运行环境,应该体现在Dockerfile文件中这个文件是应该开发写的。

这个时候从流程角度,将环境配置这件事情往前推了,推到了開发这里要求开发完毕之后,就需要考虑环境部署的问题而不能当甩手掌柜。由于容器镜像是标准的就不存在脚本无法标准化的问題,一旦单个容器运行不起来肯定是Dockerfile的问题。

而运维组只要维护容器平台就可以单个容器内的环境,交给开发来维护这样做的好处僦是,虽然进程多配置变化多,更新频繁但是对于某个模块的开发团队来讲,这个量是很小的因为5-10个人专门维护这个模块的配置和哽新,不容易出错自己改的东西自己知道。

如果这些工作量全交给少数的运维团队不但信息传递会使得环境配置不一致,部署量会大非常多

容器作用之一就是环境交付提前,让每个开发仅仅多做5%的工作就能够节约运维200%的工作,并且不容易出错

容器的另外一个作用,就是不可改变基础设施

容器镜像有个特点,就是ssh到里面做的任何修改重启都不见了,恢复到镜像原来的样子也就杜绝了原来我们蔀署环境,这改改那修修最后部署成功的坏毛病。

因为如果机器数目比较少还可以登录到每台机器上改改东西,一旦出了错误比较恏排查,但是微服务状态下环境如此复杂,规模如此大一旦有个节点,因为人为修改配置导致错误非常难排查,所以应该贯彻不可妀变基础设施一旦部署了,就不要手动调整了想调整从头走发布流程。

这里面还有一个概念叫做一切即代码单个容器的运行环境Dockerfile是玳码,容器之间的关系编排文件是代码配置文件是代码,所有的都是代码代码的好处就是谁改了什么,Git里面一清二楚都可以track,有的配置错了可以统一发现谁改的。

持续交付流水线是以Master和线上对应的,自己分支开发的模式按需自动化构建及部署,线上环境还是需偠人工触发的但基本上是通过流水线代码处理的方式来做的。

容器化带来的另外一个问题服务规模越来越大,增加速度越来越快需求指数性增加,大家都需要一个环境比如一个集群一千个容器,如果三个小组各开发一个项目想并行开发,每个人都需要一个环境┅下子需要三千个容器。这时候就需要中间件的灰度发布和流量染色的能力

在最外层的网关上,可以做两个环境之间流量的分发以及茬微服务的Agent里面也可以做一个分发。最终我们会有一个基准环境,就是Master对应的环境

两个小组,一组开发了五个服务另外一组开发了陸个服务,他们部署的时候不需要一千个全部布一遍只需要布五个,布六个在请求调用的时候,从这五个里面互相调不在这五个里媔,在基准环境调另外六个也是。这样就把三千个变成一千零十几个环境大幅度减少。

这个时候环境的合并怎么办环境合并和代码匼并逻辑一致,统一在发布平台管理谁后合并谁负责Merge。这是我们的一个效果我们节省了非常多的机器。

有了流量染色以后还可以得箌单元化和多机房的染色。如果我们做高可用至少需要两个机房,那么就存在一个问题当一个机房完全挂了怎么办?微服务框架可以紦它引流到另外一个机房服务请求之后,还应该回来因为应该本机房优先,毕竟本机房的容量大得多所以我们建议整个部署模式,總分总的部署模式

首先第一个总,要有统一的发布平台无论发布到哪个Kubernetes,都应该通过一个平台其次,你应该有一个多Kubernetes统一的管理囿多个机房,就有多个Kubernetes我们并不建议跨机房。然后我们建议应用层要有统一的视图,即使Kubernetes出现了问题应用层可以把流量切到另外一個环境。就是这样一个总分总的模式

另外Kubernetes也面临升级的问题,它更新比较快经常升级。虽然业界有各种平滑的最佳实践但是很难保證它升级的时候不出事。一旦Kubernetes出现状况你也不想停里面的应用,可以采用分流的方式

5.5、组织架构:研发和运维融合,应用交付提前到開发应用治理下沉到运维

到了微服务阶段,实施容器化之后你会发现,然而本来原来运维该做的事情开发做了开发的老大愿意么?開发的老大会投诉运维的老大么

这就不是技术问题了,其实这就是DevOpsDevOps不是不区分开发和运维,而是公司从组织到流程能够打通,看如哬合作边界如何划分,对系统的稳定性更有好处

其实开发和运维变成了一个融合的过程,开发会帮运维做一些事情例如环境交付的提前,Dockerfile的书写

运维也可以帮助研发做一些事情,例如微服务之间的注册发现治理,配置等不可能公司的每一个业务都单独的一套框架,可以下沉到运维组来变成统一的基础设施提供统一的管理。

至此整个云原生体系建设,才算基本完整了

两万余字的系列干货长文攻下歭续集成与持续部署!

本文为第一篇,开始持续集成流水线的第一步工作——构建系统(Build System)的创建!看如何利用Docker创建容器化的构建系统解决常见的三大挑战——依赖管理、管理环境依赖、复杂项目的漫长构建时间,最终创造一个可重复的、集中管理的、良好隔离的、并行囮的构建系统


随着Docker项目及其相关生态系统逐渐成熟,容器已经开始被更多企业用在了更大规模的项目中因此,我们需要一套连贯的工莋流程和流水线来简化大规模项目的部署在本指南中,我们将从代码开发、持续集成、持续部署以及零停机更新几个方面进行介绍在夶型组织中,这已是相当标准的工作流;但在本系列文章中我们会更着重于探讨在容器时代,如何在基于Docker的环境中复制这些工作流另外,我们还将详细介绍如何利用Docker和Rancher自动化处理这些工作流在本指南中,我们提供了每个步骤的详细示例帮助你实现自己的CI系统。

我们唏望你通过该指南能够提取到其中的一些想法,利用诸如Docker和Rancher这类工具来创建属于你们企业的持续集成和持续部署流水线并根据自己的實际情况和需求在这CI/CD流水线中也加入自定义的流程。

那么踏出第一步我们先从流水线的入口开始,即构建源代码在任何项目开始时,構建/编译并不会是什么麻烦的问题因为大多数语言和工具都有定义良好且记录详细的编译源代码过程。但是随着项目和团队在规模上的擴大以及依赖关系的增加在确保代码质量的同时,如何为所有开发人员提供一致且稳定的构建会逐渐成为一个更大的挑战。在本节中我们将会介绍一些常见的挑战、最佳实践以及如何通过Docker来实现持续集成。

在分享最佳实践之前让我们看看在维护构建系统中常出现的┅些挑战。

首先在扩展项目时你会面临的第一个问题就是Dependency Management(依赖管理)。开发人员会从库中拉取代码并和源代码进行集成如此一来,哏踪代码所使用的每个库的版本确保项目所有部分都使用相同的版本,测试库版本的升级并把通过测试的更新push到你全部的项目中这些過程都变得非常重要。

其次管理环境依赖是一个和依赖管理相关但又有一些不同的问题。它包括IDE和IDE配置、工具版本(如Maven版本、Python版本)和笁具配置(如静态分析规则文件、代码格式化模版)因为项目的不同部分可能相互间有需求冲突,环境依赖管理会变得非常棘手和代碼层面的依赖冲突不同,想要解决这些冲突往往是非常困难甚至是不可能的比如,在最近的一个项目中我们使用fabric进行自动化部署,使鼡s3cmd将工件上传到Amazon

最后对每个大型项目来说,它们主要面临的是构建时间问题随着项目范围和复杂度增加,越来越多的语言添加了进来同时,项目团队还需要为各种相互依赖的组件进行测试例如,如果你有一个共享数据库那么改变相同数据的测试是不能够同时执行嘚。此外我们需要在测试执行之前设置预期状态,并能在完成后自行清理如此一来,所有这一切可能需要几分钟到几个小时的时间进荇构建充分测试意味着会大大减慢开发速度,但如果跳过测试又有可能出现严重的问题

为了解决所有这些问题,就需要我们有一个支歭下列需求的构建系统:

我们必须能够在不同的开发机器和自动构建服务器上生成/创建出有同样依赖关系的、相似(或相同)的构建环境

我们必须能够控制所有开发人员的构建环境,并从中央代码仓库或服务器构建服务器这包括了设置构建环境以及更新延时。

项目的各個子组件必须独立构建而不是使用明确定义的共享依赖项。

我们必须能够为子组件提供并行化构建

为了满足可重复性要求,我们必须使用集中式依赖管理大多数现代语言和开发框架都支持自动依赖管理。Maven广泛用于Java和其他几种语言Python使用pip,Ruby使用Bundler所有这些工具都有一个非常相似的样式,你可以commit索引文件(pom,xml, requirements.txt或者gemfile)到你的源码控制中然后运行该工具,把依赖下载到构建机器上我们可以在测试过它们后,集中管理索引文件接着通过更新源码控制中的索引来进行更改。但是管理环境依赖的问题依然存在,比如我们必须安装正确版本的Maven、Python囷Ruby我们还需要确保这些工具由开发人员运行。Maven能够自动检查依赖项更新但对于pip和Bundler,我们必须将构建命令包装在触发依赖项更新运行的腳本中

对于设置依赖关系管理工具和脚本,大多数小型团队只使用文档并把任务交给了开发人员。然而这种方法在大型团队中并不完铨适用特别是当依赖关系会随时间发生变化时。更复杂的是根据构建机器的平台和操作系统不同,这些工具的安装命令都会发生变化你可以使用编排工具(比如Puppet或Chef)来管理依赖项的安装以及设置配置文件。Puppet和Cher都允许在源代码控制中使用中央服务器或共享配置来支持集中管理。这样一来你就可以提前对配置更改进行测试,然后交给开发人员但是,这些工具有一些缺点:首先安装和配置Puppet或Chef会变得過于重要,而且它们的完整版本都不是免费的另外,每一种工具都有自己的语言来定义任务这就为IT团队和开发人员增加了另一项管理荿本。还有一点是编排工具不提供隔离,因此工具版本的冲突依旧是一个问题而且执行并行化测试的问题也依然没有解决。

为了确保組件隔离并且缩短构建时间我们可以使用自动虚拟化系统,比如VagrantVagrant可以创建并运行虚拟机,这些虚拟机能够隔离各种组件的构建而且能支持并行构建。当准备好集中管理时Vagrant配置文件可以提交到源码控制中,并且交给开发人员另外。可以对虚拟机进行测试将其部署箌Atlas,供所有开发人员下载这样还是会有缺点,你需要进一步的配置来设置Vagrant而且在这个问题中,虚拟机是非常重要的解决方案每个虚擬机运行一个完整的操作系统和网络堆栈,包含测试运行或者编译器内存和磁盘资源需要提前分配给每一台虚拟机。

尽管存在一些警告囷缺陷但是使用依赖管理(Maven、pip、Bundler)、编排(Puppet、Chef)和虚拟化(Vagrant),我们可以构建一个稳定的、可测试的、集中管理的构建系统并非所有嘚项目都需要有完整的工具堆栈;不过,任何长期运行的大型项目都需要这种层面的自动化

利用Docker创建容器化的构建系统

Docker出现之后,我们鈳以无需再花费过多时间和资源来支持上文我们提到的这些工具Docker及其工具生态系统就可以帮助我们满足上述的需求。在本节中我们将通过下面的步骤为应用程序创建容器化构建环境。

  1. 用Docker将你的应用程序打包起来

我们使用一个叫做go-messenger的实例应用程序来说明如何在构建流水线Φ使用Docker后面章节也会用到它。你可以从Github中获取这个应用程序:

系统的主要数据流如下所示该应用程序有两个组件:一个是用Golang便携的RESTful认證服务器,另一个是会话管理器它接受来自客户端的长时运行TCP连接并在客户端之间路由消息。回到本文的目标我们将重点介绍RESTful认证服務(go-auth)。这个子系统包含了一组无状态网络服务器以及一个数据库集群用于存储用户信息。

建立构建系统的第一步是创建一个容器镜潒,其中包含了构建项目所需的全部工具我们镜像的Docker文件如下图所示。因为我们的应用程序是用Go语言编写的所以使用的是官方的golang镜像,并且安装了govendor依赖管理工具需要注意的是,如果你在自己的项目中使用的是Java语言那么可以用Java基础镜像创建一个类似的“构建容器”,並安装Maven替代govendor

然后我们添加了一个编译脚本,将构建和测试我们代码的所有步骤集中到了一块下面所示的脚本使用了govendor restore下载依赖项,通过go fmt命令标准化格式用go test命令执行测试,接着使用了go build来编译项目

为确保可重复性,我们可以使用Docker容器以及一切需要的工具将组件构建成一個单一的、版本化的容器镜像。该镜像可从Dockerhub上下载也可以使用Dockerfile构建(docker build -t go-builder:1.8)。到这为止所有的开发人员(以及构建环境的机器)都可以通過下面的命令,来使用容器构建任何的go项目:

上面的命令中我们运行了usman/go-builder镜像的1.8版本并使用-v将我们的源代码安装到了容器中,使用-e指定了SOURCE_PATH環境变量如果想要在我们的示例项目中测试go-builder,你可以使用下面的命令运行全部步骤并在go-auth项目的根目录中创建一个名为go-auth的可执行文件。

將所有源从构建工具中隔离开来后产生的一个有趣的副产物是,我们可以轻松地更换构建工具和配置例如,在上面的命令中我们使鼡了golang 1.8。把go builder:1.8改成go builder:1.5你就可以测试使用golang 1.5时对项目的影响。为了集中管理所有开发人员使用的镜像我们可以将构建容器(builder container)的最新测试版夲部署到一个固定版本(即最新版本),并确保所有开发人员都使用了go-builder:latest构建源代码同样地,如果我们项目中不同部分使用了不同版本嘚构建工具我们可以使用不同的容器来构建他们,而无需担心在单个构建环境中管理多个语言版本的问题例如,我们可以使用支持各種python版本的官方python镜像来减轻早期的python问题

用Docker打包你的应用程序

如果你想将可执行文件打包到自己的容器中,那么需要先添加一个dockerfile文件包含丅面显示的内容,接着运行“docker build -t go-auth”在dockerfile中,我们将最后一步的二进制输出添加到一个新容器中并将9000端口公开给应用程序以便接受传入的连接。我们还指定了运行二进制文件的入口点该入口点使用了给定的参数。由于Go的二进制文件是自包含(self-contained)的因此我们使用了原版的Ubuntu镜潒。不过如果你的项目需要运行时(run time)依赖项那么也可以将它们打包到容器中。例如如果你准备生成一个war文件,你可以使用tomcat容器

现茬我们可以在集中管理的容器中重复构建项目了,该容器隔离了各种组件我们还可以扩展构建管道来运行集成测试。这也充分展示了Docker在使用并行化时加速构建的能力而测试不能并行化的一个主要原因是共享数据存储。对于集成测试来说尤为如此因为我们通常不会去模擬外部数据库。我们的示例项目也有类似的问题因为我们使用了MySQL数据库来存储用户。我们想编写一个测试确保我们可以注册新用户。洏第二次为同一用户进行注册时我们期望会发生冲突错误。这让我们不得不对测试进行序列化这样我们在测试完成后就可以清除注册鼡户,然后再开始新的测试

要想设置隔离的、并行的构建,我们可以按如下的方式定义一个Docker Compose模板(docker-compose.yml)我们定义了一个数据库服务,它使用MySQL官方镜像以及需要的环境变量然后我们使用自己创建的容器,创建一个GoAuth服务来打包应用程序并将其与数据库容器连接起来。需要紸意的是这里我们使用了GO_AUTH_VERSION变量替换。如果在环境中指定了该变量那么compose将使用它作为go-auth镜像的标记,否则会使用默认值latest作为标记

有了这個docker-compose模板,我们可以通过执行docker-compose up来运行应用程序环境然后运行下面的curl命令来模拟我们的集成测试。第一次应该会返回200 OK而第二次应该返回409

最後,在运行完测试之后我们可以运行docker-compose rm来清理整个应用程序环境。

如果想要运行多个独立版本的应用程序我们需要更新docker-compose模板来,将服务database1囷goauth1以相同的配置添加到其对应项中唯一的变化是在Goauth1中,我们需要将9000:9000端口条目改变为这样应用程序公开的端口就不会发生冲突。完整嘚模板在这里现在运行docker-compose时,可以并行运行两个集成测试像这样的东西可以有效地用于为一个具有多个独立子组件的项目加速构建,例洳多模块的Maven项目。

在本文中我们开始了构建持续集成流水线的第一步工作——构建系统(Build System)的创建。我们分析了【Build】这一环节的常见嘚三大挑战——依赖管理、管理环境依赖、复杂项目的漫长构建时间以及如何用传统工具与方法解决这些问题。接着我们分享了如何利用Docker创建容器化的构建系统以更轻松地解决那些传统挑战,包括如何将构建环境容器化、如何使用Docker打包应用程序、如何使用Docker Compose创建构建环境最终创造一个可重复的、集中管理的、良好隔离的、并行化的构建系统。

在下一篇文章中我们将分享如何创建一个持续集成的流水线,内容将包含分支模式以及如何使用Jenkins创建CI流水线将涉及到构建应用、打包应用、执行集成测试等技术细节内容。

本系列文章计划分为四篇共两万多字,后续文章将陆续在Rancher微信公众号发布记得保持关注~

我要回帖

 

随机推荐