DevOps实施落地的2大法宝:粒度&解耦

社区广播:运维派(Yunweipai.com)是国内最早成立的IT运维社区,欢迎大家投稿,让运维人不再孤寂的成长!

徐磊

微软MVP & Regional Director

Certified ScrumMaster & DevOps Master

《凤凰项目》沙盘认证讲师

一句话概括我所做的事情就是:帮助研发团队改进研发流程,包括使用工具、使用方法、借鉴他人经验等方式,让大家的软件开发效率变得更高。

我的DevOps之路

DevOps这个词从一出现就受到很多关注,尤其是近一两年来变得非常热,以致大家对DevOps有很多的误解,这种热度确实有一定的炒作的成分,但个人觉得任何事情的出现和流行都有其内在的原因,DevOps也不例外。

本篇简单总结过去十年我所做的相关的事情,通过我的经历来看过去十年DevOps在国内的发展历程。希望这个过程可以帮助大家了解:DevOps到底是什么、是做什么的、能帮到我们什么。由于是结合我个人经验来谈DevOps,所以很多说法会带有个人的主观判断,分享给大家,旨在一起探讨。

DevOps

第一个时间点:2005年

之所以把第一个时间点放在2005年,是因为这一年我从澳洲回到北京,组建了一家外企研发中心。在这之前我就是一个纯粹的开发人员,写code、做项目、做产品、做发布,从2005年起我的角色开始转变,开始要去带一个团队,并从团队的角度考虑问题。

当我在国内找到了几名开发人员和我一起做一些项目的时候,我发现了第一个问题:当时我们的源代码管理服务器处于澳大利亚悉尼,在北京如果想要把代码提交过去非常痛苦。这种痛苦到什么程度呢?我们切入一个文件大概需要十分钟的时间,这是非常让人无法容忍的事情,会严重造成工作效率的低下。

我们找各种办法希望能解决这个问题,包括提高网络连接,但遗憾的是没有找到更好的办法。老板和微软的关系特别好,他看到了微软一个还没有发布的产品——TFS(当时还处于beta版本),我们注意到这个产品是因为它的source control是基于HTTP的,所以我们决定把现在基于VSS的source control迁移到基于HTTP的TFS的source control上。从2005年开始大概持续了两年的时间,我把公司所有的项目从VSS迁移到了HTTP。

其实VSS也是一个很不错的source control,但当出现这种跨地域访问的时候它的性能就会有很大的问题。这是我接触专业的软件工程工具或开始去想如何提高团队效率的一个起点。

第二个时间点:2008年

第二个关键时间节点是2008年,当时我和微软组织了一个叫VSTS Real World的活动,这场活动实际上就是:我们找到了很多国内有影响力的独立软件开发商,把其中比较资深的软件开发人员集中到一起,让他们去体验如何在一个完整的软件工程管理平台上,完成一个软件从需求到分析到开发到测试到打包到发布的过程。

从微软的角度来说,是希望推广他们的工具;从我的角度来说,是第一次完整地把自己之前在软件交付整个端到端的流程方面的经验分享到自己团队之外去。

活动开发的项目是以汶川地震这个背景为假设场景,要求开发一个叫“孤儿领养”的系统。

这个项目对我个人来说非常重要,它是我作为软件工程顾问所完成的第一个完整的项目。虽然是一种培训的交付形式,但其实在制作这场活动的相应的资料时,我是把自己和团队的经验通过文档、PPT、示例代码的方式,整理成一整套的资料分享给其他开发团队,并且在这5天的时间内,和大家一起完成一个真实的项目开发。在这个过程中,我们也采用了一定程度上的敏捷开发的概念,比如迭代、用户故事等。

第三个时间点:2008-2009年

上图中有一个关键时间点,标注着DevOpsDays,DevOps这个词的出现大概是在2008-2009年这个时间段内,这期间开始有越来越多的人关注到底怎样提升软件研发的效率,DevOpsDays的活动是Patrick Debois 在这个时间点第一次帮助社区开始组织这样的活动时发起的。在那个时间我对DevOps完全没有任何理解,对于我来说,我的理解就是软件工程,就是帮助团队提高效率,把工具用好。

第四个时间点:2008年-2012年

在2008年-2012年这段时间里,我所带领的外企研发团队在业务上有一个非常大的转型:2008年以前基本上是对外做外包,为澳洲总部做软件外包;2008年以后开始接触一些国内的软件工程项目,以及研发平台解决方案的工具落地项目,(现在我们叫做DevOps咨询项目)。之所以从2008年开始转型,有非常重要的外因和内因,这也是我希望通过这个过程和大家分享的。

从一个企业来说,为什么会转变自己的业务模式,为什么会改变自己的研发模式,其实很大程度上是因为有非常强的外因逼迫你不得不这样做,另外还有非常强的内因,让你自己也意识到“我可以这样做”或者说“我这样做会比以前做得更好”。

