作者简介

于洪奎
中国银行软件中心高级经理,
系统分析师、CCEP、CSM、DevOps Master
14年软件开发相关经验,其中9年开发管理经验

以下为于洪奎老师在 DOIS 2018 · 北京站的分享整理而成。

我来自中国银行软件中心的一个开发部门,中国银行软件中心从 2013年开始试点敏捷软件开发以及相关CI、CD等实践,而我们内部真正的提 DevOps 比这个要更晚些。

中国银行的 DevOps 涉及的产品线和技术栈众多,下面的分享并不能完整的给家介绍中国银行整个 DevOps 的做法,只会包括与 X86 相关的部分产品的 DevOps 实践情况。

我的分享主要包含以下四方面内容:

**第一,**和大家一起了解一下,这个题目中所谓的“器用”和DevOps,“器用”到底是什么?

第二,和大家一起分享一下我们的 DevOps,什么叫做我们的 DevOps 呢?就是我们在践行 DevOps 的时候的工具选择和一些整体上的思考,这里并不是说我们的做法就是最好的,只是和大家分享一下我们的做法,所谓,它山之石可以攻玉,抛点“小石子”供大家参考。

第三,分享一些我们认为自己做的比较成功的东西,一方面给大家Show一下,另一方面,也增加一下同业在践行 DevOps 时的信心,有些东西不仅仅是互联网公司可以做到,其实,我们金融企业、大型银行,也是可以做到的。

**第四,**分享几个我们“失败的教训”,我们常说“来,说点不开心的,让大家开心一下”,这个也是让大家一起开心一下,反思一下。所谓“失败是成功之母”,但是,仅仅有“失败”是不够的,最重要的是失败之后的学习和反思。

一. 器用与 DevOps


首先,跟大家分享的就是这张图,这张图是开发著名敏捷管理工具 Jira 的Atlassian 公司的 DevOps 成熟度调研网站的入口,网址是:https://www.atlassian.com/devops/maturity-model。

为什么和大家分享这张图呢?我认为这张图里面的关于 DevOps 描述,比较好的表达出了:我们去看 DevOps 这个词的时候,你到底希望得到什么?

我们大家现在都在做DevOps,前段时间都在搞敏捷,我相信我们很多人必定思考过,我们做这些到底是为了什么?而从这张图里面,有两个词非常的吸引我,比较清晰的表达出了,我们到底希望从DevOps中获得的内容,就是:**“frequent” 和 “reliable” **。我们做DevOps归根结底,就是希望更“高频”、更“稳定”的来发布我们的软件应用产品,这个地方给大家讲两个小故事。

第一个小故事,我在去年的时候给我们总行的某业务门部发了一个匿名的调查问卷,这个问卷里面的内容很简单,您认为我们作为中行的软件开发部门,我们在哪些方面最应该得到提升?

第一个是我们的交付不够快,我们应该更快的交付;第二个是我们交付的不够多,我们应该做更多的交付;第三个是说我们交付的质量差,我们应该提升交付的软件的质量;第四个是我们开发成本高,同样的开发内容我们报价贵,我们应该降低自己的开发成本;第五个是我们交付的软件安全性差,我们应该提升交付的软件的安全性。我把这五点简称为:多、快、好、省、安。我把这五项给我们的业务同事们让他们选一选,最多让选两项。最后得到的结果是什么呢?得到的结果是90%以上业务同事的都认为我们现在,我们应该更快的交付。

我们经常有人说,我们金融行业与其他行业有很大的不同,我们不是互联网,所以,我们的敏捷和 DevOps 也应有自己的特色,这一点我完全同意。但是,有特色,不是说脱离本质。

我们金融行业做 DevOps 不能仅仅学互联网、照搬互联网公司的做法,但是“你首先学互联网,学会互联网的快”。

我一直一来有一个观点:所有不能让企业变的敏捷和 DevOps 都是耍流氓,你去做 DevOps 和敏捷,首先你要能够快起来。当然,这个快要是可持续的快,是稳健的快。

第二个小故事,就在前几天,我们和质量部门、测试部门同事一起做了一个敏捷测试沙龙,大家都说我们敏捷之下质量得到了“提升”。我就问大家,我们践行敏捷之后质量真的提升了吗?那么和传统的开发比,我们到底有了哪些方面的提升?大家都会心的笑。

其实和采用传统开发方法的部门和产品团队相比,采用敏捷方法的开发部门和产品团队的软件交付质量并没有提升,最起码从我们内部的数据来看是这样的。

敏捷并没有提升我们软件产品的交付质量,甚至,你们发现,当我们一开始做敏捷的时候,我们的交付的确开始变快了,但是,我们的交付质量变差了,这不是感觉,是有数据支撑的。

但是,随着时间的推移,敏捷产品的交付质量在逐渐的,明显的提升,有的已经接近了传统开发方法下的交付质量水平,这个也是有数据支撑的。这其实并没有什么大惊小怪的,早就有变革曲线模型对此进行解释,管理大师彼得·圣吉也说:先变差,再变好。

通过这两个小故事,我认为这个非常好的诠释了我们对敏捷和 DevOps 的诉求,无论是从我们的业务方,还是我们自身,我们都希望更高频、更快的交付我们的软件产品,但是,这种交付也要是高质量的、稳健的。

经常有人说:敏捷和 DevOps 不是快。我认真这句话不准确,我比较赞同的一个准确的说法是:敏捷和DevOps不仅仅是快,但是,首先要

说到 DevOps 的时候有几个概念,大家可能也都比较了解,比如敏捷、精益。我这里想分享一下,从狭义上讲,这几个概念之间的关系是什么样的。首先,从广义上说,敏捷也好,精益也好,DevOps也好,从来都不承认它只关注一段,都说自己是端到端贯通的,典型的 DevOps 有无穷环,精益也没有说它不管后面,敏捷也没有说它不管前面。我这里是从狭义上说,我第一次听这个观点是来自光环的李健昊老师,从狭义上说,这几个概念在我们的开发过程中就是下图这个样子的。

我这个图总结为:精益更聚焦于把事情做对,敏捷更聚焦于把事情做快,而DevOps 更聚焦于把事情做畅。说到精益给大家推荐两本书,一本是《精益创业》,还有一本是《精益数据分析》,从精益的角度上来说,通过学习、构建和反馈过程来不断地探索商业价值和寻找商业价值,就是在不断的探索和寻找那个“对”的价值点。这里的“精益”其实与当初“精益生产”中的精益,已经有所不同了。

敏捷大家都知道,它从源头上是一帮开发的大师发起的,他们本质上更关注的是“探寻更好的软件开发方法”,他们一开始也说我们要交付客户价值、交付可工作的软件、响应变化,他们没有说我对其他的不关注。

只是从本源和狭义上看,敏捷更多的关注于软件开发方法,而对于前面的价值探寻与后面的顺畅交付,的确提的少一些。

DevOps 我就不多说了,前面已经说得很多了。后面还会说到。我们再来说说“器用”,器用这个词是个很古老的词,一开始的时候所谓的器是指武器,用是指农具,后来变成了工具使用,我们中华文明博大精深,每个词都有很多种解释,在这里我引用这个“器用”就是指工具使用,没有什么其他高深的含义。

这个就涉及到我们在理解工具的时候是怎么样的看法?

文化和行为,我们都知道文化会影响行为,行为也会反过来影响文化,但是当我们引入工具的时候,其实也是一样的,你以为自己在通过自己的行为使用工具,影响工具的功能变化,同时,反过来工具也会影响和规范,甚至引导你的行为。

二. 我们的 DevOps


上面简单的说了一下 DevOps 和工具这两个概念,下面就是我们中国银行的 DevOps,大家都非常关心,或者非常希望能够了解中行的 DevOps 到底是什么样子的,这里和大家一起去做一些分享,当然这里仅仅涉及我们X86相关的部分。

2.1 工具的选择


我一直都在说工具的如琢如磨,我们来看一看我们在说工具的时候到底在说些什么?

DevOps 的工具链很多,这只是其中的一些,也并没有多全,现在有很多地铁式、蜘蛛网式,甚至元素周期表式的工具链地图,大家可以参考许峰老师的《一文收录16张DevOps“拍照审图”》一文。

其中这张图,大家很多人肯定都认识,这是经常被应用的一张图,来自James Bowman。这张图非常推荐大家去了解,从前面到后面每一个环节上有各种各样的领域,每一个领域下有一些它推荐的,或者觉得大家应该使用的开源工具。在这些开源工具里面,我们中行用了其中不少的工具。