从2008年起,我就开始在国内承接一些软件工程类似的项目,比如研发过程改进、效率提升。我们所接触的第一家比较大型的客户是京东商城。之所以重点提起这个客户,是因为对于我个人来说,这个客户让我对软件工程有比较深的了解。

首先,京东为什么要做这个事情?我们在2012年开始和京东做这个项目的时候,京东整个研发团队的规模是大概1500人,在2013年项目结束我们离开京东这个团队的时候,它的研发规模基本翻了一倍。

以此可以看到为什么它会在这个时间点去做这样一个项目,因为这时候如果还没有人通过专业的角度去帮助他们梳理研发流程、考虑在这么大的规模下怎么保持研发交付的效率,可能他们在业务上会受到非常大的挑战。

当时我们做了什么呢?我们只做了一件事情:帮助它重新梳理软件需求上线的过程,并且通过一个工具把它相关的系统和信息收集起来,让他们的开发团队、项目经理、业务人员能很快做出决策,并且将一部分功能自动化。

这里一个大的背景是:我相信现在很多互联网公司的需求上线可能仍然是采取这种模式——上线窗口,典型的是,当时京东的上线窗口是每周二和周四,它会在每周二上线一些大版本或一些比较大的改动。

为什么选择在周二呢?周一刚进入公司可能还没进入状态,周二开始比较快速地工作,把精力放到工作上,这个时间点对于一个在线商城来说流量比较低,所以这时候上一些大版本是相对安全的;而另一个时间点——周四很容易理解,过了周五就是周末了,这个时间大家会考虑是不是要买点东西周末拿回家。

在京东内部,他们在每个上线时间点之前都会开一个上线协调会,这个协调会上就会出现:一个团队说“我作为一个产品线,我想要去发布我的需求”,而另外一个产品线的团队会站起来说“你不能发,因为我还没有准备好”,这时候就会出现这种有意见分歧的问题,这样的问题只有到马上要到上线时间点的时候才会暴露出来,所以造成很多需求延迟,没办法按照希望的状态被发布出去。

我们所做的系统是把这个信息尽早地收集起来,比如三周以后要上这样一个需求,在三周之前提到系统里,系统会链接到需求规划、测试、自动化打包、上线系统,这个过程中还会有一些审批的流程,把相关的一些关联方依赖方聚合起来,帮助判断这个需求是否能上。

其实从现在DevOps或者敏捷的角度去看这件事情,会叫测试提前,或者运维规划提前等这种概念。在那个时候京东做的就是这么一件事情,它就是把风险尽量早地暴露出来,让团队能够有更多的时间去解决这些问题,这样的话,在真正需要上线的时候可以非常顺利地完成上线操作。

通过这个项目我开始意识到:软件开发,几个人做的时候是比较简单的,当团队发展到一定规模的时候,做起来会越来越困难。这个困难的来源在于软件开发本身是件个人英雄主义的事情,它必须要依赖于每一个开发人员的智慧,去探索创造性地解决问题,这是造成所有软件项目管理问题的根源,也是其本质。对于软件开发来说,没有办法认清其本质就没有办法很好地去管理它,就没有办法让你的管理思路选择适应软件开发过程的思路而去管理这个过程,这样效率肯定上不去。

第五个时间点:2016年

到2016年,我以咨询顾问的身份参与到中国农业银行的互联网金融这个项目,去支撑和帮助他们解决在项目开发中遇到的一些问题。到现在为止,我的客户群体在向金融行业倾斜。

过去10年间,中国大陆的微软DevOps工具相关的所有大型实施项目都与我有关,通过服务过的企业和十年的实践我总结出:现在最需要软件工程过程改进,或者说需要DevOps的团队定位是:严重依赖IT的非IT行业的团队。

什么是严重依赖IT的非IT行业的团队?

比如金融行业是一个非常典型的例子。首先任何一个金融企业如果没有IT的支撑,它是根本就转不起来的,但它自己本身的业务又是和IT完全不相关的。这就造成这些企业的客户以及这些企业真正的业务从业人员对于IT的理解有非常大的误差,IT人员想要在这些企业里发挥作用,就需要和完全不理解IT的人进行沟通,同时要能够对他们进行交付,导致两方面的沟通存在很大问题,IT人员还需要对业务进行了解,沟通成本的增加对软件交付效率造成非常大的影响。

银行有非常典型的沟通问题,还有一些历史遗留问题,涉及到粒度和解耦,为什么说这两个是DevOps实施的两大法宝,这是我在给客户建议或帮助他们进行过程改进的时候所摸索出来的心得。本文将重点分享这两大法宝。

DevOps实施落地的2大法宝

DevOps

不管是敏捷、精益、持续集成、持续交付或DevOps等概念,目的都是提高效率,即提高单位资源的产出。其关键原因在于,中国的经济发展迅速,很多企业已经度过了那个靠增加投资来增加产出的阶段,现在IT从业人员薪资在增长,所使用的各种工具和环境,包括市场都非常成熟,很难找到一种短时间内获得爆发性收益的方式,企业之间到了拼内在实力的阶段,在这个阶段效率非常重要。

管理粒度。有两层含义:1动词,管理这个粒度,2名词,管理的粒度。在进行研发效率优化的时候,我们要关注的就是各种粒度,需求大小、团队大小、交付的代码量的多少,原则是越小越好。因为软件研发本身是一个复杂的过程,对于复杂过程的管理永远没办法适应其复杂度,最有效的方式是将复杂问题简单化,然后去管理简单问题。所以,从管理的角度如果想优化效率就要尽量减小管理单元。

工程解耦。软件工程涉及两个领域:管理领域——怎么去管理过程和团队;工程领域——实现要实现的内容,从软件角度来说就是怎么编码,怎么把大家脑子里的东西变成可运行的应用和服务,这个过程就是工程领域。在工程领域上想提升效率要做的就是解耦,不停地解耦,让你的程序、服务、所有部分都可以相对独立地被开发、测试、部署、运行,这样整体效率才能提升上去。

软件研发的自然属性

建立正确的认知才能有正确的办法。

软件研发

什么是软件的生产制造过程?

如果把软件的开发过程和汽车的制造过程拿来比较。要制造一辆汽车,首先得有一辆原型车,这辆原型车被确认以后,汽车的生产工厂就会不停地重复生产同样的汽车。也就是说汽车的生产过程其实就是重复生产同样的产品。

来看软件的开发过程,软件每次交付的内容都不一样。如果映射这两个过程的话,会发现软件开发的整个过程,包括需求、设计、开发、测试、构建、交付的所有过程都是在进行设计,而不是在进行制造。制造的过程是制造一个同样的产品,软件开发过程是每次产生不一样的产品。

回到刚才那个问题,到底什么是软件的生产制造过程?其实很简单,就是把软件编译打包好,右键点击zip包,选择复制、粘贴,这就是软件的生产制造过程。

汽车最大的人员和资源投入是在工厂里,需要大量的工人和技师让工厂能运转起来,制造汽车的资源投入是在重复的过程中投入比例最大,而做软件的过程资源投入的比例99.99%是在设计过程,因为那个复制&粘贴的过程不需要这么专业的人来做。

 

解了这两者之间的区别,但有没有想过,传统的软件研发/软件工程里所定义的管理方法,都是在用管理一个汽车生产线上的流程的方法来管理一个完全不同的设计过程。

这就是为什么传统的软件工程方法真正用到软件开发过程中会非常难用、还会出现各种问题的原因。如果采用传统项目管理方式来管理软件开发过程,就相当于看到一条笔直的路,要开车从这头到那头,打着火、挂上档、踩油门、松开方向盘、闭上眼睛,希望自己能够顺利地到底终点。

而事实上,结果完全不是这样,会有软件变更、用户变卦、中间出现bug、开发测试理解不一致、上线过程中环境不一样……这些问题都是无法在开发之前预见的,整个软件开发过程是一个设计过程,是无法被预计、被计划,和通过计划来控制的。

这就是我说的软件开发本身是一件个人英雄主义的事情,要靠每一个开发人员自己的创造性来解决问题,是不能通过一个看似严谨的环环相扣的过程来进行控制的。在软件研发里要强调的一点:所谓计划不是为了限制变化而是适应变化的。

敏捷让我们重新定义管理

这就必须提到敏捷。敏捷是什么,敏捷到底帮助我们认清了什么。其实敏捷真正做的事情是帮我们认清了到底什么是软件开发,软件开发的管理过程到底在管理什么。

传统的项目管理,管理的是时间、成本和范围,它认为我们的目标是一致的,在一个固定目标的情况下,我们所要管理的就只有成本、时间和范围。这就好像我们盖一栋大楼,肯定是有一个蓝图的,有了这个蓝图以后这栋大楼到底需要多久盖一层、盖一层需要多少资源、需要多少人力投入、可能会遇到什么问题,这些基本都是可预知的。

软件开发不是这样,软件开发从来没有定义清楚我现在要盖一栋大楼,也就是说你从用户那里拿到的所谓的需求,永远都是一个假设。为什么说是假设?需求和假设到底有什么区别?区别就在于:假设的价值和质量是可变的。当你的价值和质量是可变的时候,其实你拿到的就是一个假设而不是一个需求。

实际的体现点是:当你把楼盖到第十几层的时候,用户过来说我要加个地下室,你肯定觉得用户疯了,但是从用户的角度来说他觉得这个很正常,他认为你不就是一堆代码吗?为什么不能在这儿加入一行呢?他完全意识不到,他所加入的位置其实是地下室。

原因在于我们所做的软件是虚拟的,没有办法被实例化,在软件造出来之前没有任何人能看到它长什么样,没有任何人能体验到这个软件最终会给他什么。作为一个软件来说,只有当软件已经被做出来给到用户之后,用户才真正知道这个软件到底是不是符合他当初的所谓需求。也就是说,大家看到的需求文档、开发计划其实都是假设,在做出来、代码写出来给到用户之前都通通有可能是错误的。