所有标注的开源、非开源工具我们基本都多多少少用到了,我想告诉大家的是,其实用哪个工具并不重要,重要的是你在这个过程中怎么选、怎么用,以及是不是真的用工具解决了自己的问题!

2.2 Devops 工具链


上面这张图很复杂,从使用者的视角我们的过程是这样的,从前面的需求到后面的监控整个过程中我们大概使用了这些工具。这里需要反复和大家提一下的是,这个只是涉及我们X86相关的部分。

三. 成功之经验分享


3.1 源代码


我们大家都知道业界关于 SVN 和 Git 之间有争论,有的说 SVN 好,有的说 Git好,你认为 SVN 和 Git 之间的区别是什么?或者你拥护的是什么?

画外音:其实此处的互动,见仁见智,并没有标准答案!

在实际开发中,我所在的部门使用的是 SVN,我们有些部门使用的是 Git。哪个工具更好,我的答案是:“主线开发更好!”。

完全答非所问嘛!这就是我希望分享的我们自认为的成功的实践的第一点:主线开发。我们都知道,提高工作效率,很重要的一点就是:消除浪费。

那么,软件开发中的浪费是什么?我们都知道:工作切换、无效沟通、还有给开发人员配备烂机器和小屏幕。这里,我要提到是一个很多人不以为然的,但是很明显的浪费,就是分支合并,在敏捷、精益里面都会说我们要产生价值,大家想想软件开发过程中的分支合并,产生了什么用户价值?完全没有产生任何用户价值。

我一直有一个观点:所谓,分支合并,在当今的 IT 技术环境下,只是软件开发过程中的一个不产生任何价值的多余的动作。你消除不了它只有两个原因,一、你不愿,被自己的想象力束缚了手脚,觉得自己不得不这样做;二、你无能,技术水平差,就只有所谓“管理”手段补。

3.2 分支管理


上图就是我们曾经的分支,大家能想象吗?这个就是我们一个批次一个批次的投产,这个就是我们曾经的分支状况,我们为了这个分支状况有一个特别牛的项目经理画了一张表专门进行管理。厉害吧!?

这个是我们认识到了这个问题以后,经过了半年多的努力以后得到的清爽结构,我想告诉大家的是,它是可以做到的,它真的是可以做到。但是,它真的很难。

我们看到主干开发的时候,业界很多人知道这个,但是到底什么是主干开发?所谓理想的主干开发,首先所有的代码都是提交到主干分支上的,然后你的发布随时可以从主干发布,这个能够做到非常困难,需要让你的主干一直保持非常的稳定,这需要你的团队足够的自律,每一个提交代码的人都足够的自律,你的持续集成都足够的健壮,并且维护的特别好。

我们做的是一种现实的主干开发,就是你的提交依然提交到主干,但是你要发布,你要发布的时候会从这个地方拉出一个分支做release,release的时候会在分支不超过一个迭代的时候就投,投完之后这个分支就冻结了,我举了一个非常形象的模型,它像一棵树一样,它一直在长,这个就是我们现在做的主干开发的情况。但是,主干开发其实真的很困难。

上面这个图是业界经常用到的版本管理分支,我们以前也是这样的。这两种方法是决然不同的,它对于你带来的价值和效率的提升其实也是决然不同的。

都说主干开发好,但是,硬币总是有两面的,它有什么副作用?它的困难是什么?大家要想一想。

我们经常会做同业的交流,大家一听我介绍主干开发都会说这个东西好!好,你为什么不做?大家都会很会心一笑,我们做不到嘛!我们比较特殊,我们有这原因,那理由,巴拉巴拉……..

这个时候,我们要是自己问一下自己,我们为什么做不到?我怎么样可以做到?我们如果真的要想做到,最开始的一步、最小的一步切实的改变会是什么?

我和很多的同业交流的时候,特别是我们金融的同业,我们养成了一种状态,在《DevOps实践指南》中提到的一个词,叫做习得性无助,见《DevOps实践指南》第xxii页。对于像我一样在金融IT领域工作了十多年的“老油条”,我还听说过一个更贴切的词,叫做老练的无能。这种状态的养成,这一方面是环境造成的,另一方面也是自己造成的。我们要做 DevOps 的时候,首先要意识到这个的问题。