当我们管理这样一个不确定的过程的时候,如果还用传统的项目管理方式来管理它的话,必然会遇到很多问题。敏捷重新定义了软件开发管理的思路。它定义的方式就是:把惯常的项目管理认为不变的价值和质量定义为可变的变量,传统的项目管理领域里的变量——时间、范围和成本,仍然是变量,所以软件开发管理领域中的变量要比传统项目管理中的变量要多得多、复杂得多。

这其实就是软件研发的本质。软件研发的项目管理和传统的项目管理不是同一个概念,如果用传统的方式来管理软件研发的过程必然会遇到问题。

传统开发 VS 敏捷开发

上图是在比较传统开发和敏捷开发,从过程上来其实是瀑布式和迭代式的比较。瀑布式和迭代式到底有什么区别?图的上半部分是瀑布式的过程,下半部分是迭代式的过程。从图中可以看到两者最大的区别就是:迭代式的过程每一个管理单元会变得更小,交付的时间点会更加提前,实际上这就是我所说的第一个法宝——粒度。为什么敏捷开发能更加适应软件开发过程,原因就在于它缩小了管理粒度。

当你定一个三个月的开发计划,并且一次开始执行,如果中间出现问题,可能需要把很多东西从头来过。敏捷开发要求我们把开发过程变成一段一段的,每一段都是一个完整的交付过程。这样就算犯错误,所犯错误的机会成本也会低很多。

也就是说,当你的团队规模到达一定程度,当你所开发的软件体量到达一定程度,软件开发必然会变成一个非常复杂的,并且你没有办法去把它管理好的过程。当到达这样的量级时怎么处理?千万不要试图以一个非常严谨的管理流程来适应它,这是不可能做到的。你所要做的就是尽量减少你所管理的单元。简单来说就是:把你的需求从Word挪到Excel里,把你的需求从一大堆的描述变成一条一条的描述,把你的团队从几百人的大团队变成一个个几个人十来个人的小团队,把你所交付的软件从一个单体的软件变成一个个小的服务,这都是在控制粒度。

当你降低了粒度以后,并不是说你变得有多聪明了,而是在你同样的聪明程度下你所处理的问题的复杂度降低了,你就能把它处理好。

总结:计划不是用来限制变化的,而是用来适应变化的。软件开发的计划本身也是“管理单元”,计划对变化的适应能力来源于计划本身“粒度”的缩小。计划越大越有可能没办法被顺利执行,计划越小就越容易被成功地执行。

软件研发是一个复杂过程,不要试图用复杂方法处理复杂过程,尝试将复杂过程简化成简单过程,再用简单方法处理简单过程。

经常有人问我:我的团队适不适合做DevOps?我的产品适不适合做DevOps?这就是个伪命题,这个问题在于你怎么看待你所管理的过程,如果愿意并能够把管理的过程简单化,就肯定可以做DevOps,且做DevOps的过程就是在不断简单化管理过程的过程。

软件研发管理过程全景

到底软件研发管理过程是什么样的?如图所示,我们要管理的就是图上的点和线。图上最下面比较粗的线上列出来的简写其实就是CMMI定义的管理过程。

用CMMI模型可视化地展示一个软件研发的管理过程,从最左边的需求提起,可以看到包括两大部分的内容:

技术架构——从技术的角度怎样来描述产品长成什么样子,这里看到的就是一个大的产品,下面分成很多子系统,每个子系统里包含很多模块,这就是所能看到的软件的技术架构。

条目化需求,条目化需求就是用户提出的一个一个的他希望软件帮助他做到的不同的场景。

往右一点是设计过程,软件的架构设计就是将用户所希望实现的场景和技术架构进行映射,需要识别的是通过哪些技术可以实现用户所希望实现的场景,并且还要在用户场景不断影响技术架构的过程中保持架构的稳定性、可扩展性、性能等。所以它所做的就是把底下的框框和上面的框框联系起来。

再往右有一个项目计划,这里我列出来了一些项目,项目里会有开发任务、测试用例、可能还会有bug等,项目是从左边的条目化需求引过来的,这是敏捷的做法。

传统的软件开发的做法是:用户想做这个事,先做分析,需要实现哪些技术模块,然后要求把技术模块的技术点梳理成所谓的开发计划,它所传递的项目来源是来自于产品的模块,这是一种瀑布的做法。就是在软件开发过程中,将业务需求打散形成整个产品的完整设计,针对完整设计进行完整开发和完整交付。

它和直接使用条目化需求组织开发过程的区别在于:在你进行完整设计、完整开发的过程中,会发现到了最后收敛的时候,当真正实现了这些软件需求,需要通过一些软件的版本进行交付的时候,你必须要让这些模块的功能收敛到用户希望的场景上。实际上你交付的还是用户场景,只是在开发的过程中把它变成了技术语言,在最后交付的时候再把技术语言转化为业务语言。

这两次转化就意味着我们必须要整体开发整体交付,也就造成了管理粒度非常大,随之而来的就是各种问题。

敏捷开发从过程管理上要把握一个非常重要的原则:中间的开发过程必须围绕一个一个条目化的业务需求来组织,而不是围绕技术功能点。用户要什么我们就开发什么,就怎样去组织开发过程,最后交给他什么。因为就算是你把它打散成技术需求,最后交付的还是业务场景,这是没有变化的。技术与业务之间转化的过程,会造成非常多的问题,包括之前说的依赖问题,都是和过程的组织方式有关系的。

就这一点在我过去所服务过的客户里一些传统的开发团队都非常难做到,因为这和他们现在的管理方法、组织过程以及他们对软件开发的认知都是不一样的。他们可能都会提我们要做敏捷,可能也会说我们要用用户故事来进行需求梳理,但他们没有意识到用用户故事的时候,更深层次的要求是:整个开发过程都要围绕单个用户故事作为管理粒度,来推进整个管理过程并且最后进行交付。

再往右可以看到编码、版本、运维的各种环节,代码的变更会从开发任务产生出来,也可能会从测试用例产生出来,但最后都会被收敛到某一个版本上,而这个版本会按照顺序进入到我们的开发环境、测试环境、准生产环境和生产环境,最后在环境里产生出一些反馈,再回到需求,这就形成了完整的软件研发过程的闭环。

结合前面介绍的内容来看,如果从管理过程来理解软件研发,管理的就是这里面的点和线;如果从工程角度来理解软件研发,更多的倾向是:从开发测试这个环节开始,怎样能够让做出来的东西更快地进入到最后的环境,并且在这个过程中保持其跟踪性以及我们对质量的控制。

总结:研发过程改进,就是对上图中的点和线建立对应的管理单元的过程;并将这些管理单元形成能够快速交付需求的管理体系。

软件研发过程:管理属性和工程属性

软件研发过程具有管理属性和工程属性。管理属性定义了用户要我们做什么;工程属性定义了我们的团队真正做出来了什么,就是我们交付的东西,这两个是软件开发里非常重要的转换,而这个转换靠统一的版本管理来衔接。就是要建立一个统一的版本号的规范,在任何时候都可以通过一个编码快速识别出现在软件开发处于什么样的状态、现在的需求处于什么状态、现在需要交付的东西是哪个。

至此,如果再次反思这个过程就会对第一大法宝——粒度有一个深入的理解了。软件开发过程要管理的其实就是这个粒度,目标是尽量缩小管理粒度。在整个软件研发体系里流动的是被管理的内容,需求、任务、测试用例、编写的代码、交付的模块都是被管理的单元,管理单元越小意味着越容易管理,交付的效率越高。

持续交付就是持续解耦

前文讨论得更多的是管理属性,现在来看工程属性。从工程属性上我们要做的就是持续交付。持续交付到底是什么,持续交付意味着软件一直处于可交付状态。

持续交付本身并不完全等同于CI/CD,不完全等于持续集成和持续部署,因为持续集成和持续部署只能保证有一个可交付的产品,或者有一个可交付的代码集并可以很快把它转化成交付件,且在交付的过程中可以自动进行,CI/CD主要做的是这件事,而本身代码是否处于交付状态靠管理过程控制粒度进行保证。

持续交付实施框架

持续交付

上图展示的是持续交付实施框架,把持续交付分成了7大领域,并且把当前的实践状态分成了每100天交付1次和1天交付100次。实际上在任何一个团队里,当你希望把自己的交付速度提升到每天交付一百次,那你需要从这7个领域进行规划、设计、实施,在这7个领域里我们到底在做什么,归结到底就是:解耦。

持续交付的挑战:系统耦合

持续交付

想要把解耦说清楚,可以从一个简单的场景——取钱来看。站到ATM机面前,把卡插进去、输入密码、输入金额、拿走现金,对于用户来说是再简单不过的事情,但其实这里面的技术非常复杂,在ATM机里需要处理很多的事情:机器系统控制、智能卡识别、接收用户输入、连接银行系统、监控等;还要把信息和数据传输给银行,这个过程中又涉及到数据加密、数据完整性、监控等;到了核心银行系统后需要查找账户、账务信息、进行审计和风险控制等。

 

这十几二十个系统意味着数十个团队和上百人的团队规模,也就是当你把一个简单的用户场景从技术架构角度去看的时候,打散成技术点都会变得非常复杂,这在金融业银行业尤为严重。

这样复杂的系统造成的结果我称之为“涟漪效应”。在一个平静的水面扔下一颗小石子,会在水面荡开一圈圈的涟漪,如果水中有几颗树,涟漪会撞到树。如果把石子理解成需求,树就是受到影响的系统,一个石子的场景相对简单,尝试一下同时扔下两颗石子,第一颗石子扔下去荡开的涟漪在碰撞树的过程中会和第二颗石子荡开的涟漪产生交叉反应,继续影响,产生反过来的影响,这是复杂系统中分析需求、进行架构设计时难解决的问题,就是系统耦合的典型场景。怎么解耦是软件工程领域必须解决的问题。