的时候你忙忙叨叨,做的很多工作其实都只是你能做的,然而并不见得是你应该做的。因为,我们常常觉得“应该做的事情”太难了,就主动的、在想法还只是一个想法的的时候就放弃了。

主干开发,想说爱你不容易

  • 足够短的迭代周期(两周,可投产版本)
    
  • 足够短的投产前置周期(三个工作日)

  • 不顾一切保证需求串行

主干开发,就是这样一件绝对应该做,但是,也是绝对艰难的事情,特别是在金融同业里。要做到主干开发,需要足够短的迭代周期,足够短的投产前置周期,就这两点,已经足以让很多金融同业望而却步了,再加上一个保证需求串行。好了,基本上就彻底放弃了。

我想告诉大家的是,这是可以做到的,也应该做到

3.3 持续集成


持续集成是什么?

  • 开发人员每天至少提交一次代码
    
  • 代码提交后立即触发构建和测试
    
  • 构建和测试失败后应尽快处理
    

持续集成不是什么新鲜词汇了,每个人都在说持续集成,这是我定义中的持续集成,这三条,清晰的定义了在做到“持续集成”之后,应该达到的效果。连这几点最起码要求都做不到,我一般不称它为持续集成。我见到的更多的所谓持续集成,其实只能做到第二条,这种的持续集成更应该被称为:自动化构建。

这里我重点说的一点是,“构建和测试失败后应尽快处理”,“尽快处理”是什么意思?在我们的定义里,尽快处理就是:仪表盘变红不下班。我们部门的每一个产品开发团队的附近都放着一块显示屏幕,我们称其为:物理仪表盘。经过几年的努力,我们现在终于可以做到:仪表盘变红不下班。

大家想想这一条规则或者叫做纪律会有什么副作用?

对,为了下班,大家会提前提交代码。你可以下午四点的时候把代码提交了,这个我们是允许的,我们并不介意开发人员下午四点就提交代码。

“尽快处理”虽然听起来是一句模模糊糊的话,但是,我们是有清晰的定义和规则以及纪律来支撑的。

只有你把上面这每一条都做到了,持续集成才变得有意义。

我们会有持续集成的纪律,听起来很简单,但是,真的要让纪律切实的被大家所遵守,成为大家的习惯,真的没有想象的那么简单。它并不是哪个管理者说一说,宣讲一下,拉个宣传横幅,就能够做到,它需要切切实实的采取行动。

怎么做到?我给大家说一下我们的做法,不一定适合大家,但是大家可以听一听。

我们有一个物理仪表盘就像下边这张图,这个物理仪表盘搭建很简单,我相信你们只要有人研究个一天半天就能搞的,这个物理仪表盘就放在开发团队的附近。物理的东西有天然的信息辐射作用,就是你想看、不想看它都在那儿。这是第一步,也是最简单的一步。

第二步是给大家培训,我们先后进行了很多次的培训,告诉大家怎么写单元测试,怎样的单元测试才不会因为数据、环境等其他乌七八糟的问题导致仪表盘变红。

第三步是作为管理者和文化的推动者,要和团队共度第一个艰难的时刻。

给大家讲个小故事,2017年8我们有一个四个Scrum团队大产品在西安做异地封闭开发,七八十人,每周工作六天,每天晚上到10点,我被要求作为内部教练去辅导团队,我去的时候,仪表盘就一直红着,用了将近两周的时间,我们经历了三次培训,经历了修复各种乌七八糟的导致仪表盘变红的问题的阶段。8月24日中午,我至今依然清晰的记得这个日期,一切就绪,我决定启动“仪表盘变红不下班”的工作纪律,就和大家宣告了一下。

其实,我心里还是很虚的,本来就工作到晚上十点,变红了真的修不好,真的让大家通宵啊?如果真的这样的话,我都觉得自己有点不讲道理。墨菲定律啊!大家到了9点半的时候,都开始提交代码,突然仪表盘红了,然后,大家都惊呆了,我也是心里一阵紧张。

我告诉所有人,停止所有的工作,我们还有半个小时下班,尽快修复,修复完了我们就可以下班了。一阵忙碌,各种查找晚上10点20分,仪表盘修好了,大家自发的给自己鼓掌。从此,这个产品团队一直都保持着“仪表盘变红不下班”的工作纪律,已经一年了。