软件开发中的三级耦合

首先我们需要知道软件开发中到底是怎样的耦合。软件开发中有三级耦合:

代码级耦合。所有人在同一个代码分支上同时迁入迁出代码,也就是大家同时开发同一个产品,这种情况下团队规模是没有办法超过20人的,这是一个经验数字,想象一下一个超过20人的团队频繁地在同一个代码分支上进行迁入迁出,基本上是无法工作的。

组件级耦合。不管是什么开发语言都会有包管理器的概念,比如前端可能会用到npm、bower,比如做Python会用到pip,这些包管理器所做的就是进行组件级的解耦。

组件级解耦是指:当我不是直接引用你的代码,而是通过你对版本管理的包进行引用的时候,就可以在一定程度上延迟包的变化对我的影响,比如说我可以一直引用一个1.0的包,但是这个包的开发者已经在升级2.0,但我可以完全不理会他那条分支上的代码变化,我就只引用1.0的包,这时两个团队就被解耦了,如果这是一个产品的两个部分,也被解耦了。

组件级解耦有个最大的限制条件:到达软件上线时间点的时候,要统一同一个应用里的所有的包的依赖。当然我说的这是一个单体应用,所有的代码编译到一起,在一个运行时RunTime里运行,如果是这种情况,那么包管理的隔离就只能到达产品发布的时间点,如果这几个团队开发同一个产品,就算在开发过程中可以让大家去引用不同版本的包,但是如果要一起上线,那么必须在上线的时间点统一大家用的所有的包的版本,不然没办法在同一个环境运行。所以组件级耦合只能解决在开发测试过程中的一定程度的解耦,没办法帮助团队彻底解耦。

怎样才能彻底解耦?就会应用到现在炒得火热的微服务,其实它所做的就是彻底的运行环境级别的解耦。

大家经常看到,很多的web api都会在url里面标识不同的版本号。比如团队1发布了v1版本的api,并且已经被团队2消费;那么团队1可以继续按照自己的步调发布v2版本的api,而团队2可以继续使用团队1的v1版本的api;团队2可以在自己觉得舒服的时间点来升级到支持团队1的v2版本。这样,团队1和团队2就彻底解耦,可以独立完成需求,开发,测试,交付的整个过程。

这时这两个团队从需求、开发、测试到交付的整个过程都是可以不去互相影响的,因为就算运行时在生产环境,这个服务被部署了以后,他们都可以在不同的版本间进行切换,这样就保证了每个团队都可以自主地组织自己的开发过程。

实际上它就是降低了管理单元,让管理单元可以小到一个团队里边,甚至小到几个开发人员,这时可能看到的还是几百人的大团队,其实里面是一个一个小的独立运作的细胞,这些细胞都可以按照自己的步调去移动、去发布、去测试,这样大家才能更加高效地工作。

这三级解耦的过程中,团队的自由度、业务能力、交付的速度、质量的控制都会得到提升,但也会造成系统复杂度、运维复杂度的提升,这是我们在不停地进行软件开发解耦的过程中所带来的副作用。

为解决这些副作用,这两年软件工程出现了一个明星项目——Docker,它到底解决什么问题?时间回溯到1995年,那时候经常提到一个词:web service,当时的系统都是单体架构,甚至于整个架构里都只能用同一个开发商的同一种技术,比如C++,那就从上到下都只能用C++,没办法选择其他的开发商产品,也没办法选择另外的产品,原因是不同的技术栈之间的互操作性非常差,互相之间难以交互。

web service的出现就是为了解决不同技术栈之间的互操作性问题。因为从一个IT投资者的角度来说,他不希望自己被某个技术栈绑定,比如说你是一个技术管理人员,你肯定不希望说我只能招聘C++人,因为我的系统是C++写的,你当然希望市面上流行的开发语言开发的程序都能与自己的系统融合,甚至说我现在买过来一个系统,我希望不管这个系统是用什么语言开发的,都可以和我现在的程序一起工作。这在现在的你看来可能觉得不是个问题,但在那个时候是个非常大的问题,企业IT决策者、投资者没办法这么自由地选择技术栈,所以才希望通过web service去进行解耦。

这个解耦的过程一直持续到2015年,到现在你会发现不管采用什么技术栈,应用都可以进行互相操作,我们可以用很多方式去进行跨进程、跨服务、跨系统间的通讯,没有任何障碍,这会给IT管理者很大的自由度,不再受制于技术栈,但也造成了另一个非常大的问题。

当我们选择了很多的技术栈去开发系统,当这些系统被部署到我们的环境,你会发现这些系统是可以互相操作,从业务的角度没有问题,但是IT运维人员或开发人员会发现已经陷入一个非常复杂的N*N的问题矩阵。

以前我们只需要处理同一个技术栈的同一类型应用的开发、测试、部署,而现在我们需要同时处理很多不同的技术栈的开发、测试、部署。如果你用过一些开源的组件就会发现,当你在一个项目里开始引用开源组件的时候,可能你的主程序是用Java开发的、服务是另一种语言开发的、消息队列又是另一种语言开发的,这些程序都需要被部署到IT的运维环境才能一起工作。

Docker

Docker就是用来解决这个问题的,它可以帮助你使用同样的方式来运行不同技术栈的不同应用,这些不同应用又可以在统一的硬件和操作系统环境下被运行、被部署、被测试、被发布。解决了我们在不停的解耦过程中带来的副作用:系统架构复杂度和系统运维复杂度提升的问题,解决了N*N矩阵的难题。

因此,在进行软件研发过程改进或效率提升的过程中,容器技术对于我们来说是非常有价值的。

Docker对DevOps的价值有很多,如图所示,最重要的我认为是:为不同职能/技能的人员各司其职提供了条件。

我们有很多自动化部署发布的工具,也提出来很多解决办法,但是这些解决办法其实都没有Docker解决得顺畅,原因在于所有这些工具的解决方式都是在采取一个更复杂的方式来解决复杂问题,试图用复杂适配复杂,Docker是用简单来解决复杂问题,所以它解决问题的效率会很高。

Docker

如图是来自Google的一个统计,Docker和DevOps的发展趋势非常匹配,DevOps效率提升的过程就是在不停解耦,解耦到一定程度后,如果不解决运维复杂度,解耦过程中产生的效率提升都会被运维复杂度吃掉,最终达不到效率提升的目的。

DevOps实施落地的总体策略

DevOps三步工作法:建立全局观、建立反馈、持续改进。

这三步从可操作性的角度需要做什么?从建立全局观到建立反馈的过程中,要做的是:

首先要建立端到端的软件全生命周期管理的体系,这个体系就如软件研发管理过程全景图所示;

接下来把图中所有的点适配到自己的环境中,识别出对于我来说到底是什么,同时对这个体系的管理能力必须通过一些工具来实现,这个过程就是识别管理单元;

识别了管理单元之后要做的下一步是减小管理粒度;

减少管理粒度的结果就是建立了流动性。对于看板有了解的人知道,看板最重要的原则是拉动原则,拉动原则的目的是让进入到研发环节的内容尽快出去,所以要做的就是建立流动性。建立看板的第一步是建立管理流程可视化,这就是全局观,看到整个过程是什么、问题在哪里,做所有这些事情的目的就是让进入到研发环节的内容尽快出去,怎么才能尽快出去?很简单,把这个东西变小就可以更快地流动。

有了正向的流动之后,下一步要知道流动的东西是好是坏,这就是在建立反馈,而配置管理、持续解耦(包括持续集成、CI/CD)真正在做什么?持续交付真正在做的也是建立反馈,从具体落地的策略来说,实际上是在解耦,但解耦的目的是在环节中不停地建立回答“这个东西到底做的好不好?”、“可以不可以继续往下走?”等问题的反馈。

有了这些反馈以后,就已经形成了整个研发过程的闭环,现在要做的就是让这个闭环不停地流动起来,这就得靠人。所以持续改进最后一步的关键是:人+流程。

我们的研发过程改进永远不是一个项目,而只是一个起点。开始做这件事以后就没有尽头,我帮你建立起这样一个体系以后,你要做的是不听地改进这个体系,怎么能让这件事情落地,要建立起这样一个自我驱动的改进过程。

Q&A

Q:@無 為:DevOps对应的组织架构和绩效考核是什么样的?对于还在模块化、特性化向组件化优化,还没做到微服务化架构的产品,怎么做DevOps?

A:DevOps不是一个状态,而是一个追求高效的过程。你需要做的不是DevOps,而是任何可以提高效率的实践。在这一点上,DevOps和敏捷很类似,我们只能经历不断DevOps的过程,而永远不会达到真正DevOps的状态,因为你永远可以做得更好,持续改进。

组织架构和绩效考核的角度上来说,DevOps希望强调外在指标,弱化内在指标,通过统一所有交付环节的价值趋向达到高效的对外交付状态。

关于微服务架构的这个问题,我想你更多的是在问如何针对这种类型的产品进行持续交付 … … 这一点上,传统架构的产品有传统的做法,当然因为模块依赖的问题会造成很多的约束,这些约束会降低持续交付的能力;这就需要持续优化你的架构,同时采用所匹配的工程/工具系统来完成当前状态下最优化的持续交付,不停地寻找改进点,不停地解耦。

Q:@無 為:是不是所有的产品形态都适合做DevOps?有些软件产品并不是直接面向最终用户的,比如说针对企业或者运营商的产品,属于NaaS、SaaS、PaaS中间层的甚至底层的,怎么做DevOps?