我想告诉大家的是,在推行持续集成的程中,最重要的是持续集成的工作规则和工作纪律的建立,工具和平台是最好搭建的。

而你想要引入一条规则,建立一个纪律的时候,你一定要定义出这件事情到底想怎么做,过程中要给大家培训,给大家和大家一起趟路,怎么样尽快的定位和修复可能的问题,接着做一些事情强化这个行为,你要真的作为参与者参与到这个过程中,陪着大家一起度过第一、第二个艰难时刻,然后,自然而然的,就成就了团队新的习惯和纪律,也就是所谓的建立了新的“文化”。

很多时候,教练或者管理者“没文化”,却天天的喊着要建立文化,转变文化。具体到这件事情上,对教练或者管理者的文化启示就是:教练或者管理者要学会把手弄“脏”,简单来说,就是要和大家一起干!文化是干出来的,不是喊出来的、宣传横幅报贴出来的。

说到这里,你认为那些上面的持续集过程中,我们用到的工具还像之前你认为的那么重要吗?

3.4 自动化部署


自动化部署是大家的老大难:

  • 生产环境权限管理融合难
    
  • 生产环境配置参数收集难

  • 生产环境资源变更联动难

  • 增量、全量的支持统一难

  • 自动组包标准贯彻落实难

饭要一口一口的吃,我们在2016年的时候在部门年度质量目标里面写到一条:所有产品实现自动化组包,严禁手工组包。从一定意义上说,手工组包就是在浪费组织资源,所以我们在内部强烈的推了自动化组包。然后,才有我们的自动化部署。

整个软件中心,现在已经有20多个产品上了自动化部署,我们今年提的目标是100+,不知道能不能达到,但是已经有20多个产品已经实现了自动化部署,有X86等等各种各样的平台都有实现了自动化部署。

相对于手工部署的时间,自动化部署会变得很快,其实,变快只是收益中的一点点,最主要的是自动化部署的时候你在喝咖啡,而且一般不会出错,想想手工部署的情况下,运维的同学在干什么?手指如飞,眉头紧锁。对比一下两种情况,这个幸福感和平稳度决然不同。

自动化部署是我们做DevOps的时候应该努力去做的事情,但是我们在做自动化部署的时候,自动化组包,环境管理、参数管理、权限管理,如果你的数据中心和开发中心还是分开的时候,这些全都是你需要克服的点,而且每一个都不简单。这个太复杂了,我不细说了,我想告诉大家的是自动化部署是克服各种困难都要去做的事情,是应该做的事情。

四. 失败之回顾反思

下面说一点,我们的失败与反思。

自动化功能测试的苦难:

  • 2016年多个产品集中编写了将1000多个面向UI的自动化功能测试案例(Robot Framework),半年后,**全部废弃**,没有再被运行过。
    
  • 某产品编写的大量面向UI的自动化功能测试案例,全部运行一次 一般需要**一到两周**才能完成,有2-3名测试开发人员**专职负责**运行和编写,以及更新这些案例。
    

看到大家会心的笑容,我就知道我们的现状并不特殊,我们和大家一样都经历着同样的苦难,互联网公司给我们做了很好的榜样,但是很不幸的是它救不了我们,我们环境不一样。

通过我的分享就知道,你的排期任务所有的这些流程和互联网公司截然不同,有的互联网公司产品经理弄个PPT,给高层秀一下,拍个板就开干了,该抓人抓人,该要钱要钱,我们金融同业,搞个需求,从评估到立项成功,没有个一年半载是下不来的,能下来的都是快的。

回到自动化测试,上面是我们在自动化测试上的一个“苦难”,苦难之后,我们有反思的。还是那句话:干该干的,别光干那些容易干的。

因为,很多情况下,你觉得该干的并且不容易干不成的那些事,就是系统改进的关键点,否则,为什么你干了那么多能干的事情,系统仍然没有什么改善呢?

该干什么呢?我们发现在已经发布了一个高绩效组织和低绩效组织的对比过渡图里面找到那个点。