A:这个问题的核心在于我们如何理解“对外价值”,对任何一个系统来说,都有所服务的“用户”,这个用户可能是人,也可能是其他系统。把这个思路转变过来,就会发现这些系统同样可以做DevOps。并不是产品形态适不适合,而是人适不适合。

Q:@無 為:DevOps对应的流程支撑,比如怎么排除公司安全红线去做到流水线和Ops类生产环境的对接、怎样做到Ops众测和灰度发布的对接,定界定位故障恢复的标准、每个流程点的质量定义和标准有没有一个例子?

A:其实很多行业都有这个问题,比如我服务的金融行业就比较多,监管审计的要求让金融业必须采用Ops分离的方式来运作。但这个和金融行业是否能够搞DevOps完全没有关系,这只是一个约束。

如何能够既满足安全红线,又能最大化提升效率 … … 我的看法更多的是人,确切地说是那个级别的人能够认识到“效率第一”,效率大于稳健,犯错是好事,出了事我们一起扛。如果你的团队自上而下有这样的认知,你说的都不是问题。所有的所谓安全、红线、审计、监管的要求,很大程度上并不是因为这个问题真的那么严重,而只是组织里面划清界限、分清责任的一种方式。

认识到这一点,你就知道DevOps中所谈到的文化转变。而且文化转变必须自上而下,源头越高越好。 

Q:@宽妈 爱花:是否有关于DevOps流水线里好用的工具推荐介绍?

A:流水线我用的基本上是2个:TFS和Jenkins
但这两个工具都只是起到流水线串接的作用,你还需要根据自己的情况引入很多工具来满足要求。

Q:@shekwell:在公司推进DevOps时,对于开发人员的要求和能力是否更高了,需要哪些方面的能力提升?如何让员工接受这样的改变?

A:DevOps = 效率提升

所以对于能力的要求肯定是在不断提高,无论你现在是什么水平,当你考虑引入DevOps,就意味着你在试图提升人员的能力。要做到这一点,首先你要建立“容错”心态,就是允许大家犯错误,所有的改进都是建立在“犯错”的基础上的。

你要做的不是“如何让员工接受这样的改变”,是允许“员工开始这样的改变”。

Q:@黄威:DevOps是顺应数据时代的发展而产生的,在企业内部基本是面向互联网的部门先带头学习,因为不学习明天业务能否保障都不知道,可以说是业务驱动。那传统金融银行机构呢?他们现在是拥抱DevOps还是静观其变,先吃“苹果”的金融银行机构有成功或失败的案例了么?

A:这个“顺应数据时代”的说法很有意思,DevOps这个词的出现确实是在顺应时代,但不是什么“数据时代”;而是我们已经进入一个“效率为先”的时代。当企业无法继续通过增加投资获取更大收益的时候,增加存量资产的收益自然就成为了重点,这就是效率。

传统金融银行现在已经不是静观其变了,而是已经蠢蠢欲动了。从2015年开始,我的咨询服务客户就开始向金融业倾斜,原因有两个:第一是外因,就是互联网金融的兴起,对传统金融业产生了巨大冲击;第二是内因,传统金融业的从业者被慢慢渗透,一些新的管理思想已经进入了传统金融业的决策层。

成功和失败并存,在同一个组织、部门甚至团队中都存在成功的实践和失败的实践;所以我们不能说哪一家就是成功,那一家就是失败。作为顾问,我不会允许我的项目失败,但是每个项目中都有成功的点和失败的点。具体请关注我的分享。

Q:@阿牛:DevOps的切入点在哪里?如何说服管理层在这方面投入?有哪些指标可以用来做度量的?

A:效率。管理层关注的是ROI。DevOps通过整体优化提升交付效率,单位时间和单位资源的产出会提升,这些都可以通过度量完成。

Q:@紫气东来:公司新增’持续集成工程师’一职,而在DevOps实施过程中,持续集成工程师除了与项目经理共同制订DevOps策略、搭建配置DevOps环境,还应从哪些方面体现自身价值?如何让项目的DevOps实施更好地落地?

A:持续集成工程师这个领域定义得太狭窄了,应该定位成“持续交付工程师”。持续集成完全是一个技术定位,而“持续交付”则是管理+技术的定位。我想你要体现自己的价值应该向这个方向发展。

Q:@郑承良:公司做的是交易系统,新系统上线,断断续续发现一些bug,断断续续停机维护,用户体验很不好。线上系统维护有哪些好的策略和方法?

A:灰度发布,蓝绿发布,feature flag等方法都可以帮到你。

Q:@ Joney Hsiao :目前项目刚上线,大家对上线流程、环境规划、版本控制比较模糊,只要生产出现大范围影响,就乱成一锅粥,并且恢复区间还比较长,该怎么改进?(IT金融行业)

网友评论comments

发表评论

电子邮件地址不会被公开。 必填项已用*标注

暂无评论

Copyright © 2012-2017 YUNWEIPAI.COM - 运维派 - 粤ICP备14090526号-3
扫二维码
扫二维码
返回顶部