我们每10天到100天发布一次,这是我们现在的现状,你会发现,在图中处于这个阶段的组织,开发和测试人员是共同去维护自动化测试案例的,而我们上面提到的自动化功能测试案例,第一个开发是自己写的,第二个是专门的搞自动化测试的测试人员写的,唯一没有一起写,共同维护的。

看到这个点的时候,当时对我的启发很大,我想找到了那件该做的事情,我天天听到有人说要测试迁移、要开发与测试融合,可是,何为融合?如何融合?

用自动化测试这个话题,让开发和测试融合。共同维护自动化测试案例了,开发和测试就融合了。

什么叫共同维护自动化测试案例?“共同维护”到底是什么?

再直观点:开发和测试共享自动化测试的代码,共同修改自动化测试的代码。我们有的时候特别喜欢说一些模糊的、抽象的话,因为,这些话让大家觉得有一种朦胧的安全感。

从开发、测试融合,到共同维护自动化测试案例,到共享自动化测试代码,大家好好的体会一下这之间的区别。找到那个关键点,其实没有那么容易,可是,其实也没有多难。

找到只是第一步,做到,才重要。这又是一个艰难的旅程,有多少开发和测试是一个部门的?有多少测试是具备编码能力的?我相信自己问了这两个问题,很多人就默默的在心里放弃了。

我们的开发和测试分属于两个不同的部门,我们的测试人员基本没有编码能力。可是,我们正在做这件事:通过共享自动化测试代码,开发和测试共同维护自动化接口和功能测试案例,形成开发与测试的融合。因为,这是应该做的事

说到编写自动化测试案例,就有一个增加案例和案例多少的话题。

在这里面,我们正在执行一个纪律,就是:在增加自动化测试的时候,你要保证你的自动化测试案例持续的有效和可用。怎么样叫持续的有效和可用? 就是增加的自动化功能测试案例,必须可以

  • 每天至少运行一次
    
  • 运行预期应该是100%成功的

  • 如果没有成功,一定是由于应用问题,而不是因为环境、数据等非应用问题

我把这称为:有纪律的增加自动化测试案例,

增加的自动化功能(接口也算)测试案例,每天至少跑一次。一天都跑不了一次的自动化测试案例,基本上就是摆设,除了让其管理者每次看案例数的时候感觉爽一下,没有什么实际用处。

每一次的运行都应该预期是100%成功的,如果没有成功,一定要是你的应用出问题了,而不是因为什么数据问题,或者什么环境又不稳定了,其它的系统宕了所以我们有宕了等等。

只有第一个案例满足这个条件了,才允许写第二个,两个案例都满足这个条件了,才允许写第三个。如果第一个案例就满足不了上面的三个条件,就好好的想办法先让你的第一个案例可以满足上面的三个条件。

这叫做有纪律,这叫做克制。我们现在非常谨慎的增加我们的自动化测试案例,而且我们要求我们的测试融进我们的团队里面和我们一起去写自动化的测试案例。

我们的接口测试案例,基本上都是在迭代中,在开发人员的支持下,由测试人员编写的。一开始不会写怎么办?培训啊!学习啊!

说到在这个地方,单元测试有个原则叫做FIRST原则,功能测试的时候有的地方叫AIR原则,我觉的加个A有点多余,我认为自动化的功能测试应该满足SIR原则,什么叫SIR原则?你会发现其实就是没有单元测试的FIRST原则的F和T了。

F是什么?F是Fast,你会发现你的单元测试是会Fast,但是,无论如何你的自动化接口测试、自动化功能测试都很难像单元测试那么快。

T是Timely,就是能够及时的编写,你的单元测试是开发自己写的,甚至有的时候可以用TDD,所有足够的Timly,但是你的功能类的自动化测试、接口类的自动化测试就不一定可以那么Timely的编写了。

所有,我认为自动化的功能测试应该满足SIR原则

这个就是我们经过一系列的失败之后,自己的反思和行动,现在还不能算有什么成绩,过程也很艰难,不过我们会继续做下去。

说到这里,不知道大家对于DevOps中的“器用之道”是否有了不同的看法。模仿敏捷宣言的Over体,最后给大家一个寄语:

工具很重要,什么更重要?

这个问题留给大家去思考和总结。

注:本文仅代表个人观点。

作为中国历史最为悠久的银行之一,中国银行通过 “DevOps 标准—研发运营一体化能力成熟度模型之持续交付能力三级”评估!