This commit is contained in:
louzefeng
2024-07-11 05:50:32 +00:00
parent bf99793fd0
commit d3828a7aee
6071 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,99 @@
<audio id="audio" title="01 | DevOps的“定义”DevOps究竟要解决什么问题" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/1b/60/1ba0a9963fd7b9396f09df3a8f6d9360.mp3"></audio>
你好我是石雪峰。今天我们来聊一聊DevOps的“定义”。
近些年来DevOps在我们身边出现的频率越来越高了。各种大会上经常出现DevOps专场行业内的公司纷纷在都招聘DevOps工程师企业的DevOps转型看起来迫在眉睫公司内部也要设计和开发DevOps平台……这么看来DevOps似乎无处不在。
可回过头来想想关于DevOps很多问题我们真的想清楚了吗所谓的DevOps平台是否等同于自动化运维平台或持续交付平台呢DevOps工程师的岗位描述中又需要写哪些技能要求呢另外该如何证明企业已经实现了DevOps转型呢这些问题真是难倒了一众英雄好汉。说到底听了这么久的DevOps它的“定义”到底是什么好像从来没有人能说清楚。
现在我们先来看看维基百科对DevOps的定义。不过估计也没谁能看懂这到底是在说什么。
>
DevOps开发Development与运维Operations的组合词是一种文化、一场运动或实践强调在自动化软件交付流程及基础设施变更过程中软件开发人员与其他信息技术IT专业人员彼此之间的协作与沟通。它旨在建立一种文化与环境使构建、测试、软件发布得以快速、频繁以及更加稳定地进行。
于是乎每当提及DevOps是什么的时候最常出现的比喻就是“盲人摸象”。有意思的是DevOps之父Patrick第一次参加DevOpsDays中国站活动的时候也使用了这个比喻看来在这一点上中西方文化是共通的。毕竟每个人的视角都不相同看到的DevOps自然也是千差万别。
DevOps大潮汹涌而来很多人都被裹挟着去探索和实践DevOps甚至有一种极端的看法认为一切好的实践都属于DevOps而一切不好的实践都是DevOps的反模式。
当年敏捷开始流行的时候似乎也是相同的论调但这种笼统的定义并不能帮助我们理清思路甚至会带来很多负面的声音比如DevOps就是开发干掉运维又或者DevOps就是要让运维抛弃老本行开始全面转型做开发。这让很多IT从业人员一度很焦虑。
客观来说从DevOps运动诞生开始那些先行者们就从来没有试图给DevOps下一个官方的定义。当然这样做的好处很明显由于不限定人群和范围每个人都能从自己的立场来为DevOps做贡献从而使DevOps所涵盖的范围越发宽广。
但是坏处也是显而易见的。随着DevOps的不断发展刚开始接触DevOps的人往往不得要领只见树木不见森林认知的偏差使得DevOps越发地神秘起来。
与其纠结于DevOps的定义不如让我们一起回归原始来看看DevOps究竟要解决的是什么问题。
其实DevOps的秘密就来源于它的名字所代表的两种角色——**开发和运维**。那么这两种角色之间究竟有什么问题呢?我们从软件工程诞生以来所历经的三个重要发展阶段说起。
## 瀑布式开发模式
<img src="https://static001.geekbang.org/resource/image/85/af/859c32bccda5b8e9aee5b7001fca42af.png" alt="">
瀑布式开发模式将软件交付过程划分成几个阶段,从需求到开发、测试和运维,它的理念是软件开发的规模越来越大,必须以一种工程管理的方式来定义每个阶段,以及相应的交付产物和交付标准,以期通过一种重流程,重管控,按照计划一步步推进整个项目的交付过程。
可是,随着市场环境和用户需求变化的不断加速,这种按部就班的方式有一个严重的潜在问题。
软件开发活动需要在项目一开始就确定项目目标、范围以及实现方式,而这个时间点往往是我们对用户和市场环境信息了解最少的时候,这样做出来的决策往往带有很大的不确定性,很容易导致项目范围不断变更,计划不断延期,交付上线时间不断推后,最后的结果是,即便我们投入了大量资源,却难以达到预期的效果。
从业界巨头IBM的统计数字来看有34%的新IT项目延期交付将近一半的应用系统因为缺陷导致线上回滚这是一件多么令人沮丧的事情。
## 敏捷式开发模式
<img src="https://static001.geekbang.org/resource/image/0f/41/0f337a6b79641b1fb92bc5cf428f0b41.png" alt="">
基于这种问题,敏捷的思潮开始盛行。它的核心理念是,既然我们无法充分了解用户的真实需求是怎样的,那么不如将一个大的目标不断拆解,把它变成一个个可交付的小目标,然后通过不断迭代,以小步快跑的方式持续开发。
与此同时,将测试工作从研发末端的一个独立环节注入整个开发活动中,对开发交付的内容进行持续验证,保证每次可交付的都是一个可用的功能集合,并且由于质量内建在研发环节中,交付功能的质量也是有保障的。
很显然敏捷是一种更加灵活的研发模式。经常有人会问敏捷会直接提升团队的开发速度吗答案是否定的。试想一下难道说采用了敏捷方法研发编码的速度就会提高两倍甚至三倍吗回想一下很多年前在IT行业广为流传的“人月神话”我们就能发现正确的认知有多么重要。
**敏捷之所以更快,根本原因在于持续迭代和验证节省了大量不必要的浪费和返工**。关于这一点,我会在敏捷和精益的相关内容中做更加详细的介绍。
说到底,敏捷源于开发实践,敏捷的应用使得开发和测试团队抱团取暖。可是问题又来了,开发和测试团队发现,不管研发的速度变得多快,在软件交付的另一端,始终有一群人在冷冰冰地看着他们,一句“现在没到发布窗口”让多少新开发的功能倒在了上线的门槛上。
毕竟,无论开发了多少“天才”的功能,如果没有经过运维环节的部署上线,并最终发布给真实用户,那么这些功能其实并没有什么用。
## DevOps模式
<img src="https://static001.geekbang.org/resource/image/af/5f/af17eb95cc11a99bec07ca265a9f6a5f.png" alt="">
于是活在墙的另一端的运维团队成了被拉拢的对象。这些在软件交付最末端的团队始终处于一种“背锅”的状态他们也有改变的意愿所以DevOps应运而生也就是说DevOps最开始想要打破的就是开发和运维之间的对立和隔阂。
在传统模式下,度量开发团队效率的途径就是看开发完成了多少需求。于是,开发为了达成绩效目标,当然也是为了满足业务需求,不断地堆砌新功能,却很少有时间认真思考这些功能的可运维性和可测试性,只要需求状态流转到开发完成就万事大吉了。
而对于运维团队而言,他们的考核指标却是**系统的稳定性、可用性和安全性**。但现代IT系统是如此复杂以至于每一次的上线发布都是一场战役整个团队如临大敌上线失败的焦虑始终如影随形。
很多时候,我们并不知道上线之后会发生什么,只能按照部署手册一步步操作,完成之后就听天由命。所以,每逢大促活动,就会有各种“拜服务器教”的照片广为流传。
另一方面,在无数次被开发不靠谱的功能缺陷蹂躏得体无完肤之后,运维团队意识到,变更才是影响他们绩效目标的最大敌人。于是,预先设立的上线窗口就成了运维团队的自留地,不断抬高的上线门槛也使得开发团队的交付变成了不可能完成的任务,最后,“互相伤害”就成了这个故事注定的结局。
即便到了今天,部署上线在大多数公司依然是一件很神圣的事。我给你讲一件有趣的事情。
去年我在欧洲拜访DevOps之父Patrick的时候曾经去过他的公司。那天风雪交加比利时根特显得非常冷清。我们停好车后刚要推门进入他们公司恰好碰到Patrick和他的一个同事下楼抽烟。
简单寒暄之后我们才知道原来Patrick公司负责的一个系统要在15分钟后上线他们趁这个间歇出来换换脑子然后再回去大干一场。所以你看连DevOps之父在面临上线的时候都如此正式可见DevOps的发展之路依然任重而道远啊。
从一开始想要促进开发和运维的协作,团队慢慢发现,**其实在整个软件交付过程中,不仅只有开发和运维,业务也是重要的一环**。
比方说如果业务制定了一个不靠谱的需求那么无论开发和运维怎样协作得到的终究是一个不靠谱的结果以及对人力的浪费。可是业务并不清楚用户的真实情况于是运维团队慢慢转向运营团队他们需要持续不断地把线上的真实数据和用户行为及时地反馈给需求团队来帮助需求团队客观评估需求的价值并及时作出有利于产品发展的调整这样一来业务也被引入到了DevOps之中甚至诞生了BizDevOps这样一个专门的词汇。
那么,既然沟通协作放之四海皆准,安全也开始积极地参与进来。安全不再是系统上线发布之后的“定时炸弹”,而是介入到整个软件开发过程中,在每个过程中注入安全反馈机制,来帮助团队在第一时间应对安全风险,那么,对于安全团队来说,**DevSecOps**就成了他们眼中的DevOps。
这样的例子比比皆是包括职能部门、战略部门等都纷纷加入其中使得DevOps由最开始的点扩展为线再到面不断发展壮大。每个人都参与其中这使得DevOps成了每一个IT从业人员都需要学习和了解的知识和技能体系。
说到最后我还是希望基于我对DevOps的理解给出一个我自己的“定义”
**DevOps是通过平台Platform、流程Process和人People的有机整合以C协作A自动化L精益M度量S共享文化为指引旨在建立一种可以快速交付价值并且具有持续改进能力的现代化IT组织。**
## 总结
今天我带你一起梳理了DevOps的发展历程以及软件开发模式的变迁。有人说DevOps是软件工程发展至今的第三次革命可见它带给整个行业的影响是很深远的。人云亦云并不能帮助我们更好地理解DevOps建立正确的认知才是体系化学习的第一步希望你能通过今天的课程建立起你自己对于DevOps的独特认知。
## 思考题
最后给你提一个问题我给出的定义符合你心目中对DevOps的预期吗DevOps具有与生俱来的开放性你能谈一谈你对DevOps的理解和定义吗
欢迎在留言区写下你的思考和答案,我们一起讨论,共同学习进步。如果你觉得这篇文章对你有所帮助,欢迎你把文章分享给你的朋友。

View File

@@ -0,0 +1,94 @@
<audio id="audio" title="02 | DevOps的价值数字化转型时代DevOps是必选项" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/c5/4f/c5729ce41c56fa8f5cc7f197f1e3c74f.mp3"></audio>
你好我是石雪峰。今天我们来聊聊DevOps的价值。
前段时间,因为工作的缘故,我参访了一家在国内数一数二的金融企业。在跟他们科技处的同事交流的过程中,有一件事情让我非常吃惊,想跟大家分享一下。
虽然在一般人眼中,这家企业是典型的传统企业,但他们的绩效目标采用的却是**OKR模式**。
我简单介绍一下OKR。OKR也就是目标与关键成果法是在硅谷互联网公司很流行的绩效制定方法。简单来说O代表目标也就是我们要做什么KR代表关键结果用于验证我们是否已经达到了目标。
这家金融企业的大老板也就是科技处的老大给全体员工制定的众多OKR中有且只有一条属于愿景指标。说出来你可能不相信这个愿景指标就是到今年年底让DevOps在全行的三个试点项目中成功落地。
而且这并不是简单的说说而已如果最终达成了这个愿景指标所有员工的年终奖将在原有的基础上上浮10%20%。由此可见关于实施DevOps他们是在玩真的了。
全行的核心系统改造都没能成为愿景指标那为啥DevOps会有如此大的魔力让大老板都为之着迷并且成为愿望清单列表中的第一名呢这就是我今天要跟大家讨论的话题DevOps的价值以及它对现代企业的意义。
如果要选一个近年来在各大企业战略中曝光率最高的关键词,**数字化转型**绝对是排名最高的,没有之一。
比如传统汽车巨头大众公司今年宣布启动全面数字化转型计划到2023年年底投资约40亿美元实现管理和生产的数字化。而且预计到2025年大众集团的软件研发的比例将从目前的不到10%增长到60%。
## 为什么软件如此重要?
对于软件从业人员来说,这绝对是令人欢欣鼓舞的事情。同时,这也再一次印证了那句流传已久的名言,**每一家公司都将成为软件公司**。那么问题来了,在数字化转型时代,为什么软件会如此重要呢?
互联网的普及和移动通讯技术的发展所带来的移动互动网的兴起,深刻地影响了我们每个人的生活方式。
举个最简单的例子,几年前如果我们要办理银行业务,我们首先要找到附近的营业厅,抽空跑过去排号,经过很长时间的等待,才能坐到柜台前,同银行的柜员面对面地完成业务办理。当然这还是在顺利的情况下,如果忘记带证件或者排队人太多,可能还要再跑一次,办事成本相当高。
现在呢大多数情况下我们只要掏出手机打开银行的APP点击几下屏幕业务就办好了完全不用受时间和空间的限制。用户对银行服务的体验直接来源于手机应用本身。如果哪家银行的应用界面很丑操作还总是出现各种问题就会直接影响用户对这家银行的印象甚至会在潜意识里觉得这家银行不靠谱。显然没有任何一家银行愿意给人留下这样的印象。
所以,**软件慢慢从企业内部的支撑系统和成本中心,变成了企业服务的直接载体和利润中心**。企业通过软件降低运营成本,提升服务水平,而用户在获得便利的同时,也加强了同企业之间的联系。
这本是一件双赢的事情,可问题是,我们所身处的是一个**VUCA**的时代VUCA是指易变性Volatility、不确定性Uncertainty、复杂性Complexity和模糊性Ambiguity它代表了这个时代的典型特征。比如共享单车这个行业从冉冉兴起炙手可热到逐渐归于平静前后不过短短几年的时间。
企业能快速满足用户的需求在行业大势之下灵活转身在跨界打击越发普遍的情况下脱颖而出已经不仅仅是good to have的能力而是must have的能力。
可以说,**软件交付的效率和质量成了当今企业的核心价值和核心竞争力**所以任何一家企业无论是行业巨头还是初创公司无论是互联网行业还是传统行业无论是领先者还是颠覆者都有强烈的意愿去改善自身的软件交付能力而这恰恰和DevOps的理念和诞生背景不谋而合。这么看来DevOps能够成为企业愿望清单中的第一名也就不足为奇了吧。
可是,即便软件如此重要,却依然有很多公司在用一种手工作坊的方式开发软件,引用国家智库的某位领导的话来说,“**工业革命消灭了绝大多数的手工业群体,却催生了程序员这个现存最大的手工业群体**”。这句话看似危言耸听,但这种开发软件的方式的确存在,其中伴随着大量的效率浪费。企业内部的软件开发交付效率已经成了一座值得探索挖掘的金矿,效率经济可能成为新的业绩增长点。
## DevOps的价值
那么实施DevOps带给企业的价值究竟是什么呢要回答这个问题我们就不得不提到DevOps业内非常著名的现状调查报告了。
### 高效的软件交付方式
从2014年至今这个报告每年都会发布一份由业内大咖和行业领袖基于科学的分析方法通过大量的数据分析得出可以说是业内最具权威性的报告其中的很多数据和理念都被广为传播。我发现在这洋洋洒洒大几十页的报告中被引用频率或者说出镜率最高的就是DevOps的4个结果指标。
1. **部署频率**:指应用和服务向生产环境部署代码的频率。
1. **变更前置时间**:指代码从提交到成功运行在生产环境的时长。
1. **服务恢复时间**:指线上应用和服务出现故障到恢复运行的时长。
1. **变更失败率**:指应用和服务在生产环境部署失败或者部署后导致服务降级的比例。
每年这个报告都会基于这4个核心指标统计行业内高效能团队和低效能团队之间的差距。从去年的数据来看与低效能团队相比高效能团队的部署频率高了46倍变更前置时间快了2500多倍服务恢复时间也快了2600多倍失败率低了7倍。
我们先不管这份数据是怎么计算出来的,当你第一次看到这个数据的时候,它带给你的冲击是不是很强大呢?用具体的数字形式来呈现企业之间效率的差距,是很有震撼力的。
而世界上最令人“绝望”的事情就是那些比你优秀的人实际上比你还要更加努力。当你仔细查看这份报告的时候你会发现那些常年被人提及的明星公司很多都在践行DevOps甚至很多来源于这些公司的实践案例都成为了DevOps行业的经典案例。
另一方面DevOps状态报告中提到的四项结果指标分别代表了软件交付的两个最重要的方面也就是**交付效率**和**交付质量**。而且,从数据结果中,我们还能得到一个惊人的发现,那就是**高效能的组织不仅做到了高效率,还实现了高质量**,由此可见,鱼与熊掌可以兼得。
可是这就颠覆了很多人心目中的“慢工出细活”的传统软件开发理念。因为按照传统软件开发的V模式来说软件开发完成后需要经过单元测试、集成测试、系统测试和验收测试等层层关卡以此来保证软件的质量符合预期。但是对于现代软件开发而言如此重的流程和管控显然有点跟不上时代的节奏。
我们在不断提高软件交付效率时,往往是以牺牲质量为代价的,结果做得越多,错得越多,从而陷入进退两难的境地。
DevOps却反其道而行之它试图通过体系化的研发实践导入、软件架构的整体革新、组织管理理念的不断升级和企业文化的影响塑造来帮助企业改善整个软件交付过程在实现高吞吐量的同时保证服务的总体稳定性从而真正实现又快又好的软件交付目标。
### 激发团队的创造力
我们刚刚谈到的这些内容当然是DevOps带给企业的重要价值但并非全部。在专栏中我不仅希望能跟你分享知识还希望能跟你分享一些不同的观点我们一起思考和讨论获取灵感和新知。
之前我在跟Jenkins创始人KK聊天的时候他提出过这样一个问题熟悉云计算的同学可能或多或少地了解过容器编排领域的事实标准Kubernetes以及它背后的CNCF基金会那么企业为什么热衷于加入这样的基金会呢即使要付出一笔不菲的费用也在所不惜企业这么做的收益究竟是什么
不可否认CNCF是一个非常成功的运营案例成为会员还能享受白纸黑字上的福利但是对于很多中小企业而言他们的诉求可能不止如此。
很多时候,企业加入这样的组织,也是为了向内部员工表态,我们正和世界上最著名的公司站在同一条起跑线上,关注着同样的问题。这对他们的员工来说,既能起到激励作用,也能增强对企业自身的信心。
对于DevOps而言道理也是同样的因为说到底企业的问题都是人的问题最核心的价值最终都会归结到人身上所以单纯关注软件交付的能力而忽视人的感受结果往往都是片面的。
在企业内部建设DevOps工具平台的时候我也经常在思考这个问题我们费尽心思通过平台能力建设提升了5%的交付效率,即便节省下来的时间只是让员工多休息了一会儿,也是非常有意义的事情。因为**DevOps本身也包含了改善软件从业人员的生存状态提升他们的幸福水平的理念**。
这么看来实施DevOps一方面可以通过种种流程优化和自动化能力改善软件开发团队的工作节奏另一方面也可以让大家关注同一个目标彼此信任高效协作调动员工的积极性和创新能力从而让整个团队进入一种积极创造价值的状态而这所带来的影响远非建设一两个工具平台可比拟的。
## 总结
DevOps作为软件工程的第三次革命在数字化转型的大潮之下几乎成了所有通过交付软件来提供服务的企业的必选项。因为DevOps不仅可以改善企业的软件交付过程实现高质量和高效率兼得同时也可以持续改善企业内部的工程师文化提升员工信心激发员工的活力和价值创造从而帮助企业在VUCA时代占得先机获得更大的成功。如果一家企业真的可以通过DevOps落地达到以上目标而只需要多付出10%20%的年终奖,岂不是大大赚到了吗?
## 思考题
最后给你留一个思考题如果你觉得DevOps可以解决公司现有的问题想要跟领导申请立项的话你会如何说明DevOps的价值呢
欢迎在留言区写下你的思考和答案,我们一起讨论,共同进步。如果你觉得这篇文章对你有所帮助,欢迎你把文章分享给你的朋友。

View File

@@ -0,0 +1,121 @@
<audio id="audio" title="03 | DevOps的实施到底是工具先行还是文化先行" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/d7/33/d7c4bfed08f7de2e2de88d268c3e8333.mp3"></audio>
你好,我是石雪峰。
当一家企业好不容易接纳了DevOps的思想并下定决心开始实施的时候总会面临这样一个两难的选择**工具和文化,到底应该哪个先行?**
的确在DevOps的理论体系之中工具和文化分别占据了半壁江山。在跟别人讨论这个话题的时候我们往往会划分为两个不同的“阵营”争论不休每一方都有自己的道理难以说服彼此。在DevOps的世界中工具和文化哪个先行的问题就好比豆浆应该是甜的还是咸的一样一直没有一个定论。
可是对于很多刚刚接触DevOps的人来说如果不把这个问题弄清楚后续的DevOps实践之路难免会跑偏。所以无论如何这碗豆浆我先干为敬今天我们就先来聊聊这个话题。
## DevOps工具
随着DevOps理念的深入人心各种以DevOps命名的工具如雨后春笋般出现在我们身边甚至有很多老牌工具为了顺应DevOps时代的发展主动将产品名称改为DevOps。最具代表性的就是去年9月份微软研发协作平台VSTSVisual Studio Team Services正式更名为Azure DevOps这也进一步地印证DevOps已经成为了各类工具平台建设的核心理念。
在上一讲中我提到高效率和高质量是DevOps的核心价值而工具和自动化就是提升效率最直接的手段让一切都自动化可以说是DevOps的行为准则。
**一切软件交付过程中的手动环节,都是未来可以尝试进行优化的方向**。即便在运维圈里面ITILIT基础架构库)一直是运维赖以生存的基石也并不妨碍自动化的理念逐步深入到ITIL流程之中从而在受控的基础上不断优化流程流转效率。
另外正因为所有人都认可自动化的价值工具平台的引入和建设就成为了DevOps打动人的关键因素之一。
同时现在业界的很多开源工具已经相当成熟以Netflix、Amazon、Etsy等为代表的优秀公司也在不断将内部的工具平台进行对外开放各方面的参考资料和使用案例比比皆是。
无论是单纯使用还是基于这些工具进行二次开发成本都已经没那么高了一个稍微成熟点的小团队可以在很短的时间内完成一款工具的开发。以我之前所在的团队为例从0开始组建到第一款产品落地推广前后不过两个多月的时间而且与业内的同类产品相比较毫不逊色。
不过这也带来一个副作用那就是企业内部的工具平台泛滥很多同质化的工具在完成从0到1的过程后就停滞不前陷入重复的怪圈显然也是一种资源浪费。
当然对于工具决定论的支持者来说这并不是什么大问题因为引入工具就是DevOps的最佳实施路径。
有时候当你问别人“你们公司的DevOps做得怎么样啦”你可能会得到这样的回答“我们的所有团队都已经开始使用Jenkins了。”听起来感觉怪怪的。如果只是使用了最新最强大的DevOps工具就能实现软件交付效率的腾飞那么世界500强的公司早就实现DevOps了。
很多公司引入了完整的敏捷项目管理工具,但是却以传统项目管理的方式来使用这套工具,效率跟以前相比并没有明显的提升。对于自研平台来说,也是同样的道理。如果仅仅是把线下的审批流程搬到线上执行,固然能提升一部分执行效率,但是对于企业期望的质变来说,却是相距甚远。
说到底,工具没法解决人的问题,这样一条看似取巧的路径,却没法解决企业的根本问题。这时候,就需要文化闪亮登场了。
## DevOps文化
在谈论DevOps文化之前我先跟你分享一个故事。
上世纪80年代美国加州有一家汽车制造公司叫作NUMMI。当时这家公司隶属于通用公司但是由于劳资关系紧张这家公司一直以来都是通用旗下效益最差的公司。员工整天上班喝酒赌博整个工厂乌烟瘴气旷工率甚至一度达到了20%。通用公司忍无可忍,最后关闭了这家公司。
后来日本丰田公司想在美国联合建厂于是跟通用达成了合资协议。美国联合汽车工会UAW希望新公司可以重新雇佣之前遭到解雇的员工通用公司本来不想接受但是令人惊讶的是丰田公司却同意了。因为他们认为NUMMI工厂之前的情况更多是系统的原因而不是人的原因。
接下来,丰田公司将新招募的员工送到日本进行培训。短短三个月后,整个公司的面貌焕然一新,半年后,一跃成为整个通用集团效益最好的公司。
**由此可见,在不同的文化制度下,相同的人发挥出来的生产力也会有天壤之别。**
类似的故事并非个例,曾经有一群美国专家到日本参观和学习生产流水线,他们发现了一件有趣的事情。
在美国公司的生产线里面,总有一个人拿着橡胶的锤子在敲打车门,目的是检查车门是否安装完好。但即便如此,车门的质量依然很差。可是,在日本公司的工厂里面,却没有这样的角色。
他们就好奇地问道:“你们如何保障车门没有问题呢?”日方的专家回复说:“我们在设计车门的时候,就已经保证它不会出问题了。”你看,同样是采用流水线技术的两家公司,结果却大不相同。
类比DevOps如果在我们的软件交付过程中始终依靠这个拿锤子的人来保障产品的质量出了问题总是抱怨没有会使用锤子的优秀人才或许这个流程本身就出了问题。
回到文化本身,良好的文化不仅可以让流程和工具发挥更大的作用,更重要的是,它能够诱发人们思考当前的流程和工具哪里是有问题的,从而引出更多有关流程和工具的优化需求,促使流程和工具向更加有力的支持业务发展的方向持续改进。
可是企业内部的DevOps文化本身就是虚无缥缈的事情你很难去量化团队的文化水平进而改变企业的文化。盲目地空谈文化对组织也是一种伤害。因为脱离实践文化就会变成无根之水。当组织迟迟无法看到DevOps带来的实际收益时就会丧失转型的热情和信心。
所以,我们需要先改变行为,再通过行为来改变文化。而改变行为最关键的,就是要建立一种有效的机制。就像我一直强调的那样,机制就是人们愿意做,而且做了有好处的事情。
回想之前提到的某金融公司的案例如果他们的老板只是喊了句口号“我们要在年底完成DevOps试点落地”那么年底即便项目成功本质上也不会有什么改变。相反他们在内部建立了一种机制包括OKR指标的设定、关键指标达成后的激励、成立专项的工作小组、引入外部的咨询顾问以及一套客观的评判标准这一切都保证了团队走在正确的道路上。而承载这套客观标准的就是一套通用的度量平台说到底还是**需要将规则内建于工具之中,并通过工具来指导实践**。
这样一来当团队通过DevOps获得了实实在在的改变那么DevOps所倡导的**职责共担**、**持续改进**的文化自然也会生根发芽。
所以你看DevOps中的文化和工具本身就是一体两面我们既不能盲目地奉行工具决定论上来就大干快干地采购和建设工具也不能盲目地空谈文化在内部形成一种脱离实际的风气。
## DevOps的3个支柱
对工具和文化的体系化认知可以归纳到DevOps的3个支柱之中即人People、流程Process和平台Platform。3个支柱之间两两组合构成了我们实施DevOps的“正确姿势”只强调其中一个维度的重要性明显是很片面的。
<img src="https://static001.geekbang.org/resource/image/14/42/1444f92a5a0a5e8fb131c7373415a742.png" alt="">
### 人 + 流程 = 文化
在具体的流程之下,人会形成一套行为准则,而这套行为准则会潜移默化地影响软件交付效率和质量的方方面面。这些行为准则组合到一起,就构成了企业内部的文化。
一种正向的文化可以弥合流程和平台方面的缺失,推动二者的持续改进,同时可以让相同的流程和平台在不同的人手中产生迥异的效果。就好像《一代宗师》里面的那句经典台词:“真正的高手,比拼的不是武功,而是思想。”而**指导DevOps落地发展的思想就是DevOps的文化了**。
举个例子在谷歌SRE的实践中研发交付的应用需要自运维一段时间并且要在达到一定的质量指标之后才会交接给SRE进行运维。但是为了避免出现“研发一走运维背锅”的情况他们还建立了“打回”的流程也就是当SRE运维一段时间后如果发现应用稳定性不达标就会重新交还给开发自己负责维护这样一来研发就会主动地保障线上应用的质量。而且在这个过程SRE也会给予技术和平台方面的支持从而形成了**责任共担**和**质量导向**的文化。
类似的,有些公司设有**线上安全点数**的机制,在一定的额度范围内,允许团队出现问题,并且不追究责任。这就可以激励团队更加主动地完成交付活动,不必每一次都战战兢兢,生怕出错。通过流程和行为的改变,团队的文化也在慢慢地改进。
由此看来,虽然我们很难直接改变文化,但是却可以定义期望文化下的行为表现,并通过流程的改进来改变大家的行为,从而让文化得以生根发芽,茁壮成长。
### 流程 + 平台 = 工具
企业内部流程的标准化,是构成自动化的前提。试想一下,如果没有一套标准的规则,每一项工作都需要人介入进行判断和分析,那么结果势必会受到人的因素的影响,这样的话,又如何做到自动化呢?
**而平台的最大意义,就是承载企业内部的标准化流程**。当这些标准化流程被固化在平台之中时,所有人都能够按照一套规则沟通,沟通效率显然会大幅提升。
**平台上固化的每一种流程,其实都是可以用来解决实际问题的工具**。很多人分不清工具和平台的关系,好像只要引入或者开发了一个工具,都可以称之为平台,也正因为这样,企业内部的平台比比皆是。
实际上平台除了有用户量、认可度、老板加持等因素之外还会有3个显著特征。
1. **吸附效应**:平台会不断地吸收中小型的工具,逐渐成为一个能力集合体。
1. **规模效应**:平台的成本不会随着使用方的扩展而线性增加,能够实现规模化。
1. **积木效应**:平台具备基础通用共享能力,能够快速搭建新的业务实现。
简单来说,平台就是搭台子,工具来唱戏。平台提供场所,进行宣传,吸引用户,同时还能提供演出的道具,以及数据方面的分析。观众的喜好各不相同,但是平台将各种戏汇集在一起,就能满足大多数人的需求。如果平台把唱戏的事情做了,难以聚焦“台子”的质量,就离倒闭不远了。同样,如果唱戏的整天琢磨着建平台,那么戏本身的品质就难以不断精进。所以是做平台,还是做工具,无关好坏,只关乎选择。
### 平台 + 人 = 培训赋能
平台是标准化流程的载体,一方面可以规范和约束员工的行为,另一方面,通过平台赋能,所有人都能以相同的操作,获得相同的结果。这样一来,跨领域之间的交接和专家就被平台所取代,当一件事情不再依赖于个人的时候,等待的浪费就会大大降低,平台就成了组织内部的能力集合体。
但与此同时,当我们定义了期望达到的目标,并提供了平台工具,那么对人的培训就变得至关重要,因为只有这样,才能让工具平台发挥最大的效用。更加重要的是,通过最终的用户使用验证,可以发现大量的可改进空间,进一步推动平台能力的提升,从而带动组织整体的飞轮效应,加速组织的进化。
所以你看文化、工具和培训作为DevOps建设的3个重心折射出来的是对组织流程、平台和人的关注三位一体缺一不可。
最后跟你分享一个关于美国第一资本的例子。他们最初在实施DevOps时采用的是外包方式修改一个很小的问题都需要走复杂的变更流程需要几天的时间。后来他们决定采用“**开源为先**”的策略,并且严格审查原本的商业采购流程。除此之外,他们还基于开源工具搭建自己的平台,并在公司内部进行跨领域角色的交叉培养,交付效率大幅提升,实现了从每天迭代一次到每天多次的线上部署。
## 总结
讲到这里我们今天的专栏内容就到尾声了。在这一讲中我跟你讨论了DevOps中的工具和文化的实际价值以及潜在的问题和挑战最终推导出DevOps的3个支柱也就是人、流程和平台这3个支柱缺一不可。只有通过人、流程和平台的有机结合在文化、工具和人员培训赋能领域共同推进才能实现DevOps的真正落地实施。
## 思考题
最后给你留一个思考题你们公司的哪些文化是非常吸引你的这些文化对于DevOps的实施又有哪些帮助呢
欢迎在留言区写下你的思考和答案,我们一起讨论,共同学习进步。如果你觉得这篇文章对你有所帮助,欢迎你把文章分享给你的朋友。

View File

@@ -0,0 +1,119 @@
<audio id="audio" title="04 | DevOps的衡量你是否找到了DevOps的实施路线图" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/2a/8b/2a09ac576b94f720de5e9f9f1eb6768b.mp3"></audio>
你好我是石雪峰。今天我们来聊聊DevOps的实施路线图。
商业领域有一本特别经典的书,叫作《跨越鸿沟》,这本书中提出了一个“**技术采纳生命周期定律**”,对高科技行业来说,它的地位堪比摩尔定律。
<img src="https://static001.geekbang.org/resource/image/e3/f5/e352ad88f8ab68c78192ba8c0c4e24f5.png" alt="">
简单来说这个定律描述了一项新技术从诞生到普及要经历的5个阶段这5个阶段分别对应一类特殊人群即创新者、早期使用者、早期大众、晚期大众和落后者。这个定律表明技术的发展不是线性的需要经历一段蛰伏期才能最终跨越鸿沟为大众所接受成为业界主流。
当然DevOps这项所谓的新技术在企业内部的落地也注定不是一帆风顺的。那么在这种情况下你是否找到了DevOps的实施路线图呢
从2017年第一届DevOpsDays大会中国站举办以来DevOps正式在国内驶入了发展的快车道。从一门鲜为人知的新技术思想到现在在各个行业的蓬勃发展各种思想和实践的激烈碰撞DevOps的理念和价值可谓是深入人心。
这样看来DevOps已经成功地跨越了技术发展的鸿沟从早期使用者阶段进入了早期大众的阶段而这也意味着越来越多的公司开始尝试DevOps。
在2017年底Forrester的一组[调查数据](https://go.forrester.com/blogs/2018-the-year-of-enterprise-devops/)显示将近50%的受访公司表示已经引入并正在实施DevOps30%的公司表示有意向和计划来开启这项工作而对DevOps完全不感兴趣的仅占1%。可以说2018年就是企业落地DevOps的元年。
但是就像你要去往一个未知的目的地时需要导航帮你规划路径、实时定位并在出现意外情况时及时提示你是否要重新规划路径一样企业在实施DevOps的过程中其实也面临着相似的问题。企业自身难以清晰定位DevOps的现状客观评估DevOps相关的能力水平识别当前所面临的最大瓶颈以及实施DevOps的阶段性成果预期……
回顾整个IT行业的发展历程**新思想和新技术的发展,总是同标准化的模型和框架相伴相生的**。
我认为,**任何技术的成熟,都是以模型和框架的稳定为标志的**。因为当技术跨越初期的鸿沟,面对的是广大受众,如果没有一套模型和框架来帮助大众快速跟上节奏,找准方向,是很难大规模推广并健康发展的。
比如软件开发领域的CMMI模型软件能力成熟度模型、运维行业的ITIL模型等在各自的领域都久负盛名甚至一度被各个领域的从业者奉为圭臬和行为准则成为衡量能力高低的标尺。
我曾经在国内某大型通讯设备公司参与过CMMI评级项目。当时就算业务压力再大只要是关于通过评级的事情所有部门都会高优先级支持。由此可见整个公司都非常重视这个认证评级项目。
那么问题来了在DevOps这项新思想和新技术不断走向成熟的过程中是否也有类似的模型和框架能够指导企业内部的DevOps转型落地工作呢
答案是有的而且有很多。只要你去谷歌上搜一下DevOps框架、模型等关键词就能看到非常多的结果。尤其是国外的一些知名公司比如Atlassian、CloudBees、CA等基本上都有一套自己的模型和框架来帮助企业识别当前的DevOps能力水平并加以改进。
我之前参与过工信部旗下的中国信息通讯研究院牵头制定的一套DevOps能力成熟度模型。这套模型覆盖了软件交付的方方面面包括**敏捷开发管理**、**持续交付**和**技术运营**三大部分,同时,也有与应用架构设计、安全和组织结构对应的内容。
不仅如此对于开发DevOps工具的企业来说系统和工具模型更加偏向于平台能力稍加整理就可以作为平台需求输入到开发团队中。目前已经有不少公司在参考这套模型进行DevOps实践。下图展示了这个模型的整体框架如果你正在企业内部推进DevOps落地的话可以参考一下。
<img src="https://static001.geekbang.org/resource/image/57/47/572cf00d2db3666801a3b51ccf951847.png" alt="">
## 步骤与原则
业界有这么多模型和框架,是不是随便找一个,直接照着做就行了呢?当然不是。
毕竟,每家企业所处的行业现状、竞争压力、市场竞争态势都不尽相同,组织架构、战略目标、研发能力、资源投入等方面也千差万别,很难有一条标准的路径,让大家齐步走。比如,同样是金融企业,让万人规模的大银行和百人规模的城商行同台竞技,本身就有点强人所难。
所以,在实际参考模型和框架的时候,我认为应该尽量遵循以下步骤和原则:
1.**识别差距**
从“道法术器”的角度来说DevOps的成熟度模型和框架处于“法”这个层面也就是一整套实施DevOps的方法论相当于是一幅战略地图最重要的就是对DevOps实施所涉及到的领域和能力图谱建立全面的认知。
通过和模型、框架进行对标,可以快速识别出企业当前存在的短板和差距,并建立企业当前的能力状态基线,用于对比改进后所取得的效果。
2.**锚定目标**
数字化转型的核心在于**优化软件交付效率**。通过对标模型框架,企业需要明确什么是影响软件交付效率进一步提升的最大瓶颈,当前存在的最大痛点是什么,哪些能力的改善有助于企业达成预定的目标……同时,要根据企业的现状,甄别对标的差距结果,识别出哪些是真实有效的,哪些可以通过平台能力快速补齐。
比如对于一家提供CRM软件的公司来说容器化部署虽然在环境管理、部署发布等领域有非常多的优势但并非当前的核心瓶颈和亟需解决的问题那么就不应该纳入近期的改进列表中。
通过现状分析,企业可以把有限的资源聚焦在那些高优先级的任务上,识别出改进目标和改进后要达到的预期效果。这些效果需要尽量**客观**和**可量化**比如缩短50%的环境准备时长。
3.**关注能力**
**模型和框架是能力和实践的集合**,也就是道法术器的“术”这个层面,所以在应用模型的过程中,核心的关注点应该在能力本身,而不是单纯地比较数字和结果。
比如亚马逊每天23000次部署的案例经常会被拿来举例子。这个数字的确相当惊人但反过来想想所有企业都需要达到这么高的部署频率吗举个例子一个客户端应用可以在几分钟内构建完成但同样是构建对于大型系统软件来说可能需要几个小时那么到底多长时间才算达标呢
我们不能只关注这些明星企业所达到的成就,而忽略了自身的需求。所以,**正确的做法是根据锚定的目标识别所需要的能力,再导入与能力相匹配的实践,不断强化实践,从而使能力本身得到提升**。
4.**持续改进**
模型和框架本身也不是一成不变的也需要像DevOps一样不断迭代更新以适应更高的软件交付需要。另外从今年的DevOps状态报告就可以看出达到精英级别的比例从2018年的7%快速提升到2019年的20%,也就是说,行业整体的能力也在不断提升,这就对企业的软件交付能力提出了更高的要求。
好了以上这些就是我总结的企业应用DevOps能力模型和框架的步骤和原则。DevOps作为一个系统性工程同样需要与之配套的立体化实施方法只有将方法、实践和工具结合起来全方位推进才有可能获得成效。
为了帮助你更好地理解DevOps实施的过程我贴了一幅经典的部署引力图。
<img src="https://static001.geekbang.org/resource/image/69/4e/6998eeeea55f7695e31f2dc9e6a3e94e.png" alt="">
可以看出当软件发布的频率从100天1次进化到1天100次的时候分支策略、测试能力、软件架构、发布策略、基础设施能力以及数据库能力都要进行相应的改动。比如分支策略要从长线分支变成基于特性的主干开发模式而架构也要从大的单体应用不断解耦和服务化。在实际应用中企业涉及的领域甚至更多因为这些仅仅是技术层面的问题而组织文化方面也不可或缺。
## 实践案例
最后,我再跟你分享一个我之前参与改进的一个客户的案例。
刚开始跟这个客户交流的时候,他千头万绪,抓不准重点,甚至由于组织严格划分职责边界,基本上每讲到一块内容,他就要拉相应的人过来聊,在许多人都聊完之后,项目的全貌才被拼凑出来。我相信这并不是个例,很多公司其实都是如此。
于是我们引入了能力成熟度模型并基于模型对企业现有的能力水平进行了一次全盘梳理并初步识别出了100多个问题点和40多个差距项。下面这张图就是汇总的大盘图当然部分数据进行了处理。
<img src="https://static001.geekbang.org/resource/image/81/2f/8148a346c26600afcd64c10a75a5fc2f.png" alt="">
接下来针对识别出来的这些差距点我逐项跟企业进行了沟通重点在于锚定一期的改进目标和具体工作事项。在沟通过程中我发现由于企业所处行业的特殊性或者客观条件不具备有些内容并非优先改进事项于是将改进事项缩减为30个并识别出这些改进事项的相互依赖和预期目标。比如这个企业之前初始化一套环境需要2周左右的时间为了加快整体交付能力我们将改进目标定到1周以内完成。
好啦,**有了改进目标和预期效果之后,就要分析哪些关键能力制约了交付效率的提升**。还拿刚才那个例子来说,核心问题在于**环境的初始化过程复杂**以及**审批流程冗长**。其中原有的初始化过程是研发整理一份部署需求文档来说明应用所依赖的环境和版本信息并且这个需求还被整合到一个40多页的文档中。运维团队根据这个文档部署每次都很不顺利因为软件功能迭代所依赖的环境也在不断更新但文档写出来就再也没人维护了。所以很多人说文档即过时就是这个道理。
识别出核心能力在于**自动化环境管理**之后,团队决定引入基础设施即代码的实践来解决这个问题。关于具体的技术细节,我会在后面的内容中展开,这里你只需要知道,通过将写在文档中的环境配置说明,转变成配置化的信息,并维护在专门的版本控制系统中,从而使得基础环境的初始化可以在分钟级完成。
当然,审批环境的优化属于非技术问题,而是流程和组织方面的问题。当大家认识到这些审批在一定程度上制约了发布频率的提升,就主动改进了现有流程。针对不同的环境进行不同级别的审批,使得单次审批可以在当天完成。
这样优化下来环境准备的时长大大缩短从当初的2周缩短到了2天改进效果非常明显。接下来团队又识别出新的差距锚定新的目标和预期效果并且有针对性地补齐能力建设走上了持续改进的阶段。
由此可以看出,**DevOps的能力实践和能力框架模型相辅相成**能力实践定义了企业落地DevOps的路线图和主要建设顺序能力模型可以指导支撑方法的各类实践的落地建设能力实践时刻跟随企业价值交付的导向而能力模型的积累和沉淀能够让企业游刃有余地面对未来的各种挑战。
至于ITIL和CMMI这些过往的框架体系自身也在跟随DevOps的大潮在持续演进比如以**流程合规**为代表的ITIL最近推出了第4个版本。我们引用一下ITIL V4的指导原则包括**关注价值、关注现状、交互式流程和反馈、协作和可视化、自动化和持续优化、极简原则和关注实践**。
看起来是不是有点DevOps的味道呢需要注意的是DevOps不会彻底颠覆ITIL只会在保证合规的前提下尽可能地优化现有流程将流动、反馈和持续学习改进的方法注入ITIL之中从全局视角持续优化企业的价值交付流程。
## 总结
总结一下今天我给你介绍了新技术和新思想的发展需要面对的鸿沟而能力模型和框架是技术和思想走向成熟的标志对于DevOps而言也是如此。在面对诸多模型和框架的时候企业需要立足自身识别差异锚定目标关注能力并持续改善软件的开发交付效率。DevOps的实施需要立体化的实施框架通过模型、方法、能力和实践的相互作用实现全方位的能力提升。
到此为止我们整体介绍了DevOps的基本概念、核心价值、实施方法和路线图帮助你建立了一套有关DevOps的宏观概念。接下来我们就会开始深入细节尤其是针对每一项核心实践我会介绍其背后的理念、实施步骤以及所依赖的能力模型手把手地帮助你真正落地DevOps。
## 思考题
最后给你留一道思考题关于CMMI、ITIL和DevOps你觉得它们之间的关系是怎样的呢企业该如何兼顾多套模型框架呢
欢迎在留言区写下你的思考和答案,我们一起讨论,共同学习进步。如果你觉得这篇文章对你有所帮助,欢迎你把文章分享给你的朋友。

View File

@@ -0,0 +1,211 @@
<audio id="audio" title="21 | 开源还是自研企业DevOps平台建设的三个阶段" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/81/87/817c1e9aa6397e9a6f4d1a8a49a6ef87.mp3"></audio>
你好,我是石雪峰,从今天开始,专栏正式进入了“平台工具篇”。
在这个全新的章节,我重点想讲三个方面的内容:
- 帮助你梳理企业内部DevOps平台的实施路径理清平台建设的主体脉络
- 给你分享一些核心平台的建设经验,这些经验都来自于生产一线;
- 给你分析一下DevOps平台的发展方向和热门趋势让你在进行平台建设时能够跟上潮流。
我想跟你说的是,**没有人天生就是DevOps平台的产品经理但每一个人都能成为DevOps平台的产品经理**。
因为DevOps平台的产品与业务方向的产品不同它要解决的就是**一线研发交付团队的实际问题**。
普通的产品经理没有研发交付的背景,很难理解研发交付的困境,而研发交付团队又缺少产品经理的技能和思路。所以,这个领域的人才少之又少,基本只能靠内部培养,我希望你能通过专栏的学习,摸索出一些产品设计的门道。
好了今天我们就来聊一聊企业DevOps平台建设的话题。
就像我之前提到的那样在企业内部推行DevOps工具不是万能的但是没有工具却是万万不能的。
当企业决定引入DevOps工具的时候无外乎有三种选择直接使用开源工具采购商业工具自己研发工具。
你可能会说如果有能力当然是选自研工具啊自主可控又有核心竞争力。可是在DevOps状态报告中却有一些不同的发现。
那些倾向于使用完全自建工具的企业,效能水平往往不高。所谓的完全自建工具,是指不依赖于开源解决方案,整个工具完全由自己来实现。而那些大部分采用开源工具的企业,效能水平反而不差。
这就有点反常理了。企业花了这么大的时间和精力来建设内部工具,到最后却没有达到预期的效果,究竟是为什么呢?
在我看来,这是因为没有找到企业内部平台建设的正确路径。**我们要在正确的时候,做正确的事情,太超前,或者太落后,都是会有问题的**。
那么接下来我就跟你聊聊企业DevOps平台建设的三个阶段。
## 阶段一:从无到有
在这个阶段企业的DevOps平台建设处于刚刚起步的状态在整个交付过程中还有大量的本地操作和重复性的操作。
另外,企业内部一般也没有一个成体系的工具团队,来专门负责平台能力建设。
那么,对于这个阶段,**我给你的建议是:引入开源工具和商业工具,快速补齐现有的能力短板**。
所谓能力短板,其实就是当前交付工具链体系中缺失的部分,尤其是高频操作,或者是涉及多人协作的部分,比如,需求管理、持续集成等。
无论是开源工具还是商业工具基本都是比较成熟的、拿来即用的这种“即战力”是当前企业最需要的。因为工具的引入解决了从无到有的问题可以直接提升单点效率。这也是在DevOps转型初期团队的效率能够飞速提升的主要原因。
看到这里,你可能会问两个问题:“如何选择工具?”“为什么商业工具也是可选项?”
其实,这也是团队在引入工具的初期,最头疼的两个典型问题,我们一一来看下。
### 如何选择工具?
现在以DevOps为名的工具太多了。想要在这么多工具中选择一款合适的你要怎么做呢
有的人可能会把相关工具的功能列表拉出来,然后逐项比对,看哪个工具的功能更加强大。其实,我觉得,在从无到有的阶段,不需要这么复杂,**核心原则就是选择主流工具**。
主流工具就是业内大家用得比较多的,在各种分享文章里面高频出现的,使用经验一搜一大把的那种工具。我给你提供一些工具,你可以参考一下:
- 需求管理工具Jira
- 知识管理工具Confluence
- 版本控制系统GitLab
- 持续集成工具Jenkins
- 代码质量工具SonarQube
- 构建工具Maven/Gradle
- 制品管理Artifactory/Harbor
- 配置管理工具Ansible
- 配置中心Apollo
- 测试工具RF/Selenium/Appium/Jmeter/TestNG
- 安全合规工具BlackDuck/Fortify
- ……
在初期,工具要解决的大多是单点问题,主流工具意味着更好的可扩展性,比如有完整的接口列表,甚至对其他工具已经内置了插件支持。
另外,很多开发实践都是基于主流工具来设计的。业内对于这些工具摸索得也比较深,有很多现成的实践经验,这些都对应了快速补齐能力短板的目标。
我之前见过一家大型金融机构他们也在考虑将代码管理从SVN切换到Git。但是他们选择的Git平台既不是开源的GitLab、Gerrit也不是商业化的主流工具而是一个听都没听过的开源工具。
这个工具的操作流程跟一般工具都不太一样,配套的评审、集成功能也都不够完善。最后,这家机构还是改用主流工具了。
### 为什么商业工具也是可选项?
随着开源工具的成熟和完善,越来越多的公司,甚至是传统企业,都开始积极拥抱开源,似乎开源就是代表未来的趋势。
那么,是不是只选择开源工具就行了,不用考虑商业工具了呢?我觉得,这种想法也是比较片面的。
商业工具的优势一直都存在,比如,专业性、安全性、扩展性、技术支持力度等。其实,很多开源工具都有商业版本。
比如很多公司即便有开源的Nexus制品管理工具Artifactory也都是标配。因为Artifactory无论是在支持的制品类型、分布式部署、附加制品安全漏洞检查还是在与外部工具的集成等方面都有着明显的优势。
另外像Jira这种需求和缺陷管理工具与Confluence深度集成的话足够满足绝大多数公司的需求。
再举个例子安卓开发最常见的Gradle工具它的商业版本可以直接让你的编译速度提升一个数量级。在最开始时你可能觉得够用就行但是当你开始追求极致效率的时候这些都是核心竞争力。
选择商业工具的理由有很多,不选的理由大多就是一个字:贵。针对这个问题,我要说的是,**要分清一笔支出到底是成本,还是投资**。
就跟购买黄金一样,虽然也花了钱,但这是一笔投资,未来可以保值和增值,甚至是变现。对于商业工具来说,也是同样的道理。如果一款商业工具可以大幅提升团队效率,最后的产出可能远超最开始的投资。如果我们组建一个团队,仿照商业工具,开发一套自研工具,重复造轮子的成本也可能一点不少。所以,重点就是要看怎么算这笔账。
## 阶段二:从小到大
经过了第一个阶段,企业交付链路上的工具基本都已经齐全了。团队对于工具的需求开始从够用到好用进行转变。另外,随着业务发展,团队扩大,差异化需求也成了摆在面前的问题。再加上,人和数据都越来越多,工具的重要性与日俱增。
那么,工具的稳定性、可靠性,以及大规模使用的性能问题,也开始凸显出来。
对于这个阶段,**我给你的建议是:使用半自建工具和定制商业工具,来解决自己的问题**。
所谓半自建工具,大多数情况下,还是基于开源工具的二次开发,或者是对开源工具进行一次封装,在开源工具上面实现需要的业务逻辑和交互界面。
比如基于Jenkins封装一套自己的构建打包平台完全可以利用Jenkins API和插件扩展实现。我附上了一幅架构示意图你可以参考一下。
<img src="https://static001.geekbang.org/resource/image/fa/de/fad880b4dbd8464e3ccd37886f42c0de.png" alt="">
那么,半自建工具有哪些注意事项呢?虽然各个领域的工具职能千差万别,但从我的经验来看,主要有两点:**设计时给扩展留出空间;实现时关注元数据治理**。
### 设计时给扩展留出空间
刚开始建设平台的时候,很容易就事论事,眼前有什么问题,就提供什么功能。这固然是比较务实的态度,但对于平台而言,还是要有顶层设计,给未来留出扩展性。这么说可能比较抽象,我来给你举几个实际的例子,也是我们之前踩过的“坑”。
**案例一:**
平台的初期设计没有考虑租户的特性,只是为了满足单一业务的使用。当功能比较成熟,想要对外输出的时候,我们发现,要重新在更高的维度插入租户,导致系统需要进行大幅改造,不仅功能页面需要调整,连权限模型都要重新设计。
如果在设计平台之初,就考虑到未来的扩展需求,把单一业务实现为一个平台租户,会不会更好些呢?
**案例二:**
为了满足快速上线的需要我们对Jenkins进行了简单封装实现了在线打包平台。但是打包页面的参数都“写死”在了页面中。另外每接入一个项目就需要单独实现一个页面。后来面对上百个应用的接入所带来的差异化需求平台只能推倒重来。
如果最开始在设计的时候,就采用接口获取的方式,将参数实现配置化,会不会更好些呢?
除此之外,在技术选型的时候,前后端分离的开发方式、主流的技术栈选型、一些典型的设计模式、相对统一的语言类型,其实都有助于平台空间的后续扩展。
**功能可以快速迭代,人员可以快速进入团队,形成战斗力,在设计平台的时候,这些都是需要思考的问题**
当然,**顶层规划,不代表过度设计**。我只是说,要在可以预见的范围内,预留一些空间,从而规避后期的尴尬。
### 实现时关注元数据治理
所谓元数据也就是常说的meta-data可以理解为钥匙链这些数据可以串起整个平台的数据结构。比如应用名称、模块名称、安全ID等等。
各个平台在组织数据结构的时候,都需要用到这些元数据,而且一旦使用了,轻易都不好改变。因为,在数据模型里面,这些元数据很有可能已经作为各种主键、外键的约束存在了。
对于单一平台来说,怎么维护这些元数据,都没什么大问题,但是,对于后续平台间的打通而言,这些元数据就成了一种标准语言。如果平台间的语言不通,就需要加入大量的翻译处理过程,这就导致系统性耦合加大,连接变得脆弱。
比如同样是购物车模块在我的平台里面叫购物车而在你的平台里面叫shopping-cart而且还按照平台划分比如shopping-cart-android、shopping-cart-ios甚至还有一些特性维度比如shopping-cart-feature1等等。显然想让两边的数据对齐并不容易。
**当然,元数据的治理并不是单一平台能够解决的事情,这同样需要顶层规划**
比如在公司内部建立统一的CMDB在其中统一管理应用信息。或者建立应用创建审批流程通用一个标准化流程来管控应用的生命周期同时管理应用的基础信息。这些都属于技术债务做得越晚还债的成本就越高。
## 阶段三:从繁到简
到了第三个阶段恭喜你已经在DevOps平台建设方面有了一定的积累在各个垂直领域也积累了成功案例。那么在这个阶段我们要解决的主要问题有3点
- 平台太多。做一件事情,需要各种切来切去;
- 平台太复杂。想要实现一个功能,需要对相关人员进行专业培训,他们才能做对;
- 平台价值说不清。比如,使用平台,能带来多大价值?能给团队和业务带来多大贡献?
对于这个阶段,**我给你的建议是:使用整合工具来化繁为简,统一界面,简化操作,有效度量。**
整合工具,就是包含了开源工具、半自研工具、商业工具的集合。
**你要提供的不再是一个工具,而是一整套的解决方案;不是解决一个问题,而是解决交付过程中方方面面的问题。**
### 企业工具平台治理
如果最开始没有一个顶层规划,到了这个时候,企业内部大大小小的工具平台应该有很多。你需要做的第一步,就是**平台化治理工作**。
首先,你要识别出来有哪些工具平台,使用情况是怎样的,比如有哪些业务在使用,实现了哪些功能。
如果要把所有工具平台收编起来,这不是一件容易的事情,甚至超出了技术的范畴。尤其是对很多大企业来说,工具平台是很多团队的根基,如果不需要这个平台,就意味着团队的重心也得调整。
所以,我给你的第一条建议是比较温和可行的,那就是,**找到软件交付的主路径**。用一个平台覆盖这条主路径,从而串联各个单点上的能力,让一些真正好的平台能够脱颖而出。而要做到这个事情,就需要**持续交付流水线**了。
这些年来,我一直在从事持续交付平台的建设,也总结了很多经验。我会在后面的内容中,跟你好好聊聊,如何设计一个现代的持续交付流水线平台。
流水线平台与一体化平台之间,还是有很大差距的。毕竟,各种工具平台的设计思路、操作路径、界面风格,差别很大。
所以,在实际操作的过程中,我给你的第二条建议就是,**区分平台和工具,让平台脱颖而出**。
比如,测试环境存在大量的工具,而一整套测试平台,实际上可以满足测试方方面面的需求,也就是说,测试人员只要在这个平台上工作就够了。当企业内部繁杂的工具收敛为几个核心平台之后,对于用户来说,就减少了界面切换的场景,可以通过平台和平台对接完成日常工作。
### 打造自服务的工具平台
到了这个阶段,**自服务**就成了平台建设的核心理念。
**所谓自服务,就是用户可以自行登录平台实现自己的操作,查看自己关心的数据,获取有效的信息**
而想要实现自服务,**简化操作**是必经之路。说白了,如果一件事情只要一键就能完成,这才是真正地实现了自服务。
这么说可能有点夸张。但是,打破职能间的壁垒,实现跨职能的赋能,依靠的就是平台的自服务能力。很多时候,当你在埋怨“平台设计得这么简单,为啥还是有人不会用”的时候,其实这只能说明一个问题,就是**平台依然不够简单**。
之前Jenkins社区就发起过一个项目叫作“5 Click5 Minutes”意思是希望用户只需要5次点击花5分钟时间就能完成一个Jenkins服务的建立。
这个项目的结果就是现在的Jenkins创建导航通过把建立服务的成本降到最低从而帮助更多的用户上手使用。
你看,用户体验是否简单,与技术是否高深无关,重点在于是否能够换位思考。所以,在建设平台的时候,要始终保有一份同理心。
## 总结
企业内部的平台化建设是个长期问题如果你要问我企业要建设DevOps平台有什么经验总结吗我的回答就是“四化”**标准化、自动化、服务化和数据化**。实际上,这些也是指导平台建设的核心理念。
- 标准化:一切皆有规则,一切皆有标准;
- 自动化:干掉一切不必要的手工操作环节,能一键完成的,绝不操作两次;
- 服务化:面向用户设计,而不是面向专家设计,让每个人都能在没有外界依赖的前提下,完成自己的工作;
- 数据化:对数据进行收集、汇总、分析和展示,让客观数据呈现出来,让数据指导持续改进。
## 思考题
最后,关于平台化建设,你有什么私藏的好工具吗?可以分享一下吗?
欢迎在留言区写下你的思考和答案,我们一起讨论,共同学习进步。如果你觉得这篇文章对你有所帮助,欢迎你把文章分享给你的朋友。

View File

@@ -0,0 +1,128 @@
<audio id="audio" title="22 | 产品设计之道DevOps产品设计的五个层次" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/e8/e1/e8639c970b8feb98631186660bd31de1.mp3"></audio>
你好,我是石雪峰。
在上一讲中我们聊到了企业DevOps平台建设的三个阶段。那么一个平台产品到底做到什么样才算是好的呢不知道你有没有想过这个问题反正做产品的这些年来我一直都在思考这个事儿。直到我听到了梁宁的专栏里面讲到的用户体验的五层要素才发现**无论什么产品,其实都是为了解决一群特定的人在特定场景的特定问题**。
那么回到我们的DevOps产品我们可以借鉴一下梁宁老师的思路来看看DevOps产品设计体验的五个层次**战略存在层、能力圈层、资源结构层、角色框架层和感知层**。
<img src="https://static001.geekbang.org/resource/image/fd/8c/fd05c31feebb1fd92c845a9347e5cd8c.png" alt="">
这么多专有名词一股脑地蹦出来,估计你头都大了吧?没关系,接下来我会逐一解释一下。
## 第一个层次:战略存在层
在决定开发一个DevOps产品的时候我们首先要回答的根本问题就是这个产品解决了什么样的痛点问题换句话说我们希望用户通过这个产品得到什么显然目标用户和痛点问题的不同会从根本上导致两套DevOps产品之间相距甚远。
举个例子业界很多大公司在内部深耕DevOps平台很多年有非常多很好的实践。但是当他们准备把这些内部平台对外开放提供给C端用户使用的时候会发现存在着严重的水土不服问题。
有些时候内外部产品团队有独立的两套产品对外提供的产品版本甚至比对内的版本要差上几年。这就是用户群体的不同造成的。C端用户相对轻量级需要的功能大多在具体的点上而企业内部因为多年的积累有大量的固有流程、系统、规则需要兼顾。所以整套产品很重甚至是完全封闭的一套体系难以跟用户现有的平台进行打通。
所以,我见过很多产品团队,他们对自己初期的产品定位并非在用户需求本身,而是在同类竞争对手身上。也就是说,他们先从模仿业界做得比较好的同类产品开始,从产品设计、功能模块到用户交互等,一股脑地参考同类产品,美其名曰“至少先赶上业界主流水平再说”。于是乎,团队开足马力在这条路上渐行渐远。
当然,借鉴同类产品的先进经验,这个做法本身并没有什么问题,毕竟,这些经验已经经过市场和用户的检验,至少走偏的风险不大。可问题是,**同类产品的经验并不能作为自己产品的战略**。
亚马逊的CEO贝佐斯就说过一句特别著名的话“**要把战略建立在不变的事物上。**”比如,如果竞争对手推出了一项新的功能,或者他们改变了自己的方向,那么我们的战略是否要随之变化,继续迎头赶上呢?这是一个值得产品团队深思的问题。
以我所在的电商行业为例,我们的产品始终在强调用户体验,但好的产品设计和用户体验绝不是因为友商做了什么花哨的改变,而是始终着眼于那些长久不变的事物之上,也就是**多、快、好、省**。因为不管什么时候用户选择在你的平台购物肯定不会是因为你的产品比其他家的要贵吧同样的道理对于DevOps产品来说也是这样。
那么有没有永远不变的内容可以作为DevOps产品的战略定位呢显然也是有的那就是**效率、质量、成本和安全**。归根结底,**产品的任何功能都是要为战略服务的**。比如,构建加速,要解决的就是效率问题,而弹性资源池,自然更加关注成本方面的问题。在任何时候,如果你的产品能在某个点上做到极致,那么恭喜你,你就找到了自己产品的立身之本。
**明确目标用户定义刚性需求服务于典型场景并最终在某一个点上突出重围这就是我们在准备做DevOps产品的时候首先要想清楚的问题**。无论是对内产品,还是对外产品,道理都是一样的。
## 第二个层次:能力圈层
战略很好,但是不能当饭吃。为了实现战略目标,我们需要做点什么,这就是需要产品化的能力。所谓产品化,就是将一个战略或者想法通过产品分析、设计、实验并最终落地的过程。
很少公司会有魄力一上来就投入百人团队开发DevOps产品大多数情况下都是一两个有志青年搭建起草台班子从一个最简单的功能开始做起。资源的稀缺性决定了我们永远处于喂不饱的状态而在这个时候最重要的就是所有为有所不为。
我们一定要明确,哪些是自己产品的核心竞争力,而哪些是我们的边界和底线,现阶段是不会去触碰的。当我们用这样一个圈子把自己框起来的时候,至少在短期内,目标是可以聚焦的。
当然,随着产品的价值体现,资源会随之而扩充,这个时候,我们就可以调整、扩大自己的能力圈。但说到底,**这些能力都是为了实现产品战略而存在的,这一点永远不要忘记**。
我还是拿个实际的案例来说明这个问题。之前在企业内部启动持续交付流水线项目的时候我们这个草台班子总共才4个人而我们面对的是千人的协同开发团队。在每个业务领域内部都有很多的产品工具平台在提供服务缺少的就是平台间的打通。
对于企业而言,一套完整覆盖端到端的研发协作平台看起来很美,但是,要做这么一套东西,投入巨大不说,还会同现有的工具平台产生冲突,这样就变成了一个零和游戏。
所谓零和游戏,就是所有玩家资源总和保持固定,只是在游戏过程中,资源的分配方式发生了改变。
就现在的这个例子来说,如果平台潜在用户总量是一定的,有一方向前一步,必定有另外一方向后一步,这显然不是我们这个“小虾米团队”现阶段能做到的。
所以,我们就给自己的产品定义了一个能力圈,它的边界就在于不去替换现有的工具平台,而是只专注于做链路打通的事情。这样一来,既有平台仍然可以单独提供服务,也可以通过标准化的方式提供插件,对接到我们的平台上来,我们的平台就成了它们的另外一套入口,有助于用户规模的扩大。
而对于我们自己来说,这些平台能力的注入,也扩展了我们自己的能力圈外沿,这些既有平台的用户就成了我们的潜在用户群体。这种双赢的模式,后来被证明是行之有效的,平台获得了很大的成功。
在跟很多朋友交流产品思路的时候,我总是把**主航道和护城河理论**挂在嘴边。**所谓主航道,就是产品的核心能力,直接反射了产品战略的具体落地方式**。对于流水线产品来说,这个能力来源于对软件交付过程的覆盖,而不论你将来开发任何产品,这条主路径都是无法回避的。那么,产品就有了茁壮成长的环境和土壤。而**护城河就是你这个产品的不可替代性,或者是为了替代你的产品需要付出的高额代价**。
还是引用流水线产品的例子,我们的护城河一方面来源于用户数据的沉淀,另一方面就在于这些外部能力的接入。你看,随着接入平台的增多,我们自身产品的护城河也越发难以逾越,这就是对于能力圈更加长远的考量了。
## 第三个层次:资源结构层
为什么做和做什么的问题,我们已经解决了,接下来,我们就要掂量掂量自己在资源方面有哪些优势了。
资源这个事儿吧,就像刚才提到的,永远是稀缺的,但这对于所有人来说都是公平的。所以,**对资源的整合和调动能力就成了核心竞争力**。当你没有竞争对手的时候,用户选择你的产品并不是什么难事,因为既然解决了一个痛点问题,又没有更好的选择,用一用也无妨。
可现实情况是,无论是企业内部,还是外部,我们都身处在一个充满竞争的环境,最开始能够吸引用户的点,说起来也很可笑,很多时候就在于让用户占了你的资源的便宜,也就是用户认为你的产品有一些资源是他们不具备的。
举个例子在很长一段时间内App的构建和打包都是基于本地的一台电脑来做的这样做的风险不用多说但是大家也没什么更好的选择。尤其是面对iOS这种封闭的生态环境想要实现虚拟化、动态化也不是一句话的事情甚至有可能触犯苹果的规则红线。
这时,如果你的产品申请了一批服务器,并且以标准化的方式部署在了生产机房,那么这些资源就成了产品的核心能力之一。
随着越来越多的用户跑来占便宜,产品对于大规模资源的整合能力就会不断提升,从而进一步压低平均使用成本,这就形成了一个正向循环。
产品蕴含的资源除了这些看得见、摸得着的机器以外,还有很多方面,比如,硬实力方面的,像速度快、机器多、单一领域技术沉淀丰富,又比如,强制性的,像审批入口、安全规则,还有软性的用户习惯,数据积累等等。
对于内部DevOps产品来说还有一项资源是至关重要的那就是**领导支持**。这一点我们已经在专栏[第6讲](https://time.geekbang.org/column/article/154695)中深入讨论过了,我就不再赘述了。
## 第四个层次:角色框架层
当用户开始使用你的产品时,不要忘了,他们是来解决问题的,而每一个问题背后都存在一个场景,以及在这个场景中用户的角色。脱离这个场景和角色的设定,单纯讨论问题是没有意义的。
所以,我们总说,**要站在用户的角度来看待问题,要在他们当时的场景下,去解决他们的问题,而不是远远地观望着,甚至以上帝视角俯视全局**。
举个例子当你和其他部门在为了一个功能设计争得面红耳赤差点就要真人PK的时候你们的领导走进了会议室你猜怎样瞬间气氛就缓和起来似乎刚才什么也没发生过。这难道是因为我们的情绪管理能力很强吗其实不然这主要是因为我们身处的场景发生了变化我们的角色也发生了改变。
再举个产品的例子,当我们在开发流水线产品的时候,为了满足用户不同分支构建任务的需求,我们提供了分支参数的功能。但是,在收集反馈的时候,全都是负面声音,难道这是个“伪需求”吗?
其实不是。通过实际数据,我们可以看到,很多用户已经开始使用这个功能了。这不是得了便宜又卖乖吗?问题就在于,**我们没有站在用户当时的角色框架下,来思考这个问题**。
因为,分支功能是需要用户手动输入的,但分支名又长又容易出错,每次都要从另外一个系统或者本地复制粘贴。当这个场景出现一次的时候并不是什么大事,但是,如果每个人每天都要做几十次的话,这就是大问题了。其实,解决思路很简单,增加历史信息或者自动关联的功能就可以啦。
所以你看,有时候我们不需要多么伟大的创造和颠覆,基于核心场景的微创新也能起到正向的作用。
说到底,其实就是一句话:**不要让你的产品只有专业人士才会使用。**
为了兼容灵活性,很多产品都提供了很多配置,但是,对于当时这个场景来说,绝大多数配置,都是没人关心的。**产品应该提供抽象能力屏蔽很多细节,而不是暴露很多细节,甚至,好的产品自身就是使用说明书**。这一点,在注意力变得格外稀缺的现在,重要性不可忽视。
## 第五个层次:感知层
现在,我们来看看最后一个层次:**感知层**,这也是距离用户最近的一个层次。
不可否认这是一个看脸的时代但是产品终究是给人用的而不是给人看的。所以很多人甚至强调对于内部产品来说UI完全不重要家丑不外扬就好了。
可是,换位思考一下,你希望自己每天打交道的是一个设计凌乱、完全没有美感的产品吗?
答案很有可能是否定的。可这对于很多DevOps的产品经理来说是最难的一点。这是因为没有人天生就是DevOps产品经理很多人都是半路出家做开发的做测试的甚至是当老板的。
让不专业的人做专业的事情,结果可想而知,好多产品功能的设计都堪称是“反人类”的。
关于这个层次,我提供两点建议:
<li>
**多跟前端工程师交流**。现在的前端框架已经非常成熟了,基于模板,我们可以快速地搭建出一个平台。而且,模板的框架自身,也蕴含着很多的设计思想。
</li>
<li>
**多学习一些基本的设计原则**。你可以参考[Element官网](https://element.eleme.cn/)上的设计理念章节,里面谈到了**一致、反馈、效率和可控**四个方面,每个方面又涉及很多细节。参照着成熟的产品,再对照这些基本设计理念,你放心,你会进步神速的。
</li>
## 总结
今天我们介绍了DevOps产品设计的五个层次包括战略存在层、能力圈层、资源结构层、角色框架层和感知层。其实当用户吐槽你的产品或者产品迟迟没有提升的时候我们可能就要沉下心来对照着这五个层次来看看问题到底出在哪里了。
## 思考题
你有用到过什么好的DevOps产品吗它们有哪些功能让你眼前一亮不由得为这个产品点赞吗
欢迎在留言区写下你的思考和答案,我们一起讨论,共同学习进步。如果你觉得这篇文章对你有所帮助,欢迎你把文章分享给你的朋友。

View File

@@ -0,0 +1,225 @@
<audio id="audio" title="23 | 持续交付平台:现代流水线必备的十大特征(上)" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/ee/00/ee1ca66e80d23a855f2689b6d2ce1100.mp3"></audio>
你好,我是石雪峰。
作为DevOps工程实践的集大成者和软件交付的“理想国”持续交付对企业的DevOps落地起到了举足轻重的作用。我接触过的企业全都在建设自己的流水线平台由此可见**流水线是持续交付中最核心的实践,也是持续交付实践最直接的体现**。
那么,如何建设一个现代流水线平台呢?这个平台,应该具备哪些特性呢?
根据我自己在企业内部建设落地流水线平台的经验,以及业界各家公司的平台设计理念,我提取、总结了现代流水线设计的十大特性。
在接下来的两讲中,我会结合平台设计,给你逐一拆解这些特性背后的理念,以及如何把这些理念落地在平台设计中。我把这十个特性汇总在了下面的这张图片里。今天,我先给你介绍下前五个特性。
<img src="https://static001.geekbang.org/resource/image/dd/b0/dd73fb488bc5fb93e0148107e1e470b0.png" alt="">
## 特性一:打造平台而非能力中心
与其他DevOps平台相比流水线平台有一个非常典型的特征那就是**它是唯一一个贯穿软件交付端到端完整流程的平台**。正因为这样,流水线平台承载了整个软件交付过程方方面面的能力,比如,持续集成能力、自动化测试能力、部署发布能力,甚至是人工审批的能力等。
那么,我们把软件交付过程中所需要的能力都直接做到流水线平台上,是不是就可以了呢?
这个想法是好的,但是在企业中,这并不具备可操作性。因为软件交付的每一个环节都是一项非常专业的工作,比如,仅仅是自动化测试能力这一项做好,就需要一个具备专业技能的团队的长期投入。
而且,把所有能力都做到流水线平台中,会使平台变得非常臃肿。再说了,我们也很难组建一个这么大的团队,来实现这个想法。
另外企业的DevOps平台建设并不是一两天的事情。每家企业内部都有很多固有平台这些平台长期存在已经成为了团队软件交付日常操作的一部分。如果全部推倒重来不仅会打破团队的习惯影响短期效率还会带来重复建设的巨大成本这并不利于流水线平台的快速落地。
那么,既然这条路走不通,流水线平台如何定位才比较合理呢?我认为,**正确的做法是,将持续交付流水线平台和垂直业务平台分开,并定义彼此的边界**。
所谓的垂直业务平台,就是指**单一专业领域的能力平台**,比如自动化测试平台、代码质量平台、运维发布平台等等,这些也是软件交付团队日常打交道最频繁的平台。
流水线平台只专注于**流程编排、过程可视化,并提供底层可复用的基础能力**。比如,像是运行资源池、用户权限管控、任务编排调度流程等等。
垂直业务平台则专注于**专业能力的建设、一些核心业务的逻辑处理、局部环节的精细化数据管理等**。垂直业务平台可以独立对外服务,也可以以插件的形式,将平台能力提供给流水线平台。
这样一来,我们就可以**快速复用现有的能力,做到最小成本的建设**。随着能力的不断扩展,流水线平台支持的交付流程也会变得非常灵活。
借用《持续交付2.0》中的一句话来说,**流水线平台仅作为任务的调度者、执行者和记录者,并不需要侵入垂直业务平台内部**。
<img src="https://static001.geekbang.org/resource/image/c9/fd/c9f4c396592a37694fbbe05e354ea7fd.png" alt="">
这样设计的好处很明显。
从流水线平台的角度来看,通过集成和复用现有的垂直业务能力,可以快速拓展能力图谱,满足不同用户的需求。
从垂直业务平台的角度来看,它们可以持续向技术纵深方向发展,把每一块的能力都做精、做透,这有助于企业积累核心竞争力。另外,流水线可以将更多用户导流到平台中,让垂直业务平台接触更多的用户使用场景。
不仅如此,在执行过程中,流水线携带了大量的软件开发过程信息,比如本次任务包含哪些需求,有哪些变更,这些信息可以在第一时间通知垂直业务平台。垂直业务平台拿到这些过程信息之后,可以通过精准测试等手段,大大提升运行效率。这里的核心就是**构建一个企业内部DevOps平台的良好生态**。
业界很多知名的软件设计都体现了这个思路。比如Jenkins的插件中心、GitHub的Marketplace。它们背后的理念都是基于平台建立一种生态。
我之所以把这个特性放在第一个来介绍,就是因为,**这直接决定了流水线平台的定位和后续的设计理念**。关于具体怎么设计平台实现能力的快速接入,我会在第八个特性中进行深入介绍。
## 特性二:可编排和可视化
在现代软件开发中,多种技术栈并存,渐渐成为了一种常态。
举个最简单的例子,对于一个前后端分离的项目来说,前端技术栈和后端技术栈显然是不一样的;对于微服务风格的软件架构来说,每个模块都应该具备持续交付的能力。
所以,传统的标准化软件构建发布路径已经很难满足多样化开发模式的需要了。这样看来,流水线平台作为软件交付的过程载体,流程可编排的能力就变得必不可少了。
**所谓的流程可编排能力,就是指用户可以自行定义软件交付过程的每一个步骤,以及各个步骤之间的先后执行顺序**。说白了,就是“我的模块我做主,我需要增加哪些交付环节,我自己说了算”。
但是,很多现有的“流水线”平台采用的还是几个“写死”的固定阶段,比如构建、测试、发布,以至于即便有些技术栈不需要进行编译,也不能跳过这个环节。
我之前就见过一家企业,他们把生成版本标签的动作放在了上线检查阶段。我问了之后才知道,这个步骤没有地方可以放了,只能被临时扔在这里。你看,这样一来,整个交付过程看起来的样子和实际的样子可能并不一样,这显然不是可视化所期待的结果。
流程可编排,需要平台前端提供一个可视化的界面,来方便用户定义流水线过程。典型的方式就是,**将流水线过程定义为几个阶段,每个阶段按顺序执行。在每个阶段,可以按需添加步骤,这些步骤可以并行执行,也可以串行执行**。
前端将编排结果以一种标准化的格式进行保存一般都是以JSON的形式传递给后端处理。后端流程引擎需要对用户编排的内容进行翻译处理并传递给执行器来解释运行即可。
你可以参考一下下面这张流程编排的示意图。在实际运行的过程中,你可以点击每一个步骤,查看对应的运行结果、日志和状态信息。
<img src="https://static001.geekbang.org/resource/image/76/e1/765961df0fff0efd529cc5d1f70a62e1.png" alt="">
从表面上看,这主要是在考验平台前端的开发能力,但实际上,**编排的前提是系统提供了可编排的对象,这个对象一般称为原子**。
所谓原子,就是一个能完成一项具体的独立任务的组件。这些组件要具备一定的通用性,尽量与业务无关。
比如下载代码这个动作,无论是前端项目,还是后端项目,做的事情其实都差不多,**核心要实现的就是通过几个参数,完成从版本控制系统拉取代码的动作**。那么,这就很适合成为一项原子。
**原子的设计是流水线平台的精髓,因为原子体现了平台的通用性、可复用性和独立性**
以我们比较熟悉的Jenkins为例一个原子就是流水线中的一个代码片段。通过封装特性将实现隐藏在函数实现内部对外暴露调用方法。用户只需要知道如何使用不需要关心内部实现。
要想自己实现一个原子其实并不复杂在Jenkins中添加一段Groovy代码就行了。示例代码如下
```
// sample_atom_entrance.groovy
def Sample_Atom(Map map) {
new SampleAtom(this).callExecution(map)
}
// src/com/sample/atoms/SampleAtom.groovy
class SampleAtom extends AbstractAtom {
SampleAtom(steps) {
super(steps)
}
@Override
def execute() {
// Override execute function from AbstractAtom
useAtom()
}
private def useAtom(){
steps.echo &quot;RUNNING SAMPLE ATOM FUNCTION...&quot;
}
```
## 特性三:流水线即代码
这些年来,“什么什么即代码”的理念已经深入人心了。在应用配置领域,有 Configuration As Code在服务器领域有 Infrastructure As Code……流水线的设计与实现同样需要做到 Pipeline As Code也就是流水线即代码。
比如Jenkins 2.0 中引入的 Jenkinsfile 就是一个典型的实现。另外Gitlab中提供的GitlabCI同样是通过一种代码化的方式和描述式的语言来展示流水线的业务逻辑和运行方式。
流水线代码化的好处不言而喻:**借助版本控制系统的强大功能,流水线代码和业务代码一样纳入版本控制系统,可以简单追溯每次流水线的变更记录**。
在执行流水线的过程中如果流水线配置发生了变化同样需要体现在本次流水线的变更日志里面。甚至是在版本的Release Notes中也增加流水线、环境的变更记录信息。一旦发生异常这些信息会大大提升问题的定位速度。
当然,如果只是想要实现流水线变更追溯,你也可以采用其他方式。比如,将流水线配置存放在后台数据库中,并在每次流水线任务执行时,记录当时数据库中的版本信息。
实际上,流水线即代码的好处远不止于此。因为**它大大地简化了流水线的配置成本,和原子一样,是构成现代流水线的另外一个支柱**。
我跟你分享一个流水线即代码的示例。在这个例子中,你可以看到,整个软件交付流程,都以一种非常清晰的方式描述出来了。即便你不是流水线的专家,也能看懂和使用。
```
image: maven:latest
stages:
- build
- test
- run
variables:
MAVEN_CLI_OPTS: &quot;--batch-mode&quot;
GITLAB_BASE_URL: &quot;https://gitlab.com&quot;
DEP_PROJECT_ID: 8873767
build:
stage: build
script:
- mvn $MAVEN_CLI_OPTS compile
test:
stage: test
script:
- mvn $MAVEN_CLI_OPTS test
run:
stage: run
script:
- mvn $MAVEN_CLI_OPTS package
- mvn $MAVEN_CLI_OPTS exec:java -Dexec.mainClass=&quot;com.example.app.A
```
## 特性四:流水线实例化
作为软件交付流程的建模,流水线跟面向对象语言里面的类和实例非常相似。一个类可以初始化多个对象,每个对象都有自己的内存空间,可以独立存在,流水线也要具备这种能力。
**首先,流水线需要支持参数化执行**
通过输入不同的参数,控制流水线的运行结果,甚至是控制流水线的执行过程。
比如,一条流水线应该满足不同分支的构建需要,那么,这就需要将分支作为参数提取出来,在运行时,根据不同的需要,手动或者自动获取。
考虑到这种场景,在平台设计中,你可以事先约定一种参数的格式。这里定义的标准格式,就是**以“#”开头,后面加上参数名称**。通过在流水线模板中定义这样的参数,一个业务可以快速复用已有的流水线,不需要重新编排,只要修改运行参数即可。
**其次,流水线的每一次执行,都可以理解为是一个实例化的过程。**
每个实例基于执行时间点的流水线配置,生成一个快照,这个快照不会因为流水线配置的变更而变更。如果想要重新触发这次任务,就需要根据当时的快照运行,从而实现回溯历史的需求。
**最后,流水线需要支持并发执行能力。**
这就是说,流水线可以触发多次,生成多个运行实例。这考察的不仅是流水线的调度能力、队列能力,还有持久化数据的管理能力。
因为,每次执行都需要有独立的工作空间。为了加速流水线运行,需要在空间中完成静态数据的挂载,比如代码缓存、构建缓存等。有些流水线平台不支持并发,其实就是因为没有解决好这个问题。
## 特性五:有限支持原则
流水线的设计目标,应该是满足**大多数、常见场景下的快速**使用,并提供一定程度的定制化可扩展能力,而不是满足所有需求。
在设计流水线功能的时候,我们往往会陷入一个怪圈:我们想要去抽象一个通用的模型,满足所有的业务场景,但是我们会发现,业务总是有这样或者那样的特殊需求。这就像是拿着一张大网下水捞鱼,总是会有漏网之鱼,于是,网做得越来越大。对于平台来说,平台最后会变得非常复杂。
比如拿最常见的安卓应用构建来说目前绝大多数企业都在使用Gradle工具通用命令其实只有两步
```
gradle clean
gradle assemblerelease / gradle assembledebug
```
但是在实际的业务场景中应用A用到了Node.js需要安装npm应用B用到了Git-lfs大文件需要先执行安装指令应用C更甚需要根据选项配置执行Patch模式和完整打包模式。
如果试图在一个框架中满足所有人的需求,就会让配置和逻辑变得非常复杂。无论是开发实现,还是用户使用,都会变得难以上手。
以Jenkins原生的Xcode编译步骤为例这个步骤提供了53个参数选项满足了绝大多数场景的需求但是也陷入到了参数的汪洋大海中。
所以,**流水线设计要提供有限的可能性,而非穷举所有变量因素**。
在设计参数接口的时候我们要遵循“奥卡姆剃刀法则”也就是“如无必要勿增实体”。如果有用户希望给原子增加一个变量参数那么我们首先要想的是这个需求是不是90%的人都会用到的功能。如果不是,就不要轻易放在原子设计中。
你可能会问,这样的话,用户的差异化诉求,该如何满足呢?其实,这很简单,你可以**在平台中提供一些通用类原子能力**比如执行自定义脚本的能力、调用http接口的能力、用户自定义原子的能力等等。只要能提供这些能力就可以满足用户的差异化需求了。
## 总结
在这一讲中,我给你介绍了现代流水线设计的前五大特性,分别是打造平台而非能力中心、可编排和可视化、流水线即代码、流水线实例化,以及有限支持原则。在下一讲中,我会继续介绍剩余的五大特性,敬请期待。
## 思考题
你所在的企业有在使用流水线吗?你觉得,流水线还有什么必不可少的特性吗?
欢迎在留言区写下你的思考和答案,我们一起讨论,共同学习进步。如果你觉得这篇文章对你有所帮助,也欢迎你把文章分享给你的朋友。

View File

@@ -0,0 +1,195 @@
<audio id="audio" title="24 | 持续交付平台:现代流水线必备的十大特征(下)" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/23/b4/2356db3d895ce9e66900ab057ef303b4.mp3"></audio>
你好,我是石雪峰。今天,我来接着跟你聊聊现代流水线必备的十大特性的下半部分,分别是流程可控、动静分离配置化、快速接入、内建质量门禁和数据采集聚合。
<img src="https://static001.geekbang.org/resource/image/dd/b0/dd73fb488bc5fb93e0148107e1e470b0.png" alt="">
## 特性六:流程可控
在上一讲中,我提到过,流水线是覆盖软件交付端到端完整过程的平台,也就是说,流水线的主要作用是**驱动软件交付过程的效率提升和状态可视化**。
在线下交流的时候,我发现,不少同学对这个概念的理解都存在着一些误区,他们觉得需要建设一条大而全的流水线,在这条流水线上完成软件交付的所有过程。
其实,流水线是要覆盖端到端的流程,但这并不是说,一定要有一条流水线跑通从代码提交开始到软件发布为止的全流程。实际上,在企业中,往往是多条流水线覆盖不同的环节,比如开发阶段流水线、集成阶段流水线,以及部署阶段流水线。这些流水线一起覆盖了整个软件交付流程。
这就体现了流水线的流程可控性,**流水线可以为了满足不同阶段的业务目标而存在,并且每条流水线上实现的功能都不相同**。为了达到这个目的,流水线需要支持多种触发方式,比如定时触发、手动触发、事件触发等。其中,**事件触发就是实现持续集成的一个非常重要的能力**。
以Gitlab为例你可以在代码仓库中添加WebhookWebhook的地址就是触发流水线任务的API这个API可以通过Gitlab的API实现自动注册。
需要注意的是,**要实现Webhook的自动注册访问Gitlab的账号时必须要有对应代码仓库的Master级别权限否则是无法添加成功的**。
当注册完成Webhook代码仓库捕获到对应的事件后比如代码Push动作会自动调用Webhook并且将本次代码提交的基础信息比如分支、提交人等传递给注册地址。
流水线平台接收到接口访问后,可以根据规则过滤请求,最典型的就是**触发分支信息**。当满足规则条件后则执行流水线任务并将结果再次通过Gitlab的API写回到代码仓库中。这样一来每次提交历史都会关联一个流水线的执行记录可以用于辅助代码合并评审。
我画了一张流程图,它展示了刚刚我所描述的过程以及调用的接口信息。
<img src="https://static001.geekbang.org/resource/image/c0/e2/c06719043cb3a22f6dd7da3b71a044e2.png" alt="">
除了多种触发方式以外,流水线还需要支持人工审批。这也就是说,每个阶段的流转可以是自动的,上一阶段完成后,就自动执行下一阶段;也可以是手动执行的,必须经过人为确认才能继续执行,这里的人为确认需要配合权限的管控。
其实人工审批的场景在软件交付过程中非常常见。如果是自建流程引擎人工审批就不难实现但是如果你是基于Jenkins来实现这个过程虽然Jenkins提供了input方法来实现人为审批的功能但我还是比较推荐你自己通过**扩展代码**来实现。比如将每个原子的执行过程抽象为before()、execute() 和 after() 三个阶段可以将人工审批的逻辑写在before()或者after()方法中。
这样一来对于所有原子都可以默认执行基类方法从而获得人工审批的能力。是否开启人工审批可以通过原子配置中的参数实现。你就不需要在每个原子中人工注入input方法了流水线的执行过程会更加清晰。
我给你分享一个抽象原子类的设计实现,如下面的代码所示:
```
abstract class AbstractAtom extends AtomExecution {
def atomExecution() {
this.beforeAtomExecution()
// 原子预处理步骤,你可以将通用执行逻辑,比如人工审批等写在这里
echo('AtomBefore')
before()
// 原子主体核心逻辑
echo('AtomExecution')
execute()
// 原子后处理步骤,你可以将通用执行逻辑,比如人工审批等写在这里
echo('AtomAfter')
after()
this.afterAtomExecution()
}
}
```
## 特性七:动静分离配置化
流水线的灵活性不仅体现在流程可编排、流程可控方面,每一个原子都需要持续迭代功能。那么,如何在不改变代码的情况下,实现原子的动态化配置呢?
这就需要用到**动静分离**的设计方法了。那么,什么是动静分离呢?
其实,**动静分离就是一种配置化的实现方式**。这就是指,将需要频繁调整或者用户自定义的内容,保存在一个静态的配置文件中。然后,系统加载时通过读取接口获取配置数据,并动态生成用户可见的交互界面。
你可能觉得有点抽象,我来给你举个例子。你可以看一下下面这张截图。
<img src="https://static001.geekbang.org/resource/image/50/49/5096345bd515d2223146e9bbf88e5f49.png" alt="">
如果我想对某一个原子扩展一个新的功能提供一个新的用户配置参数传统的做法就是在前端页面中增加一段html代码。这样的话原子功能的每一次变更都需要前端配合调整原子的独立性就不复存在了而是跟页面强耦合在一起。
另外,前端页面加入了这么多业务逻辑,如果哪天需要同时兼容不同的原子版本,那么前端页面也需要保存两套。一两个应用这么玩也就罢了,如果有上百个应用,那简直没法想象。
那么,具体要怎么做呢?**最重要的就是定义一套标准的原子数据结构**。
比如,在上面这张图的左侧部分,我给你提供了一个参考结构。对于所有的原子来说,它对外暴露的功能都是通过这套标准化的方式来定义的。前端在加载原子的时候,后端提供的接口获取原子的数据结构,并按照约定的参数类型,渲染成不同的控件类型。
不仅如此,控件的属性也可以灵活调整,比如控件的默认值是什么,控件是否属于必填项,是否存在可输入字符限制等等。那么,当你想增加一个新的参数的时候,只需要修改原子配置,而不需要修改前端代码。**结构定义和具体实现的分离,可以大幅简化原子升级的灵活性**。
无论在原子结构设计,还是前后端交互等领域,**定义一个通用的数据结构是设计标准化的系统的最佳实践**。
对于流水线平台来说,除了原子,很多地方都会用到配置化的方式。比如,系统报告中体现的字段和图表类型等,就是为了满足用户差异化的需求。而且,将配置纳入版本控制,你也可以快速查询原子配置的变更记录,达到一切变更皆可追溯的目标。
## 特性八:快速接入
前面我提到过,流水线的很多能力都不是自己提供的,而是来源于垂直业务平台。那么,**在建设流水线平台的时候,能否快速地实现外部平台能力的接入,就成了一个必须要解决的问题**。
**经典的解决方式就是提供一种插件机制,来实现平台能力的接入**。比如Jenkins平台就是通过这种方式建立了非常强大的插件生态。但是如果每个平台的接入都需要企业内部自己来实现插件的话那么企业对于平台接入的意愿就会大大降低。
实际上,**接入成本的高低,直接影响了平台能力的拓展,而流水线平台支持的能力多少,就是平台的核心竞争力**。
那么,有没有一种更加轻量化的平台接入方法呢?我给你提供一个解决思路:**自动化生成平台关联的原子代码**。
在第七个特性中,我们已经将原子的数据结构通过一种标准化的描述式语言定义完成了,那原子的实现代码是否可以也自动化生成呢?实际上,在大多数情况下,外部平台打通有两种类型。
- 平台方提供一个本地执行的工具也就是类似SonarQube的Scanner的方式通过在本地调用这个工具实现相应的功能。
- 通过接口调用的方式,实现平台与平台间的交互,调用的实现过程无外乎同步和异步两种模式。
既然平台接入存在一定的共性,那么,我们就可以规划解题方法了。
首先,**流水线平台需要定义一套标准的接入方式**。以接口调用类型为例,接入平台需要提供一个任务调用接口、一个状态查询接口以及一个结果上报接口。
- **任务调用接口**:用于流水线触发任务,一般由接入平台定义和实现。对于比较成熟的平台来说,这类接口一般都是现成的。接口调用参数可以直接转换成原子的参数,一些平台的配置化信息(比如接口地址、接口协议等),都可以定义在原子的数据结构中。
- **状态查询接口**:用于流水线查询任务的执行状态,获取任务的执行进度。这个接口也是由接入平台定义和实现的,返回的内容一般包括**任务状态**和**执行日志**等。
- **数据上报接口**:用于任务将执行结果上报给流水线平台进行保存。这个接口由流水线平台定义,并提供一套标准的数据接口给到接入方。接入方必须按照这个标准接口上报数据,以简化数据上报的过程。
通过将平台接入简化为几个标准步骤,可以大幅简化平台接入的实现成本。按照我们的经验,一套平台的接入基本都可以在几天内完成。
## 特性九:内建质量门禁
在[第14讲](https://time.geekbang.org/column/article/163072)中,我给你介绍了内建质量的理念,以及相关的实施步骤。你还记得内建质量的两大原则吗?
- 问题发现得越早,修复成本就越低;
- 质量是每个人的责任,而不是质量团队的责任。
**毫无疑问,持续交付流水线是内建质量的最好阵地,而具体的展现形式就是质量门禁**。通过在持续交付流水线的各个阶段注入质量检查能力,可以让内建质量真正落地。
一般来说,流水线平台都应该具备质量门禁的能力,我们甚至要把它作为流水线平台的一级能力进行建设。在流水线平台上,要完成**质量规则制定**、**门禁数据收集和检查**,以及**门禁结果报告的完整闭环**。质量门禁大多数来源于垂直业务平台比如UI自动化测试平台就可以提供自动化测试通过率等指标。只有将用于门禁的数据上报到流水线平台才能够激活检查功能。
那么,质量门禁的功能应该如何设计呢?
从后向前倒推,首先是设置**门禁检查功能**。这个功能也是一种流水线的通用能力所以和人工审核的功能类似也可以放在原子执行的after()步骤中或者独立出来一个步骤就叫作qualityGates()。
每次原子执行时都会走到这个步骤,在步骤中校验当前流水线是否已经开启了门禁检查功能,并且当前原子是否提供了门禁检查能力。如果发现已配置门禁规则,而且当前原子在检查范围内,就等待运行结果返回,提取数据,并触发检查工作。你可以参考下面的示例代码。
```
def qualityGates() {
// 获取质量门禁配置以及生效状态
boolean isRun = qualityGateAction.fetchQualityGateConfig(host, token, pipelineId, oneScope)
// 激活检查的情况等待结果返回最多等待30分钟
if (isRun) {
syncHandler.doSyncOperation(
30,
'MINUTES',
{
// 等待执行结果返回,质量门禁功能必须同步执行
return httpUtil.doGetToExternalResult(host, externalMap.get(oneScope), token)
})
// 提取返回数据
qualityGateAction.fetchExecutionResult(host, token, externalMap.get(oneScope), buildId)
// 验证质量门禁
qualityGateAction.verify(oneScope)
}
}
```
解决了如何检查的问题,我们再往前一步,看看质量门禁的规则应该如何定义。
在企业内定义和管理质量规则的一般都是QA团队所以需要给他们提供一个统一入口方便他们进行规则配置和具体数值的调整。
对质量门禁来说,检查的类型可以说是多种多样的。
- 从比较类型来说,可以比较结果大于、等于、小于、包含、不包含等;
- 从比较结果来说,可以是失败值、警告值。失败值是指,只要满足这个条件,就直接终止流水线执行。而警告值是说,如果满足这个条件,就给一个警告标记,但是不会终止流水线执行。
这些条件往往需要根据QA团队定义的规则来适配。
**质量规则可以由一组子规则共同组成**比如单元测试通过率100%、行覆盖率大于50%、严重阻塞代码问题等于0……
所以,你看,想要定义一个灵活的质量门禁,就需要在系统设计方面花点功夫了。在之前的实践中,我们就采用了适配器加策略模式的方式,这样可以满足规则的灵活扩展。
策略模式是23种设计模式中比较常用的一种。如果你之前没有了解过我给你推荐一篇[参考文章](https://design-patterns.readthedocs.io/zh_CN/latest/behavioral_patterns/strategy.html)。如果想要深入学习设计模式,极客时间也有相应的专栏,或者你也可以购买经典的《[设计模式](https://item.jd.com/10100236.html)》一书。其实,**核心就在于面向接口而非面向过程开发,通过实现不同的接口类,来实现不同的检查策略**。
## 特性十:数据聚合采集
作为软件交付过程的载体,流水线的可视化就体现在可以在流水线上看到每一个环节的执行情况。这是什么意思呢?
在系统没有打通的时候,如果你想看测试的执行结果,就要跑到测试系统上看;如果想看数据库变更的执行状态,就得去数据库管理平台上看。这里的问题就是,没有一个统一的地方可以查看本次发布的所有状态信息,而这也是流水线的可视化要解决的问题。
当平台的能力以原子的形式接入流水线之后,流水线需要有能力获取本次执行相关的结果数据,这也是在平台对接的时候,务必要求子系统实现数据上报接口的原因。至于上报数据的颗粒度,其实并没有一定之规,原则就是**满足用户对最基本的结果数据的查看需求**。
以单元测试为例,需要收集的数据包括两个方面,一个是单元测试的执行结果,比如一共多少用例,执行多少,成功失败分别多少。另外,即使收集覆盖率信息,至少也要包含各个维度的覆盖率指标。但是,对于具体每个文件的覆盖率情况,这种粒度的数据量比较大,可以通过生成报告的方式来呈现,不用事无巨细地都上报到流水线后台进行保存。
在企业内部没有建立独立的数据度量平台之前,流水线平台承载了全流程数据的展示功能。但是,毕竟流水线的目标是为了展示客观的数据结果,而不是在于对数据进行分析挖掘。所以,当企业开始建设数据度量平台时,流水线也可以作为数据源之一,满足度量平台对于各项工程能力的度量需求。
## 总结
到此为止我给你完整地介绍了现代流水线必备的十大特性。其实流水线的功能特性远不止这10个。随着云计算和云原生应用的发展云原生流水线也成为了越来越多人讨论的话题。关于这方面的内容我会在后续的课程中给你分享我的一些想法。
可以说一个好的持续交付流水线平台就是企业DevOps能力的巅峰展现。这也难怪越来越多的公司开始在这个领域发力甚至把它作为核心能力对外输出成为企业商业化运作的一份子。深入掌握这10个特性并把它们落实在流水线平台的建设中是企业DevOps平台建设的必经之路。
就像美国著名女演员莉莉·汤姆林Lily Tomlin的那句经典名言所说的那样
>
The road to success is always under construction.(通往成功的道路,永远在建设之中)
企业迈向持续交付的成功之路也不是一帆风顺的,永无止境的追求是指引我们前进的方向,也希望你能在流水线建设之路上不断思考,不断实践,持续精进。
## 思考题
你目前在使用的流水线平台有哪些不好用、待改进,或者是“反人类”的设计吗?看完这两讲的内容,你有什么新的想法和改进建议吗?
欢迎在留言区写下你的思考和答案,我们一起讨论,共同学习进步。如果你觉得这篇文章对你有所帮助,也欢迎你把文章分享给你的朋友。

View File

@@ -0,0 +1,186 @@
<audio id="audio" title="25 | 让数据说话:如何建设企业级数据度量平台?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/92/46/92ae154d247afa71db16602933d80f46.mp3"></audio>
你好,我是石雪峰。今天我来跟你聊聊数据度量平台。
先说个题外话。在2019年的DevOps World | Jenkins World大会上CloudBees公司重磅发布了他们的全新产品[SDM - Software Delivery Management](https://www.cloudbees.com/software-delivery-management) 。在我看来,这注定是一个跨时代的产品。
简单来说SDM想要解决的问题就是**将割裂的软件开发流程收敛到一个平台上**,通过收集软件开发全流程的数据,并进行智能分析,从而让整个软件交付过程的方方面面对所有人都可视化。
无论这个产品最终是否能够获得成功,它背后的设计理念绝对是非常超前的,因为这是**第一次有一个解决方案把业务视角和开发视角连接了起来**。
对业务人员来说,他们能够实时看到特性的交付进度;对开发人员来说,他们也能实时看到交付特性的业务指标和用户反馈;对管理人员来说,他们可以纵观整个流程,发现交付过程中的阻塞和效率瓶颈。
这听起来是不是很神奇呢?别急,关于这个产品的更多特性,我会在后续的特别放送中给你带来更多的介绍,敬请期待。
言归正传,我走访过的公司无一例外地都在花大力气建设数据度量平台。这些度量平台虽然看起来长得都不一样,但是他们想要解决的核心问题都是一致的,那就是**软件研发过程可视化**。
为什么可视化对于软件研发来说这么重要呢?这是因为,可视化可以大幅降低软件开发的协作成本,增加研发过程的透明度,从而大大减少研发过程中的浪费和返工。
举个最简单的例子,每周开会的时间成本一般都比较高,但如果老板能对项目的状态有清晰的了解,何必还要费这么大力气汇报工作呢?
在专栏的[第19讲](https://time.geekbang.org/column/article/169385)中我给你介绍了DevOps度量体系的相关内容。你还记得好的度量指标一般都具有的典型特征吗这些特征就是**明确受众、直指问题、量化趋势、充满张力**。
其实,在评价一个度量平台的时候,这些特征同样适用。因为,在数据度量平台上呈现的内容,正是度量指标。这也就是说,将度量指标的数据和详情汇总起来,再根据度量指标的维度,展现出各式各样的视图,从而满足不同用户的需求。
这样一来,整个团队的交付情况,包括交付效率和质量,就可以通过客观数据展示出来,而不再依赖于个人的主观臆测。有了客观的数据做尺子,团队的改进空间也就一目了然了。
听起来是不是特别美好?但实际上,度量平台要想满足这种预期,可不是一件简单的事情。
我认为,在数据度量平台的建设和落地过程中,事前、事中和事后这三个阶段都存在着大量的挑战。接下来,我就从这三个阶段入手,给你聊聊度量平台建设的一些思路。
## 事前:指标共识
毫无疑问,度量指标是数据度量平台的基础。在建设平台之前,如果指标本身的定义、数据来源、计算方法、统计口径等没有在团队内部达成共识的话,那么,数据度量平台呈现出来的数据也同样是有问题的。
我给你举个例子。需求流转周期这个指标,一般是计算需求卡片在需求的各个状态的停留时长的总和,包括分析、设计、开发、测试、发布等。
其中的测试流转周期计算的是从需求卡片进入待测试状态到测试完成进入待发布状态的时长例如5天。但是在真正支持测试任务的系统中也有一个测试流转周期。这个流转周期计算的是每个测试任务的平均执行时间这样算出来的测试周期可能只有1天。
先不说这两种计算方式谁对谁错,我想表达的是,**即便是针对同一个指标,在不同平台、根据不同计算方法得到的结果也大不相同**。
如果不能把指标的定义对齐,那么在实施度量的过程中,大家就会不清楚到底哪个数据是正确的,这显然不利于度量工作的推进。
另外,在定义度量指标的时候,一般都会召开指标评审会议。但这个时候,因为拿不出具体的数据,大家光盯着指标定义看,往往也看不出什么问题。等到平台上的数据出来了,才发现有些数据好像不太对。于是,要再针对指标重新梳理定义,而这往往就意味着平台开发的返工和数据重新计算。**在平台建设的过程中,数据校准和指标对齐工作花费的时间很有可能比开发平台本身的时间都要多**。
“**数据本身不会说话,是人们赋予了数据意义**”,而“这个意义“就是度量指标。
在定义指标的时候,大家都愿意选择对自己有利的解释,这就导致大家看待数据的视角无法对齐。
所以,在实施度量平台建设之前,最重要的就是**细化度量指标的数据源和计算方法,而且一定要细化到可以落地并拿出数据结果的程度**。
比如,开发交付周期这个指标一般是指从研发真正动工的时间点开始,一直到最终上线发布为止的时长。但是这个描述还是不够细化,所以,我们团队对这个指标的描述是:**从研发在需求管理平台上将一个任务拖拽到开始的开发阶段起,一直到这个任务变成已发布状态为止的时间周期。**
这里的任务类型包括**特性、缺陷和改进任务**三种,不包含史诗任务和技术预研任务类型。我们会对已达到交付状态的任务进行统计,未完成的不在统计范围中。你看,只有描述到这种颗粒度,研发才知道应该如何操作,数据统计才知道要如何获取有效的数据范围。
我建议你**在着手启动数据度量平台建设之前,至少要保证这些指标数据可以通过线下、甚至是手工的方式统计出来,并在内部达成共识**。
切忌一上来就开始盲目建设!很多时候,我们虽然花了大力气建设平台,最终也建设出来了,但结果却没人关注,核心问题还是出在了指标上。
数据平台作为企业内部的公信平台,数据的准确性至关重要。如果数据出现了偏差,不仅会导致错误的判断,带来错误的结果,还会对平台自身的运营推广造成很大的伤害。
## 事中:平台建设
随着软件交付活动复杂性的上升,在整个交付过程中用到的工具平台也越来越多。虽然通过持续交付流水线平台实现了交付链路的打通,通过交付流水线来驱动各个环节的工具平台来完成工作,但是,客观来说,企业内部的工具平台依然是割裂的状态,而非完整的一体化平台。
这就带来一个问题:每个平台或多或少都有自己的数据度量能力,甚至也有精细化维度的数据展示,但是这些数据都是存储在各个工具平台自身的数据库中的。
我给你举个例子。Jira是一个业界使用比较普遍的需求管理平台也是一个成熟的商业工具所以对于这类商业化系统都提供了比较完善的API。再加上Jira自带的JQL查询语言可以相对比较简单地查询并获取元数据信息。但是对于一个自研平台来说对外开发的API可能相对简单甚至有的系统都没有对外暴露API。在这种情况下如果想要获取平台数据要么依赖于开发新的API要么就只能通过JDBC直接访问后台数据库的形式来提取数据。
不仅如此,还有些平台的数据是通过消息推送的方式来获取的,无法主动地获取数据,只能通过订阅消息队列广播的方式来获取。
所以,你看,**对于不同的元数据平台,数据获取的方式也是千差万别的**。
### 挑战一:大量数据源平台对接
那么,作为一个统一的数据度量平台,面对的第一个挑战就是,**如何从这些种类繁多的平台中提取有用的数据,并且保证数据源接入的隔离性,做到灵活接入呢?**
我给你的建议还是采用流水线设计的思路,那就是**插件化**,只不过,这次要实现的插件是**数据采集器**。你可以看一下这张简单的架构示意图:
<img src="https://static001.geekbang.org/resource/image/e9/2a/e9806c2956d151804423f7f237fe152a.png" alt="">
采集器是针对每一个对接的数据源平台实现的它的作用就是对每个数据源进行数据建模从而对平台屏蔽各种数据获取方式将采集到的数据进行统一格式化上报和存储。在采集器上面可以设计一个Operation层用来调整采集器的执行频率控制采集数据的范围。
如果数据量比较大你也可以让采集器对接类似Kafka这样的消息队列这些都可以按需实现。这样一来新平台如果想要接入只需要针对这个平台的数据特性实现一个采集器即可平台的整体架构并不需要变化。
你可以看看下面的这段采集器的示例代码:
```
@Override
public void collect(FeatureCollector collector) {
logBanner(featureSettings.getJiraBaseUrl());
int count = 0;
try {
long projectDataStart = System.currentTimeMillis();
ProjectDataClientImpl projectData = new ProjectDataClientImpl(this.featureSettings,
this.projectRepository, this.featureCollectorRepository, jiraClient);
count = projectData.updateProjectInformation();
log(&quot;Project Data&quot;, projectDataStart, count);
} catch (Exception e) {
// catch exception here so we don't blow up the collector completely
LOGGER.error(&quot;Failed to collect jira information&quot;, e);
}
}
```
### 挑战二:海量数据存储分析
一般来说常见的数据存储方式无外乎RDMS关系型数据库和NoSQL非关系型数据库两种类型。那么究竟应该如何选择还是要看数据度量平台的数据特征。
- 第一个典型特征就是**数据量大**。对于一个大型公司而言,每天的代码提交就有近万笔,单单这部分数据就有几十万、上百万条。
- 第二个特征就是**数据结构不统一**。这个其实很好理解,毕竟需求相关的数据字段和代码相关的数据字段基本上没有什么共性,而且字段的数量也会根据指标的调整而调整。
- 第三个特征就是**数据访问频繁**。度量平台需要在大规模的数据集中进行随机访问、数据的读取运算等操作,这就要求很好的横向扩展能力。
另外,数据度量平台一般都会保存元数据和加工数据。所谓元数据,就是采集过来的、未加工过的数据,而加工数据则是经过数据清洗和数据处理的数据。
我还是举个代码库的例子来说明一下。元数据就是一条条用户的代码提交记录,而加工数据则是按照分钟维度聚合过的提交信息,包括数量、行数变化等。这些加工过的数据可以很简单地提供给前端进行图表展示。存储加工数据的原因就在于,避免每次实时的大量数据运算,以提升度量平台的性能。
基于这些典型特征和场景,不难看出,非关系型数据库更加适合于大量元数据的保存。
我推荐你使用HBase这是一个适合于非结构化数据存储的数据库天生支持分布式存储系统。而对于加工数据的保存你可以采用关系型数据库MySQL。
当然数据库的选型不止这一种业界还有很多开源、商业工具。比如开源的数据度量平台Hygieia就采用的是MongoDB而商业工具中的Insight也在业内的很多大型公司在大规模使用。
我再给你分享一幅数据度量的架构图。从这张图中你可以看到底层数据都是基于HBase和HDFS来存储的。
<img src="https://static001.geekbang.org/resource/image/0f/ec/0fd99a661eede0fbc0ae7e282464ceec.png" alt="">
### 挑战三:度量视图的定制化显示
度量平台需要满足不同维度视角的需求所以一般都会提供多个Dashboard比如管理层Dashboard、技术经理Dashboard、个人Dashboard等。但是这种预置的Dashboard很难满足每个人的差异化需求就像“一千个人眼里有一千个哈姆雷特”一样度量平台的视图也应该是千人千面的。
那么如果想要实现度量视图的自定义,比如支持图标位置的拖拽和编辑,自己增加新的组件、并按照自定义视图发送报告等,那就需要在前端页面开发时下点功夫了。好在对于现代前端框架,都有现成的解决方案,你只需要引用对应的组件即可。
我给你推荐两个前端组件,你可以参考一下:
- [插件一](https://github.com/jbaysolutions/vue-grid-layout)
- [插件二](https://github.com/STRML/react-grid-layout)
这两个组件都可以支持widget的拖拽、缩放、自动对齐、添加、删除等常见操作。这样一来每个人都可以自由地按需定制自己的工作台视图不同角色的人员也可以定制和发送报告而不需要从度量平台提取数据再手动整理到PPT里面了。
以vue-grid-layout为例在使用时你可以将echarts图表放在自定义组件里面同时你也可以自己实现一些方法具体的方法可以参考一下[这篇文章](https://www.cnblogs.com/yasoPeng/p/9961732.html)。
在了解了刚开始建设度量平台的三个常见挑战之后,你应该已经对度量平台的架构有了一个大体的认识,接下来,我们来看看第三个阶段。
## 事后:规则落地
以现在的开发效率来说建设一个数据度量平台并不是件困难的事情。实际上建设度量平台只能说是迈出了数据度量的第1步而剩余的99步都依赖于平台的运营推广。
这么说一点也不夸张甚至可以说如果根本没人关心度量平台上的数据那么可能连第1步的意义都要画上个问号。
在开始运营的时候,度量平台面临的最大挑战就是**数据的准确性**这也是最容易被人challenge的地方。
造成数据不准确的原因有很多,比如,度量指标自身的计算方式问题、一些异常数据引入的问题、部门维度归类聚合的问题。但是实际上,往往带来最多问题的还是研发操作不规范。
举个例子,像需求交付周期这种数据强依赖于需求卡片流转的操作是否规范,如果研发上线后一次性把卡片拖拽到上线状态,那么这样算出来的需求交付周期可能只有几秒钟,显然是有问题的。
正确的做法是,根据真实的状态进行流转,比如研发提测关联需求,后台自动将需求卡片流转到待测试状态;测试验收通过后,卡片再次自动流转到测试完成状态等。**尽量实现自动化操作,而不是依赖于人的自觉性**。
再举个例子,像需求关联的代码行数,如果研发提交的时候并没有对代码和需求建立关联,那么统计出来的数据也会有很大的失真。这些不规范的数据并不会因为后续操作的改变而改变,也很难进行数据的修复和清理,会一直留存在度量系统的数据池中,是抹不掉的印记。
所以,度量平台只有通过项目自上而下的驱动才能起到真正的作用。要**对不规范的操作建立规则,对恶意操作的数据进行审计,把度量发现的问题纳入持续改进,对每项指标的走势进行跟踪和定位**。
另外,为了让数据可以直指问题,在度量平台中,也需要体现出来当前的数据是好还是坏。
方式和方法有很多比如建立参考值比如对于单测覆盖率制定最低50%的参考值这样在度量图表中就能体现出当前数据和参考值的差距。或者你也可以在每一项可以横向比较的指标旁边体现当前处在大部门的哪个位置是前10%还是后10%?这样的数据都有助于推动改进行为。
说到底,**度量的目的是持续改进**。如果统计了100个指标的数据并都体现在度量平台上却说不出来到底哪个指标给团队带来了改进以及改进是如何实现的那么这种度量平台的价值又在哪里呢
## 总结
好啦,在这一讲中,我给你介绍了建设数据度量平台的核心价值,也就是**让软件交付过程变得可视化**。在这一点上业界各大公司的思路都是一致的。也正因为如此数据度量平台是当前企业DevOps平台建设不可或缺的一环。
在平台建设的时候,你需要关注事前、事中和事后三个阶段的事情。
- 事前就是要对指标的定义达成共识。这里的指标要细化到数据源和详细的计算公式层面,即便没有度量平台,也可以计算出相应的结果;
- 事中就是平台建设方面面对多数据源平台可以采用采集器插件的方式灵活适配建议使用HBase等非关系型数据库进行数据存储可以利用现有的前端组件来实现可视化界面展示。
- 事后就是数据的运营和规则落地。只有度量数据能够反映出问题,并驱动团队改进,度量才有意义。
## 思考题
你在企业中建设和应用度量平台的时候,还遇到过哪些问题呢?你又是如何解决的呢?
欢迎在留言区写下你的思考和答案,我们一起讨论,共同学习进步。如果你觉得这篇文章对你有所帮助,也欢迎你把文章分享给你的朋友。

View File

@@ -0,0 +1,219 @@
<audio id="audio" title="26 | 平台产品研发:三个月完成千人规模的产品要怎么做?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/63/98/63cb07b82c2518f59fc51e3d3a2ac398.mp3"></audio>
你好,我是石雪峰。
虽然我们之前聊了这么多的平台建设思路,但是,可能很多人都没有机会经历一个平台从构思到开发、再到推广落地的完整过程。
如果要开发一个千人使用的DevOps产品需要多长时间呢你可能会说需要半年甚至是更长的时间我之前也是这么觉得的。
但是2018年在启动流水线平台建设的时候老板“大手一挥”要求在三个月内见到成效我都快惊呆了。
因为,我们要真正地从零开始:原型图都没有一张,代码都没有一行,临时组建的一个草台班子还分散在北京、上海两地,团队成员之前都没怎么打过招呼,这能行吗?
今天,我想给你分享的就是这个真实的故事。我来跟你一起复盘下这次“急行军”的历程,看看我们做对了什么,又做错了什么,有哪些干货是可以拿来就用的,又有哪些“坑”是你一定要努力回避的。
其实作为一个非专业的DevOps产品经理你终将面对这样的挑战但你要相信**只要开始去做了,就没有什么是不可能的**。
## 项目启动
时间回到一年前当时我所在的这个“草台班子”是个啥情况呢团队组成是这样的两个后台开发在北京一个半前端开发在上海还有一个基础设施工程师和一个流水线开发工程师再加上半个全能打杂的产品经理也就是我满打满算一共6个人。
项目从11月中旬开始构思12月初开启动会当时除了我之外没有任何人清楚我们要做的到底是个什么玩意儿。这该怎么办呢
玩过游戏的同学应该都知道打好开局有多重要所以为了这个Kickoff会议我事先做了大量的准备工作其中就包括0.2版本的产品原型图。与其说是一个原型图,不如说就是一个草稿,简陋得不能再简陋了。
<img src="https://static001.geekbang.org/resource/image/ac/fe/ac58f3b2040056ee030008370dc6c3fe.png" alt="">
项目的Kickoff会议是项目组成员和未来产品的第一次见面留下一个积极的印象非常重要。所以从第一刻开始我就铆足了精神。
首先,我发出了一封热情洋溢的会议邀请。在会议邀请中,我仔细地陈述了我们为什么要做这件事,为什么是现在,为什么不做不行。
在正式开会的时候,我再一次明确了项目的重要性和紧急性,并给大家演示了第一版的系统原型图(没错,就是简陋到极致的刚刚的这张原型图)。
即便这样,三个月的工期也让大家非常焦虑。为了缓解紧张情绪,证明这个项目的可行性,我还做了两件事:
1. 搭建了一个系统demo几个简单的页面
1. 由于用到了另外一个开源产品的核心技术,于是,我就对这个技术进行了简单演示。
虽然我自己心里对这个计划也相当“打鼓”,但我还是希望告诉大家,这并不是不可能的任务,努力帮助大家树立信心。
在项目启动会上,团队达成了两个非常关键的结论:**一个是系统方案选型;另一个是建立协作机制**。
首先,由于时间紧任务重,我们决定使用更易于协作的前后端分离的开发模式。后来,事实证明,这是一个非常明智的选择。这不仅大幅提升了开发效率,也大大降低了之后向移动端迁移的成本。在开发移动端产品的时候,后端接口大部分都可以直接拿来使用。
在技术框架方面,由于大家对前后端分离的模式达成了共识,我们就采用**Python+Django+VUE**的方式来做。你可能会问为啥不用基于Java的Spring系列呢因为我觉得对于内部系统来说这些典型的框架应付起来基本都绰绰有余关键还是要选你熟悉的、易上手的那个。从这个角度来看Python显然有着得天独厚的优势。即便之前只是写写脚本想要上手Python也不是一件困难的事情。
在项目协作方面,我等会儿会专门提到,由于团队成员分散在北京、上海两地,彼此之间不够熟悉和信任,所以,**建立固定的沟通机制就非常重要**。
至少,在项目初期,我们每周都要开两次电话会议:
- 一次是面向全员的。一方面同步项目的最新进展,另一方面,也给大家一些紧迫感,让大家觉得“其他人都在按照计划执行,自己也不能落后”。
- 另外一次是面向跨地域骨干的。这主要还是为了增进联系,并且对一些核心问题进行二次的进展确认。不拉上全员,也是为了避免过多地浪费项目成员的时间。
最后,项目毕竟还是有一些技术风险的,所以还需要启动预研。我们这个项目的主要风险是在**前端交互**上。
这是一个从来没人实现过的场景,有大量的用户界面编排操作在里面。所以,我们专门指定了一位同学,让他啥也别想,一门心思地进行技术攻关。
事实证明,但凡能打硬仗的同事,在后来都是非常靠谱且独当一面的,这与年龄无关,哪怕是应届生,也同样如此。
讲到这里,我要先给你总结一下在项目启动阶段要重点关注的几件事情:
- 明确项目目标,树立团队的信心;
- 沟通开发模式和技术架构选型,以快速开发和简单上手为导向;
- 建立沟通渠道,保持高频联系;
- 识别项目的技术风险,提前开启专项预研。
## 开发策略
人类社会活动的每一个环节,都需要越来越多的人为了同一个目标推进工作,软件开发也不例外。那么,我们是怎么做的呢?
首先,就是**研发环境容器化**。
**对于接触一个全新技术栈的开发来说,本地搭建一套完整可运行的环境总是绕不过去的坎**。即便是对照着文档一步步操作,也总会有遗漏的地方。除此之外,项目依赖的各种中间件,哪怕稍微有一个版本不一致,最后一旦出现问题,就要查很久。
既然如此为什么不一上来就采用标准化的环境呢这就可以发挥容器技术的优势了。主力后台开发同学自己认领了这个任务先在本地完成环境搭建并调试通过接着把环境配置容器化。这样一来新人加入项目后几分钟就能完成一套可以工作的本地开发环境。即便后续要升级环境组件比如Django框架版本也非常简单只要推送一个镜像上去再重启本地环境就可以了。
其次就是选择分支策略。虽然DevOps倡导的是主干开发但是我们还是选择了“三分支”的策略因为**我们搭建了三套环境**。
测试环境对应dev分支作为开发主线所有新功能在特性分支开发自测通过后再通过MR到dev分支并部署到测试环境进行验收测试一般验收测试由需求提出方负责。
接下来定期每周两次从dev上master分支master分支对应了预发布环境保证跟生产环境的一致性数据也会定期进行同步。只有在预发布环境最终验收通过后才具备上线生产环境的条件。通过将master分支合并到release分支最后完成生产环境部署。这种分支策略的示意图如下
<img src="https://static001.geekbang.org/resource/image/43/25/435d72ddc0b694e4efa84dc8cef3be25.png" alt="">
为什么要采用三套环境的“三分支”策略呢?
这里的主要原因就是,团队处于组建初期,磨合不到位,经常会出现前后端配置不一致的情况。更何况,我们这个项目不只有前后端开发,还有核心原子业务开发,以及基础设施维护。任何一方的步调不一致,都会导致出现问题。
另外,内部平台开发往往有个通病,就是**没有专职测试**。这也能理解,总共才几个人的“草台班子”,哪来的测试资源啊?所以,基本上只能靠研发和产品把关。
但是,毕竟测试也是个专业的工种,这么一来,总会有各种各样的问题。再加上,产品需求本身就没有那么清晰、灵活多变,所以,**多一套环境,多一套安全**。
但不可否认的是,这种策略并非是最优解,只不过是适应当时场景下的可行方案。当团队磨合到位,而且也比较成熟之后,就可以简化一条分支和一套环境了。不过,前提是,**只有快速迭代,快速上线,才能发挥两套环境的优势**。
>
Use what you build to build what you use.(使用你开发的工具来开发你的工具)
这是我们一以贯之的理念。既然是DevOps平台那么团队也要有DevOps的样子所以作为一个全功能团队研发自上线和研发自运维就发挥到了极致。
同时,我们并没有使用公司统一的上线流程,而是自己建立了一个标准化的上线流程并固化在工具里面,团队的每一个人都能完成上线动作。
这样一来,就不会再依赖于某个具体的人员了,这就保持了最大的灵活性。即便赶上大促封网,也不会阻塞正常的开发活动。
## 开发协作流程
仅仅是做到上面这几点,还不足以让整个团队高效运转起来,因为**缺少了最重要的研发协作流程**。
作为项目负责人,我花了很大的精力优化研发协作流程,制定研发协作规范。当这一切正常运转起来后,我发现,这些前期的投入都是非常值得的。
在工具层面我们使用了Jira。对于小团队来说Jira的功能就足够优秀了可以满足大多数场景的需求。但是Jira的缺点在于使用和配置门槛稍微有点高。因此团队里面需要有一个熟悉Jira的成员才能把这套方法“玩”下去。
在Jira里面我们采用了**精益看板加上迭代**的方式,基本上两周一个迭代,保持开发交付的节奏。这种开发工作流刚好适配我们的分支策略和多环境部署。
需求统一纳入Backlog管理当迭代开始时就拖入待开发状态研发挑选任务启动开发并进入开发中。当开发完成后也就意味着功能已经在测试环境部署。这个时候就可以等待功能验收。只有在验收通过之后才会发布到预发布环境。并经过二次验收后最终上线发布给用户。
开发流程并不复杂,你可以看一下下面这两版流程图。
图片版:
<img src="https://static001.geekbang.org/resource/image/be/98/be2b81f9744fe06876fac21c61a4b798.png" alt="">
文字版:
<img src="https://static001.geekbang.org/resource/image/ec/8e/ec61ade9f0b2c3b014e27a7ac367298e.png" alt="">
定义好开发工作流之后,接下来,就需要明确原则和规范了。对于一个新组建的团队来说,**规则是消除分歧和误解的最好手段,所以一定要让这些规则足够得清晰易懂**。比如在我们内部就有一个“3-2-1”原则
3**创建**任务三要素
- 有详细的问题说明和描述
- 有清晰的验收标准
- 有具体的经办人和迭代排期
2**处理**任务两要素
- 在开发中代码变更要关联Jira任务号
- 在开发完成后要添加Jira注释说明改动内容和影响范围
1**解决**任务一要素
- 问题报告人负责任务验收关闭
当然,团队规则远不止这几条。你要打造自己团队内部的规则,并且反复地强调规则,帮助大家养成习惯。这样一来,你会发现,**研发效率提升和自组织团队都会慢慢成为现实**。
除此之外,**你也不要高估人的主动性,期望每个人都能自觉地按照规则执行**。所以,定期和及时的提醒就非常必要。比如,每天增加定时邮件通知,告诉大家有哪些需求需要验收,有哪些可以上线发布,尽量让每个人都明白应该去哪里获取最新的信息。
另外,每次开周会时,都要强调规则的执行情况,甚至每天的站会也要按需沟通。只有保持短促、高频的沟通,才能产生理想的效果。
## 产品运营策略
关于产品运营策略,“酒香不怕巷子深”的理念已经有些过时了。想要一个产品获得成功,**团队不仅要做得好,还要善于运营和宣传,而这又是技术团队的一大软肋**。
开发团队大多只知道如何实现功能,却不知道应该怎么做产品运营。往往也正因为如此,团队很难获取用户的真实反馈,甚至开发了很多天才的功能,用户都不知道。产品开发变成了“自嗨”,这肯定不符合产品设计的初衷。
考虑到这些,我们在平台运营的时候,也采取了一些手段。我想提醒你的是,**很多事情其实没有没有多难,关键就看有没有想,有没有坚持做**。
比如,你可以建立内部用户沟通群,在产品初期尽量选择一些活跃的种子用户来试用。那些特别感兴趣、愿意尝试新事物、不断给你提建议的都是超级用户。这些用户未来都是各个团队中的“星星之火”,**在项目初期,你一定要识别出这些用户**。
另外每一次上线都发布一个release notes并通过邮件和内部沟通群的方式通知全员一方面可以宣传新功能另一方面也是很重要的一方面**就是保持存在感的刷新**。你要让用户知道这个产品是在高速迭代的过程中的,而且每次都有不一样的新东西,总有一样会吸引到他们,或者让他们主动提出自己的问题。
在用户群里面注意要及时响应用户的问题。你可以在团队内部建立OnCall机制每周团队成员轮值解决一线用户的问题既可以保证问题的及时收敛也能让远离用户的开发真真切切地听到用户的声音。这样的话在需求规划会和迭代回顾会的时候开发就会更多地主动参与讨论。
以上这些都是比较常规的手段,在我们的产品运营中,还有两个方法特别有效,我也推荐给你。
平台运营就跟打广告是一样的越是在人流最大、关注度最高的地方打广告效果也就越好。每个公司一般都有类似的首页比如公司内部的技术首页、技术论坛、日常办公的OA系统等等这些地方其实都会有宣传的渠道和入口。**你要做的就是找到这个入口,并联系上负责这个渠道的人员**。我们的产品就一度实现了热门站点的霸屏,宣传效果非常明显,用户量直线上升。
<img src="https://static001.geekbang.org/resource/image/ac/c6/aca17122846f83e9d8700af0ad3952c6.png" alt="">
另一个方法有些取巧,但对于技术团队来说,也非常适用,那就是**通过技术分享的渠道来宣传产品**。
相信每个团队都会有定期的技术分享渠道,或者是技术公众号等,**你可以把平台的核心技术点和设计思想提炼出来,拟定一个分享话题,并在内部最大范围的技术分享渠道中进行分享**。
很多时候,单纯地宣传一个产品,很多人是“不感冒”的。但是,如果你在讲一些新技术,并结合产品化落地的事情,对技术人员的吸引力就会大很多。所以,**换个思路做运营,也是提升产品知名度的好方法**。我把我之前总结的产品运营渠道和手段汇总成了一幅脑图,也分享给你。
<img src="https://static001.geekbang.org/resource/image/67/27/676b53d64ba520cc1c56d429b5d01a27.png" alt="">
## 团队文化建设
最后,我想再跟你简单聊聊团队文化建设的事情。毕竟,无论什么样的工具、流程、目标,最终都是依靠人来完成的。**如果忽略对人的关注,就等同于本末倒置,不是一个成熟的团队管理者应该做的事情**。我给你分享我的两点感受。
**1.让专业的人做专业的事情**
很多时候,千万不要小看专业度这个事情。任何一个组织内部的职能都需要专业能力的支撑,这些专业能力都是量变引发的质变。
我举个最简单的例子你还记得我在前面提到的0.2版本的原型草稿吗实际上到了0.3版本,引用前端工程师话来说,“原型做得比系统还漂亮”。这是为什么呢?难道是我这个“半吊子”产品经理突然开窍了吗?
显然不是。其实答案很简单,就是我去找了专业产品经理做外援,让他帮我改了两天的原型图。对于专业的人来说,这些事情再简单不过了。
找专业的人来做这些事情,不仅可以帮助你快速地跨越鸿沟,也能留下很多现成的经验,供你以后使用,这绝对不是一个人埋头苦干可以做得到的。
不仅是产品方面,技术领域也是一样的。**我们要勇于承认自己的无知,善于向别人求助,否则到头来,损失的时间和机会都是自己买单,得不偿失**。
**2.抓大放小,适当地忽略细节**
在协作的过程中,团队总会在一些细节上产生冲突。如果任由团队成员在细节上争论不休,久而久之,就会影响团队之间的信任感。这个时候,就需要引导团队将注意力集中在大的方向上,适当地暂缓细节讨论,以保证团队的协作效率。
比如一个业务逻辑是放在前端处理还是放在后端处理结果并没有太大区别说白了就是放在哪儿都行。但是前端同学会坚持认为逻辑处理都应该由后端来解决以降低前端和业务的耦合性这样说也没有错。可是后端同学也会有自己的想法比如针对前端拦截器的处理机制后端到底要不要配合着返回前端要求的返回码而不是直接抛出http原始的返回码呢
类似的这些问题,没有谁对谁错之分,但是真要是纠结起来,也不是一两句话就能说清楚的。
这个时候,就需要有人拍板,选择一条更加符合常规的方式推进,并预留出后续的讨论空间。甚至,为了促进多地合作,自己人这边要适当地牺牲一些,以此来换取合作的顺利推进。这样一来,你会发现,有些不可调和的事情,在项目不断成功、人员不断磨合的过程中,也就不是个事情了。
## 总结
在这一讲中,关于如何开发产品,可以说,我是把自己在过去几个项目经历中的总结倾囊相授了。
其实,就像我在讲“[DevOps工程师需要的技能](https://time.geekbang.org/column/article/151398)”中提到的那样,软实力(比如沟通协作、同理心、持续改进等)对促进产品快速迭代开发演进有着重大的作用。作为非专业产品经理,我也在慢慢地积累自己的产品心经,有机会再给你好好聊聊。
你可能还在想,最终千人的目标是否实现了呢?我想说的是,有些时候,真实生活比故事还要精彩。
就在预订目标的倒数第二天平台用户只有997个。当时我跟同事吐槽这个数字他们说要不要拉几个用户进来我说“算了吧随它去吧。“结果你猜怎样在当天周五下班的时候我又去平台上看了一眼不多不少刚好1000个注册用户。当时我的第一感觉就是**要相信,当我们把自己的全身心和热情都灌注在一个产品的开发过程中时,美好的事情会自然而然地发生**。
## 思考题
你对这一讲的哪部分内容印象最深刻呢?你有什么其他有助于产品快速研发落地的观点吗?
欢迎在留言区写下你的思考和答案,我们一起讨论,共同学习进步。如果你觉得这篇文章对你有所帮助,也欢迎你把文章分享给你的朋友。

View File

@@ -0,0 +1,272 @@
<audio id="audio" title="27 | 巨人的肩膀:那些你不能忽视的开源工具" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/a0/d4/a052611ce7637a0da2daee351537a4d4.mp3"></audio>
你好,我是石雪峰。
自研工具平台对公司来说是一件高成本和高投入的事情对于技术人员的要求也非常高。很少有公司能够像BAT一样投入近百人的团队来开发内部系统工具毕竟如果没有这么大规模的团队平台产生的收益也比较有限。
另外,也很少有公司像一些行业头部公司一样,会直接投入大量资金购买成熟的商业化工具或者通过乙方合作的方式联合共建。
这些方法的长期投入都比较大,不太适用于中小型企业。那么,有其他可以低成本、快速见效的解决方案吗?
实际上,现在的开源工具已经非常成熟了,只要稍加熟悉,就能快速地基于开源工具搭建一整套研发交付工具链平台。
几年前,我跟几个朋友利用业余时间就搭建了这样一套开源的端到端流水线解决方案。我依稀记得,这个解决方案架构图是在北京开往上海的高铁上完成的。目前,这个方案在行业内广为流传,成为了很多公司搭建自己内部工具链平台的参考资料。这个系统的架构图如下:
<img src="https://static001.geekbang.org/resource/image/54/65/540e6527c7e2d54d0e33abc591349a65.png" alt="">
今天我会基于这个解决方案给你介绍一下研发代码提交阶段、集成测试阶段和部署发布阶段的工具使用技巧工具选型以主流开源解决方案为主商业工具为辅涵盖了Jira、GitLab、Jenkins、SonarQube和Kubernetes等希望可以手把手地帮助你快速搭建一套完整的持续交付平台。
**对于持续交付工具链体系来说,工具的连通性是核心要素**,所以我不会花太多时间介绍工具应该如何搭建,毕竟这类资料有很多,或者,你参考一下官网的搭建文档就可以了。尤其是现在很多工具都提供了容器化的部署方式,进一步简化了自身工具的建设成本。
## 需求管理 - Jira
在Jira官网上的醒目位置写着一句话**敏捷开发工具的第一选择**。在我看来Atlassian公司的确有这个底气因为**Jira确实足够优秀跟Confluence的组合几乎已经成为了很多企业的标配**。这也是为什么我没有选择开源工具Redmine或者其他诸如Teambition等的SaaS化服务。
当然近些年来各大厂商也在积极地对外输出研发工具能力以腾讯的TAPD为代表的敏捷协同开发工具就使用得非常广泛。但是其实产品的思路都大同小异搞定了Jira其他工具基本也就不在话下了。
作为敏捷协同工具Jira新建工程可以选择团队的研发模式是基于Scrum还是看板方法你可以按需选择。在专栏的[第8讲](https://time.geekbang.org/column/article/156884)和[第9讲](https://time.geekbang.org/column/article/158789)中我给你介绍了精益看板你完全可以在Jira中定制自己团队的可视化看板。
看板的配置过程并不复杂,我把它整理成了文档,你可以点击网盘[链接](https://pan.baidu.com/s/1SAmWYv7WeYgM6yZSRs5nag)获取提取码是mrtd。需要提醒你的一点是**别忘了添加WIP在制品约束别让你的精益看板变成了可视化看板**。
需求作为一切开发工作的起点,是贯穿整个研发工作的重要抓手。**对于Jira来说重点是要实现跟版本控制系统和开发者工具的打通**。接下来,我们分别来看下应该如何实现。
如果你也在使用特性分支开发模式你应该知道一个特性就对应到一个Jira中的任务。通过任务来创建特性分支并且将所有分支上的提交绑定到具体任务上从而建立清晰的特性代码关联。我给你推荐两种实现方式。
第一种方式是基于Jira提供的原生插件比如 [Git Integration for Jira](https://marketplace.atlassian.com/apps/4984/git-integration-for-jira)。这个插件配置起来非常简单你只需要添加版本控制系统的地址和认证方式即可。然后你就可以在Jira上进行查看提交信息、对比差异、创建分支和MR等操作。但是这个插件属于收费版本你可以免费使用30天到期更新即可。
<img src="https://static001.geekbang.org/resource/image/16/d9/1641afb86fdb0872d0b83e893a4803d9.png" alt="">
第二种方式,就是**使用Jira和GitLab的Webhook进行打通**。
首先你要在GitLab项目的“设置 - 集成”中找到Jira选项按下图添加相应配置即可。配置完成之后你只需要在提交注释中添加一个Jira的任务ID就可以实现Jira任务和代码提交的关联这些关联体现在Jira任务的Issue links部分。
另外你也可以实现Jira任务的状态自动流转操作无需手动移动任务卡片。我给你提供一份 [配置说明](http://confluence.gjingao.com/pages/viewpage.action?pageId=6520911) ,你可以参考一下。
<img src="https://static001.geekbang.org/resource/image/55/48/55e7b81af5f2f96e124493e3d36d9648.png" alt="">
不过如果只是这样的话还不能实现根据Jira任务来自动创建分支所以接下来还要进行Jira的Webhook配置。在Jira的系统管理界面中你可以找到“高级设置 - Webhook”选项添加Webhook后可以绑定各种系统提供的事件比如创建任务、更新任务等这基本可以满足绝大多数场景的需求。
假设我们的系统在创建Jira任务的时候要自动在GitLab中基于主线创建一条分支那么你可以将GitLab提供的创建分支API写在Jira触发的Webhook地址中。参考样例如下
>
https : //这里替换成你的GitLab服务地址/repository/branches?branch=${issue.key}&amp;ref=master&amp;private_token=[这里替换成你的账号Token]
<img src="https://static001.geekbang.org/resource/image/50/f2/504a61becf60fe6a2ddcfca5f624b9f2.png" alt="">
到这里Jira和GitLab的打通就完成了。我们来总结下已经实现的功能
1. GitLab每次代码变更状态都会同步到Jira任务中并且实现了Jira任务和代码的自动关联Issue links
1. 可以在MR中增加关键字 Fixes/Resolves/Closes Jira任务号实现Jira的自动状态流转
1. 每次在Jira中创建任务时都会自动创建特性分支。
关于Jira和开发者工具的打通我把操作步骤也分享给你。你可以点击[网盘链接](https://pan.baidu.com/s/1ByoVZRTzG48yt8Nmgf2cJg)获取提取码是kf3t。现在很多工具平台的建设都是以服务开发者为导向的所以距离开发者最近的IDE工具就成了新的效率提升阵地包括云IDE、IDE插件等都是为了方便开发者可以在IDE里面完成所有的日常任务对于管理分支和Jira任务自然也不在话下。
## 代码管理 - GitLab
这个示例项目中的开发流程是怎样的呢?我们一起来看下。
第1步在需求管理平台创建任务这个任务一般都是可以交付的特性。你还记得吗通过前面的步骤我们已经实现了自动创建特性分支。
第2步开发者在特性分支上进行开发和本地自测在开发完成后再将代码推送到特性分支并触发提交阶段的流水线。这条流水线主要用于**快速验证提交代码的基本质量**。
第3步当提交阶段流水线通过之后开发者创建合并请求Merge Request申请将特性分支合并到主干代码中。
第4步代码评审者对合并请求进行Review发现问题的话就在合并请求中指出来最终接受合并请求并将特性代码合入主干。
第5步代码合入主干后立即触发集成阶段流水线。这个阶段的检查任务更加丰富测试人员可以手动完成测试环境部署并验证新功能。
第6步特性经历了测试环境、预发布环境并通过部署流水线最终部署到生产环境中。
在专栏的[第12讲](https://time.geekbang.org/column/article/161549)中,我提到过,持续集成的理念是通过尽早和及时的代码集成,从而建立代码质量的快速反馈环。所以,**版本控制系统和持续集成系统也需要双向打通**。
这里的双向打通是指版本控制系统可以触发持续集成系统,持续集成的结果也需要返回给版本控制系统。
接下来,我们看看具体怎么实现。
### 代码提交触发持续集成
首先你需要在Jenkins中安装[GitLab插件](https://plugins.jenkins.io/gitlab-plugin)。这个插件提供了很多[GitLab环境变量](https://github.com/jenkinsci/gitlab-plugin#defined-variables)用于获取GitLab的信息比如gitlabSourceBranch这个参数就非常有用它可以提取本次触发的Webhook的分支信息。毕竟这个信息只有GitLab知道。只有同步给Jenkins才能拉取正确的分支代码执行持续集成过程。
当GitLab监听到代码变更的事件后会自动调用这个插件提供的Webhook地址并实现解析Webhook数据和触发Jenkins任务的功能。
其实,我们在自研流水线平台的时候,也可以参考这个思路:**通过后台调用GitLab的API完成Webhook的自动注册从而实现对代码变更事件的监听和任务的自动化执行**。
当GitLab插件安装完成后你可以在Jenkins任务的Build Triggers中发现一个新的选项勾选这个选项就可以激活GitLab自动触发配置。其中比较重要的两个信息我在下面的图片中用红色方块圈出来了。
<img src="https://static001.geekbang.org/resource/image/18/64/18400444f248087f0b3f33c34303ed64.png" alt="">
- 上面的链接就是Webhook地址每个Jenkins任务都不相同
- 下面的是这个Webhook对应的认证Token。
你需要把这两个信息一起添加到GitLab的集成配置中。打开GitLab仓库的“设置-集成”选项可以看到GitLab的Webhook配置页面将Jenkins插件生成的地址和Token信息复制到配置选项中并勾选对应的触发选项。
GitLab默认提供了多种触发选项在下面的截图中只勾选了Push事件也就是只有监听到Git Push动作的时候,才会触发Webhook。当然你可以配置监听的分支信息只针对特性分支执行关联的Jenkins任务。在GitLab中配置完成后可以看到新添加的Webhook信息点击“测试”验证是否可以正常执行如果一切正常则会提示“200-OK”。
<img src="https://static001.geekbang.org/resource/image/9b/8d/9b30070e1c038d301943c2d8adcc948d.png" alt="">
### 持续集成更新代码状态
打开Jenkins的系统管理页面找到GitLab配置添加GitLab服务器的地址和认证方式。注意这里的Credentials要选择GitLab API Token类型对应的Token可以在GitLab的“用户 - 设置 - Access Tokens”中生成。由于Token的特殊性只有在生成的时候可见以后就再也看不到了。所以在生成Token以后你需要妥善地保存这个信息。
<img src="https://static001.geekbang.org/resource/image/e5/32/e533cac2cc18bb852f2e8ff200427232.png" alt=""><br>
<img src="https://static001.geekbang.org/resource/image/db/bf/db49222bd6fac25909294de44d0204bf.png" alt="">
那么配置完成后要如何更新GitLab的提交状态呢这就需要用到插件提供的[更新构建结果](https://github.com/jenkinsci/gitlab-plugin#build-status-configuration)命令了。
对于自由风格类型的Jenkins任务你可以添加构建后处理步骤 - Publish build status to GitLab它会自动将排队的任务更新为“Pending”运行的任务更新为“Running”完成的任务根据结果更新为“Success”或者是“Failed”。
对于使用流水线的任务来说,官方也提供了相应的[示例代码](https://github.com/jenkinsci/gitlab-plugin#declarative-pipeline-jobs)你只需要对照着写在Jenkinsfile里面就可以了。
```
updateGitlabCommitStatus name: 'build', state: 'success'
```
这样一来每次提交代码触发的流水线结果也会显示在GitLab的提交状态中可以在查看合并请求时作为参考。有的公司更加直接如果流水线的状态不是成功状态那么就会自动关闭提交的合并请求。其实无论采用哪种方式初衷都是**希望开发者在第一时间修复持续集成的问题**。
<img src="https://static001.geekbang.org/resource/image/ac/12/ac621c245c87edb3de95f7aac626c012.png" alt="">
我们再阶段性地总结一下已经实现的功能:
1. 每次GitLab上的代码提交都可以通过Webhook触发对应的Jenkins任务。具体触发哪个任务取决于你将哪个Jenkins任务的地址添加到了GitLab的Webhook配置中
1. 每次Jenkins任务执行完毕后会将执行结果写到GitLab的提交记录中。你可以查看执行状态决定是否接受合并请求。
## 代码质量 - SonarQube
SonarQube作为一个常见的开源代码质量平台可以用来实现静态代码扫描发现代码中的缺陷和漏洞还提供了比较基础的安全检查能力。除此之外它还能收集单元测试的覆盖率、代码重复率等。
对于刚开始关注代码质量和技术债务的公司来说,是一个比较容易上手的选择。关于技术债务,在专栏的[第15讲](https://time.geekbang.org/column/article/165480)中有深入讲解,如果你不记得了,别忘记回去复习一下。
那么,代码质量检查这类频繁执行的例行工作,也比较适合自动化完成,**最佳途径就是集成到流水线中也就是需要跟Jenkins进行打通**。我稍微介绍一下执行的逻辑,希望可以帮你更好地理解这个配置的过程。
SonarQube平台实际包含两个部分
- 一个是平台端,用于收集和展示代码质量数据,这也是我们比较常用的功能。
- 另外一个是客户端也就是SonarQube的Scanner工具。这个工具是在客户端本地执行的也就是跟代码在一个环境中用于真正地执行分析、收集和上报数据。这个工具之所以不是特别引人注意是因为在Jenkins中后台配置了这个工具如果发现节点上没有找到工具它就会自动下载。你可以在Jenkins的全局工具配置中找到它。
<img src="https://static001.geekbang.org/resource/image/e9/2d/e919f073a1269135dcf45d04dadf8b2d.png" alt="">
了解了代码质量扫描的执行逻辑之后我们就可以知道对于SonarQube和Jenkins的集成只需要单向进行即可。这也就是说只要保证Jenkins的Scanner工具采集到的数据可以正确地上报到SonarQube平台端即可。
这个配置也非常简单你只需要在Jenkins的全局设置中添加SonarQube的平台地址就行了。注意勾选第一个选项保证SonarQube服务器的配置信息可以自动注入流水线的环境变量中。
<img src="https://static001.geekbang.org/resource/image/f2/38/f2907fecbee87af49cd1fffc9b6fb438.png" alt="">
在执行Jenkins任务的时候同样可以针对自由风格的任务和流水线类型的任务添加不同的上报方式。关于具体的内容你可以参考SonarQube的[官方网站](https://docs.sonarqube.org/latest/analysis/scan/sonarscanner-for-jenkins/),这里就不赘述了。
到此为止我们已经实现了GitLab、Jenkins和SonarQube的打通。我给你分享一幅系统关系示意图希望可以帮助你更好地了解系统打通的含义和实现过程。
<img src="https://static001.geekbang.org/resource/image/0e/53/0ecc003fb103eb633c5c02c291342d53.png" alt="">
## 环境管理 - Kubernetes
最后我们再来看看环境管理部分。作为云原生时代的操作系统Kubernetes已经成为了云时代容器编排的事实标准。对于DevOps工程师来说Kubernetes属于必学必会的技能这个趋势已经非常明显了。
在示例项目中我们同样用到了Kubernetes作为基础环境所有Jenkins任务的环境都通过Kubernetes来动态初始化生成。
这样做的好处非常多。一方面可以实现环境的标准化。所有环境配置都是以代码的形式写在Dockerfile中的实现了环境的统一可控。另一方面环境的资源利用率大大提升不再依托于宿主机自身的环境配置和资源大小你只需要告诉Kubernetes需要多少资源它就会帮助你找到合适的物理节点运行容器。资源的调度和分配统一通过Kubernetes完成这就进一步提升了资源的有效利用率。想要初始化一套完整的环境对于中小系统来说是分分钟就可以完成的事情。关于这一点我会在讲“云原生时代应用的平台建设”时跟你探讨。
那么,**想要实现动态初始化环境需要打通Jenkins和Kubernetes**。好在Jenkins已经提供了官方的[Kubernetes插件](https://plugins.jenkins.io/kubernetes)来完成这个功能。你可以在Jenkins系统配置中添加云 - Kubernetes然后再参考下图进行配置。
需要注意的是,**必须正确配置Jenkins的地址系统配置 - Jenkins Location否则会导致新建容器无法连接Jenkins。**
<img src="https://static001.geekbang.org/resource/image/b2/b0/b20afc90dc6736828c0f1bdab8fa9bb0.png" alt="">
生成动态节点时需要使用到JNLP协议我推荐你使用**Jenkins官方提供的镜像**。
JNLP协议的全称是Java Network Launch Protocol是一种通用的远程连接Java应用的协议方式。典型的使用场景就是在构建节点也就是习惯上的Slave节点上发起向Master节点的连接请求将构建节点主动挂载到Jenkins Master上供Master调度使用。**区别于使用SSH长连接的方式这种动态连接的协议特别适合于Kubernetes这类的动态节点**。镜像配置如下图所示:
<img src="https://static001.geekbang.org/resource/image/30/f5/307b1ab57a92f0359a0de3de09dff9f5.png" alt="">
在配置动态节点的时候,有几个要点你需要特别关注下。
1. ** 静态目录挂载**。由于每次生成一个全新的容器环境,所以就需要将代码缓存(比如.git目录、依赖缓存.m2, .gradle, .npm以及外部工具等静态数据通过volume的方式挂载到容器中以免每次重新下载时影响执行时间。
1. 如果你的Jenkins也是在Kubernetes中运行的注意**配置Jenkins的JNLP端口号**使用环境变量JENKINS_SLAVE_AGENT_PORT。否则在系统中配置的端口号是不会生效的。
1. 由于每次初始化容器有一定的时间损耗,所以你可以**配置一个等待时长**。这样一来,在任务运行结束后,环境还会保存一段时间。如果这个时候有新任务运行,就可以直接复用已有的容器环境,而无需重新生成。
1. **如果网络条件不好,可以适当地加大创建容器的超时时间**默认是100秒。如果在这个时间内无法完成容器创建那么Jenkins就会自动杀掉创建过程并重新尝试。
如果一切顺利动态Kubernetes环境就也可以使用了。这时我们就可以完整地运行一条流水线了。在设计流水线的时候你需要注意的是**流水线的分层**。具体的流水线步骤,我已经写在了系统架构图中。比如,提交阶段流水线需要完成拉取代码、编译打包、单元测试和代码质量分析四个步骤,对应的代码如下:
```
// pipeline 2.0 - Commit stage - front-end
pipeline {
agent {
// Kubernetes节点的标签
label 'pipeline-slave'
}
environment {
// 镜像仓库地址
HARBOR_HOST= '123.207.154.16'
IMAGE_NAME = &quot;front-end&quot;
REPO = 'front-end'
HOST_CODE_DIR = &quot;/home/jenkins-slave/workspace/${JOB_NAME}&quot;
GROUP = 'weaveworksdemos'
COMMIT = &quot;${currentBuild.id}&quot;
TAG = &quot;${currentBuild.id}&quot;
TEST_ENV_NAME = 'test'
STAGE_ENV_NAME = 'staging'
PROD_ENV_NAME = 'prod'
BUILD_USER = &quot;${BUILD_USER_ID}&quot;
// 需要挂载到容器中的静态数据
COMMON_VOLUME = ' -v /nfs/.m2:/root/.m2 -v /nfs/.sonar:/root/.sonar -v /nfs/.npm:/root/.npm '
}
stages {
stage('Checkout') {
steps {
git branch: 'xxx', credentialsId: '707ff66e-1bac-4918-9cb7-fb9c0c3a0946', url: 'http://1.1.1.1/shixuefeng/front-end.git'
}
}
stage('Prepare Test') {
steps {
sh '''
docker build -t ${IMAGE_NAME} -f test/Dockerfile .
docker run --rm -v ${HOST_CODE_DIR}:/usr/src/app ${IMAGE_NAME} /usr/local/bin/cnpm install
'''
}
}
stage('Code Quality') {
parallel {
stage('Unit Test') {
steps {
sh '''
docker run --rm -v ${HOST_CODE_DIR}:/usr/src/app ${IMAGE_NAME} /usr/local/bin/cnpm test
'''
}
}
stage('Static Scan') {
steps {
sh 'echo &quot;sonar.exclusions=node_modules/**&quot; &gt;&gt; sonar-project.properties'
script {
def scannerHome = tool 'SonarQubeScanner';
withSonarQubeEnv('DevOpsSonar') {
sh &quot;${scannerHome}/bin/sonar-scanner&quot;
updateGitlabCommitStatus name: 'build', state: 'success'
}
}
}
}
}
}
}
}
```
如果你按照刚刚我所介绍的步骤操作的话,你就会得到这样一张完整的流水线演示效果图:
<img src="https://static001.geekbang.org/resource/image/0f/b3/0f36a2ac9cfc8d5878ac7cf68dcc05b3.png" alt="" title="系统截图">
结合Jenkins自身的人工审批环节可以实现多环境的自动和手动部署构建一个真正的端到端持续交付流水线。
## 总结
在今天的课程中我通过一个开源流水线的解决方案给你介绍了如何建立一个开源工具为主的持续交付流水线平台。你应该也有感觉对于DevOps来说真正的难点不在于工具本身而在于如何基于整个研发流程将工具串联打通把它们结合在一起发挥出最大的优势。这些理念对于自建平台来说也同样适用你需要在实践中多加尝试才能在应用过程中游刃有余。
## 思考题
关于这套开源流水线解决方案,你对整体的工具链、配置、设计思路还有什么疑问吗?在实施过程中,你遇到了哪些绕不过去的问题呢?
欢迎在留言区写下你的思考和答案,我们一起讨论,共同学习进步。如果你觉得这篇文章对你有所帮助,也欢迎你把文章分享给你的朋友。

View File

@@ -0,0 +1,187 @@
<audio id="audio" title="28 | 迈向云端:云原生应用时代的平台思考" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/3b/df/3b0b613ee12ad5b836858e067a4cabdf.mp3"></audio>
你好,我是石雪峰。
最近几年,相信你一定从各种场合听到过“云原生”这个词。比如云原生应用的[12要素](https://12factor.net/zh_cn/)、最近大火的现象级技术Docker以及容器编排技术Kubernetes。其中Kubernetes背后的CNCF也就是云原生应用基金会也成了各大企业争相加入的组织。
DevOps似乎也一直跟云技术有着说不清的关系比如容器、微服务、不可变基础设施以及服务网格、声明式API等都是DevOps技术领域中的常客。云原生应用似乎天生就和DevOps是绝配自带高可用、易维护、高扩展、持续交付的光环。
那么所谓的云原生到底是什么意思呢我引用一下来自于CNCF的官方定义
>
<p>Cloud native computing uses an open source software stack to deploy applications as microservices, packaging each part into its own container, and dynamically orchestrating those containers to optimize resource utilization.<br>
云原生使用一种开源软件技术栈来部署微服务应用,将每个组件打包到它自己的容器中,并且通过动态编排来优化资源的利用率。</p>
我总结一下这里面的关键字:**开源软件、微服务应用、容器化部署和动态编排**。那么简单来说云原生应用就是将微服务风格的架构应用以容器化的方式部署在云平台上典型的是以Kubernetes为核心的云平台从而受益于云服务所带来的各种好处。
我在专栏中也反复强调过容器技术和Kubernetes是划时代的技术是每一个学习DevOps的工程师的必备技能。就像很多年前要人手一本《鸟哥的Linux私房菜》在学习Linux一样Kubernetes作为云时代的Linux同样值得你投入精力。
今天我并不是要跟你讲Kubernetes我想通过一个项目以及最近两年我的亲身经历给你分享一下云原生究竟会带给DevOps怎样的改变。这个项目就是Jenkins X。
在2018年初我分享过有关Jenkins X的文章在短短几天的时间内阅读量就过万了。这一方面体现了Jenkins在国内的巨大影响力另外一方面也凸显了Jenkins与这个时代的冲突和格格不入。为什么这么说呢因为Jenkins作为一个15年的老系统浑身上下充满了云原生的反模式 ,比如:
1. Jenkins是一个Java单体应用运行在JVM之上和其他典型的Java应用并没有什么区别
1. Jenkins使用文件存储以及各种加载模式、资源调度机制等确保了它天生不支持高可用
1. Jenkins虽然提供了流水线但是流水线依然是执行在主节点上这就意味着随着任务越来越多主节点消耗的资源也就越来越多不仅难以扩展还非常容易被随便一个不靠谱的任务搞挂掉。
举个最简单的例子如果一个任务输出了500MB的日志当你在Jenkins上点击查看全部日志的时候那就保佑自己的服务器能挺过去吧。因为很多时候服务器可能直接就死掉了。当然**我非常不建议你在生产环境做这个实验。**
那么如果想让Jenkins实现云原生化要怎么做呢有的同学可能会说“把Jenkins放到容器中然后丢给Kubernetes管理不就行了吗”如果你也是这么想的那就说明无论是对Kubernetes还是云原生应用你的理解还不够到位。我来给你列举下如果要把Jenkins改造为一个真正的云原生应用要解决哪些问题
1. 可插拔式的存储典型的像是S3、OSS
1. 外部制品管理
1. Credentials管理
1. Configuration管理
1. 测试报告和覆盖率报告管理
1. 日志管理
1. Jenkins Job
1. ……
你看我还只是列举了其中一部分以云原生应用12要素的标准来说要做的改造还有很多。
以日志为例当前Jenkins的所有日志都是写在Master节点上的如果想改造成云原生应用的方法首先就是要把日志看作一种输出流。输出流不应该由应用管理写在应用运行节点的本地而是应该由专门的日志服务来负责收集、分析、整理和展示。比如ElasticSearch、Fluent或者是AWS的CloudWatch Logs都可以实现这个功能。
那么Jenkins X是怎么解决这个问题的呢
我们来试想一个场景:当开发工程师想要开发一个云原生应用的时候,他需要做什么?
首先他需要有一套可以运行的Kubernetes环境。考虑到各种不可抗力因素这绝对不是一件简单的事情。尤其是在几年前如果有人能够通过二进制的方式完成Kubernetes集群的搭建和部署这一定是一件值得吹牛的事情。好在现在公司里面都有专人负责Kubernetes集群维护各大公有云厂商也都提供了这方面的支持。
现在,我们继续回到工程师的视角。
当他接到一个需求后他首先需要修改代码然后把代码编译打包在本地测试通过。接下来他要将代码提交到版本控制系统手动触发流水线任务并等待执行完毕。如果碰巧这次调整了编译命令他还要修改流水线配置文件。最后经过千辛万苦生成了一个镜像文件并把镜像文件推送到镜像服务器上。这还没完他还需要修改测试环境的Kubernetes资源配置调用kubectl命令完成应用的更新并等待部署完成。如果对于这次修改系统验证出了新的问题那么不好意思刚刚的这些步骤都需要重头来过。
你看虽然云原生应用有这么多好处但是大大提升了开发的复杂度。一个工程师必须要熟悉Kubernetes、流水线、镜像、打包、部署等一系列的环节和新技术新工具才有可能完成一次部署。如果这些操作都依赖于外部门或者其他人那你就且等着吧。这么看来这条路是走不下去的。
**在云时代,一切皆服务**。那么在云原生应用时代DevOps或持续交付理应也是以一种服务的形式存在。就好比你在用电的时候一定不会去考虑电厂是怎么运转的电是怎么送到家里来的你只要负责用就可以了。
那么我们来看看Jenkins X是怎么一步步地把Jenkins“干掉”的。其实我希望你能记得**是不是Jenkins X本身并不重要在这个过程中使用到的工具和技术以及它们背后的设计理念才是更重要的**。
## 1.自动化生成依赖的配置文件
对于一个云原生应用来说,除了源代码本身之外,还依赖于哪些配置文件呢?其中就包括:
- Dockerfile用于生成Docker镜像
- Jenkinsfile应用关联的流水线配置
- Helm Chart把应用打包并部署运行在Kubernetes上的资源文件
- Skaffold用于在Kubernetes中生成Docker image的工具
考虑到你可能不太熟悉这个Skaffold工具我简单介绍一下。
实际上,如果想在 Kubernetes 环境中生成Docker镜像你会发现一般来说这都依赖于Docker服务也就是Docker daemon。那么常见的做法无外乎Docker-in-Docker和Docker-outside-Docker。
其中Docker-in-Docker就是在基础镜像中提供内建的Docker daemon和镜像生成环境这依赖于官方镜像的支持。而Docker-outside-Docker比较好理解就是将宿主机的Docker daemon挂载到Docker镜像里面。
有三种典型的实现方式第一种是挂载节点的Docker daemon第二种就是使用云平台提供的外部服务比如Google Cloud Builder第三种就是使用无需Docker daemon也能打包的方案比如常见的Kaniko。
而Skaffold想要解决的就是你不需要再关心如何生成镜像、推送镜像和运行镜像它会通通帮你搞定依赖的就是skaffold.yaml文件。
这些文件如果让研发手动生成那会让研发的门槛变得非常高。好在你可以通过Draft工具来自动化这些操作。Draft是微软开源的一个工具它包含两个部分。
- 源代码分析器。它可以自动扫描你的源代码根据代码特征识别出你所用到的代码类型比如JavaScript、Python等。
- build pack。简单来说build pack就是一种语言对应的模板。通过在模板中定义好预设的环境依赖配置文件包括上面提到的Dockerfile、Jenkinsfile等从而实现依赖项的自动生成和创建。当然你也可以定义自己的build pack并作为模板在内部项目中使用。
很多时候模板都是一种特别好的思路它可以大大简化初始配置成本提升环境和服务的标准化程度。对于流水线来说也是如此毕竟不是很多人都是这方面的专家只要能针对90%的场景提供一组或几组最佳实践的模板就足够了。
这样一来,无论是已经存在的代码,还是权限初始化的项目,研发都不需要操心如何实现代码打包、生成镜像,以及部署的过程。这也会大大节省研发的精力。毕竟,就像我刚刚提到的,不是每个人都是容器和构建方面的专家。
## 2.自动化流水线过程
当应用初始化完成之后流水线应该是开箱即用的状态。也就是说比如项目采用的是特性分支加主干开发分支发布的策略那么build pack中就预置了针对每条分支的流水线配置文件。这些文件定义了每条分支需要经过的检查过程。
那么,当研发提交代码的时候,对应的流水线就会被自动触发。对于研发来说,这一切都是无感知的。只有在必要的时候(比如出现了问题),系统才会通知研发查看错误信息。这就要求**流水线的Jenkinsfile要自动生成版本控制系统和CI/CD系统也需要自动打通**。比如Webhook的注册和配置、MR的评审条件、自动过滤的分支信息等等都是需要自动化完成的。
这里所用到的技术主要有三点。
1. **流水线即代码**。毕竟,只有代码化的流水线配置才有可能自动化。
1. **流水线的抽象和复用**。以典型的Jenkinsfile为例大多数操作应该提取到公共库也就是shared library中而不应该hard code在流水线配置文件里面以提升抽象水平和能力复用。
1. **流水线的条件判断**。对于同一条流水线来说,根据不同的条件,可以实现不同的执行路径。
## 3.自动化多环境部署
对于传统应用来说尤其是对上下游依赖比较复杂的应用来说环境管理是个老大难的问题。Kubernetes的出现大大简化了这个过程。当然**前提是云原生应用部署在Kubernetes上时所有依赖都是环境中的资源**。
依靠Kubernetes强大的资源管理能力能够动态初始化出来一套环境是一种巨大的进步。
Jenkins X默认就提供了预发环境和生产环境。不仅如此对于每一次的代码提交所产生的PRJenkins X都会自动初始化一个预览环境出来并自动完成应用在预览环境的部署。这样一来每次代码评审的时候都能够打开预览环境查看应用的功能是否就绪。通过借助用户视角来验收这些功能也提升了最终交付的质量。
这里面所用到的技术除了之前我在第16讲中给你介绍过的GitOps主要就是**Prow工具**。
你可以把Prow看作ChatOps的一种具体实现。实际上它提供的是一种**高度扩展的Webhook时间处理能力**。比如,你可以通过对话的方式,输入 /approve 命令Prow接收到这个命令后就会触发对应的Webhook并实现流水线的自动执行以及一系列的后台操作。
## 4. 使用云原生流水线
在今年年初Jenkins X进行了一次全面的升级开始支持Tekton流水线。Tekton的前身是2018年初创建的KNative项目这是一个面向Kubernetes的Serverless解决方案。但随着这个项目边界的扩大它渐渐地把整个交付流程的编排都纳入了进来于是就成立了Tekton项目用来提供Kubernetes原生的流水线能力。
Tekton提供了最底层的能力Jenkins X提供了上层抽象也就是通过一个yaml文件的形式来描述整个交付过程。我给你分享了一个流水线配置文件的例子
```
agent:
label: jenkins-maven
container: maven
pipelines:
pullRequest:
build:
steps:
- sh: mvn versions:set -DnewVersion=$PREVIEW_VERSION
- sh: mvn install
release:
setVersion:
steps:
- sh: echo \$(jx-release-version) &gt; VERSION
comment: so we can retrieve the version in later steps
- sh: mvn versions:set -DnewVersion=\$(cat VERSION)
- sh: jx step tag --version \$(cat VERSION)
build:
steps:
- sh: mvn clean deploy
```
在这个例子中你可以看到流水线过程是通过yaml格式来描述的而不是通过我们之前所熟悉的groovy格式。另外在这个文件中你基本上也看不到Tekton中的资源类型比如Task、TaskRun等。
实际上Jenkins X基于Jenkins原有的流水线语法结构重新定义了一套基于yaml格式的语法。你依然可以使用以前的命令在yaml中完成整个流水线的定义但是在后台Jenkins X会将这个文件转换成Tekton需要使用的CRD资源并触发Kubernetes执行。
说白了用户看起来还是在使用Jenkins但实际上流水线的执行引擎已经从原来的JVM变成了现在Kubernetes。流水线的执行和调度由Kubernetes来完成整个过程中每一步的环境都是动态初始化生成的容器所有的数据都是通过外部存储来保存的。
经过这次升级终于实现了真正意义上的平台云原生化改造。关于这个全新的Jenkins流水线语法定义你可以参考下[官方文档](https://jenkins-x.io/docs/reference/pipeline-syntax-reference/)。
我再给你分享一幅Serverless Jenkins和Tekton的关系示意图希望可以帮助你更好地理解背后的实现机制。
<img src="https://static001.geekbang.org/resource/image/4c/8f/4cb1d827f29ca6d2a55f13ab9b60a58f.jpeg" alt="">
>
[https://dzone.com/articles/move-toward-next-generation-pipelines](https://dzone.com/articles/move-toward-next-generation-pipelines)
最终我们希望达到的目的就是不再有一个一直存在的Jenkins Master实例等待用户调用而是一种被称为是“Ephemeral Jenkins”的机制也就是一次性的Jenkins只有在需要的时候才会启动一个Master实例用完了就关闭掉从一种静态服务变成了一种转瞬即逝的动态服务也就是看似不在、又无处不在的形式以此来驱动云原生应用的CI/CD之旅。
讲到这里,我们回头再看看最开始的那个场景。对于享受了云原生流水线服务的工程师而言,他所需要关注的就只有把代码写好这一件事情,其他原本需要他操心的事情,都已经通过后台的自动化、模板化实现了。
即便是在本地开发调试你也完全可以利用Kubernetes提供的环境管理能力甚至在IDE里面只要保存代码就能完成从打包、镜像生成、推送、环境初始化和部署的完整过程。我相信这也是云原生工具赋能研发的终极追求。
## 总结
最近这两年经常有人问我Jenkins是不是过时了类似Argo、Drone等更轻量化的解决方案是否更加适合云原生应用的发展
其实社区的开发者也在问自己这样的问题而答案就是Jenkins X项目。这个项目整合了大量的开源工具和云原生解决方案其中包括
- 基于Kubernetes的云原生开发体验
- 自动化的CI/CD流程
- 多套预置的环境,并能够灵活初始化环境
- 使用GitOps在多环境之间进行部署晋级
- 云原生的流水线架构和面向用户的易用配置
- 可插接自定义的流水线执行引擎
我必须要承认,云原生带给平台的改变是巨大且深刻的。这两年,我一方面惊叹于社区的巨大活力和创新力,另一方面,我也深刻地意识到“未来已来”,这种变更的脚步越来越近。
在云原生时代,我们需要打造的也应该是一个自动化、服务化、高度扩展的平台。这也就是说,**用于打造云原生应用的平台自身也应该具备云原生应用的特征**,并通过平台最大化地赋能研发工程师,提升他们的生产力水平。
## 思考题
对于DevOps的落地推行来说建设工具仅仅是完成了第一步那么如何让工具发挥真正的威力并在团队中真正地进行推广落地呢你有哪些建议呢
欢迎在留言区写下你的思考和答案,我们一起讨论,共同学习进步。如果你觉得这篇文章对你有所帮助,也欢迎你把文章分享给你的朋友。

View File

@@ -0,0 +1,66 @@
<audio id="audio" title="开篇词 | 从默默无闻到风靡全球DevOps究竟有什么魔力" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/52/82/525f04574f139e662577f79b70e7ba82.mp3"></audio>
你好我是石雪峰目前在京东商城负责工程效率体系建设和平台研发。从业十多年我一直在软件行业深耕尤其是从2015年接触DevOps至今我一直在企业内部从事DevOps的落地实践工作也曾帮助多家大型企业进行DevOps的相关能力评估积累了很多实战经验。
在写开篇词的时候我才意识到DevOps从诞生至今已经整整十个年头了。十年之间DevOps从默默无闻到风靡全球很多人都在反思和总结DevOps究竟有什么魔力。
十年前的2009年我在一家日本软件公司工作长期被外派到日本尼康公司做项目。虽然当时敏捷已经兴起但在日本软件开发还是瀑布模式的天下。每当一个新项目来临时我们经常不分白天黑夜地埋头苦干几个月完全不敢想象如果不能顺利交付会怎么样。
可是,怕什么就来什么。有一次,我负责开发一款客户端软件,给客户交付的方式是事先刻录一张光盘,把光盘带去现场,一边部署,一边演示。刚开始还挺顺利的,可是到了生产数据拉取的环节,系统竟然异常退出了。我至今都还记得那位项目负责人不满的表情。
调试后我发现客户的生产环境使用的是Oracle数据库而我们使用的是微软的Access数据库数据访问协议不一致数据自然会同步失败。
之后的三个月,我总共休息了两天,每天的节奏就是吃饭睡觉写程序,干到搭乘最后一班电车回家,唯一的娱乐活动就是在吃加班餐的时候吐槽老板。
所以,当时我就在想,一定会有一种更好的软件开发方式,**在这种方式下,团队间沟通和协作的重要性一点也不亚于写代码、写文档、做测试之类的常规工作**。但我不知道的是远在大洋彼岸DevOps的旅程才刚刚开始。
十年后也就是2019年以移动互联网、云计算、微服务、大数据、人工智能等为代表的技术日新月异技术的迭代和演进都在以十倍速的方式向前发展数字化转型浪潮正在席卷各行各业。“软件正在吞噬世界”“每一家企业终将成为软件企业”……行业领袖口中的这些预言都在慢慢地变成现实。
如今,软件正在深刻地改变着我们的生活方式。前段时间,我去新疆旅行。在旅行途中,我发现即便是在沙漠边缘的小镇,微信支付也是畅通无阻。另外,用户喜新厌旧的成本已经低到可以忽略不计,企业之间的竞争已经升级为软件即服务的竞争。
所以,**如何快速地持续交付高质量的软件,满足用户的多样化需求,并借此提升企业的利润和市场占有率,已经成为企业必须要面对的现实问题**。
可问题是,现在很多企业采用的软件开发方式,同十年前我所在的公司其实并没有什么区别,甚至由于组织分工的细化,内部沟通的消耗成本更加高昂。
你应该也遇到过这样的场景吧两个部门为了数据打通来回拉锯各种方案和排期一天一个样还美其名曰“PK”。原本特别简单的一件事情非要扯上几天甚至几周才能有点眉目。每当这个时候我都忍不住想说“嘿兄弟我不是来抢你饭碗的我只是想通过系统间的打通来简化一些工作而已何必搞得这么复杂呢
所以你看,**软件开发过程的改进除了依赖于技术进步还依赖于流程、理念、文化等全方位的改进而这正是DevOps带给软件开发方式的一场革命**。
从2017年DevOpsDays大会北京站举办以来DevOps在国内的发展正式驶向了快车道。作为从业者之一我深刻地感受到DevOps的影响力与日剧增不仅仅是互联网行业就连传统的电信、金融甚至是政府机构也都把DevOps作为核心能力在快速建设。
现在已经很少有人会问DevOps有什么用、DevOps是否适合我之类的问题了更多人开始关注要如何落地实践DevOps并且让DevOps充分发挥它的价值真正改善软件交付方式提高IT工程师的幸福指数。
除此之外越来越多的企业开始招聘DevOps方面的人才对DevOps的技能和经验背景的要求越来越高DevOps专家的岗位薪资甚至仅次于高级管理层一跃成为IT行业的金字塔顶端。
我个人认为,**DevOps已经成为了所有IT从业人员应知应会的必备技能**。在这些技能中技术和实践当然非常重要但文化和理念更是尤为珍贵。如果每个从业者都认同DevOps的文化和理念认同快速交付价值远胜于部门间的零和博弈认同我们应该共享一个目标并从自身做起持续改善上下游的关系那么怎么可能还会出现刚刚我提到的PK的例子呢
也许你从各种渠道了解过DevOps的相关信息但是因为市场上资料庞杂、个人精力有限等原因还存在着以下几个困惑
- 如何梳理出一套清晰的DevOps理念和完整的知识体系
- 如何获得一线大厂的实践经验让DevOps真正落地
- 如何获得一条渐进式的DevOps学习曲线让自己在正确的方向上不断增值
这些问题,正是多年来我一直在思考的,也希望在这个专栏中传递给你的核心内容。
学习DevOps的过程对你来说将会是一场探索之旅。DevOps涉及软件开发的方方面面因此你将漫步于需求、开发、测试、运维的完整开发流程途经管理实践和工程实践的领域探寻方法论、最佳实践和工具平台的有机结合方式让自己在全栈工程师和斜杠青年的道路上更进一步。
DevOps涉及的领域如此之广想在一个专栏中学遍所有内容几乎是不可能的事情所以我从**实战**的角度出发臻选出最重要的内容帮你梳理出一条DevOps的最佳学习路径。
本专栏主要由4个部分组成。
- 第1部分是“基础知识篇”。我将详细介绍DevOps的定义、价值、实施与衡量在最开始帮你建立起正确的DevOps体系认知。
- 第2部分是“落地实践篇”。这一部分占据整个专栏一半的篇幅是最核心的部分。我将带你通盘梳理DevOps的转型路径你一定不要错过。
- 第3部分是“平台工具篇”。它涵盖平台建设的3个阶段、产品研发和设计、不可忽视的开源工具等帮你找到快速搭建平台的钥匙。
- 第4部分是“转型案例篇”。我将分享12个实际案例将前面提到的理论、落地实践和工具融入其中让你能够融会贯通。
另外我还设置了特别放送环节。在这个环节我会跟你分享一些经典的学习资料、DevOps工程师的必备技能等内容让你全方位、多层次地掌握DevOps。
<img src="https://static001.geekbang.org/resource/image/5e/bb/5e4f4b63da1b998f13acd7ae87b6a7bb.jpg" alt="">
其实整个专栏的整理和写作对我来说也是一场修行。毕竟作为DevOps多年的实践者我在用它解决问题的同时也发现了更多的问题好奇心和对效率建设的执着追求让我乐此不疲。现在能够静下心来把我多年的经验与反思整理出来跟你分享也是一件非常有意义的事情。
在这个过程中我也越发地感受到DevOps的思想和文化的落地依然任重道远。每个时代都会有一群先锋走在时代的前沿中流击水鹰击长空希望通过本专栏的学习**你也可以成为DevOps的思想者和实践者**,实现个人价值和企业价值的双赢。
最后我想请你聊一聊关于DevOps你都有哪些困惑对于专栏你又有哪些期待欢迎你写在留言区我们一起交流期待你的反馈。
好了从现在开始就让我们一起踏上这场DevOps的奇妙旅程一路同行不断进步。

View File

@@ -0,0 +1,192 @@
<audio id="audio" title="期中总结 | 3个典型问题答疑及如何高效学习" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/29/d5/293f08f27499d3e043b76c3e16b418d5.mp3"></audio>
你好,我是石雪峰。不知不觉中,专栏已经上线快两个月了,整体进度过半。我在专栏写作之初就给自己定下了一个小目标:**认真对待每一条留言**。到现在单单是回复留言我就已经写了3万多字了。
其实,对我来说,每一次看留言和回复留言,都是一个不断反思和学习的过程。实际上,很多时候,很多留言和讨论甚至比文章本身都更精彩,也更接地气。
今天是期中总结,我分为两个部分内容来讲:
- 第1部分我从众多留言中挑选了3个典型问题进一步展开讲解。
- 第2部分我想跟你说说心里话。两个月的高强度写作也让我从一个讲师的角度重新审视了“如何高效学习”这件事情我把这些想法分享给你希望可以帮助你更好地提升自己。
## 典型问题
首先,我们来看一些典型问题。
### 问题一
>
敏捷开发模式没有花费大量时间去研究业务,这会不会出现因为对业务没有分析透,导致方向偏离,甚至系统开发到一半发现总体业务架构不合理,需要返工的情况呢?
相信你也知道实施DevOps有助于产品快速和高质量的交付那么我想问的是快速和高质量的交付是否就一定意味着业务的成功呢显然没有这么简单。
实际上,影响业务成功的因素有很多,比如,行业趋势、产品竞争力、用户消费习惯、政策法律法规等等。在这众多因素之中,需求质量的高低,或者说,需求是否靠谱,也很重要。
毕竟,如果交付了一大堆没用的需求,不仅没法提升业务,反而还会浪费大量的时间和精力,错过真正有价值的机会。
我们身处在一个飞速变化的时代,企业对于用户想要什么其实并不清楚。很多需求都是人为拍脑袋拍出来的。在提出一个新需求的时候,需求价值到底有多少呢?这不仅很难预测,而且还很难衡量。
所以,产品人员就倾向于采用“广撒网”的方式,提出一大堆需求,来提升命中的几率。毕竟,如果一次猜不对,打不准,那就多打几次呗。
这么看来,采用敏捷开发方式,还是瀑布开发方式,与需求是否靠谱并没有直接关系。即便是采用瀑布模式,依然也有“大力出悲剧”的案例,比如摩托罗拉的铱星计划。
既然无法事先预测需求是否靠谱,那么要解决这个问题,就需要业务团队和交付团队的通力协作了。
**从业务侧来说,就是要采取精益创业的思想,通过最小可行产品,将需求进行拆解,通过原型产品降低市场的试错成本**。这就引出了我在[“业务敏捷”](https://time.geekbang.org/column/article/155791)这一讲中提到的**影响地图**、**卡诺模型**、**用户故事**等一系列的手段和方法,核心还是采用**持续迭代、小步快跑的方式**来获取市场反馈。正因为如此,更加灵活拥抱变化的敏捷开发模式才被广泛地接受。
说完了业务侧,再来看看交付侧。
一个想法被提出来以后,需要经过软件开发交付过程,才能最终交付到用户手中。那么,就要**用尽一切手段来缩短这条交付链路的时长**。
如果开发的时间成本是一定的那么剩余的部分就是DevOps中的各种工程实践试图要去解决的问题。
比如,通过持续集成来降低软件集成中的解决成本,降低软件缺陷在最后一刻被发现的修复成本;通过自动化测试,降低大量手工回归测试用例执行的成本,降低新功能导致已有功能出现回退的修复成本。软件交付过程中的其他部分也大都如此,这也是每个领域都会有自己的实践集合的原因。
反过来看,功能上线之后,依然需要交付侧提取、汇总和及时反馈业务指标,来证明需求的靠谱程度,从而帮助业务侧更加有序地进行决策。对反映不好的功能及时止损,对反映不错的功能加大投入。
这样一来,**业务侧的需求拆解、需求分析减小了需求颗粒度,提升了需求的靠谱度;交付侧的工程实践大大缩短了上线交付周期,提升了质量**。这就帮助业务在不增加成本的前提下可以验证更多的需求。这个过程的成本越低频率越高企业存活下来的几率和整体竞争力也会越高。这也正是DevOps想要解决的核心真问题。
### 问题二
>
公司对于配置管理的关注度不是很高,有没有什么好的落地实践方法,来建设完整的配置管理体系呢?
在专栏的[第10讲](https://time.geekbang.org/column/article/160477)我从4个核心原则出发介绍了配置管理的相关知识引起了很多同学的共鸣。
的确作为一个长期被忽视但是格外重要的实践配置管理不仅是诸多DevOps工程实践的基础也是工程能力的集大成者。
正因为如此,**配置管理体系的建设,并不只是做好配置管理就够了。实际上,这还依赖于其他工程实践的共同实施**。
关于配置管理怎么落地,我跟你分享一个案例。
这家公司最早也没有专职的配置管理,软件的集成和发布都是由研发团队自行管理的。推动建立配置管理体系的契机,源于公司决定加快版本发布节奏,从三周一个版本变成两周一个版本。看起来,这只是版本发布周期缩短了一周,但是,就像我在专栏[第4讲](https://time.geekbang.org/column/article/148878)中演示的部署引力图一样,想要达成这个目标,需要方方面面的努力,其中就包括配置管理。
于是,公司决定引入配置管理岗位。初期,他们重点就做两件事:
- 重新定义分支策略,从长分支改为了短分支加特性分支的模式;
- 管理集成权限,从任何时间都能集成代码,到按照版本周期管控集成。
在这个过程中,配置管理同学梳理了代码仓库的目录结构和存储方式,并基于开发流程建立了在线提测平台,从而实现了研发过程的线上化以及权限管理的自动化。
接下来,配置管理与平台和流程相结合,开发过程开始向前、向后延展。
- **向前**:在需求管理阶段,建立需求和代码的关联规范,严格约束代码提交检查,并且将构建工具和环境配置等纳入统一管控,可追溯历史变更;
- **向后**:在部署运维阶段,定义版本发布和上线规则,建立单一可信的发布渠道,可统一查询所有正式发布版本的信息,包括版本关联的需求信息、代码信息、测试信息等。
团队在走上有序开发的正轨之后,就针对发现的问题,逐步加强了平台和自动化能力的建设。
- 代码提交失控:做集成线上化,测试验收通过之后,自动合并代码;
- 环境差异大:通过容器化和服务端配置管理工具,实现统一的初始化;
- 构建速度慢:通过网络改造和增量编译等,提升构建速度。
这样一来,版本发布这件事情,从原本耗时耗力的操作,最终变成了一键式的操作,团队也达成了预期的双周发版的目标。
在这个案例中,配置管理更多是从流程和平台入手,通过规则制定、权限管控、统一信息源,以及版本控制手段,重塑了整个开发协作的交付过程。
所以,在把握原则的基础上,面对诸多实践,想要确定哪些实践可以解决实际问题,**最好是要从预期结果进行反推**。
如果你不知道该从哪里入手,不妨看看现在的软件交付流程是否是由配置管理来驱动的,是否还有一些数据是失控和混乱的状态,版本的信息是否还无法完整回溯。如果是的话,那么,这些都是大有可为的事情。
总之,**任何一家公司想要落地配置管理,都可以先从标准化到自动化,然后再到数据化和服务化**。这是一条相对通用的路径,也是实施配置管理的总体指南。
### 问题三
>
度量指标要如何跟组织和个人关联?这么多指标,到底该如何跟项目关联起来呢?
我在[第19讲](https://time.geekbang.org/column/article/169385)中介绍了正向度量的实践,引发了一个小高潮。文章发出后,有不少同学加我好友,并跟我深入沟通和探讨了度量建设的问题。由此可见,当前,企业的研发度量应该是一个大热门。
但是,度量这个事情吧,你越做就越会发现,这是个无底洞。那么,在最最开始,有没有可以用来指导实践的参考步骤呢?当然是有的。我总结了四个步骤:**找抓手、对大数、看差距、分级别。**
**第1步找抓手。**
对于度量体系建设来说,很多公司其实都大同小异。最开始的时候,核心都是需要有一个抓手来梳理整个研发过程。这个抓手,往往就是需求。因为,**只有需求是贯穿研发交付过程始终的,没有之一**。
当然,你也可以思考一下,除了需求,是否还有其他选项?那么,**围绕需求的核心指标,首先是需要提取的内容**。如果,连一个需求在交付周期内各个阶段的流转时长都没有,那么,这个度量就是不合格的。
**第2步对大数。**
对大数,也就是说,当度量系统按照指标定义,提取和运算出来指标数据之后,最重要的就是**验证数据的真实有效性,并且让团队认可这个客观数据**。
很多时候,如果公司里面没有一套权威指标,各个部门、系统就都会有自己的度量口径。如果是在没有共识的前提下讨论这个事情,基本也没什么意义。所以,说白了,一定要让团队认可这些大数的合理性。
**第3步找差距。**
抓手有了核心大数也有了大家也都承认这个度量数据的客观有效性了。但是在这个阶段肯定有些地方还是明显不合理。这个时候就需要对这个领域进一步进行拆分。比如测试周期在大的阶段里只是一个数字但实际上这里面包含了N多个过程比如功能测试、产品走查、埋点测试等等。
如果没有把表面问题,细分成各个步骤的实际情况,你就很难说清楚,到底是哪个步骤导致的问题。所以,**在达成共识的前提下,识别可改进的内容,这就是一个阶段性的胜利**。
**第4步分级别。**
**实际上,不是所有指标都可以关联到个人的**。比如,如果要计算个人的需求前置周期,这是不是感觉有点怪呢?同样,应用的上线崩溃率这种指标,也很难关联到一个具体的部门。
所以,**我们需要根据不同的视角和维度划分指标**。比如,可以划分组织级指标、团队级指标和项目级指标。
**划分指标的核心还是由大到小,从指标受众和试图解决的问题出发,进行层层拆解,从而直达问题的根本原因**,比如用户操作原因、数据计算原因、自动化平台原因等等。当然,这是一件非常细致的工作。
我们再来回顾下我们刚刚深入剖析了3个DevOps的典型问题。
首先你要非常清楚地知道DevOps在面对未知需求时的解题方法和解题套路那就是业务侧尽量拆解分析靠谱需求交付侧以最快、最低的成本完成交付。它们之间就是一个命运共同体一荣俱荣一损俱损。
配置管理作为DevOps的核心基础实践在实施的过程中并不只局限在单一领域。实际上要从研发流程优化的视角出发驱动标准化、自动化和数据可视化的能力建设。
最后,关于度量指标部分,你要注意的是,**向上,要支撑核心指标;向下,要层层分解,展示真实细节**。
讲解完这3个典型问题之后接下来进入第2部分这也是我极力要求增加的部分。其实我就是想跟你说说心里话。
## 如何高效学习?
跟你一样,我也是极客时间的用户,订阅了很多感兴趣的课程。在学习的过程中,我一直在思考,如何在有限的时间内高效学习。直到我自己成为了课程老师,从用户和老师两个角度思考这个问题,有了一些感悟,想要跟你分享一下。
忙,是现在大多数人的真实生活写照。我们每天从早到晚,忙于工作,忙于开会,忙于刷手机……忙得一塌糊涂。
但是,如果要问,过去的一天,自己都在忙什么,要么是大脑一片空白,要么是碎碎念式的流水账。可见,我们每天忙的很多事情,都没有什么价值。
其实,很多事情,都没有我们想象得那么重要。我们常常把目光聚焦于眼前,眼前的事情就变成了整个世界。但是,如果把时间拉长到一周,甚至一年,你会发现,这些事情,做与不做没有什么分别。
正因为时刻处于忙碌的状态,所以,抽出一整段时间学习,就变成了一件奢侈的事情。但我要祝贺你,因为至少你比大多数人有意识,有危机感,愿意拿出零碎的时间,来充实自己。
既然花了这么难得的时间,你肯定希望能有所收获,无论是在知识上,还是能力上,抑或是见识上,至少不白白浪费这段时间。
那么,我想问的是,你真的有收获吗?
史蒂芬·科维曾经说过,大多数人聆听的目的是为了“怼回去”,而不是为了真正的理解。
>
Most of people listen with the intent to reply, but not with the intent to understand.
这里面的“怼回去”稍微有点夸张,实际上,我发现,当我在交流的时候,脑海里总是不自觉地想象如何回复对方,而不是专心地听对方讲话,感悟他的意图和情绪。
所以你看,听这种学习方式,总是会受到固有思维模式的影响。也就是说,在很多时候,我们往往会把自己置身于一种评论者的身份。
那么,什么是评论者的身份呢?这就是说,**站在一种置身事外的立场,以一种审视的角度,来看待每一件事情,并试图找到一些问题。当然,这些问题,都是在已有的认知局限中发现的**。
这些反馈,对于知识的生产者而言,其实是一件好事,因为他能够时刻审视自己,反思自己,并从中找到不足之处。
但是,对学习者来说,能不能在学习的过程中,暂时放弃评论者的身份,转而做一个实践者呢?
比如,以极客时间的专栏为例,对于作者提到的内容,你有哪些不同的观点呢?面对同样的问题,你又有哪些更好的手段呢?
其实,每一个作者之所以能成为作者,都有他的独到之处。那么,**能够让他的思想为你所用,让他的知识与你互补,让你自己成为交流的赢家,这才是对得起时间的更好选择**。
最后,以极客时间的专栏为例,我认为:
- 60分的体验就是可以看完所有的文稿而不是仅仅听完课程音频
- 70分的体验就是可以仔细学习文稿中的附加资源比如代码、流程图以及补充的学习信息等。这些都是精选的内容可以帮助你在15分钟之外扩充自己的知识面
- 80分的体验就是可以积极参与到专栏的留言和讨论中甚至可以就自己的问题跟作者深入交流建立连接
- 90分的体验就是可以结合工作中的实际场景给出自己的思考和答案并积累出自己的一整套知识体系并且可以反向输出给其他人
- 100分的体验就是持续改进。我想能够具备这种思想可能要比100分本身更重要。
那么,你想做到多少分的体验呢?你可以自己想一想。
好了,接下来,我们即将进入“工具实践篇”,希望你可以继续保持学习的热情,坚持下去,期待美好的事情自然发生。
## 思考题
对于前面已经更新的内容,你还有什么疑惑点吗?或者说,你在实践的过程中,有什么问题吗?
欢迎在留言区写下你的思考和答案,我们一起讨论,共同学习进步。如果你觉得这篇文章对你有所帮助,也欢迎你把文章分享给你的朋友。

View File

@@ -0,0 +1,145 @@
<audio id="audio" title="期末总结 | 在云时代,如何选择一款合适的流水线工具?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/5f/0f/5f53af4f60aaf9bb462535db0d3f980f.mp3"></audio>
你好,我是石雪峰。今天是期末总结,我们来聊一聊,在云时代,如何选择一款合适的流水线工具。
在过去的几年里,我一直专注于软件持续交付的工程实践领域。我发现,越来越多的公司(无论规模大小)开始重视软件持续交付能力的建设了,基本上每家公司都有自己的流水线平台。
以前提到CI/CD工具基本上就默认是Jenkins也没什么其他太好的选项。但是最近两年随着云容器技术的快速发展在CI/CD流水线领域新工具和解决方案出现了爆发式的增长。比如不甘寂寞的GitLab CI、轻量级的容器化解决方案Drone。最近一段时间GitHub的Actions也火了一把。可见作为软件交付主路径上的核心工具**流水线**是每一家企业都不愿意错过的领域。
对于行业发展来说这当然是好事情。老牌工具Jenkins自己都开始反省“在云容器时代是不是过于保守十几年的老架构是否已经难以支撑云时代的快速发展了”于是他们就另辟蹊径孵化出了Jenkins X项目。
但是,对于用户来说,选择工具时就很为难:“这些工具看起来大同小异,要解决的也是类似的问题,到底应该选择哪个呢?”
今天我就来给你梳理一下流行的CI/CD工具并给你提供一些选择建议。我挑选了5个工具分为3组介绍分别是Jenkins系的Jenkins和Jenkins X、版本控制系统系的GitLab CI和GitHub Actions以及新兴的、正在快速普及的云原生解决方案Drone。我会从5个方面入手对它们进行对比和介绍包括工具的易用性、流水线设计、插件生态、扩展性配置以及适用场景。
## Jenkins/Jenkins X
关于Jenkins我想已经不需要做太多介绍了。在过去的15年里面Jenkins一直都在为无数的软件开发者默默服务。从一组数字中我们就能看出来它的影响力官方能统计到的集群数有26万多个、插件将近1700个、执行的任务数超过3000万次这还不包括大量公司自建、本地电脑运行的节点信息。另外一年两次的Jenkins全球大会往往能够吸引上千人参与这对于国外的技术大会来说已经是超大规模的盛会了。
当然Jenkins的优缺点也很明显。
- 优点:普及率高,搞过开发的基本应该都接触过;插件生态成熟且丰富,可以适用于任何场景。
- 缺点软件架构和UI设计风格有些过时配置操作比较复杂插件的安全性、通用性方面也存在很多问题最重要的是在云容器领域多少有些格格不入。
我重点说说Jenkins X。很多人都不清楚Jenkins和Jenkins X是什么关系这就好比刚开始我们很难说清楚Java和JavaScript的关系一样。实际上JavaScript除了名字上带有“Java”字眼蹭了个热度之外本质上它们之间并没有什么关系。而对于Jenkins和Jenkins X来说虽然并不能说二者一点关系没有但其实它们面对的场景和要解决的问题是不同的。所以并不能说Jenkins X就是下一代Jenkins或者是Jenkins迟早会迁移到Jenkins X上面。
Jenkins X最开始的确是作为Jenkins的子项目存在的但是发展到现在它已经有了独立的品牌和Logo并且和Jenkins一起作为CDF持续交付基金会的初始项目。Jenkins X想要解决的核心问题是**Kubernetes上的原生CI/CD解决方案**。所以Jenkins X和Kubernetes是强绑定的关系**它致力于通过一系列的自动化工具和最佳实践来降低云原生环境下的研发配置和使用CI/CD的成本并尽可能地做成开箱即用的状态**。
而Jenkins更像一个百宝箱你可以通过插件扩展来解决各种各样的问题并没有一定之规。
我给你举个例子来形象地对比一下Jenkins和Jenkins X这两个项目。
Jenkins就好比你在开车你知道目的地但是走哪条路开多快中间要不要休息一下什么时候加油这些都是你自己来决定的。当然灵活性带来的就是多变性你并不知道是不是下一秒就封路了或者是汽车突然坏了。
而Jenkins X更像是一辆高速列车你只要上对了车列车会把你安全、快速地送往目的地而你并不需要关心这个车是怎么设计的时速应该是多少甚至你在哪里能够下车它都规定好了。
Jenkins X项目中内建了大量的开源工具和解决方案可以说是开源工具的理想国和试验田核心目的就是为了简单、快速、开箱即用。比如对Tekton的集成就被视为对Jenkins自身的颠覆因为这彻底改变了Jenkins流水线调度机制。因为在Jenkins X看来Jenkins只不过是Jenkins X中的一个应用是一个黑盒子编排通过Tekton来实现换句话说即便你想用其他应用来取代Jenkins也不是不可能的。
值得注意的是Jenkins X中有很多约束比如你必须使用GitOps的方案来完成应用的晋级和部署没有其他的选择。**如果你没有使用Helm管理应用也不想使用GitOps那就现阶段来说Jenkins X对你就不是一个可选项**。
我们来总结一下Jenkins X项目
- **工具的易用性**采用了开箱即用的设计提供大量的模板来降低新应用上手CI/CD的成本。虽然安装复杂但是目前已经提供了JX Boot工具通过初始化向导帮你完成环境搭建。而且随着云服务商的引入环境方面应该都是可以默认提供的就像你不需要操心如何搭建Kubernetes一样因为会有人以服务的形式把Jenkins X提供出来。
- **流水线设计**Tekton取代了Jenkins成为了流水线的默认引擎作为Kubernetes的原生解决方案这也是未来的发展趋势。在编排方面它采用了yaml方式继承了原有Jenkinsfile的语法特征并对Tekton的资源进行隐藏和抽象通过描述式的语言以代码化的方式实现可以说是当前的通用解决方案。不过它目前并没有提供可视化的编排界面。
- **插件生态**继承了Jenkins丰富的插件生态以及庞大的开发者社区。
- **扩展性配置**采用容器化的解决方案对于Tekton来说更是如此。每个步骤都在容器中完成可扩展性非常强。
- **适用场景**我认为Jenkins X项目现在还处于快速开发的阶段适用于原型产品验证。对于那些没有固有模式想要沿用Jenkins X的设计流程的项目来说可以尝试使用。不过由于云服务商的接入度不足目前应该还存在很多挑战你可以保持学习和跟进。毕竟这个项目中的很多工具和设计思路都是非常有价值的。
<img src="https://static001.geekbang.org/resource/image/79/4f/79f9d1264ef1881af524afd9c9cc0c4f.png" alt="">
## GitLab CI/GitHub Actions
除了Jenkins国内使用比较多的应该当属GitLab CI了。前些年也有过社区的讨论到底应该使用GitLab CI还是Jenkins很显然这样的讨论并不能达成共识毕竟“萝卜白菜各有所爱”。而GitHub Actions的推出也是看中了流水线编排领域的“蛋糕”。曾经GitHub和TravisCI是珠联璧合可以说是“开源双碧”。GitHub也一再强调**自己只想把代码托管服务做到极致,其他领域都交给合作伙伴完成**。但是今天的Package功能和Actions功能都体现出了GitHub自建生态的野心。
其实,这两个产品有很多相似之处,因为它们都是依托于一个成熟的代码托管平台衍生出来的原生流水线功能。
对于软件开发而言,最重要的无疑就是源代码。之前,我有个同事就说过,只要掌握了源代码,你就可以为所欲为了。比如,基于代码拓展代码评审工具、内建各类静态动态代码检查功能、增加包管理和依赖管理工具等,这些是代码编译之前和编译之后的必备功能。增加内建的持续集成功能,也有助于在代码评审的时候做到机器辅助。
当这些功能都集成到代码托管系统中时你就会发现它不再是一个简单的版本控制系统了而是一整套DevOps平台。它们的设计理念是一个平台解决所有DevOps的工具问题。这一点在GitLab的路线图规划中也体现得淋漓尽致GitLab对主流工具都进行了对比并提供了一个工具的全景图。可以说在行业对标方面GitLab是做到极致了。你可以参考一下下面这张全景图和他们自己写的对比[文章](https://about.gitlab.com/blog/2018/09/03/how-gitlab-ci-compares-with-the-three-variants-of-jenkins/)。
<img src="https://static001.geekbang.org/resource/image/58/bc/58c8f850329b90378e6f9ee3a8eb15bc.png" alt="">
>
图片来源:[https://about.gitlab.com/devops-tools/](https://about.gitlab.com/devops-tools/)
回到流水线方面GitLab CI和GitHub Actions都和版本控制系统进行了深度集成。我们还是从五个方面来整体看一下。
**1.工具的易用性**
- **易于上手**由于是内建功能GitLab CI/GitHub Actions使用起来都非常简单你并不需要单独构建和维护一个独立的CI服务器来实现这个功能。
- **原生体验**由于是原生功能所以无论是在流水线状态展示方面还是在代码评审流程的集成方面它们都做到了原生化的体验显示的信息和丰富程度是外部独立的CI工具所无法比拟的。
- **一体化协同平台**工具链繁多、集成配置复杂、信息分散都是DevOps工具方面的痛点问题。而一体化的研发协同平台的价值就在于能够集中解决这些问题。开发者不需要在各种工具系统中跳来跳去可以在一个地方解决所有问题在一个地方看到所有有用的数据。
- **在线文档**GitLab的文档和示例都非常丰富GitHub就相对薄弱一些不过两者的文档基本都够用。
**2.流水线设计**
- **流水线描述**GitLab CI和GitHub Actions都采用了yaml形式的流水线过程描述文件二者的语法规则虽然不同但基本上大同小异。但相对来说GitHub的语法规则更加符合当前Kubernetes的资源描述风格。关于这两个产品的语法风格你可以看下这两份资料[GitHub Actions](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/workflow-syntax-for-github-actions)[GitLab CI](https://docs.gitlab.com/ee/ci/yaml/)
- **流水线编辑**两个产品都支持在线编辑流水线文件GitHub在这方面更加人性化一些。当你打开Actions的时候系统会给你推荐一些模板你可以直接选择生成Actions配置。如果想自己编辑Actions文件的话系统的右侧也提供了很多示例代码片段让你可以通过简单的复制、粘贴完成这项工作。另外GitHub新版本提供了在线的可视化编辑器毕竟GitHub Actions是全新设计的集合了各方面的优势。
**3.插件生态**
- **GitLab生态**作为一个开源软件GitLab的优势也恰恰在于开源官方对于社区PR和feature的响应也是非常及时的。但是由于GitLab是基于Ruby语言、Rails框架开发的这个语言就成了比较大的瓶颈毕竟熟练掌握Ruby语言的国内开发者相对还是比较少的所以GitLab的插件生态并没有做起来。
- **GitHub生态**GitHub有建设Marketplace的长期经验再加上开源贡献者众多所以在短短一年左右的时间里他们已经积累了1700多个Actions组件可以帮助你快速地搭建自己的流水线。从扩展性和生态丰富性方面来说GitHub更胜一筹。
- **使用成本**必须要强调的是GitHub是商业软件虽然对待开源项目采用免费策略**但是如果企业级使用的话,成本也是必须要考虑的因素之一**而自建GitLab如果采用社区版本就没有这么多限制了这也是优势之一。
**4.扩展性配置**
它们都支持多种环境类型。GitLab很早就提供了对容器和Kubernetes的支持GitHub在这方面自然也不会落后官方提供了Linux、Windows和Mac环境的支持你也可以自建节点并注册到GitHub中。不过必须强调一点GitHub如果是非企业版本的话是不支持私有化部署的这也就意味着如果你想把企业内部的资源注册到GitHub上那么就意味着这些资源必须对外可见。
**5.适用场景**
由于国内GitLab自建服务的普及如果你对CI的功能要求没有那么高那么GitLab CI就足够了。但是在功能广度方面由于缺少庞大的插件生态很多功能还是更多地依赖于你自己实现所以如果软件交付流程非常复杂依赖于多种环境GitLab CI就不是那么适用了。
而GitHub在企业中的使用场景就更加有限了一方面是成本问题另一方面SaaS化服务依赖于内部开放性。所以如果是开源项目或者创业项目不希望自己维护一套很重的研发基础设施那么我建议你考虑使用GitHub的方案。
在最新发布的2019年Forrester的趋势报告中GitLab和Jenkisn都入选了云原生CI工具的榜单并且处于行业领先地位你可以看一下报告的图片。虽然图中没有写明Jenkins但是其背后的CloudBees公司以及目前在云原生项目Jenkins X中有深度合作的Google公司都处于领先地位由此可以看出各大公司都已经开始在云原生领域布局了。
<img src="https://static001.geekbang.org/resource/image/16/6f/16ce91c79b1de82c33119c3e8964ee6f.png" alt="">
## Drone
这也是一个近来冉冉升起的CI工具领域的新星。在咱们专栏的留言中有很多同学提到过这个工具可见**好工具是会自己说话的**。
Drone主打的就是云原生CI整体设计非常轻量级即便没有什么经验一两天也能快速上手搭建。在我看来Jenkins X虽然也是主打云原生但由于引入了大量组件和流程约束整体还是略显笨重一些。相反Drone的实现非常优雅无论是流水线的语法还是环境的扩展性方面都让人不由得赞叹。
作为一个开源软件Drone使用Go语言实现。在我看来Go就是为云原生而存在的无论是Docker、Kubernetes还是我参与的Jenkins X项目都是通过Go语言来实现的。所以这个项目对于内部开发团队快速提升Go语言的DevOps平台建设能力也是一个很好的参考学习案例。
对于Drone平台我目前也在学习和探索阶段我从下面这几个方面谈谈我个人的看法。
**1.工具的易用性**
Drone的搭建非常简单你可以采用自建服务的形式也可以使用SaaS服务。UI风格设计体现了恰到好处的理念整体非常清爽同时也能跟其他工具如GitHub进行集成。
**2.流水线设计**
作为云原生的解决方案流水线同样采用yaml形式、具备描述式表达和流水线即代码的功能。虽然没有过于复杂的语法但是Drone的流水线语法风格是我个人最喜欢的它的结构非常清晰。
**3.插件生态**
Drone也提供了插件机制而且官方还提供了对主流版本控制系统和云服务商的集成支持。虽然数量远远比不上Jenkins生态但是你能想到的基本都有了。比如常见的Artifactory、SonarQube、Ansible等工具甚至还包含了对微信、钉钉这类国内流行的通讯软件的集成。由于它的开放特性未来它也会提供更多的插件。
**4.扩展性配置**
对于Drone来说最大的特征就是容器优先。上面提到的这些工具虽然都支持容器但是并没有把容器作为默认支持的第一选项。而在Drone中容器则是标配这也是典型的云原生CI工具的特征**一切都在容器中运行**。也正因为如此非容器化开发部署的项目如果采用Drone就不太合适了。另外除了容器方式之外Drone也支持本地执行这为一些特殊的场景提供了可能性比如绑定设备的自动化测试等
**5.适用场景**
我认为,**Drone在云原生CI/CD方面的设计代表了未来的趋势**。对于基于容器开发交付的产品来说如果你在寻找一个对应的云原生解决方案那么我推荐你用Drone。它也比较适合于中小型团队、初创公司想要快速受益于CI/CD又不想投入太多精力的场景。同时作为一款Go语言开发的开源软件随着业务扩展你大可以自建插件满足差异化的需求。
## 总结
最后,为了方便你理解和进行对比学习,我把这五个云原生流水线工具的特征汇总了图片里。
<img src="https://static001.geekbang.org/resource/image/e8/b3/e8a17696ad63fe145a6d258069ab2bb3.jpg" alt="">
到此为止,这几款主流的流水线工具,我就介绍完了。在文章的最后,我还想再补充两点:
1. **工具并非决定性的因素**不要轻易陷入“工具决定论”的思想之中就好比真正的编程高手可能都不需要IDE选择好的工具并不代表就有好的结果。
1. 工具是“存在即合理”的,它们都有各自擅长的领域,**没有绝对意义上的最好,只有最适合的场景**。另外即便是同一个工具在不同的人手中发挥的作用也不一样选择自己最熟悉的工具一般都不会有错。比如你要问我选择什么工具的话我肯定推荐Jenkins。但这并不是因为Jenkins完美无缺而仅仅是因为我用得顺手而已。
## 思考题
对于Drone这款工具在生产环境的应用你有哪些实际的经验又踩过哪些“坑”呢
欢迎在留言区写下你的思考和答案,我们一起讨论,共同学习进步。如果你觉得这篇文章对你有所帮助,也欢迎你把文章分享给你的朋友。

View File

@@ -0,0 +1,127 @@
<audio id="audio" title="特别放送(一)| 成为DevOps工程师的必备技能" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/f3/b0/f355c5af97c63158c38fb57b222031b0.mp3"></audio>
你好我是石雪峰今天到了“特别放送”环节。有很多留言问道“DevOps专家这个岗位需要的技能和技术栈有哪些成长路径是怎样的呢
我相信这应该是很多刚开始接触DevOps的同学最关心的问题。毕竟从实用的角度出发每个人都希望能够尽快上手实践。所以今天我来跟你聊聊我认为的DevOps工程师的必备技能以及学习路径。不过在此之前我们要先了解DevOps工程师的岗位职责。
全球最大职业社交网站LinkedIn领英2018年发布的一份[报告](https://business.linkedin.com/content/dam/me/business/en-us/talent-solutions/cx/2018/pdf/33-most-recruited-jobs.pdf)显示,当今全球最热门的招聘职位分别是**DevOps工程师、企业客户经理和前端开发工程师**。其中排名第一的就是DevOps工程师。
无独有偶2019年全球最大知识共享平台Stack Overflow的[开发者调查报告](https://insights.stackoverflow.com/survey/2019)显示在薪资排行榜上DevOps工程师排名第三仅次于技术经理和SRE网站可靠性工程师。而在去年的调查报告中DevOps工程师的收入甚至排名第二。
无论是人才市场需求还是收入薪资水平这种种迹象都表明DevOps工程师已经成为了当今最炙手可热的岗位收入也攀升至IT行业的金字塔顶端。难怪有越来越多的人开始接触和学习DevOps。
但是DevOps这样一个刚刚诞生10年的“新兴事物”并不像一门专业技术那样有一条相对清晰的学习路径以及经典的学习资料比如你要学习Java就可以从《Java编程思想》看起。
除此之外DevOps似乎又跟软件工程的方方面面有着说不清的关系。我跟你分享一幅DevOps技能发展路线图根据这幅路线图你要从编程语言入手理解操作系统原理、系统性能、网络安全、基础设施即代码、CI/CD、运维监控和云技术等等。
<img src="https://static001.geekbang.org/resource/image/df/b3/df028795541ad1758d13004acd68fcb3.png" alt="">
>
图片来源:[https://roadmap.sh/devops](https://roadmap.sh/devops)
怎么样是不是看到这么一堆名词就瞬间头大了吧如果要把这些所有的技术全部精通那至少得是CTO级别的岗位。对普通人来说这并不太现实。毕竟**啥都懂点儿但是啥都不精通本身就是IT从业者在职业发展道路上的大忌**。
如果要说清楚这个岗位核心就是要回答3个问题
1. DevOps工程师在公司内承担的主要职责是什么
1. 为了更好地承担这种职责,需要哪些核心技能?尤其是从我接触过的这些公司来看,有哪些技能是当前最为紧俏的呢?
1. 学习和掌握这些技能,是否存在一条可参考的路径呢?
接下来,我们就重点聊一聊这些内容。
## DevOps工程师的岗位职责
关于DevOps工程师这个岗位一直以来都存在着很大的争议。很多人认为DevOps应该是一种文化或者实践而不应该成为一个全新的职位或者部门因为这样会增加公司内部的协作壁垒。
其实我倒觉得没有必要纠结于这个Title因为很多时候DevOps跟公司内部已有的角色存在着重叠。比如开发变成了DevOps开发运维变成了DevOps运维。另外在不同的公司里面类似角色的岗位名称也大不相同。比如在DevOps状态报告中DevOps就和SRE被归为一类进行统计。而在公司中实际负责推行DevOps的部门至少我见过的就有工程效能团队、运维团队、配管团队甚至还有项目管理团队。可见不同公司对于DevOps工程师的职责定义也同样存在着差异。
但不管怎样我觉得谈到DevOps工程师职责的时候除了本职工作的内容以外至少还应该额外关注3个方面
**1.工具平台开发**
关于工具平台开发争议应该是最小的而且这也是很多公司推行DevOps的起点。**因为工具是自动化的载体而自动化可以说是DevOps的灵魂**。随着公司规模越来越大,研发内部的协作成本也随之水涨船高,那么工具平台的能力水平就决定了公司交付能力的上限。
但问题是,因为种种原因,很多公司只有大大小小的分散工具,并没有一套完整的研发协同工作平台,这本身就制约了协作效率的提升。你可以想象一下,研发每天要在大大小小的系统里面“跳来跳去”,很多功能甚至还是重复的,这显然是很浪费时间的。
比如你明明已经在代码托管平台上做了代码评审结果提测平台上面还有个必填项是“你是否做过了评审”是不是很让人抓狂呢这背后的主要原因就是缺乏顶层设计或者压根就没有专人或者团队负责这个事情。这样一来团队各自为战发现一个痛点就开发一个工具发现一个场景就引入一个系统再加上考核指标偏爱从0到1的创造性工作也难怪每个高T升级都要有自己的系统加持了。但如果任由这种趋势发展下去内部的重复建设就难以避免了。
所以对于DevOps工程师而言除了要关注原有的工具重构、新功能的开发之外更要聚焦于整个软件交付流程将现有的工具全面打通以实现可控的全流程自动化。也就是说不仅仅要追求点状的工具还要包括整条线上的工具链从而形成覆盖软件交付完整流程的工具体系。
另外工具平台同样是标准化流程的载体同时也是DevOps实践的载体所以在设计实现时需要考虑这些实践的支持。举个例子在配置管理领域将一切纳入版本控制是不二法则。那么在建设工具平台的时候就需要始终有这样的意识比如记录流水线的每一次配置变更的版本并且能够支持快速的对比回溯。
**2.流程实践落地**
其次,无论是工具平台的推广落地,还是结合平台的流程改进,都需要有人来做。毕竟,即便是完全相同的工具,在不同人的手里,发挥的作用也千差万别,把好好的敏捷管理工具用成了瀑布模式的人也不是少数。而针对流程本身的优化,也是提升协作效率的有效手段。
比如在有的公司里,单元测试需要手动执行,那么当工具平台具备自动化执行的能力,并且能够输出相应的报告时,这部分的操作流程就应该线上化完成。再比如,以往申请环境需要走严格的线上审批流程,当环境实现自动化管理之后,这些流程都可以变为自服务,通过工具平台进行跨领域角色的交叉赋能,从而实现流程优化的目标。
另外我接触过的一些公司倾向于在不改变流程的前提下推动DevOps落地。坦率地说这种想法是不现实的。如果流程上没有约束开发和测试共同为结果负责那开发为什么要跟测试共同承担责任呢出了问题又怎么可能不扯皮呢因此**如果你在公司内部负责流程改进,遇到问题就应该多问几个为什么,找到问题的本源,然后将流程和工具相结合,双管齐下地进行改进。**
所以,**理念和实践的宣导内部员工的培训持续探索和发现流程的潜在优化点这些也都是DevOps工程师要考虑的事情**。
**3.技术预研试点**
最后,各种新技术新工具层出不穷,哪些适用于公司现有的业务,哪些是个大坑呢?如果适合的话,要如何结合公司的实际情况,评估潜在的工具和解决方案,而不是盲目地跟随业界最佳实践呢?类似技术债务的识别和偿还这种重要不紧急的事情,到底什么时候做合适呢?
另外,如果公司决定开始推行单元测试,那么,选用什么样的框架,制定什么样的标准,选择什么样的指标,如何循序渐进地推进呢?这些同样非常考验团队的功底。如果步子一下子跨得太大了,到最后就可能成为形式主义了。
你可能会觉得我就是一个小开发、小运维怎么能推动这么大的事情呢但实际上DevOps从来都不是某一个人或者某一个角色的职责而是整个研发交付团队所共享的职责。在你力所能及的范围内比如在你所在的部门内部开展DevOps的理念宣导和技术培训鼓动领导参加行业的大会在和上下游团队协作的时候向前一步这些都是DevOps所倡导的自服务团队应该具备的能力。
## DevOps工程师的主要技能
说完了DevOps工程师主要负责的事情接下来我们就来看看DevOps工程师所要具备的能力。我从实用的角度出发总结了DevOps工程师的核心能力模型。
其中,**能力模型分为两个方面:专业能力和通用能力**。专业能力也就是常说的硬实力是IT从业人员身上的特有能力比如软件工程师会写代码就跟导演会拍电影司机会开车一样。而通用能力更加接近于软实力这些能力并不局限于某一个岗位或者职业是所有人都应该努力培养的能力。很多时候当硬实力到达天花板之后软实力的差异将决定一个人未来的高度这一点非常重要。
### 软实力
我们今天先从软实力说起。在讲具体的软实力之前,我先跟你分享一个小故事。
我在国外听过这样一种说法在企业中印度裔的工程师往往比华裔工程师的岗位职级要高。为什么会这样呢我曾经做过一个跨中美印三地的工程团队的负责人我发现每次我跟印度工程师交代一个事情他们总能又快又好地做出一个特别清晰漂亮的PPT。我特意问过他们是怎么做到的。原来他们在上学时受过这方面的训练还专门练习过表达、演讲等技能可见事出必有因软实力对个人的发展至关重要。
那么作为一名DevOps工程师需要具备什么软实力呢
**1.沟通能力**
DevOps倡导的核心理念就是沟通和协作所以难怪沟通能力会排在软实力的第一名。
**在推动DevOps落地的过程中你需要同时具备向上沟通、向下沟通和横向沟通的能力**。提炼DevOps实施框架和落地价值寻求领导层的支持需要**向上沟通**;打破组织间的边界,建立跨团队的协同,需要**横向沟通**;引导团队快速完善平台工具能力,表明工作的意义和价值,提升大家的主动性,需要**向下沟通**。所以你看,其实每天的工作中都充满了大量的沟通。
需要注意的是,**沟通能力不仅限于语言能力,很多时候,开发运维的沟通是基于代码完成的**。所以,良好的注释风格、清晰结构化的描述方式……这些细节往往也能提升沟通的效率。
比如有一种很DevOps的方式就是ChatOps是以GitHub的Hubot为代表的对话式运维慢慢扩展为人机交互的一种形式。通过建立一种通用的沟通语言打破开发和运维之间的隔阂。
**2.同理心**
DevOps希望团队可以共享目标共担责任但是实际上哪个团队不想更加自动化、更加高效地工作呢所以DevOps工程师要能够站在对方的角度来看问题设身处地地想想他们的困难是什么我能做些什么来帮助他们。这种同理心也是弥合团队分歧建立良好的协作文化所必需的能力。
除此之外,**培养团队以用户为中心的思想,也是很好的方式**。这里的用户,不是外部用户,而是在交付流程中存在交付关系的上下游部门。在交付一个版本的时候,要尽力做到最好,而不是不管三七二十一,先丢过去再说。
我还是要再强调一下,**同理心只有在流程和机制的保证之下才能生根发芽**。
**3.学习能力**
DevOps工程师需要了解的东西真得很多因此能够在有限的时间里快速学习新的技能并且有意愿主动地改进提升也是一种能力。
在DevOps工程师的眼里从来没有“完美”二字。比如完美的流程、完美的技术实现、完美的软件架构等。他们似乎天生就有一种能力那就是能发现问题并时刻想着可以做到更好。但实际上如果没有日积月累的思考没有外部优秀实践的学习没有开放的沟通和交流是没有办法知道原来还有一种更好的工作方式的。引用质量管理大师戴明博士的一句话
>
Dont just do the same things better find better things to do.
很多时候,我们都在等待一个完美的时机,比方说,你打算学习一个新的知识点,但要等到工作都完成了,没人来打扰,有大段的时间投入才开始学习。**但实际上哪来这么多准备就绪的时候呢真正的学习者都是在没有条件来创造条件的过程中学习的。所以如果想开始学习DevOps我信奉的原则只有一个那就是先干再说**。
## 总结
今天我给你介绍了DevOps工程师的前景可以说现在是这个岗位的黄金时期。我还给你介绍了DevOps工程师的主要职责包括工具平台开发流程实践落地和技术预研试点这些都是在完成本职工作的基础上需要额外考虑的。在个人技能要求方面我重点提到了3项软实力希望你始终记得软实力不等于玩虚的这对未来个人的发展高度至关重要。
在下一讲中我会跟你分享DevOps工程师必备的硬技能以及成长路径敬请期待。
## 思考题
你所在的公司是否有DevOps工程师的岗位呢他们的职责要求是怎样的呢你觉得还有哪些软实力是DevOps工程师所必备的呢
欢迎在留言区写下你的思考和答案,我们一起讨论,共同学习进步。如果你觉得这篇文章对你有所帮助,欢迎你把文章分享给你的朋友。

View File

@@ -0,0 +1,183 @@
<audio id="audio" title="特别放送(三)| 学习DevOps不得不了解的经典资料" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/3f/f7/3fcf422d8f32b70500096cd9630ceef7.mp3"></audio>
你好,我是石雪峰。
今天又到了特别放送的环节在学习交流DevOps的过程中经常有人会问这样的问题
- 我想学习DevOps可以推荐一些好的书和资源吗
- DevOps相关的最新行业案例我可以在哪里获取呢
- 你是怎么知道这么多有趣的故事的呢?
这些问题的“出镜率”特别高所以我今天专门来跟你聊聊有关DevOps学习资料的事情。
你应该也有感觉在这个信息爆炸的时代如果想要了解一个新的事物相关的信息不是太少而是太多了。像DevOps这种热门话题相关的资料网上一搜就一大把。各种新书也像“采用了DevOps实践”一样发布频率越来越快。信息一多我们就很容易焦虑这么多资料什么时候才能看完啊
更何况,如果单单只是臻选有用的资料,就要花费大量的时间,按照精益的理论来说,这也是不增值的活动呀。在这个时间稀缺的时代,想要花大段的时间投入到一件事情上,找到一个靠谱和有价值的信息,就成了很多人开始学习的第一步,
所以为了让你在专栏之余可以更加有效地持续学习我特意整理了一份我认为DevOps从业人员需要了解和关注的资料你可以参考一下。
需要强调的是,有针对性地精读一本好书的一部分内容,要比泛泛地读好几本书要更有收获一些,也就是“**贵精不贵多”,先定下一个小目标,然后沉下心来反复地学习实践,这个道理在大多数领域都是适用的**。
## 一份报告
如果说DevOps领域有行业公认的权威资料的话DevOps状态报告自然是不二之选。
从2014年开始这份报告每年发布一次主要编写方也经历了好几次变迁从最开始的Puppet实验室、IT Revolution到DORADevOps Research &amp; Assessment的加入再到去年DORA和Puppet分家两边各自推出了自己的DevOps状态报告。
但从影响力来说我更推荐DORA的这份报告从去年开始这份报告正式改名为加速度DevOps状态报告。
提到DORA你可能不太熟悉但是如果说到DORA的两位核心创始人Nicole博士和Jez Humble相信你一定有所耳闻他们也是我今天推荐的一些书的作者。
有意思的是去年DORA宣布加入谷歌其主要成员也被谷歌云收编比如Jez Humble目前就是谷歌云的技术布道师。
回到报告本身我在2017年就开始进行报告的本地化工作。从近两年来看报告的体量在持续扩大比如今年的报告洋洋洒洒有80页内容而且是全英文的。
那么,关于这份报告,重点是要看什么呢?纵观过去几年的报告模式,我给你画个重点:**核心是看趋势、看模型和看实践**。
**首先看趋势**
每年的报告都会有一些核心发现这些发现代表了DevOps行业的发展趋势。比如今年的报告就指出云计算能力的使用依然是高效能组织和中低效能组织的分水岭所以如果公司还在纠结是否要上云不妨从DevOps的角度思考一下使用云计算能力带给交付能力的提升可以有多明显。
另外公司内的DevOps组织比例也从2014年的14%提升到了今年的27%。由此可见越来越多的公司在拥抱DevOps至少从组织层面可以看到越来越多带有DevOps职责或者是以DevOps命名的团队出现。这对于公司内部职责的划分和团队架构演进具有一定的指导意义。
当然不得不提的还有衡量DevOps实施效果的4个核心指标也就是**变更前置时间、部署频率、变更失败率和故障修复时长**。
从2014年的第一份报告开始每年的报告都在对比这4个核心指标在不同效能团队之间的变化和差异。实际上就我观察国内很多公司的DevOps度量体系都深受这些指标的影响或多或少都有它们的影子。
可以说这4个指标已经成为了衡量DevOps效果的事实标准甚至有人直接把指标拿给老板看“你看高效能组织比低效能组织的故障恢复时长要快2000倍由此可以证明DevOps是势在必行的。”
我个人觉得,没有必要纠结于数字本身,这东西吧,看看就好,更多的还是要透过数据看趋势。
比如,去年的指标数据就显示,在交付能力方面,不同组织间的差距在缩小,相应的质量维度的指标差异却在拉大。这就说明,通过初期的自动化能力建设,团队可以快速地提升交付水平。但是,由于缺少质量能力的配套,很容易产生更多的问题,这就带来一个警示,在快速提升交付能力的同时,质量建设也不能落在后面。
<img src="https://static001.geekbang.org/resource/image/79/ac/79665c64da0a9ccab7f0244c5e59eeac.png" alt="">
**关于报告,其次是看模型**
我在[第4讲](https://time.geekbang.org/column/article/148878)中提到过一个观点:**任何技术的走向成熟,都是以模型和框架的稳定为标志的**。因为当技术跨越初期的鸿沟,在面对广大的受众时,如果没有一套模型和框架来帮助大众快速跟上节奏,找准方向,是难以大规模推广和健康发展的。
在软件开发领域是这样,在其他行业也是如此,要不然,为啥会有那么多国标存在呢?所以说,模型和框架的建立是从无序到有序的分水岭。
在今年的状态报告中,研发效能模型进一步细化为软件交付运维模型和生产力模型。今天我不会深入解析模型本身,但我会在专栏后面的内容中结合实际案例进行详细解释,从而帮助你更好地理解。
但是从过往的报告可以看出每一年关于模型的进化是整个报告的核心内容报告也在不断覆盖新的领域试图更加全面地揭示影响软件开发效能的核心要素。在实践DevOps的时候你可以参考这个能力模型识别当前的瓶颈点在遇到拿捏不准的决策时也可以参考模型中要素的影响关系。
比如,公司内部经常会争论是否需要更加严格的审批流程,希望借助严格的审批流程,促使软件交付更加有序和可靠。很多系统和需求在提出的时候,都是以这种思想为指导的。我一直对这种流程的有效性抱有怀疑,加入更多的领导审批环节,除了出问题的时候大家一起“背锅”之外,并没有带来什么增值活动。
在今年的模型中,这种观点得到了印证。**重流程管控不利于软件交付效能的提升,轻流程管控也不会影响软件交付质量,关键要看公司是否选择一种“更好”的做法来实现管控的目的**。
<img src="https://static001.geekbang.org/resource/image/c8/63/c87bd960e6743511dae31617f99e0c63.png" alt="">
最后,我们要重点关注**实践**。
在实施DevOps的时候经常会有这样的困扰道理都懂却仍然做不好DevOps。所以DevOps落地的核心无外乎实践和文化而实践又是看得见摸得着的这一点当然值得关注。在状态报告中有很大篇幅都在介绍实践部分这些实践都是在大多数公司实施总结出来的并且得到了实际的验证具有很强的参考性。
比如今年的报告重点介绍了技术债务、灾难恢复测试和变更管理流程这几个方面的实践这些都是企业实施DevOps时的必经之路。
比如灾难恢复测试,很多公司都有非常详尽的文档,但是如果找他们要操作记录,他们却又很难拿出来。
我之前就见过一家国内Top的公司说是在做关键数据的备份但实际去看才发现这个备份任务已经很长时间处于失败状态了。
如果有定期的灾难恢复测试,类似的这种问题是一定可以发现的。而**往往在灾难发生的时候,才能体现一家公司的工程能力水平**。
比如Netflix正是因为混沌工程才没有受到AWS云服务down机的影响这和日常的演练是密不可分的。
从2014年至今的DevOps状态报告的中英文版本我已经收集并整理好了你可以点击[网盘](https://pan.baidu.com/s/1W7-_et-wulD7AueBU2KTow)链接获取提取码是mgl1。
## 几本好书
讲完了报告,接下来,我再给你推荐几本好书。
**1.《[持续交付](https://item.jd.com/1027475074.html)》&amp;《[持续交付2.0](https://item.jd.com/12512514.html)》**
谈到DevOps里面的工程实践持续交付可以说是软件工程实践的终极目标。对于在企业内部推进DevOps工程能力建设的人来说这两本书可以说是案头必备常看常新。
对我自己来说因为2011年机缘巧合地拿到了第一版第一次印刷的《持续交付》这本书我的职业生涯彻底改变了。因为我第一次发现原来软件交付领域有这么多门道。帮助组织提升交付效率这个事情真是大有可为。
《持续交付》围绕着软件交付的原则,给出了一系列的思想、方法和实践,核心在于:**以一种可持续的方式,安全快速地把你的变更(特性、配置、缺陷、试验),交付到生产环境上,让用户使用**。你可以参考一下软件交付的8大原则。
- 为软件交付创建一个可重复且可靠的过程
- 将几乎所有事情自动化
- 将一切纳入版本控制
- 频繁地做痛苦的事情
- 内建质量
- DONE意味着已发布
- 交付过程是每个成员的责任
- 持续改进
很多人都有《持续交付》这本书,但我敢打赌,真正能沉下心来把这本书看透的人并不多,因为这本书里面通篇都是文字,而且有些难懂,如果没有相关的实践背景,基本上就跟看天书差不多了。
所以,通读《持续交付》并不是一个好的选择,我建议你**尽量带着问题有选择性地去读**。
到了《持续交付2.0》乔梁老师创新性地将精益创业的思想和《持续交付》结合起来更加强调IT和业务间的快速闭环也更加适应当今DevOps的发展潮流。
另外,乔梁老师的文笔更加流畅,读起来更加轻松,他会结合案例进行说明,对于实际操作的指导性也更强。毫无疑问,他是国内软件工程领域的集大成者。
如果你对软件开发流程的工程实践不太了解,你可以读一读这两本书。
当然,对于开发、测试、运维人员这些软件交付过程中必不可少的角色来说,也可以用来拓展知识领域。
**2.《[精益创业](https://item.jd.com/11055746.html)》&amp;《[Scrum精髓](https://item.jd.com/11462889.html)》&amp;《[精益产品开发](https://item.jd.com/12132997.html)》&amp;《[精益开发与看板方法](https://item.jd.com/11862173.html)》**
关于管理实践和精益方面我给你推荐4本书。
《精益创业》提出的MVP最小可行产品思想已经被很多的企业奉为圭臬。它的核心是只有经过真实市场和用户的验证想法才是真正有效的产品需要在不断的验证和反馈过程中持续学习持续迭代而不是试图一步到位耗尽所有资源从而失去了回旋的余地。
《Scrum精髓》适合于使用Scrum框架的敏捷团队学习和实践以避免Scrum实施过程中形似而不神似的问题。同时这也是立志成为Scrum Master的同学的红宝书。
《精益产品开发》是何勉老师在2017年出版的一本基于精益思想和精益看板方法的著作。在精益软件开发领域这本书和李智桦老师的《精益看板方法》都是看一本就够了的好书。
这几本书比较适合想要了解敏捷或者是在实际工作中践行敏捷开发方法的同学阅读。另外精益思想可以说是DevOps的理论源泉很多的文化导向以及持续改进类工作都跟精益思想有密切的关系。
**3.《[DevOps实践指南](https://item.jd.com/12350780.html)》&amp;《[Accelerate加速](https://item.jd.com/29263749137.html)》**
如果你想了解DevOps的全貌以及核心理论体系和实践《DevOps实践指南》和《Accelerate加速》就是最好的选择了。这两本书的作者都是DevOps行业内的领军人物作为Thought Leader他们引领的DevOps的体系在不断向前演进。
其中《DevOps实践指南》也就是俗称的Handbook重点介绍了DevOps实践的三步工作法还包含了大量DevOps实施过程中的参考案例。而《Accelerate加速》的作者就是DevOps状态报告的作者。他在这本书中揭示了状态报告背后的科学方法并提出了DevOps能力成长模型以帮助你全面提升软件交付能力。
**4.《[凤凰项目](https://item.jd.com/11789836.html)》&amp;《[人月神话](https://item.jd.com/12401749.html)》&amp;《[目标](https://item.jd.com/12610010.html)》**
最后,我想再推荐三本小说,这也是我读过的非常耐看的几本书了。
其中《凤凰项目》提出的DevOps三步工作法和《DevOps实践指南》一脉相承《人月神话》是IT行业非常经典的图书畅销40余年《目标》则是约束理论的提出者高德拉特的经典著作他所提出的改进五步法构成了现代持续改进的基础。
## 大会,网站和博客
当然报告和书只是DevOps资源中的一小部分还有很多信息来源于大会、网站和博客我挑选了一些优质资源分享给你。
- [DEOS](https://events.itrevolution.com) DevOps国际峰会以案例总结著称
- [DevOpsDays](https://devopsdays.org/)大名鼎鼎的DevOpsDays社区
- [TheNewStack](https://thenewstack.io/) :综合性网站,盛产高质量的电子书;
- [DevOps.com](https://devops.com/) :综合性网站;
- [DZone](https://dzone.com) 综合性网站,盛产高质量的电子书;
- [Azure DevOps](https://devblogs.microsoft.com/devops/):综合性网站,盛产高质量的电子书;
- [Martin Fowler](https://www.martinfowler.com/bliki/) Martin Fowler的博客
- [CloudBees Devops](https://www.cloudbees.com/devops) Jenkins背后的公司的博客。
在这些资源中,有一些值得你重点关注一下。
比如Gene Kim发起的DOESDevOps企业峰会就是获取实践案例的绝佳场地而DZone和NewStack经常会推出免费的电子书和报告也值得订阅Martin Fowler的博客每一篇内容都是精品对于很多技术细节可以说是起到了正本清源的作用值得好好品味。
说了这么多,最后我还想再花一点点时间,跟你聊聊学习这个事情。我跟你分享一幅美国学者爱德加·戴尔提出的学习金字塔模型图,这个模型也是目前比较有参考性的模型之一。
<img src="https://static001.geekbang.org/resource/image/f2/d6/f2de4f052d1c4e90d5caf3e5f863bfd6.jpeg" alt="">
>
图片来源:[https://www.businessdirect.bt.com/](https://www.businessdirect.bt.com/)
在这个模型中,学习的方式分为两种,一种是主动学习,一种是被动学习。其实,无论是读书,看视频,还是听专栏,都属于是被动式的学习,最终收获的知识可能只有输入信息的一半儿,这还是在记性比较好的情况下。大多数时候,看得越多,忘得越多,这并不是一种特别有效的学习方式。
实际上对于DevOps这种理念实践、技术文化、硬技能、软实力交织在一起的内容来说主动学习的方式是不可或缺的比如**案例讨论,线下交流,在实践中学习**等。
所以希望你能多思考多总结结合工作中的实际问题摸索着给出答案并积极分享跟大家讨论。只有主动思考才能消化吸收最终总结沉淀出一套自己的DevOps体系认知。
## 总结讨论
好了今天我跟你聊了DevOps的学习资料包括状态报告、书籍和大会、网站、博客。不过对于DevOps来说这些也仅仅是点到为止。
我想请你来聊一聊你自己在学习和实践DevOps的过程中有没有私藏的干货和渠道呢如果有的话希望你可以分享出来我们共建一个DevOps相关的资源库并在GitHub上进行开源维护从而帮助更多人了解和学习DevOps。
欢迎在留言区写下你的思考和答案,我们一起讨论,共同学习进步。如果你觉得这篇文章对你有所帮助,欢迎你把文章分享给你的朋友。

View File

@@ -0,0 +1,120 @@
<audio id="audio" title="特别放送(二)| 成为DevOps工程师的必备技能" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/64/51/648ba3c530957179fd48d8275be09751.mp3"></audio>
你好我是石雪峰。在上一讲我介绍了DevOps工程师的具体职责以及DevOps工程师必备的3项软实力分别是沟通能力、同理心和学习能力。有了这些认知之后我们今天来看看“重头戏”DevOps工程师必备的硬实力以及学习路径。
## DevOps工程师必备的硬实力
所谓硬实力,说白了就是指一个人的技术能力。软实力通常是“只可意会不可言传”的,但技术本身就具体多了,重要的是,技术水平的高低相对来说也更好衡量。在公司里面,技术人员要想获得晋升,重点就是依靠技术能力。
IT行业覆盖的技术领域非常广而且近些年的新技术也是层出不穷的从入门到精通任何一门技术都需要大量时间和精力的投入。那么在面对这么多技术的时候究竟要选择从哪个开始入手真是一个难题。对于希望成为DevOps工程师甚至是DevOps专家的你来说究竟有哪些必须掌握的核心技术呢
**1.代码能力**
现在这个时代代码能力可以说是最重要的硬实力了。IT行业自然不用说像运维有运维开发测试也有测试开发就连产品经理都要懂代码不然可能都没办法跟开发同学顺畅交流。
对于工具平台自身的建设而言,代码能力自然是重中之重。这不仅仅在于通过写代码来实现工具平台本身,还在于你能了解开发的完整过程。这些平台的用户每天跟代码打交道的时间可能比跟人打交道的时间还多,如果你不能理解他们的日常工作方式,那么你做出来的工具平台,又怎么能真正解决团队的问题呢?
这里提到的**代码能力包含两个方面,分别是脚本语言能力和高级语言编程能力**。
- **脚本语言能力**。这对于运维工程师来说自然是驾轻就熟各种VIM、Emacs手到擒来Shell和Python也是轻车熟路。而对于开发人员来说难点不在于语法本身而在于对关联操作系统和命令的理解上。毕竟脚本语言是一种快速的自动化手段追求的是高效开发简单易用。
- **高级语言编程能力**。你需要至少掌握一门高级语言无论是Java、Python还是Ruby和PHP。**其实语言只是工具,你不用过度纠结于选择哪门语言,要求只有一个,就是你能用它来解决实际问题**比如能够支持你实现面向移动端或者Web端的工具平台开发。**为了写出好代码,而不仅仅是写出能用的代码,你也需要对于一些常见的开发框架和开发模式有所了解**。这是一个相对漫长的过程绝对不是什么“21天精通XX语言”就够了。因为看得懂和写得好完全是两码事。
好的代码是需要不断打磨和推敲的。**与其说写好代码是一门技术,不如说是一种信仰**。我们团队的内部沟通群名叫作“WBC团队”“WBC”也就是“Write Better Code”的缩写这其实也是我们团队对自己的一种激励。在日常的开发过程中我们会不断发现和总结更好的实现方式在内部分享互相学习从而持续提升代码能力。我截取了一部分我们最近优化流水线脚本的经验总结你可以参考一下。其实每个人都能总结出自己的代码心经。
<img src="https://static001.geekbang.org/resource/image/91/0b/9124fd4c7ef664ba04af700faca06e0b.jpg" alt="">
**2.自动化能力**
在自动化方面你首先需要对CI/CD也就是持续集成和持续交付建立起比较全面的认知。因为CI/CD可以说是DevOps工程领域的核心实践目前大部分公司都在集中建设软件的持续交付能力尤其是以流水线为代表的持续交付平台很多时候就同DevOps平台划上了等号。
接下来为了实现全流程的自动化你需要能够熟练使用CI/CD各个关键节点上的典型工具并且了解它们的设计思路。
一方面目前很多公司都在拥抱开源参与开源开源工具自身的成熟度也非常高并且逐渐取代商业工具成为了主流方案。通过直接使用开源工具或者基于开源工具进行二次开发也是自动化领域投入产出比最高的方式。所以像版本控制工具Git、代码托管平台Gitlab、CI工具Jenkins、代码扫描工具Sonar、自动化配置管理Ansible、容器领域的Docker、K8S等等这些高频使用的工具都是你优先学习的目标。
另一方面,**无论是开源工具,还是自研工具,工具与工具之间的链路打通也是自动化的重要因素**。所以在理解开源工具的实现方式的基础上就要能做到进可攻退可守。无论是封装还是自研有了工具的加持CI/CD也会更加游刃有余。
关于DevOps的工具图谱我跟你分享一个信通院的DevOps能力成熟度模型版本供你参考。值得注意的是**工具不在多,而在精**。其实,工具的设计思路和理念有共通之处,只要精通单个节点上的工具,就可以做到以点带面。
<img src="https://static001.geekbang.org/resource/image/91/bd/91b7d3327892002d68029c7817fe06bd.png" alt="">
**3.IT基础能力**
我始终认为运维是个特别值得尊敬的工种也是DevOps诞生的原点。如果你不是运维出身那你要重点掌握运维的基础概念最起码要了解**Linux操作系统方面的基础知识**,包括一些**常用的系统命令使用**,以及**网络基础和路由协议**等。毕竟对于开发者来说他们通常习惯基于IDE集成开发环境图形界面工作。比如如果问一个iOS开发同学怎么通过命令行的方式进行构建调试或者如何用代码的方式实现工程的自动化配置他可能就答不上来了。
另外,随着基础设施即代码的技术不断成熟,你还要能看懂环境的配置信息,应用自动化构建、运行和部署的方式等,甚至可以自行修改环境和应用配置,这样才能实现所谓的开发自运维。虽然在大多数公司,运维的专业能力一般都会通过运维平台对外提供服务,但对于基础概念,还是需要既知其然,也知其所以然。
**4.容器云能力**
云计算对于软件开发和部署所带来的变化是革命性的。未来企业上云或者基于云平台的软件开发会慢慢成为主流。而容器技术又天生适合DevOpsKubernetes可以说是云时代的Linux基于它所建立的一整套生态环境为应用云化带来了极大的便利。
所以无论是容器技术的代表Docker还是实际上的容器编排标准Kubernetes你也同样需要熟悉和掌握。尤其是在云时代基于容器技术的应用开发和部署方式都是DevOps工程师必须了解的。
**5.业务和流程能力**
在任何时候DevOps的目标都是服务于业务目标DevOps本身也从来不是墨守成规的方式而是代表了一种变革的力量。所以加强对业务的理解有助于识别出DevOps改进的重点方向而流程化的思维建设有助于突破单点放眼全局。
很多时候,**企业需要的不仅仅是一个工具,而是工具所关联的一整套解决方案,其中最重要的就是业务流程**。
对于DevOps工程师来说**要有能力发现当前流程中的瓶颈点,并且知道一个更加优化的流程应该是怎样的**,这一点也是制约工程师进一步拓展能力的瓶颈之一。
举个例子对于开发DevOps平台工具来说你可能认为最合适承担的团队就是开发团队因为他们的代码能力最强。但是实际上DevOps平台的设计很多时候都是由最熟悉企业内部研发流程的团队来主导的。正因为DevOps工程师的工作应该同业务紧密联系更加关注于全局交付视角所以很多时候配置管理、质量管理、项目管理和技术运维团队更多地在承担相近的角色。**毕竟,只有方向正确,所做的一切才是加法。**
<img src="https://static001.geekbang.org/resource/image/df/d2/df7819fcd4372b837317754a4c72c9d2.png" alt="">
## 学习路径
那么要想成为DevOps工程师是否有一条普适性的学习路径呢实际上这个问题就跟我们要在公司推行DevOps是否存在一条通用的改进路径一样并不是一个容易回答的问题。
从前面的能力模型可以看出DevOps工程师特别符合现在这个时代的要求他具备多重复合能力是典型的全栈工程师或者“梳子型”人才。因为只有这样才能充分弥合不同角色之间的认知鸿沟堪称团队内部的万金油。
基于过往在公司内部推行DevOps的经验以及当前行业的发展趋势我有几条建议送给你
**1.集中强化代码能力**
**未来的世界是软件驱动的世界**。我们以前总说的必备能力,比如外语、开车等,未来都可以被软件所取代。而编程能力即将成为下一个必备能力,甚至连国务院发布的《新一代人工智能发展规划》中都提到,要在中小学普及推广编程教育。
**而写可以用的代码,和写好的代码之间,距离绝不只是一点点而已**。你可能会说,以后都用人工智能来编程了,可问题是人工智能从何而来?又是谁来训练和标注人工智能的呢?所以,越是基础的能力,越不会过时,比如数学、核心的编程思想、数据结构,以及基于代码构建对世界的认知和建模能力。
所以如果你现在只是刚开始接触代码我建议你给自己定一个目标专门强化自己的代码能力至少花1年时间从新手变成熟手这对于你未来在IT行业的发展至关重要。
跟你分享一个小技巧。你可以基于成熟的开源软件来边学习边应用比如像Adminset这种轻量级的自动化运维平台已经可以解决大多数中小公司的问题了。其实代码能力不仅仅是掌握语法和框架更重要的是基于场景整体设计数据和业务流程并通过代码实现出来。毕竟只有结合实际的应用场景进行学习才是最有效率的。
**2.培养跨职能领域核心能力**
相信经过几年的工作,你已经具备了当前岗位所需要的基本能力,这是你当前赖以为生的根本。那么在这些能力的基础上,逐步发展跨领域跨界的能力,尤其是那些核心能力,就成了投入产出比最高的事情。
举个例子,如果你是软件开发工程师,那么恭喜你,你已经走在了代码的道路上,接下来,运维能力就是你要尝试攻克的下一个目标。而在这些目标中,比如操作系统、自动化部署以及云能力,就是你要最优先发展的跨界能力,因为它们是运维的核心,也是了解运维最好的出发点。反过来说,如果你从事的是运维行业,那么除了常用的脚本以外,核心代码能力就是你的目标。
其实,我们每天的工作其实都离不开跨界,比如,运维每天部署的应用,为什么要部署这么多实例?每个实例之间的调用关系又是怎样的?**多问几个为什么,往往就有新的收获。**
不仅如此,在接触跨领域的时候,除了基础核心技能,那些最常见的工具,你也要花时间来了解。现在网上的资料足够多,快速入门应该并不困难。
**3.DevOps核心理念和业务思维**
如果你不理解DevOps到底是什么那何谈成为DevOps工程师呢因此像DevOps中的核心理念比如精益敏捷、持续交付以及很多实践你都要有所了解。当然如果你订阅了这个专栏我将带你走过前面的这段路你可以快速地进入下一阶段在实战中练习。
DevOps在公司的落地是大势所趋也许你所在的团队也会参与其中那么除了做好自己的本职工作外你也可以多参与多思考看看推进的过程是怎样的涉及到的角色又在做些什么项目的整体进展和计划是什么。在实战中练习和补齐短板对于积累经验来说是不可或缺的。**很多时候,不是没有学习的机会,只是我们自己不想看到罢了。**
另外,可能你现在距离业务还比较远,那么你可以尝试了解一些大的业务目标,多跟你所在团队的上下游进行沟通,看看他们现在的关注点在什么地方。既然业务的目标需要整个团队紧密协作才能完成,那么每个团队都是其中的一份子,所以他们身上也同样体现了业务的目标。
**4.潜移默化的软实力建设**
类似沟通能力、同理心、自驱力、学习能力、主动性等,无论从事任何职业,都是你身上的闪光点。很多天生或者从小养成的习惯,需要长时间潜移默化的训练才能有效果。
很多时候IT从业人员给人的印象都是不善表达再加上东方文化的影响本身就比较含蓄这对很多沟通和表达来说都是潜在的障碍。这个时候就要尽量把握已有的机会比如多参加团队内部的读书分享、公司内部的讲师培训报名等。即便刚开始分享的内容还不足你脑中的1%但至少也是一个好的起点。我的建议就是6个字**勤练习,多总结**。就像DevOps一样持续改进和持续反馈培养自己的自信心。
## 总结
总结一下我在这两讲给你介绍了DevOps工程师要重点关注的3大职责分别是工具平台开发、流程实践落地和技术预研试点。另外我还基于实用角度提炼了8大核心能力模型分为3条软实力和5条实力并给出了4条提升DevOps核心能力的建议。为了方便你复习和理解我画了一张脑图把这两讲内容进行了汇总你可以参考一下。
<img src="https://static001.geekbang.org/resource/image/48/07/48de933119e78f7f94cd2abe91073d07.png" alt="">
最后我想强调的是就像DevOps没有明确的定义一样DevOps工程师的技能也没有明确的限定所以你要时刻保持好奇心持续学习总结出自己的能力体系并在实践积累经验这样才能在激烈的竞争中占得先机。
## 思考题
针对我们这两讲的内容,你觉得自己需要提升哪方面的能力呢?你有哪些快速提升能力的小窍门吗?
欢迎在留言区写下你的思考和答案,我们一起讨论,共同学习进步。如果你觉得这篇文章对你有所帮助,欢迎你把文章分享给你的朋友。

View File

@@ -0,0 +1,152 @@
<audio id="audio" title="特别放送(五)| 关于DevOps组织和文化的那些趣事儿" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/d8/ee/d81e325d77022ec265531c388f549fee.mp3"></audio>
你好我是石雪峰今天又到了特别放送环节。写到这儿专栏已经接近尾声了我想再跟你聊聊DevOps的组织和文化。
DevOps文化好像是一个矛盾结合体一方面文化这种东西似乎只可意会不可言传另一方面文化对DevOps实践的重要性又是毋庸置疑的。
在各种行业大会上,关于文化的议题总是屈指可数。原因也很简单,关于文化,一般都说不明白,即便能说明白,也改变不了什么。因为文化的改变可不是像引入一个工具那么简单,很多时候都需要思想上的转变。
谈到DevOps文化我想到去年我和几个朋友一起组织《DevOps实践指南》的拆书帮活动。这个活动就是通过连续几周的线上分享我们帮助大家总结提炼书中的核心知识。
在分享的过程中有这样一件事我印象特别深刻。事情的起源是原书的第14章中有这样一段描述
>
团队在客户面前没有任何需要隐藏的,对自己也同样如此。与其把影响线上系统的问题视为一种秘密,不如尽可能地将它透明化,主动将内部的问题广而告之给外部用户。
某大型公司的IT负责人刚好负责分享这个章节他表示为了尊重原文他保留了这段描述但是在国内的环境下这并不现实。即便是他自己一个坚定的DevOps实践者也很难做到这种程度。因为如果把公司内部的问题通通开放给客户那估计转天就可以收拾东西回家了。
也正因为公司一般不会在第一时间对外公布故障,所以也难怪,这些事情基本都是通过“云头条”这类公众号第一时间公布出来的。
但是,似乎大家的记忆力也都不太好,很多时候,这些事情过去了也就不了了之了,除了听说“谁又背锅了,谁又被牵连了“之类的流言蜚语之外,也没有什么特别之处。
这也可以理解,毕竟家丑不可外扬,内部吐吐槽也就罢了,如果凡事都到外面去宣传,那公司岂不是形象全无?更有甚者,还会影响用户对公司的信心。你想,如果天天就你问题最多,那谁还敢用你的服务呢?
我们都知道DevOps文化的几个关键词**协作**、**分享共担**、**无指责文化**、**在错误中学习**……这些道理大家都懂,但真正遇到问题、需要平衡不同部门利益的时候,是否还能以这些文化为准则,来指导行为模式,就是另外一码事了。
说白了如果想看团队是否具备DevOps文化与嘴上说说相比更重要的是看怎么做。所以今天我给你分享几个故事看看在面对同样的问题时其他公司是怎么做的并思考一下为什么这样是一种更好的做法
## GitLab删库的故事
时间回到2017年1月31日全球最大的代码托管协作平台之一的GitLab出现了一次长达18小时的停机事故原因居然是一个IT工程师把生产数据库的数据给清空了。
由于遇到了爬虫攻击主备数据库之间的同步延迟已经超过了WAL的记录上限导致数据同步无法完成。当时遇到这种问题的操作就是移除所有备份数据库上的数据记录然后全量触发一次新的同步。但是由于数据库配置并发数和连接数等一系列的配置问题导致数据库的数据备份一直失败。
这个时候时间已经来到了标准国际时间的晚上11点半。由于时差的关系对于身在荷兰的工程师来说这时已经是深夜1点半了。当值工程师认为有可能是之前失败的同步遗留的数据导致的数据库备份失败所以决定再一次手动清空备份服务器的数据。
但是,也许是由于疏忽,他并没有意识到,当时他操作的是**生产数据库**。几秒钟后当他回过神来取消操作的时候一切都已经来不及了。最终的结果是总共有超过300G的线上数据丢失直接导致了服务进入恢复模式。
按道理说这种事情虽然难以接受但其实并不少见。更加严重的是当GitLab尝试恢复数据的时候才发现他们所谓的“精心设计”的多重备份机制竟然都无法拯救被删除的数据。
最夸张的是,直到这会儿,他们才发现,由于升级后工具版本不匹配,数据库的定时备份一直处于失败状态。他们原以为邮件会告警这个问题,但巧合再一次出现,针对自动任务的报警也没有生效。
事已至此,要么是隐藏事实,然后给外界一个不疼不痒的解释,要么就是把问题完全公开,甚至是具体到每一个细节,你会选择怎么处理呢?
GitLab公司的选择是后者。他们第一时间将系统离线并将事件的所有细节和分析过程记录在一个公开的谷歌文档中。不仅如此他们还在世界上最大的视频网站YouTube上对恢复过程进行全程直播。
考虑到有些用户不看YouTube他们还在Twitter上同步更新问题状态硬生生地将一场事故变成了一个热门话题。当时同时在线观看直播的用户超过5000人甚至一度冲到了热门榜的第二位。
除此之外在几天后公司的CEO亲自给出了一篇长达4000字的问题回溯记录包含问题发生的背景、时间线、核心原因分析针对每一种备份机制的说明以及将近20条后续改进事项由此获取了用户的信任和认可。可以说在这一点上他们真的做到了透明、公开和坦诚相待并且做到了极致。
>
问题回溯的资料: [https://about.gitlab.com/2017/02/10/postmortem-of-database-outage-of-january-31/](https://about.gitlab.com/2017/02/10/postmortem-of-database-outage-of-january-31/)
至于那位倒霉的工程师的结果,估计你也听说了,对他的惩罚就是强迫他看了几十分钟的《彩虹猫》动画。说实话,这个动画有点无聊。但是,如果这种事情发生在咱们身边,估计直接就被开掉了。我知道你肯定好奇这个《彩虹猫》到底是个啥动画片,我也特别无聊地找来看了下,如下所示:
<img src="https://static001.geekbang.org/resource/image/86/c1/86a033098638db7244c2ec6f661808c1.png" alt="">
从此以后GitLab的开放越发“变本加厉”。现在你可以在任何时间去查看服务的实时状态包括每一次过往的事故分析。同时名叫“GitLab状态”的Twitter账号实时更新当前的问题目标就是在任何用户发现问题之前尽量主动地将问题暴露出来至今已经发布了将近6000条问题。
同时你还可以查看GitLab服务的详细监控视图和监控数据包括GitLab的运维标准手册、备份脚本。这些通通都是对外开放的。只要你想用你就可以直接拿来使用如果你觉得哪里不靠谱也可以直接提交改动给他们。我提取了一些截图和地址你可以参考一下。
1.GitLab状态Twitter[https://twitter.com/gitlabstatus](https://twitter.com/gitlabstatus%5Breference_end%5D)
<img src="https://static001.geekbang.org/resource/image/cb/7f/cba011cebb4cdf8318772bf04bd95d7f.png" alt="">
2.GitLab状态网页[https://status.gitlab.com/](https://status.gitlab.com/%5Breference_end%5D)
<img src="https://static001.geekbang.org/resource/image/7d/50/7d5909f0a8c2c6e7903aa0a7fddfcf50.png" alt="">
3.GitLab内部监控大屏[https://dashboards.gitlab.com/](https://dashboards.gitlab.com/%5Breference_end%5D)
>
<img src="https://static001.geekbang.org/resource/image/4c/6c/4c79b3a2c797cc0e2651dd9a53216a6c.png" alt="">
这并不是GitLab公司发疯了实际上开放已经成为了主流公司的标配。比如在GitHub上你同样可以看到类似的信息。
<img src="https://static001.geekbang.org/resource/image/69/fc/69c4413d897ca9bd82747580c51092fc.png" alt="">
故事讲到这儿,就可以告一段落了。**面对事故的态度,很大程度上体现了公司的文化**。
首先,就是**在错误中学习**。
GitLab的分析报告不仅是对问题本身的描述很大程度上也是希望把他们的经验尤其是修复过程中的经验分享出来通过错误来积累经验改善现有的流程和工具从而彻底地避免类似问题的出现。
每个人、每个公司都会犯错,**对错误的态度和重视程度,决定了成长的高度**。所以,假如说我要去一家公司面试,面试官问我有没有问题,那我非常关心的一定是他们公司对错误的态度,以及具体的实际行动。
另外,就是**建立信任和及时反馈,公开透明是关键**。这不仅是对外部用户而言的,对内部协作的部门和组织来说,也是这样。因为只有充分的透明,才能赢得对方的信任,很多事情才有得聊,否则,建立协作、责任共担的文化,就成了一句空谈。
在开始建立DevOps文化的时候你首先要明白上下游所需要的信息是否能够自主简单、随时地获取到如果不能的话这就是一个很好的潜在改进事项。
## Etsy三只袖子毛衣的故事
Etsy是美国的一家手工艺电商平台从2015年上市以来它的市值一度接近80亿美元。当然除了快速增长的市值以外最为人称道的就是它们的DevOps能力而它们的案例也大量出现在了《DevOps实践指南》一书中。
那么,为什么这个名不见经传的公司能够做到这种程度呢?实际上,通过一件小事,我们就能看出来原因。
你可能不知道的是,一家在线电子商务公司每日浏览频率最高的单体页面不是首页,也不是具体哪个商品的页面,而是**网站的不可用页面**也就是我们习惯说的502页面。有些公司甚至为了提升502页面的用户体验利用好这部分流量在502页面做了很多文章比如把502页面作为一个产品推广的阵地等。
当Etsy的网站不可用的时候你看到的是一个小姑娘在织毛衣的画面而这个毛衣竟然有三只袖子。
<img src="https://static001.geekbang.org/resource/image/48/51/48b597fce55138868119d2fb55dea751.png" alt="">
实际上“三只袖子的毛衣”代表了Etsy对于错误的态度。我们都知道一件毛衣应该只有两只袖子这是常识。如果有人真的织出来第三只袖子我们的第一反应就是觉得这很可笑这只是个人的问题却很少去想他为什么会做这种反常识的事情背后的根因是什么。
但是Etsy公司却不是这样的。在每年的年终总结大会上公司都会颁发各种奖项其中一个奖项的奖品就是“三只袖子的毛衣”获奖者是公司年度引入最大问题的个人。
这是因为,在他们看来,**犯错误并不是什么大不了的事情。错误本身并不是个人的问题,而是公司系统和制度的问题,正因为有了这样的错误,才给了公司改进和成长的空间**。从某种意义上说,这也是一种贡献。
当然,除了制造噱头之外,通过这种行为,其实公司想表达的是它们对文化的偏好,也就是要**建立一种心理安全**、**快速变化**、**及时反馈**、**鼓励创新的文化**,由此来激发整个团队的士气和战斗力。
无独有偶2019年的DevOps状态报告也特别指出**心理安全的文化氛围,有助于团队生产力的提升**。更重要的是状态报告还把它作为一条重要能力放入了DevOps能力模型之中。
因为只有当员工感受到心理安全时才会把注意力集中在解决问题和快速完成工作上而不是花费大量的时间用于互相攻击和部门政治。在跨部门寻求合作的时候才会思考如何让组织的价值最大化而不是想“谁过来动了我的奶酪我要如何制造更高的门槛来保护自己的利益”。对于DevOps这种注重协作的研发模式来说这一点真的太重要了。
## Netflix招聘成年人的故事
美国硅谷聚集了世界上大多数精英的IT公司但是精英中的精英就是FAANG也就是Facebook、Apple、Amazon、Netflix和Google这五家公司的首字母简称这五家公司基本引领了硅谷技术的风向标。大多数人对其中的4家公司都非常熟悉但是对Netflix却知之甚少。那么这家公司凭啥能跻身为精英中的精英呢
如果我告诉你在Netflix每个工程师不仅拿着数一数二的薪水还可以自己决定什么时候休假爱休多长时间就休多长时间而且报销不需要经过审批填多少就报多少。另外即便只加入公司一天就离职了公司给予的补偿也足够他们活上一年半载。
看到这里,你是不是觉得这家公司的老板疯了呢?
这个叫作里德·哈斯廷斯的人还真没疯。我所说的这一切背后的原因都被记录在了《奈飞文化手册》一书中这也是号称硅谷最重要的文件的作者在离开Netflix之后写的一本阐述Netflix文化的书。
Netflix认为**与其建立种种流程来约束员工,不如砍掉所有不必要的流程,给员工一个自由发挥自我价值的空间**。因为,把所有员工都视为一个成年人是他们的行为准则。**作为一个成年人,你应该能够为自己的行为负责,同时为公司的发展负责,由此做出最好的选择,并付出最大的努力**。
正是这种开放的氛围使得Netflix至今开源了171个项目和插件。其中像混沌工程的鼻祖混乱猴子[Chaos Monkey](https://github.com/Netflix/chaosmonkey))、断路器工具[Hystrix](https://github.com/Netflix/Hystrix)、服务注册工具[Eureka](https://github.com/Netflix/eureka)、部署工具[Spinnaker](https://www.spinnaker.io/) 都是DevOps领域最为著名的开源工具。
**开源为先的共享精神**正在成为越来越多的公司重视开源的动力之一。让真正优秀的人做有价值的事情而不是让他们整日为复杂的流程、公司的内部政治和无意义的工作所影响他们才能发挥最大的价值。对DevOps来说也是如此。
## 总结
说到这儿三个故事已经讲完了。我们来总结一下在DevOps文化中最为知名的几点内容
1. 建立免责的文化,并在错误中学习;
1. 通过对外开放透明,建立信任,促进协作;
1. 打造心理安全的氛围,鼓励创新;
1. 开源为先的共享精神。
改变企业文化绝不是一个人、一句话的事情管理层的认同和导向非常重要。但是我们并不能期望每家公司都能成为FAANG一样的硅谷巨头。所以从我做起从力所能及的范围做起别觉得文化跟自己没有关系这才是最重要的。
最后,希望你看完这一讲以后,可以重新审视一下,团队内部是否建立了正向的错误回溯机制?是否鼓励内部分享和创新?是否和上下游之间做到了开放和协作为先?是否在身体力行地减少重复建设?
## 思考题
你对今天的哪些内容印象最深刻呢你又有哪些跟DevOps文化相关的故事可以拿来分享呢
欢迎在留言区写下你的思考和答案,我们一起讨论,共同学习进步。如果你觉得这篇文章对你有所帮助,也欢迎你把文章分享给你的朋友。

View File

@@ -0,0 +1,99 @@
<audio id="audio" title="特别放送(四)| Jenkins产品经理是如何设计产品的" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/f4/ca/f413fa247e11f3545a5ed38cc92d65ca.mp3"></audio>
你好,我是石雪峰。这是一期临时增加的特别放送。
前两天我去葡萄牙里斯本参加了2019年的DevOps World | Jenkins World大会。这是一年一度的社区聚会参会人会围绕Jenkins和DevOps展开为期3天的密集交流信息量非常大。很多新技术、行业趋势、产品设计思路都在大会上涌现了出来我觉得非常有价值也很有必要整理出来分享给你。
2019年是Jenkins诞生15周年对于任何一个软件来说15年都不是一个短暂的时间。在这个时间点社区也在展望过去15年来的Jenkins发展历程并憧憬下一个15年Jenkins的变化。
可以说从DevOps产品的角度来说Jenkins本身就是一个非常出色的典型案例。
最开始这是一个由于Jenkins创始人KK无法忍受同事天天导致编译失败而开发的一个人项目。到今天这个项目已经有将近900名或全职、或兼职的贡献者26万多个Master节点超过3000万个任务了。这些数字还仅仅是官方可以统计到的部分如果再加上企业内网、个人电脑上的实例那就更加不计其数了。
今年我印象最深刻的是Jenkins创始人KK并没有在主会场上讲太多的产品细节、设计思路、发展方向等而是仅仅用了10多分钟回顾了自己的心路历程。在演讲的最后他将舞台交给了一位Jenkins产品经理。这位产品经理是何方神圣呢为什么是一位产品经理来讲这些内容呢这激起了我极大的好奇心。
一直以来KK都被视为Jenkins的头号产品经理。的确技术专家兼产品经理是比较普遍的一个现象。这是因为与普通面向用户的产品相比DevOps产品有几个非常鲜明的特征。
- **技术背景要求高**。因为DevOps产品要解决的很多问题都是一线的技术问题
- **面向的用户是开发人员**。这就意味着,如果你不了解开发的真实工作方式,就很难设计出开发友好的产品;
- **专业工具繁多**。产品引用到的开源组件和工具都是专业领域的内容比如Jenkins就是一个典型的持续集成系统如果你不了解Jenkins又怎么设计Jenkins呢
在几天的会议过程中针对DevOps产品经理面对的这些挑战我专门跟这位神奇的Jenkins产品经理进行了沟通。他就是Jeremy Hartley一个来自荷兰的大哥。
我先给你介绍下社区的运作方式。以Jenkins这个产品为例它背后的主要贡献者都来自于CloudBees公司。虽然这些人都属于同一个公司但实际上他们大多各自分散在家办公一年到头也见不了几次面。
比如产品经理Jeremy在荷兰创始人KK在加州基础设施的负责人Oliver在比利时K8S的插件维护者在西班牙。因此每年的FOSDEM年初的欧洲最大的开源软件大会以及年末的Jenkins World大会就成了这些世界各地的开发者汇聚到一起的难得机会。
言归正传与产品经理的积极外向、滔滔不绝的一般形象不同Jeremy可以说是一个异类。他从始至终都给人一种温文尔雅的感觉甚至在公开演讲的时候他的语气也非常平和没有太多的情绪表达只是把他和他的产品的故事娓娓道来。
Jeremy早先在一家互联网在线视频公司干了10年。他半开玩笑地说即便干了10年也不如跟腾讯合作一个项目来得出名。后来他加入XebiaLabs。这是一家专门做DevOps平台产品的公司在国内可能不是特别出名但如果提到DevOps工具元素周期图相信你肯定听说过这就是这家公司迭代更新的。
<img src="https://static001.geekbang.org/resource/image/fa/bc/fa1f9db00986532b0acc1790043178bc.png" alt="">
>
图片来源:[https://xebialabs.com/periodic-table-of-devops-tools/](https://xebialabs.com/periodic-table-of-devops-tools/)
在今年的4月份他加入了CloudBees成为了主管开源和商业版本Jenkins的高级产品经理。在跟他交流的过程中我对产品经理这部分内容的印象非常深刻。我梳理了一些要点分享给你。如果你已经是DevOps产品经理或者是立志要成为DevOps产品经理的话你一定要认真看一下。
## 一、自我颠覆
什么叫自我颠覆呢我给你举个例子。比如Jenkins的用户UI项目Blue Ocean很多人应该都知道目前这个项目的主要开发已经停止了。社区仍然会修复缺陷和安全漏洞也会接受开发者共享的PR但是不会再投入专职工程师进行开发工作了新需求也都处于无限暂停的状态。
实际上不仅仅是Blue Ocean去年Jenkins大会上星光闪耀的项目比如Five super power、Jolt in Jenkins、Evergreen等项目也都因为方向调整和人员变动而处于半终止、暂缓开发的状态。那么为什么在短短一年的时间内会有这么大的颠覆性变化呢我把这个问题抛给了Jeremy。
他的观点是,这些项目并非没有意义,但是确实没有达到项目原本的预期。对于产品经理来说,**管理预期是一项非常重要的能力**。当需求走到产品经理的时候,做哪个、不做哪个经常是个问题。团队往往会进行协商,挑选出来最有希望的项目,但这并不代表这些项目注定会成功。相反,很多想法只有做了才知道是不是靠谱,用户是不是买单。**如果使用场景有限,又没有很好的增长性,及时叫停反而是一种好的选择**。
Blue Ocean项目诞生之初可以说是让人眼前一亮充满期待甚至一度和Jenkins流水线一起被视为2.0版本的最大功能。但是几年之后,由于产品性能、插件扩展支持等种种原因,真正在企业中大规模使用的机会并不多。正因为项目没有达到预期,产品团队就决定停止这个项目。
但是与此同时全新的Jenkins用户界面项目已经被提到了日程表中。这个全新的用户界面大量借鉴了Blue Ocean的设计思路并最终通过一套用户界面取代了现有的Blue Ocean。我想正是这种不断的自我颠覆才让一个15年的软件始终保持着活力和创新力。
## 二、化繁为简
对于Jenkins这样的产品来说很多插件都是开发者提供的但是开发者往往倾向于追求功能的全面性这从很多插件的设计中就能看出来。
开发者不加筛选地把所有功能都罗列在用户面前,自然是得心应手。但是,对普通用户来说,当他第一眼看到这个复杂产品的时候,他的使用意愿就会大打折扣。
另外面对这么多的插件从表面上看用户好像有很多选择但是有些插件的名字长得差不多你并不知道哪个能用。或者有些插件适用于当前的Jenkins版本但是一旦Jenkins升级它们就无法正常使用了。但是用户在升级之前并不知道是否适配往往是在升级完成之后才会发现问题只能再进行版本回滚。类似这些插件使用中的问题都给用户带来了很大的使用障碍。
在探讨这个问题的时候Jeremy也认为**系统过于复杂有悖于产品设计的初衷**,但是,作为一个公开的平台,他们并不能约束开发者的行为,所以就需要一种方法来平衡功能的全面性和功能的易用性。
比如在重新考虑Jenkins插件生态的时候一方面产品团队会针对全新的业务场景提供官方的插件支持。举个例子在云原生开发场景下通过和云服务商深度合作提供更多的官方插件来满足典型的云服务商的使用场景。无论是对亚马逊的AWS、微软的Azure还是未来国内的主流云服务商他们都会通过这种方式来进行合作。无论你使用的开源产品还是商业产品都能通过这个项目来获得收益。
另一方面产品团队也会进一步对现有的1600多款插件进行分类并将其中的一部分插件纳入CloudBees的保障项目之下。这就意味着将由CloudBees公司来保证这类插件的兼容性和可用性。对于专业用户来说他们依然可以按照自己的方式自由地选择和开发插件而对于普通用户来说官方推荐的插件集合就足够了。
不仅仅是插件,产品的易用性体现在产品设计的方方面面。凡是阻塞用户使用的问题,都是需要优先解决的。
比如对于一个10多年的产品来说历史积累的文档数量巨大很多时候用户都无法找到真正有用的信息。所以Jenkins产品团队启动了一个文档治理的项目会重新梳理所有文档并把它们迁移到GitHub平台上。另外他们还会结合新的产品功能整理出最佳实践。比如对于流水线使用来说官方也总结了很多[最佳实践](https://support.cloudbees.com/hc/en-us/articles/230922208-Pipeline-Best-Practices)供入门者参考,你可以结合前面两讲的内容一起学习。
**要始终记得,不要让你的产品只有专家才会使用。将复杂的问题简单化,是产品经理不论何时都要思考的问题。**
## 三、退后一步
DevOps的产品经理大多是技术人员出身因此会特别容易一上来就深入细节甚至是代码实现的细节。
Jeremy同样也是程序员出身他做过很长一段时间的前端开发。当我问他“**一个好的产品应该如何平衡用户视角和实现视角**”的时候,他给我的回答是,**要尽量退后一步来看问题**。
**退后一步,就是说不要把关注点只聚焦在问题表面,而是要尽量站在旁边,以第三方的视角来全面审视问题**
他举了个Jenkins的流水线即代码的例子。在实际使用的时候流水线文件中经常会有大量的代码有时候流水线代码甚至会有上千行。代码越多系统的不稳定因素就越多测试起来也越麻烦。同时按照现有的运行机制来说很多代码都是运行在master节点上的这就给集群的master节点带来了很大压力。
要想解决这个问题从实现的角度出发就是提供一种标准化、结构化的语法格式也就是声明式流水线语法以此来降低流水线的编写难度减少流水线代码量并且让这个代码结构更加清晰。但是这些优化依然不能解决集群master节点压力过大的问题这就相当于问题只看了一部分。
退后一步来看,这就需要一种全新的视角,来提升流水线整体的隔离性。所以,产品团队目前就在设计一种新的流水线组件 **building block**,也就是构建块。
**所谓构建块,是指一整块的代码片段,而不是一条条独立的指令**。这些构建块结合到一起就可以满足一个具体场景的问题。比如Maven打包构建的场景构建块可以帮你解决环境、工具、构建命令等一系列问题。这些构建块以代码形式在子节点上运行既降低了流水线的编写难度也缓解了master节点上的压力。对用户来说使用构建块也更为简单可以直接把它放在自定义的步骤中执行。
对于产品经理来说,找到方案、解决问题自然是职责所在,但与此同时,他们往往需要同时保有两种思维,即**用户思维和实现思维**。能够在这两种思维之间自由切换,是产品经理走向成熟的标志。
## 总结
说到这儿,我来回答一下最开始的那个问题,也就是“为什么是产品经理来分享产品的规划呢?”这是因为,无论要开发一个多大还是多小的产品,都需要有这样一拨人来退后一步,找到用户的真实问题,化繁为简,实现这个功能,并不断颠覆自己,持续打磨和改进。这对于任何一个想要解决更多人问题的产品来说,都是至关重要的。
## 思考讨论
关于这次Jenkins World大会你还有什么希望进一步了解的内容吗欢迎你积极提问我会知无不言。
如果你觉得这篇文章对你有所帮助,也欢迎你把文章分享给你的朋友。

View File

@@ -0,0 +1,10 @@
你好,我是石雪峰。
《DevOps实战笔记》已经结课一段时间了你掌握得怎么样了呢我给你准备了一个结课小测试来帮助你检验自己的学习效果。
这套测试题共有20道选择题考题范围覆盖专栏的 30 讲正文,题目类型为单选题和多选题,满分 100 分,系统自动评分。
还等什么,点击下面按钮开始测试吧!
[<img src="https://static001.geekbang.org/resource/image/28/a4/28d1be62669b4f3cc01c36466bf811a4.png" alt="">](http://time.geekbang.org/quiz/intro?act_id=155&amp;exam_id=344)

View File

@@ -0,0 +1,57 @@
<audio id="audio" title="结束语 | 持续改进,成就非凡!" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/ec/28/ec038cefca0b45ec59a6dffd6a48b628.mp3"></audio>
不知道你是否看过或者听说过《中国好声音》这个节目?在这个节目中,导师总会发出“灵魂拷问”:“你的梦想是什么?”
和很多“80后”的男孩子一样我最初的梦想就是当一名飞行员翱翔天空。但是随着视力越来越差身体越长越高我才发现并非所有的梦想都能实现。好在我还留了一手因为我还有另外一个梦想那就是当一名老师。现在我的这个梦想已经在极客时间上实现了。
为什么想当老师呢?说真的,我也不记得当初是怎么想的了,可能是因为在中小学生眼中,老师这个形象都是霸气侧漏的。但随着年龄的增大,我越发觉得,当老师这个事情真的没有那么容易。你应该也听说过“教学相长”这个词,但你有没有想过,“教”为什么在“学”的前面,是“教学相长”,而不是“学教相长”呢?
或许,只有当你的身份从一名学生变为一位老师的时候,你才能真的想明白这个问题。实际上,很多时候,教的人可能比学的人收获要大得多。为什么这么说呢?
任何一门课程,任何一个知识点,你在学的时候可以不懂,大不了就当没听过,等到真正用到的时候,临时再学也是可以的。但是,作为老师,你不仅要懂,还要逻辑清晰、思维缜密,甚至要尽可能地用有趣的方式把别人教会,这可就没那么简单了。
不过,任何一个知识领域都是博大精深的,你不可能对每一个细节都了如指掌,这就会逼着你不断学习、不断思考、不断精进。我想,这就是输出式学习之所以高效的奥秘所在。
对于专栏写作来说这个道理也同样适用。几个月的持续输出无论是对精力、体力还是家庭和谐力都是一场漫长的试炼。在专栏完结的时间点我看到的不仅仅是20万字的内容更多的是自己身上的不足而这些都是我成长道路上的灯塔指引我面向未来持续精进。
在最后,我想给你分享我在专栏写作中的三个心得,希望这些心得可以帮助你在未来的学习道路上披荆斩棘,无往而不利。
当你跨越技术领域的门槛之后,**知识的体系化程度**就成了决定你未来发展高度的一个重要因素。只有建立了自己的知识体系,并不断地吸收外界精华,你才能让这些知识和经验在身体内不断循环、沉淀,并最终成为你的一部分。这也是写作专栏几个月以来,我想给你分享的第一个心得:建立自己的知识体系,持续进行输出式学习。
对于一篇专栏的写作来说,你知道什么时间点最可怕吗?那就是当你打开一个空白的文档,却不知道第一个字应该写什么的时候。这跟我们平时的工作是很相似的,**你知道这件事要做到什么程度,可就是不知道该如何开始**。脑子里思绪万千,身体的疲劳有时还在同你作对,当你在不断地自我怀疑的时候,时间却悄悄地跑掉了,而你终究还是得自己面对这个问题。这该如何是好呢?
有句经典的话大概是这么说的:“一件事情,当你不想去做的时候,理由可以有一百个,**但是当你决定做的时候,理由只有一个,那就是做**。”很多事情并没有你想象的那么困难。我们不是科学家也不是要解决人类的未解之谜我们面对的都是身边的问题。我们之所以觉得这些事情很难缺少的往往不是能力、经验和学识而是“先干再说”的勇气和信心。因为只要开始做了你就已经成功一半了。对于DevOps这种改进类工作来说更是如此**你要先想尽一切办法完成它,有机会再追求完美**,这可比一开始就全盘规划要实际得多。这也是我想分享给你的第二个心得:完成比完美更重要,很多事情可以先干再说。
我们家也有一句特别经典的话,那就是**有日子就快**。这句话的意思就是,**对于一件事情,你只要确定了里程碑,时间就会带领你快速地抵达那个终点**。比如,对于一个项目的推进来说,事先看见全貌和里程碑节点就是至关重要的。在专栏的写作过程中,我认为最最重要的一份素材,就是编辑同学帮我整理的《专栏发布排期计划》,里面注明了我每星期、每天需要完成的任务。
虽然计划就是为了被打破而存在的它永远也赶不上变化尤其是在软件的世界里Delay似乎是一件不可避免的事情但是这个计划存在的目的是帮你守住一件事情的下限。既然最差也就如此了多做一点就多一点成功那你又何必纠结和焦虑呢所以在推进项目的时候尤其是在依赖多人协作的时候一个清晰的项目计划至关重要。这恰恰是我想分享给你的第三个心得让计划帮你守住底线让行动为成功添砖加瓦。
我想,此时此刻还在坚持看下去、听下去的你内心里一定有一团火焰,激励着自己有朝一日可以脱颖而出。因此,在最后的最后,我特别想给你分享一些我个人的职业生涯发展的经验,这也是帮助我从一个默默无闻的小兵成长为极客时间作者的秘密。
**1.找到自己适合的领域**
要知道,**并非所有人都适合所有领域**。有的人天生就是编程高手有的人天生就爱与人沟通与其在你不擅长的领域死磕不如找到自己擅长的领域并不断深耕。与此同时要以这个领域为起点不断向外扩展营造自己的“护城河”体系提升自己的专业素养。这些是你将来安身立命的本事你一定要让自己有几个拿得出手的核心技能。如果你现在还答不上来你擅长的领域和核心技能是什么那么2020年请继续努力。
**2.打造自己的专属标签**
当你掌握了一门核心手艺之后,你可以在这个圈子里不断地总结和分享,建立起别人对你的初始认知。只要你用心,你就会发现,这种分享的机会其实有很多,如果你苦于没有途径,欢迎你来找我。
不过,这还并不足以让你脱颖而出,最多也只能达到平均水准。这时候,你需要的就是等待一个机会,比如一门新技术、一种新思想、一个新工具,什么都可以。然后,你要快速地抓住这个机会,让自己站在第一线,去分享,去实践,去布道,让它成为你的专属标签。
**3.不断积累成功,打造自己的良好口碑**
你要知道,有一种能力,叫作“让别人相信你”的能力。企业在为某个职位寻找合适的人选时,为什么选你而不选别人呢?除了你自身过硬的技术素养之外,**你能不能让别人相信你的能力,是你能否突破天花板的重要因素**。那这种能力从何而来呢?我认为,这是来自于过往点滴的积累,最终由量变产生的质变。所以,请你善待每一个机会,善待每一个人。在企业中,要么**提升自己的执行力**,要么**提升自己的创新力**,要么**让自己能够快速地整合资源**,只有这样,你才能具备成功的资本。
**4.保持责任心、进取心和事业心**
不管做什么事情,最重要的就是责任心,要把自己该做的事情做好,**做正确的事情而不仅仅是KPI要求的事情**。另外,你要保持进取心,并且对新事物、新技术保持长久的好奇和开放的心态,而不是故步自封,局限在自己的一亩三分地上。如果可能的话,要把自己的工作视为一个事业,你要保持着“**每一行代码都是你的名片,每一个产品都是你的代言人**”的信念,和团队一起努力,共同成长,只要还有一丝改进空间,就不要轻言放弃。
正如这篇文章的标题所说的,只有持续改进,才能成就非凡,也必将不枉此生。
希望这个专栏能够带给你一些灵感和新知不管怎样感谢你陪我一起走过2019年的夏天、秋天和冬天。
最后,我给你准备了一份调研问卷,欢迎你点击下面的图片,去填写问卷,给我和专栏提供一些宝贵的建议,期待你的反馈。
[<img src="https://static001.geekbang.org/resource/image/7d/f7/7de2d3cdb3df56733dc756c7f91a4ef7.jpg" alt="">](https://jinshuju.net/f/dpwPVd)
P.S. 最最后,感谢我的夫人在这半年里给予我的无私“支持和理解”,如果不是她,这个专栏早就写完了。

View File

@@ -0,0 +1,12 @@
你好!
《DevOps实战笔记》的结课问卷已经回收完毕今天我们来公布一下获奖用户名单。
在这里,我首先要感谢各位同学给我们的反馈。在这些反馈里,有指出我们做得好的地方,也有指出我们可以继续优化的地方。本着“对专栏的改进最有帮助”的原则,我们挑选了 5 位用户,送出“数据结构与算法知识地图(上 +下)”,或者是价值 99 元的极客时间课程阅码。中奖名单如下:
<img src="https://static001.geekbang.org/resource/image/63/4f/631ffe83d321f53e50b18928785d7c4f.jpg" alt="">
非常感谢以上 5 位同学提出的宝贵意见,也恭喜他们!
雪峰老师曾在开篇词里将专栏学习称为“一场奇妙的DevOps旅行”现在希望你不仅走过了这场旅行的每一条路也收获了新的知识、思考与见解。当然专栏的结束也是另一种开始我们会和雪峰老师继续迭代、优化专栏内容雪峰老师也会持续关注并回复你的留言所以也希望你可以继续关注本专栏并将你的问题或者建议通过留言反馈给我们

View File

@@ -0,0 +1,140 @@
<audio id="audio" title="05 | 价值流分析关于DevOps转型我们应该从何处入手" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/9b/ae/9b64eb475fd7994730604fd3c1c264ae.mp3"></audio>
你好,我是石雪峰。
关于“DevOps如何落地”的问题向来是关注度很高的所以从今天开始我会用16讲的篇幅跟你聊聊这个话题的方方面面。作为“落地实践篇”的第1讲我先跟你聊聊DevOps转型的那些事儿。
相信你一定听说过持续交付吧现在几乎每家实施DevOps的企业都宣称他们已经有了一套持续交付平台或者是正在建设持续交付平台。但是如果你认为只需要做好持续交付平台就够了那就有点OUT了。因为现在国外很多搞持续交付产品的公司都在一门心思地做另外一件事情这就是VSM价值流交付平台。
比如Jenkins的主要维护者CloudBees公司最新推出的DevOptics产品主打VSM功能而经典的持续交付产品GoCD的VSM视图也一直为人所称道。那么这个VSM究竟是个啥玩意儿呢
要说清楚VSM首先就要说清楚什么是价值。简单来说**价值就是那些带给企业生存发展的核心资源**,比如生产力、盈利能力、市场份额、用户满意度等。
VSM是Value Stream Mapping的缩写也就是我们常说的价值流图。它起源于传统制造业的精益思想用于分析和管理一个产品交付给用户所经历的业务流、信息流以及各个阶段的移交过程。
说白了VSM就是要说清楚在需求提出后怎么一步步地加工原材料进行层层的质量检查最终将产品交付给用户的过程。通过观察完整流程中各个环节的流动效率和交付质量识别不合理的、低效率的环节进行优化从而实现整体效率的提升。
这就好比我们在餐厅点了一道菜,这个需求提出后,要经历点单、原材料初加工(洗菜)、原材料细加工(切菜)、制作(炒菜),最终被服务员端到餐桌上的完整过程。但有时候,厨师已经把菜做好摆在窗口的小桌上了,结果负责上菜的服务员正在忙,等他(她)忙完了,才把菜端到我们的餐桌上,结果热腾腾的锅气就这么流失了。
对软件开发来说,也是如此。由于部门职责的划分,每个人关注的都是自己眼前的事情,这使得软件交付过程变得碎片化,以至于没有一个人能说清楚整个软件交付过程的方方面面。
所以通过使用价值流图对软件交付过程进行建模使整个过程可视化从而识别出交付的瓶颈和各个环节之间的依赖关系这恰恰是“DevOps三步工作法”的第一步“流动”所要解决的问题。
我简单介绍下“DevOps三步工作法”。它来源于《DevOps实践指南》可以是说整本书的核心主线。高度抽象的“三步工作法”概括了DevOps的通用实施路径。
- **第一步:流动**。通过工作可视化,限制在制品数量,并注入一系列的工程实践,从而加速从开发到运营的流动过程,实现低风险的发布。
- **第二步:反馈**。通过注入流动各个过程的反馈能力,使缺陷在第一时间被发现,用户和运营数据第一时间展示,从而提升组织的响应能力。
- **第三步:持续学习和试验**。没有任何文化和流程是天生完美的,通过团队激励学习分享,将持续改进注入日常工作,使组织不断进步。
## 关键要素
你并不需要花大力气去研究生产制造业中的价值流分析到底是怎么玩的你只要了解有关VSM的几个关键要素和核心思想就行了。那么VSM中有哪些关键要素和概念呢有3点是你必须要了解的。
1. **前置时间**Lead Time简称LT。前置时间在DevOps中是一项非常重要的指标。具体来说它是指一个需求从提出典型的就是创建一个需求任务的时间点开始一直到最终上线交付给用户为止的时间周期。这部分时间直接体现了软件开发团队的**交付速率**,并且可以用来计算**交付吞吐量**。**DevOps的核心使命之一就是优化这段时长**。
1. **增值活动时间和不增值活动时间**Value Added Time/Non-Value Added Time简称VAT/NVAT。在精益思想中最重要的就是**消除浪费**,也就是说最大化流程中那些增值活动的时长,降低不增值活动的时长。在软件开发行业中,典型的不增值活动有很多,比如无意义的会议、需求的反复变更、开发的缺陷流向下游带来的返工等。
1. **完成度和准确度**% Complete/Accurate简称%C/A。这个指标用来表明工作的质量也就是有多少工作因为质量不符合要求而被下游打回。这里面蕴含了大量的沟通和返工成本从精益的视角来看也是一种浪费。
在实践中,企业往往将需求作为抓手,来串联打通各个环节,而前置时间是需求管理的自然产物,采集的难度不在于系统本身,而在于各环节的操作是否及时有效。有的团队也在使用需求管理工具,但是前置时长大多只有几秒钟。问题就在于,他们都是习惯了上线以后,一下子把任务状态直接从开始拖到最后,这样就失去了统计的意义。
需要注意的是,关于前置时间,有很多种解释,一般建议采用**需求前置时间**和**开发前置时间**两个指标进行衡量,关于这两个指标的定义,你可以简单了解一下。
>
需求前置时间:从需求提出(创建任务),到完成开发、测试、上线,最终验收通过的时间周期,考查的是团队整体的交付能力,也是用户核心感知的周期。
>
开发前置时间:从需求开始开发(进入开发中状态),到完成开发、测试、上线,最终验收通过的时间周期,考查的是团队的开发能力和工程能力。
对于增值活动时长,我的建议是初期不用过分精细,可以优先把等待时长统计出来,比如一个需求从准备就绪,到进入开发阶段,这段时间就是等待期。同前置时间一样,很多时候,研发的操作习惯也会影响数据的准确性,比如有的研发喜欢一次性把所有的需求都放到开发阶段,然后再一个个处理掉,这就导致很多实际的等待时间难以识别。所以,如果完全依靠人的操作来确保流程的准确性,就会存在很大的变数。**通过流程和平台的结合来驱动流程的自动化流转这才是DevOps的正确姿势。**
举个例子,研发开发完成发起提测后,本次关联的需求状态可以自动从“开发中”变成“待测试”状态,而不是让人手动去修改状态,这样就可以避免人为因素的影响。通过代码,流水线和需求平台绑定,从而实现状态的自动流转。
关于完成度和准确度在使用VSM的初期可以暂不处理。实际上我见过一些公司在跑通主流程之后着手建设质量门禁相关的指标比如研发自测通过率这些指标就客观地反映了VSM的完成度和准确度。关于质量门禁在专栏后面我会花一讲的时间来介绍你一定不要错过。
## 方式
关于VSM的关键要素知道这些就足够了。那么作为企业DevOps转型工作的第一步我们要如何开展一次成功的VSM活动呢一般来说有2种方式。
1.**召开一次企业内部价值流程梳理的工作坊或者会议。**
这是我比较推荐的一种方式。对于大型企业而言,可以选取改进项目对象中某个核心的业务模块,参加会议的人员需要覆盖软件交付的所有环节,包括工具平台提供方。而且,参会人员要尽量是相对资深的,因为他们对自身所负责的业务和上下游都有比较深刻的理解,比较容易识别出问题背后的根本原因。
不过,这种方式的实施成本比较高。毕竟,这么多关键角色能够在同一时间坐在一起本身就比较困难。另外,面对面沟通的时候,为了给对方保留面子,大家多少都会有所保留,这样就会隐藏很多真实的问题。
所以,一般情况下,像团队内部的**敏捷回顾会**,或者是**版本发布总结会**,都是很合适的机会,只需要邀请部分平常不参会的成员就行了。
2.**内部人员走访。**
如果第1种方式难以开展你可以退而求其次地采用第2种方式。通常来说企业内部的DevOps转型工作都会有牵头人甚至会成立转型小组那么可以由这个小组中的成员对软件交付的各个环节的团队进行走访。这种方式在时间上是比较灵活的但对走访人的要求比较高最好是DevOps领域的专家同时是企业内部的老员工这样可以跟受访人有比较深入坦诚的交流。
无论哪种方式,你都需要识别出几个关键问题,缩小谈话范围,避免漫无目的地东拉西扯,尽量做到有效沟通。比如,可以建立一个问题列表:
- 在价值交付过程中,你所在团队的主要职责是什么?
- 你所在团队的上下游团队有哪些?
- 价值在当前环节的处理方式,时长是怎样的?
- 有哪些关键系统支持了价值交付工作?
- 是否存在等待或其他类型的浪费?
- 工作向下游流转后被打回的比例是多少?
为了方便你更好地理解这些问题,我给你提供一份测试团队的访谈示例。
<img src="https://static001.geekbang.org/resource/image/e1/58/e147f1cbae3847793d7c10eaccba0058.jpg" alt="">
通过访谈交流我们就可以对整个软件交付过程有一个全面的认识并根据交付中的环节、上下游关系、处理时长、识别出来的等待浪费时长等按照VSM模型图画出当前部门的价值流交付图以及各个阶段的典型工具如下图所示
<img src="https://static001.geekbang.org/resource/image/b4/6c/b469758cb927c11b04edf254dd1a666c.png" alt="">
当然实际交付流程相当复杂涉及到多种角色之间的频繁互动是对DevOps转型团队的一种考验。因为这不仅需要团队对软件开发流程有深刻的认识还要充分了解DevOps的理念和精髓在沟通方面还得是一把好手能够快速地跟陌生人建立起信任关系。
## 价值
话说回来为什么VSM会是企业DevOps转型的第一步呢实际上它的价值绝不仅限于输出了一幅价值流交付图而已。VSM具有非常丰富的价值包括以下几个方面
**1.看见全貌。**
如果只关注单点问题我们会很容易陷入局部优化的怪圈。DevOps追求的是**价值流动效率最大化**,也就是说,就算单点能力再强,单点之间的割裂和浪费对于价值交付效率的影响也是超乎想象的。所以,对于流程改进来说,第一步,也是最重要的一步,就是能够看见全貌,这样才能从全局视角找到可优化的瓶颈点,从而提升整体的交付效率。
另外,**对于全局交付的建模,最终也会体现到软件持续交付流水线的建设上**,因为流水线反映的就是企业客观的交付流程。这也就很好理解,为啥很多做持续交付流水线的公司,现在都延伸到了价值流交付平台上。因为这两者之间本身就存在一些共性,只不过抽象的级别和展现方式不同罢了。
**2.识别问题。**
在谈到企业交付效率的时候,我们很容易泛泛而谈,各种感觉满天飞,但感觉既不可度量,也不靠谱,毕竟,它更多地是依赖于个人认知。换句话说,即便交付效率提升了,也不知道是为啥提升的。
而VSM中的几个关键指标也就是前置时长、增值和不增值时长以及完成度和准确度都是可以客观量化改进的指标。当面对这样一幅价值流图的时候我们很容易就能识别出当前最重要的问题和改进事项。
**3.促进沟通。**
DevOps倡导通过团队成员间的沟通和协作来提升交付效率但客观现实是在很多企业中团队成员基本都是“网友关系”。即便都在一个楼里办公也会因为部门不同坐在不同的地方基本上只靠即时通讯软件和邮件交流。偶尔开会的时候能见上一面但也很少有深入的交流。如果团队之间处于你不认识我、我也不认识你的状况下又怎么有效协作呢
另外很多时候在我们开展VSM梳理的时候团队才第一次真正了解上下游团队的职责、工作方式以及让他们痛苦低效的事情。这时我们通常会设身处地地想“只要我们多做一点点就能大大改善兄弟团队的生存状况了。”实际上这种**同理心对打破协作的壁垒很有帮助**可以为改善团队内部文化带来非常正面的影响。实际上这也是我推荐你用会议或者工作坊的方式推进VSM的根本原因。
**4.驱动度量。**
我们都认可数据的力量让数据驱动改进。但是面对这么庞杂的数据体系到底哪些才是真正有价值的呢VSM就可以回答这个问题。
在VSM访谈的时候我们要问一个团队的交付周期、准确率等指标问题如果你发现这个团队支支吾吾只能给出模糊的回答这时你就要注意啦这里本身就大有问题。因为这就表示当前环节的度量指标不够清晰或者指标过于复杂团队不清楚关键的结果指标。
另外,如果数据的提取需要大量时间,比如需要采用人为统计算数的方式,那么这就体现了这个环节的平台建设能力不足,无法自动化地收集和统计数据,甚至有些关键数据还没有沉淀到数据系统中,只能通过人工本地化的方式进行管理。
这些都是DevOps转型的过程中需要解决的问题可以优先处理。可以说**VSM是一场团队协作的试炼**。收集VSM数据的过程本身就需要平台间的打通和数据共享以及自动化的推进这有助于度量活动的开展。
**5. 价值展现。**
对于企业而言任何投入都需要有产出。要实现DevOps的转型企业需要投入大量的精力。那么如何让高层领导明白企业交付效率改善所带来的价值呢价值流梳理就是一种很好的方式。因为VSM从价值分析而来到价值优化而去本身就是在回答DevOps对于企业的价值问题。
## 总结
在这一讲中我给你介绍了DevOps转型的第一步——VSM价值流图包括它的来源、3个关键要素以及在企业中开展VSM的2种方式。最后我介绍了VSM的5大价值分别是看见全貌、识别问题、促进沟通、驱动度量和价值展现。
就像我们常说的DevOps转型是一场没有终点的旅程VSM的梳理也不会是一帆风顺的。因为对于企业价值交付流程的梳理需要随着认知的深入不断地进行迭代和优化。不过好的开始是成功的一半当我们开始梳理VSM的时候我们的着眼点就会慢慢调整到DevOps模式并真正地开启我们的DevOps转型之旅。
<img src="https://static001.geekbang.org/resource/image/7c/dc/7c5851cdbeb135853f4d8d46b023dfdc.jpeg" alt="">
## 思考题
最后给你留一道思考题你认为在公司内部梳理价值流的最大障碍是什么在提取价值流图中的3个关键要素的数据时你遇到过什么挑战吗
欢迎在留言区写下你的思考和答案,我们一起讨论,共同学习进步。如果你觉得这篇文章对你有所帮助,欢迎你把文章分享给你的朋友。

View File

@@ -0,0 +1,105 @@
<audio id="audio" title="06 | 转型之路企业实施DevOps的常见路径和问题" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/dc/5e/dc2955e14fcafca78f65e7db4336435e.mp3"></audio>
你好我是石雪峰。今天我来跟你聊聊企业实施DevOps的常见路径和问题。
由于种种原因我曾直接或者间接地参与过一些企业的DevOps转型过程也跟很多企业的DevOps负责人聊过他们的转型故事。这些企业的转型过程并不是一帆风顺的在最开始引入DevOps的时候他们也面临很多普遍的问题比如企业业务都忙不过来了根本没有时间和精力投入转型工作之中或者是企业内部的系统在经历几代建设之后变得非常庞大以至于谁都不敢轻易改变。
但是,即便存在着种种问题,我也始终认为,**DevOps转型之路应该是有迹可循的**。很多企业所面临的问题并不是独一无二的,甚至可以说,很多公司都是这样一步步走过来的。所以,在转型之初,如果能够参考借鉴一条常见的路径,并且对可能遇到的问题事先做好准备,企业的转型过程会顺利很多。
## 两种轨迹
其实对于企业的转型来说DevOps也并没有什么特别之处跟更早之前的敏捷转型一样如果想在企业内部推行一种新的模式无外乎有两种可行的轨迹**一种是自底向上,一种是自顶向下。**
### **自底向上**
在这种模式下企业内部的DevOps引入和实践源自于一个小部门或者小团队他们可能是DevOps的早期倡导者和实践者为了解决自身团队内部以及上下游团队交互过程中的问题开始尝试使用DevOps模式。由于团队比较小而且内部的相关资源调动起来相对简单所以这种模式比较容易在局部获得效果。
当然DevOps的核心在于团队间的协作仅仅一个小团队内部的改进还算不上是DevOps转型。但是就像刚刚提到的那样如果企业太大以至于很难一次性改变的话的确需要一些有识之士来推动这个过程。如果你也身处在这样一个团队之中那么我给你的建议是采用“羽化原则”也就是首先在自己团队内部以及和自己团队所负责的业务范围有强依赖关系的上下游团队之间建立联系**一方面不断扩展自己团队的能力范围另一方面逐步模糊上下游团队的边界由点及面地打造DevOps共同体**。
当然如果想让DevOps转型的效果最大化你一定要想方设法地让高层知晓局部改进的效果让他们认可这样的尝试最终实现横向扩展在企业内部逐步铺开。
###
**自顶向下**
你还记得我在专栏[第2讲](https://time.geekbang.org/column/article/146839)中提到的那家把DevOps定义为愿景OKR指标的金融企业吗这就是典型的自顶向下模式也就是企业高层基于自己对于行业趋势发展的把握和团队现状的了解以行政命令的方式下达任务目标。在这种模式下公司领导有足够的意愿来推动DevOps转型并投入资源各个团队也有足够清晰的目标。
那么这样是不是就万事大吉了呢其实不然。在企业内部有这样一种说法只要有目标就一定能达成。因为公司领导对于细节的把握很难做到面面俱到团队为了达成上层目标总是能想到一些视角或数据来证明目标已经达成这样的DevOps转型说不定对公司业务和团队而言反而是一种伤害。
举个例子有一次我跟一家公司的DevOps转型负责人聊天。我问道“你们的前置时间是多久”他回答说“一周。”我心想这还挺好的呀。于是就进一步追问“这个前置时间是怎么计算的呢”他回答说“我们计算的是从开发开始到功能测试完成的时间。”我心想这好像有点问题。于是我就又问道“那从业务方提出需求到上线发布的时间呢”他回答“这个啊大概要两个月时间。”你看难怪业务方抱怨不断呢提个需求两个月才能上线。但是如果仅仅看一周的开发时长感觉是不是还不错呢
所以,一套客观有效的度量指标就变得非常重要,关于这个部分,我会用两讲的时间来和你详细聊聊。
说到这儿不知道你发现了没有无论企业的DevOps转型采用哪条轨迹**寻求管理层的认可和支持都是一个必选项**。如果没有管理层的支持DevOps转型之路将困难重重。因为无论在什么时代变革一直都是一场勇敢者的游戏。对于一家成熟的企业而言无论是组织架构、团队文化还是工程能力、协作精神都是长期沉淀的结果而不是在一朝一夕间建立的。
除此之外转型工作还需要持续的资源投入这些必须借助企业内部相对比较high level的管理层的推动才能最终达成共识并快速落地。如果你所在的公司恰好有这样一位具备前瞻性视角的高层领导那么恭喜你你已经获得了DevOps转型道路上至关重要的资源。
我之前的公司就有这样一位领导他一直非常关心内部研发效率的提升。听说他要投入大量资源加紧进行DevOps能力建设时我兴奋地描绘了一幅美好的图景但当时他说了一句意味深长的话“这个事你一旦做起来就会发现并不容易。”后来在实施DevOps的过程中这句话无数次得到了印证。
## 通用路径
因此你看管理层的支持只是推动DevOps转型的要素之一在实际操作过程中还需要很多技巧。为了帮助你少走弯路我总结提取了一条通用路径现在分享给你。
**第1步寻找合适的试点项目**
试点项目是企业内部最初引入DevOps实践并实施改进工作的业务对象。可以说一个合适的项目对于企业积累DevOps实践经验是至关重要的。我认为一个合适的项目应该具备以下几个特征
- **贴近核心业务**。DevOps要以业务价值为导向。对于核心业务管理层的关注度足够高各项业务指标也相对比较完善如果改进效果可以通过核心业务指标来呈现会更有说服力。同时核心业务的资源投入会有长期保障。毕竟你肯定不希望DevOps转型落地项目因为业务调整而半途而废吧。
- **倾向敏捷业务**。敏捷性质的业务需求量和变更都比较频繁更加容易验证DevOps改造所带来的效果。如果一个业务以稳定为主要诉求整体处于维护阶段变更的诉求和意愿都比较低那么这对于DevOps而言就不是一个好的选择。我之前在跟一家军工企业沟通的时候了解到他们每年就固定上线两次那么在这种情况下你说还有没有必要搞DevOps呢
- **改进意愿优先**。如果公司内部的团队心比天高完全瞧不上DevOps觉得自己当前的流程是最完美的那么你再跟他们费力强调DevOps的价值结果很可能事倍功半。相反那些目前绩效一般般的团队都有非常强烈的改进诉求也更加愿意配合转型工作。这时团队的精力就可以聚焦于做事本身而不会浪费在反复拉锯的沟通上。
**第2步寻找团队痛点**
找到合适的团队,大家一拍即合,接下来就需要识别团队的痛点了。所谓痛点,就是当前最影响团队效率的事情,同时也是改进之后可以产生最大效益的事情。
不知道你有没有读过管理学大师高德拉特的经典图书《目标》,他在这本书中,提出的最重要的理论就是约束理论。关于这个理论,我会在后面的内容中展开介绍,现在你只需要记得“木桶原理”就行了,即最短的木板决定了团队的容量。
至于如何找寻痛点,我已经在上一讲详细介绍过了。你不妨在内部试点团队中开展一次价值流分析活动,相信你会有很多意外的发现。如果你不记得具体怎么做了,可以回到[第5讲](https://time.geekbang.org/column/article/152806)复习一下。
**第3步快速建立初期成功**
找到了合适的团队也识别出了一大堆改进事项你是不是感觉前景一片大好准备撸起袖子加油干了呢打住这个时候切记不要把面铺得太广把战线拉得太长这其实是DevOps转型初期最典型的一个陷阱。
首先,转型初期资源投入有限,难以支撑大量任务并行。其次,由于团队成员之间还没有完全建立起信任关系,那些所谓的最佳实践很容易水土不服。如果生搬硬套的话,很可能会导致大量摩擦,从而影响改进效果。最后,管理层的耐心也没有想象中那么多,如果迟迟看不到效果,很容易影响后续资源的投入。
所以,**最关键的就是识别一个改进点,定义一个目标**。比如环境申请和准备时间过程那么就可以定义这样一个指标优化50%的环境准备时长。这样一来,团队的目标会更加明确,方便任务的拆解和细化,可以在几周内见到明显的成果。
**第4步快速展示和持续改进**
取得阶段性的成果之后,要及时向管理层汇报,并且在团队内部进行总结。这样,一方面可以增强管理层和团队的信心,逐步加大资源投入;另一方面,也能够及时发现改进过程中的问题,在团队内部形成持续学习的氛围,激发团队成员的积极性,可以从侧面改善团队的文化。
当然,类似这样的案例在企业内部都极具价值。如果可以快速扩展,那么效果就不仅仅局限于小团队内部,而是会上升到公司层面,影响力就会更加明显了。
以上这四个步骤基本涵盖了企业DevOps转型的通用路径。不过即便完全按照这样的路径进行转型也很难一帆风顺。在这条路径之下也隐藏着一些可以预见的问题最典型的就是**DevOps转型的J型曲线**这也是在2018年DevOps状态报告中的一个重点发现。
<img src="https://static001.geekbang.org/resource/image/eb/85/ebefde97d464b2b99cfd55ec1f5a3b85.png" alt="">
在转型之初,团队需要快速识别出主要问题,并给出解决方案。在这个阶段,整个团队的效能水平比较低,可以通过一些实践引入和工具的落地,快速提升自动化的能力和水平,从而帮助团队获得初期的成功。
但是,随着交付能力的提升,质量能力和技术债务的问题开始显现。比如,由于大量的手工回归测试,团队难以压缩测试周期,从而导致交付周期陷入瓶颈;项目架构的问题带来的技术债务导致集成问题增多,耦合性太强导致改动牵一发而动全身……
这个时候,团队开始面临选择:是继续推进呢?还是停滞不前呢?继续推进意味着团队需要分出额外的精力来加强自动化核心能力的预研和建设,比如优化构建时长、提升自动化测试覆盖率等,这些都需要长期的投入,甚至有可能会导致一段时间内团队交付能力的下降。
与此同时与组织的固有流程和边界问题相关的人为因素也会制约企业效率的进一步提升。如何让团队能够有信心减少评审和审批流程同样依赖于质量保障体系的建设。如果团队迫于业务压力暂缓DevOps改进工作那就意味着DevOps难以真正落地发挥价值很多DevOps项目就是这样“死”掉的。
那么说到这儿你可能会问这些到底应该由哪个团队来负责呢换句话说企业进行DevOps转型是否需要组建一个专职负责的团队呢如果需要的话团队的构成又是怎样的呢
关于这些问题,我的建议是,**在转型初期,建立一个专职的转型工作小组还是很有必要的**。这个团队主要由DevOps转型关联团队的主要负责人、DevOps专家和外部咨询顾问等牵头组成一般是各自领域的专家或者资深成员相当于DevOps实施的“大脑”主要负责制定DevOps转型项目计划、改进目标识别、技术方案设计和流程改造等。
除了核心团队管理团队和工具团队也很重要。我挂一个转型小组的团队组成示意图供你参考。当然DevOps所倡导的是一专多能跨领域的人才对于企业DevOps的实施同样不可或缺在挑选小组成员的时候这一点你也需要注意下。
<img src="https://static001.geekbang.org/resource/image/c7/ae/c7c8b813a3a9e8232f83acb783e94cae.jpg" alt="">
## 总结
今天我给你介绍了企业DevOps转型的常见轨迹分别是自底向上和自顶向下。无论采用哪种轨迹寻求管理层的支持都至关重要。接下来我和你一起梳理了DevOps转型的通用路径你要注意的是任何变革都不会是一帆风顺的企业的DevOps转型也是如此。在经历初期的成功之后我们很容易陷入“J型曲线”之中如果不能突破困局就很容易导致转型半途而废回到起点。最后我们一起探讨了是否需要专职的DevOps转型团队。在企业刚刚开始尝试DevOps的时候这样的团队对于快速上手和建立团队的信心还是很有必要的。
无论如何,就像陆游在《冬夜读书示子聿》一诗中写的那样:“纸上得来终觉浅,绝知此事要躬行。”**听过了太多实施DevOps的方法和路径却还是无法真正享受到它的巨大效益差的可能就是先干再说的信心和动力吧。**
## 思考题
你在企业中实施DevOps时遇到过什么问题吗你是怎么解决这个问题的呢你是否走过一些弯路呢
欢迎在留言区写下你的思考和答案,我们一起讨论,共同学习进步。如果你觉得这篇文章对你有所帮助,欢迎你把文章分享给你的朋友。

View File

@@ -0,0 +1,130 @@
<audio id="audio" title="07 | 业务敏捷帮助DevOps快速落地的源动力" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/92/a2/929eb0314a531ae0d8e3c920ec1c9ca2.mp3"></audio>
你好,我是石雪峰,今天我要跟你分享的主题是业务敏捷,那么,我们先来聊一聊,什么是业务敏捷,为什么需要业务敏捷呢?
先试想这样一个场景你们公司内部成立了专项小组计划用三个月时间验证DevOps落地项目的可行性。当要跟大老板汇报这个事情的时候作为团队的负责人你开始发愁怎么才能将DevOps的价值和业务价值关联起来以表明DevOps对业务价值的拉动和贡献呢
如果朝着这个方向思考,就很容易钻进死胡同。因为,从来没有一种客观的证据表明,软件交付效率的提升,和公司的股价提升有什么对应关系。换句话说,软件交付效率的提升,并不能直接影响业务的价值。
实际上,软件交付团队一直在努力通过各种途径改善交付效率,但如果你的前提是需求都是靠谱的、有效的,那你恐怕就要失望了。因为,实际情况是,业务都是在不断的试错中摸着石头过河,抱着“宁可错杀一千,也不放过一个”的理念,各种天马行空的需求一起上阵,搞得软件交付团队疲于奔命,宝贵的研发资源都消耗在了业务的汪洋大海中。但是,这些业务究竟带来了多少价值,却很少有人能说得清楚。
在企业中推行DevOps的时间越长就越会发现开发、测试和运维团队之间的沟通障碍固然存在但实际上业务部门和IT部门之间的鸿沟有时候会更加严重。试问有多少公司的业务方能够满意IT部门的交付效率又有多少IT团队不会把矛头指向业务方呢说白了就一句话**如果业务不够敏捷IT再怎么努力也没用啊**所以,我觉得很有必要跟你聊一聊有关需求的话题。
回到最开始的那个问题如果DevOps不能直接提升公司的业务价值那么为什么又要推行DevOps呢实际上如果你把DevOps的价值拆开业务价值和交付能力两个部分就很好理解了。
在现在这个多变的时代,没人能够准确地预测需求的价值。所以,交付能力的提升,可以帮助业务以最小的成本进行试错,将新功能快速交付给用户。同时,用户和市场的情况又能够快速地反馈给业务方,从而帮助业务校准方向。而业务的敏捷能力高低,恰恰体现在对功能的设计和需求的把握上,如果不能灵活地调整需求,专注于最有价值的事情,同样会拖累交付能力,导致整体效率的下降。
也就是说,在这样一种快速迭代交付的模式下,业务敏捷和交付能力二者缺一不可。
所以,开发更少的功能,聚焦用户价值,持续快速验证,就成了产品需求管理的核心思想。
## 开发更少的功能
很多时候,团队面临的最大问题,就是需求太多。但实际上,很多需求一开始就没想好,甚至在设计和开发阶段还在不断变更,这就给交付团队带来了极大的困扰。所以,在把握需求质量的前提下,如何尽可能地减小需求交付批次,采用最小的实现方案,保证高优先级的需求可以快速交付,从而提升上线实验和反馈的频率,就成了最关键的问题。
关于需求分析,比较常见的方法就是影响地图。
影响地图是通过简单的“Why-Who-How-What”分析方法实现业务目标和产品功能之间的映射关系。
- Why代表目标它可以是一个核心的业务目标也可以是一个实际的用户需求。
- Who代表影响对象也就是通过影响谁来实现这个目标。
- How代表影响也就是怎样影响用户以实现我们的目标。
- What代表需要交付什么样的功能可以带来期望的影响。
如果你是第一次接触影响地图,可能会听起来有点晕。没关系,我给你举个例子,来帮你理解这套分析方法。
比如一个专栏希望可以在上线3个月内吸引1万名用户那么这个Why也就是最核心的业务目标。为了达成这个目标需要影响的角色包含哪些呢其实就包含了作者、平台提供方、渠道方和最终用户。需要对他们施加哪些影响呢对作者来说需要快速地回答用户的问题提升内容的质量对平台来说需要对专栏进行重点曝光增加营销活动对渠道方来说需要提高推广力度和渠道引流对于用户来说增加分享有礼、免费试读和个人积分等活动。
那么基于以上这些影响方式,转化为最终的实际需求,就形成了一张完整的影响地图,如下图所示:
<img src="https://static001.geekbang.org/resource/image/2c/d9/2c8f3c2e85f517501f2ebe14120c82d9.png" alt="">
你可能会问,需求这么多,优先级要怎么安排呢?别急,现在我就给你介绍一下“卡诺模型”。
>
[卡诺模型](https://www.kanomodel.com/)Kano Model是日本大师授野纪昭博士提出的一套需求分析方法它对理解用户需求对其进行分类和排序方面有着很深刻的洞察。
<img src="https://static001.geekbang.org/resource/image/c7/e4/c70d3184824a47b13b0917fce4e54ee4.png" alt="">
卡诺模型将产品需求划分为五种类型:
1. 兴奋型指超乎用户想象的需求是可遇不可求的功能。比如用户想要一个更好的功能手机乔布斯带来了iPhone这会给用户带来极大的满足感。
1. 期望型:用户的满意度会随着这类需求数量的增多而线性增长,做得越多,效果越好,但难以有质的突破。比如,一个电商平台最开始是卖书,后面逐步扩展到卖电脑、家居用品等多个类别。用户更多的线性需求被满足,满意度自然也会提升。
1. 必备型:这些是产品必须要有的功能,如果没有的话,会带来非常大的影响。不过有这些功能的话,也没人会夸你做得有多好,比如安全机制和风控机制等。
1. 无差别型:做了跟没做一样,这就是典型的无用功。比如你花了好大力气做了一个需求,但是几乎没有用户使用,这个需求就属于无差别型。
1. 反向型:无中生有类需求,实际上根本不具备使用条件,或者用户压根不这么想。这类需求做出来以后,通常会给用户带来很大的困扰,成为被吐槽的对象。
对于五类需求来说核心要做到3点
- **优先规划期望型和必备型需求**,将其纳入日常的交付迭代中,保持一定的交付节奏;
- **识别无差别型和反向型需求**,这些对于用户来说并没有产生价值。如果团队对需求的分类有争议,可以进一步开展用户调研和分析。
- **追求兴奋型需求**因为它会带来产品的竞争壁垒和差异化。不过对于大公司而言经常会遇到创新者的窘境也就是坚持固有的商业模式而很难真正投入资源创新和自我颠覆。这就要采用精益创业的思想采用MVP最小可行产品的思路进行快速验证并且降低试错成本以抓住新的机遇。
在面对一大堆业务需求的时候,首先要进行识别和分类。当然,最开始时,人人都相信自己的需求是期望型,甚至是兴奋型的,这也可以理解。毕竟,这就好比公司里面所有的缺陷问题等级都是最高级一样,因为只要不提最高级,就会被其他最高级的问题淹没,而长期得不到解决。而**解决的方法,就是让数据说话,为需求的价值建立反馈机制,而这里提到的价值,就是用户价值**。
## 聚焦用户价值
“以终为始”这四个字在精益、DevOps等很多改进的话题中经常会出现。说白了就是要“指哪打哪而不是打哪指哪”。产品开发方经常会问“这个功能这么好为什么用户就不用呢”**这就是典型的用产品功能视角看问题,嘴上喊着“用户是上帝”的口号,但实际上,自己却用上帝视角来看待具体问题**。
如果你所在的公司也在搞敏捷转型,那你应该也听说过用户故事这个概念。需求不是需求,而是故事,这也让很多人不能理解。那么,用户故事是不是换了个马甲的需求呢?
关于这个问题,我曾经特意请教过一位国内的敏捷前辈,他的话让我记忆犹新。他说,从表面上看,用户故事是一种采用故事来描述需求的形式,但实际上是业务敏捷性的重要手段。它改变的不仅仅是需求的书写方式,还是需求达成共识的方式。也就是说,如果所谓的敏捷转型,没有对需求进行拆解,对需求达成共识的方式进行改变,对需求的价值进行明晰,那么可能只是在做迭代开发,而跟敏捷没啥关系。
在以往进行需求讨论的时候,往往有两个极端:一种是一句话需求,典型的“给你一个眼神,你自己体会”的方式,反正我就要做这件事,至于为什么做、怎么做一概不管,你自己看着办;另一种是上来就深入实现细节,讨论表字段怎么设计、模块怎么划分,恨不得撸起袖子就跟研发一起写代码。
每次需求讨论都是一场唇枪舌剑,达成的共识都是以一方妥协为前提的,这样显然不利于团队的和谐发展。更重要的是,始终在功能层面就事论事,而不关注用户视角,这样交付出来的需求很难达到预期。
而用户故事则是以用户的价值为核心,圈定一种角色,表明通过什么样的活动,最终达到什么样的价值。团队在讨论需求的时候,采用一种讲故事的形式,代入到设定的用户场景之中,跟随用户的操作路径,从而达成用户的目标,解决用户的实际问题。这样做的好处在于,经过团队的共同讨论和沟通,产品、研发和测试对需求目标可以达成共识,尤其是对想要带给用户的价值达成共识。
在这个过程中,团队不断探索更好的实现方案和实现路径,并补充关联的用户故事,从而形成完整的待办事项。更重要的是,团队成员逐渐培养了用户和产品思维,不再拘泥于技术实现本身,增强了彼此之间的信任,积极性方面也会有所改善,从而提升整个团队的敏捷性。
用户故事的粒度同样需要进行拆分拆分的原则是针对一类用户角色交付一个完整的用户价值也就是说用户故事不能再继续拆分的粒度。当然在实际工作中拆分的粒度还是以迭代周期为参考在一个迭代周期内交付完成即可一般建议是35天。检验用户故事拆分粒度是否合适可以遵循INVEST原则。
那么什么是INVEST原则呢
- Independent独立的减少用户故事之间的依赖可以让用户故事更加灵活地验证和交付而避免大批量交付对于业务敏捷性而言至关重要。
- Negotiable可协商的用户故事不应该是滴水不漏、行政命令式的而是要抛出一个场景描述并在需求沟通阶段不断细化完成。
- Valuable有价值的用户故事是以用户价值为核心的所以每个故事都是在对用户交付价值所以要站在用户的视角思考问题避免像最近特别火的那句话一样“我不要你觉得我要我觉得。”
- Estimatable可评估的用户故事应该可以粗略评估工作量无论是故事点数还是时间都可以。如果是一个预研性质的故事则需要进一步深挖可行性避免不知道为什么做而做。
- Small小的用户故事应该是最小的交付颗粒度所以按照敏捷开发方式无论迭代还是看板都需要在一个交付周期内完成。
- Testable可测试的也就是验收条件如果没有办法证明需求已经完成也就没有办法进行验收和交付。
## 持续快速验证
所谓用户价值,说起来多少有些虚无缥缈。的确,就像我们无法预测未来一样,**需求的价值难以预测,但是需求的价值却可以定义**。所以需求价值的定义可以理解为需求价值的度量分为客观指标和主观2个方面。
- 客观指标:也就是客观数据能够表明的指标,比如对电商行业来说,可以从购买流程角度,识别商品到达率、详情到达率、加入购物车率、完成订单率等等;
- 主观指标:也就是用户体验、用户满意度、用户推荐率等等,无法直接度量,只能通过侧面数据关联得出。
但是无论是客观指标,还是主观指标,每一个需求在提出的时候,可以在这些指标中选择需求上线后的预期,并定义相关的指标。一方面加强价值导向,让产品交付更有价值的需求,另外一方面,也强调数据导向,尽量客观地展现实际结果。
当然,产品需求是一个复杂的体系,相互之间也会有影响和依赖,怎么从多种指标中识别出关键指标,并跟需求本身进行关联,这就是一门学问了。不过你别担心,我会在度量相关的内容中跟你详细讨论一下。
在很多企业中精益创业的MVP思想已经深入人心了。面对未知的市场环境和用户需求为了快速验证一个想法可以通过一个最小化的产品实现来获取真实的市场反馈并根据反馈数据修正产品目标和需求优先级从而持续迭代产品需求。
<img src="https://static001.geekbang.org/resource/image/d4/b3/d433037a08130b6e36141c0a63342db3.png" alt="">
这套思想基本上放之四海而皆准,但是在企业中实际应用的时候,也会出现跑偏的情况。比如,在需求提出的时候,产品预定义了一组指标,但是在上线后由于缺乏数据支撑,需求价值的评估变成了纯粹的主观题,比如业务方自主判断需求是达到预期,符合预期还是未达到预期。这样一来,十有八九统计出来的结果都是符合预期及以上。但问题是,这样推导出来的结果对产品方向是否真的有帮助呢?
所以,采用客观有效的反馈机制就成了必选项。从技术层面来说,一个业务需求的背后,一般都会关联一个埋点需求。所谓埋点分析,是网站分析的一种常用的数据采集方法。设计良好的埋点功能,不仅能帮助采集用户操作行为,还能识别完整的上下文操作路径,甚至进行用户画像的聚类和分析,帮助识别不同类型用户的行为习惯。从用户层面来说,众测机制和用户反馈渠道是比较常见的两种方式,核心就是既要听用户怎么说,也要看用户怎么做。
## 总结
DevOps的关注点要从研发环节继续向上游延伸一直把业务团队包括进来。也就是说IT部门不仅仅是被动的按照业务需求交付功能还要更加快速地提供业务数据反馈辅助业务决策。同时交付能力的提升也进一步降低了业务的试错成本而业务的敏捷性也决定了研发交付的需求价值和交付节奏通过影响地图进行需求分析再通过卡诺模型分析需求属性和优先级通过用户故事和整个团队达成共识通过持续快速验证帮助产品在正确的道路上发展前进。
引入业务的DevOps就成了BizDevOps这也是DevOps发展的一种潮流。最后我帮你梳理下BizDevOps的核心理念
- 对齐业务和开发目标、指标;
- 把握安全、合规指标;
- 及时对齐需求,减少无用开发;
- 体现DevOps的价值
- 让开发团队开始接触业务,不单单是执行,调动积极性。
## 思考题
你所在的企业中对于需求的价值是如何衡量的呢?是否有一套指标体系可以客观地展现需求的价值呢?
欢迎在留言区写下你的思考和答案,我们一起讨论,共同学习进步。如果你觉得这篇文章对你有所帮助,欢迎你把文章分享给你的朋友。

View File

@@ -0,0 +1,110 @@
<audio id="audio" title="08 | 精益看板(上):精益驱动的敏捷开发方法" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/d2/46/d2ac48b55e9cbb72d085238c59802d46.mp3"></audio>
你好,我是石雪峰。
提到敏捷开发方法你可能会情不自禁地联想到双周迭代、每日站会、需求拆分等。的确作为一种快速灵活、拥抱变化的研发模式敏捷的价值已经得到了行业的普遍认可。但是即便敏捷宣言已经发表了将近20个年头很多公司依然挣扎在敏捷转型的道路上各种转型失败的案例比比皆是。
我曾经就见过一家公司,一度在大规模推行敏捷。但是,这家公司很多所谓的敏捷教练都是项目经理兼任的,他们的思维和做事习惯还是项目制的方式。即便每天把团队站会开得有模有样,看板摆得到处都是,但从产品的交付结果来看,并没有什么显著的变化。没过多久,由于组织架构的调整,轰轰烈烈的敏捷转型项目就不了了之了。
这家公司虽然表面上采用了业界流行的敏捷实践也引入了敏捷工具但是团队并没有对敏捷的价值达成共识团队领导兼任Scrum Master好好的站会变成了每日工作汇报会。甚至在敏捷项目复盘会上领导还宣称“敏捷就是要干掉变化我们的目标就是保证团队按照计划进行。”这种“貌合神离”的敏捷并不能帮助企业达到灵活响应变化、快速交付价值的预期效果。
作为一种最广泛的敏捷框架Scrum的很多理念和实践都深入人心比如很多时候迭代式开发几乎等同于跟敏捷开发。但是Scrum对于角色的定义并不容易理解在推行Scrum的时候如果涉及到组织变革就会举步维艰。
实际上企业的敏捷转型并没有一条通用的路径所用的方法也没有一定之规。今天我就跟你聊聊另外一种主流的敏捷开发方法——精益看板。与Scrum相比看板方法的渐进式改变过程更加容易被团队接受。我之前所在的团队通过长期实践看板方法不仅使产品交付更加顺畅还提升了团队的整体能力。
那么,这个神奇的精益看板是怎么回事呢?
如果你之前没听说过精益看板,还是很有必要简单了解下它的背景的。其实,“看板”是一个日语词汇,泛指日常生活中随处可见的广告牌。而在生产制造系统中,看板作为一种信号卡,主要用于传递信息。很多人认为看板是丰田公司首创的,其实并非如此,比如在我之前所在的尼康公司的生产制造车间里,看板同样大量存在。
当然,看板之所以能广为人知,还是离不开丰田生产系统。《改变世界的机器》一书首次提到了著名的丰田准时化生产系统,而看板正是其中的核心工具。
简单来说,看板系统是一种拉动式的生产方式。区别于以往的大规模批量生产,看板采用按需生产的方式。也就是说,下游环节会在需要的时候,通过看板通知上游环节需要生产的工件和数量,然后上游再启动生产工作。
说白了,所谓拉动式生产,就是从后端消费者的需求出发,向前推导,需要什么就生产什么,而不是生产出来一大堆没人要的东西,从而达到减低库存、加速半成品流动和灵活响应变化的目的。我你分享一张有关丰田生产方式的图片,它演示了整个丰田生产方式的运作过程,你可以参考一下。
<img src="https://static001.geekbang.org/resource/image/a6/2d/a69ccb0d561d1d866f6bfe87384dbb2d.png" alt="">
>
图片来源:[https://www.toyota-europe.com/world-of-toyota/this-is-toyota/toyota-production-system](https://www.toyota-europe.com/world-of-toyota/this-is-toyota/toyota-production-system)
软件开发中的看板方法,借鉴了丰田生产系统的精益思想,同样以限制在制品数量、加快价值流动为核心理念。也就是说,**如果没有在制品限制的拉动系统,只能说是一个可视化系统,而不是看板系统,这一点非常重要**。
比如很多团队都在使用Jira并在Jira中建立了覆盖各个开发阶段的看板围绕它进行协作这就是一个典型的可视化板而非看板。那么为什么对于看板方法而言约束在制品数量如此重要呢
就像刚才提到的,**加快价值流动是精益看板的核心。在软件开发中,这个价值可能是一个新功能,也可能是缺陷修复,体验优化**。根据利特尔法则,我们知道:**平均吞吐率=在制品数量/平均前置时间**。其中在制品数量就是当前团队并行处理的工作事项的数量。关于前置时间你应该并不陌生作为衡量DevOps产出效果的核心指标它代表了从需求交付开发开始到上线发布这段时间的长度。
比如1个加油站只有1台加油设备每辆车平均加油时长是5分钟如果有10辆车在等待那么前置时长就是50分钟。
但是这只是在假设队列中的工作都是顺序依次执行的情况下在实际的软件开发过程中。如果一个开发人员同时处理10件事情那么在每一件事情上真正投入的时间绝不是1/10。
还拿刚刚的例子来说如果1台加油设备要给10辆车加油这就意味着给每一辆车加油前后的动作都要重复一遍比如取出加油枪、挪车等。这样一来任务切换的成本会造成极大的资源消耗导致最终加满一辆车的时长远远超过5分钟。
所以,**在制品数量会影响前置时间,并行的任务数量越多,前置时间就会越长**,也就是交付周期变长,这显然不是理想的状态。
不仅如此,**前置时间还会影响交付质量,前置时间增长,则质量下降**。这并不难理解。比如,随着工作数量的增多,复杂性也在增加,多任务切换总会导致失误。另外,人的记性没那么可靠。对于一个需求,刚开始跟产品沟通的时候就是最清晰的,但是过了一段时间就有点想不起来是怎么回事了。这个时候,如果按照自己的想法来做,很有可能因为对需求的理解不到位,最终带来大量的返工。
再进一步展开来看的话软件开发工作总是伴随着各种变化和意外。如果交付周期比需求变化周期更长那就意味着紧急任务增多。比如老板发现一个线上缺陷必须高优先级修复类似的紧急任务增多就会导致在制品数量进一步增多。这样一来团队就陷入了一个向下螺旋这对团队的士气和交付预期都会造成非常不好的影响以至于有些团队90%的精力都用来修复问题了,根本没时间交付需求和创新。
更加严重的问题是这个时候业务部门对IT部门的信任度就会直线下降。业务部门往往会想“既然无法预测需求的交付实践那好吧我只能一次性压给你一大堆需求。”这样一来就进一步导致了在制品数量的上升。
可见,一个小小的在制品数量,牵动的是整个研发团队的信心。我把刚刚提到的连环关系整理了一下,如下图所示:
<img src="https://static001.geekbang.org/resource/image/ea/44/eaf59898b2d1428c96c07df6ef897944.png" alt="">
当然针对刚才加油站的问题你可能会说“多加几台加油设备不就完了吗何必依赖同一台机器呢”的确当并行任务过多的时候适当增加人员有助于缓解这个问题但是前置时间的缩短是有上限的。这就好比10个人干一个月的事情给你100个人3天做完这就是软件工程管理的经典图书《人月神话》所讨论的故事了我就不赘述了。这里你只需要知道随着人数的增多人与人之间的沟通成本会呈指数级上升。而且从短期来看由于内部培训、适应环境等因素新人的加入甚至会拖慢原有的交付速度。
了解了精益看板的核心理念,以及约束在制品数量的重要性,也就掌握了看板实践的正确方向。那么,在团队中要如何开始一步步地实施精益看板方法呢?在实施的过程中,又有哪些常见的坑,以及应对措施呢?这正是我要重点跟你分享的问题。我把精益看板的实践方法分为了五个步骤。
- 第一步:可视化流程;
- 第二步:定义清晰的规则;
- 第三步:限制在制品数量;
- 第四步:管理工作流程;
- 第五步:建立反馈和持续改进。
今天,我先给你介绍精益看板实践方法的第一步:可视化流程。在下一讲中,我会继续跟你聊聊剩余的四步实践。
## 第一步:可视化流程
在看板方法中提高价值的流动效率快速交付用户价值是核心原则所以第1步就是要梳理价值交付流程通过对现有流程的建模让流程变得可视化。关于价值流建模的话题在专栏[第5讲](https://time.geekbang.org/column/article/152806)中我已经介绍过了,如果你不记得了,别忘记回去复习一下。
其实,在组织内部,无论采用什么研发模式,组织结构是怎样的,价值交付的流程一直都是存在的。所以,在最开始,我们只需要忠实客观地把这个现有流程呈现出来就可以了,而无需对现有流程进行优化和调整。也正因为如此,看板方法的引入初期给组织带来的冲击相对较小,不会因为剧烈变革引起组织的强烈不适甚至是反弹。所以,**看板方法是一种相对温和的渐进式改进方法**。
接下来,就可以根据价值流定义看板了。看板的设计没有一个标准样式,因为每个组织的价值流都不相同。对于刚刚上手看板方法的团队来说,看板的主要构成元素可以简单概括成“一列一行”。
**1.一列。**
这是指看板的竖向队列,是按照价值流转的各个主要阶段进行划分的,比如常见的需求、开发、测试、发布等。对识别出来的每一列进一步可以划分成“进行中”和“已完成”两种状态,这也是精益看板拉动式生产的一个显著特征。对于列的划分粒度可以很细,比如开发阶段可以进一步细分成设计、编码、自测、评审、提测等环节,或者就作为一个单独的开发环节存在。划分的标准主要有两点:
- **是否构成一个独立的环节**。比如对于前后端分离的开发来说,前端开发和后端开发就是两个独立的环节,一般由不同的角色负责,这种就比较适合独立阶段。
- **是否存在状态的流转和移交**。看板是驱动上下游协同的信号卡,所以,我们需要重点关注存在上下游交付和评审的环节,这也是提示交付吞吐率和前置时长的关键节点。
除此之外,看板的设计需要定义明确的起点和终点。对于精益看板来说,覆盖端到端的完整价值交付环节是比较理想的状态。但实际上,在刚开始推行看板方法的时候,由于组织架构、团队分工等多种因素,只能在力所能及的局部环节建立看板,比如开发测试环节,这并不是什么大问题,可以在局部优化产出效果之后,再尝试向前或向后延伸。
另外,即便看板可以覆盖端到端的完整流程,各个主要阶段的关注点各不相同,所以,也会采用看板分类分级的方式。对于开发看板来说,起点一般是需求准备就绪,也就是说,需求经过分析评审设计并同研发团队沟通一致准备进入开发的状态,终点可以是提测或者发布状态。流程的起点和终点同样要体现在看板设计中,以表示在局部环节的完整工作流程。
<img src="https://static001.geekbang.org/resource/image/4f/be/4f34bc80c89c696864d7640687eec7be.png" alt="">
**2.一行。**
这是指看板横向的泳道。泳道用于需求与需求之间划清界限,尤其在使用物理看板的时候,经常会因为便利贴贴的位置随意等原因导致混乱,而定义泳道就可以很好地解决这个问题。比如,高速公路上都画有不同的行车道,这样车辆就可以在各自的车道内行驶。
当然,泳道的意义不只如此。泳道还可以按照不同维度划分。比如,有的看板设计中会加入紧急通道,用于满足紧急需求的插入。另外,非业务类的技术改进需求,也可以在独立泳道中进行。对于前后端分离的项目来说,一个需求会拆分成前端任务和后端任务,只有当前后端任务都完成之后才能进行验收。这时,就可以把前后端任务放在同一个泳道中,从而体现需求和任务的关联关系,以及任务与任务之间的依赖关系,快速识别当前阻塞交付的瓶颈点。
当然看板的设计没有一定之规。在我们团队的看板中往往还有挂起类需求区域、缺陷区域以及技术攻关类区域等用于管理特定的问题类型。比如对于长期挂起的需求在一定时间之后就可以从看板中移除毕竟如果是几个月都没有进入任务队列的需求可能就不是真正的需求这些可以根据团队的实际情况灵活安排。如果你在使用Jira这样的工具虽然没有区域的概念但是可以通过泳道来实现比如按照史诗任务维度区分泳道然后新建对应区域的史诗任务就可以啦。
<img src="https://static001.geekbang.org/resource/image/4d/23/4d78eac23b10166656d58e5dae684723.png" alt="">
## 总结
今天我给你介绍了敏捷常用的两种框架Scrum和看板。看板来源于丰田生产系统以拉动式生产为最典型的特征。关注价值流动加速价值流动是精益看板的核心限制在制品数量就是核心实践因为在制品数量会直接影响团队的交付周期和产品质量甚至还会影响团队之间的信任导致团队进入向下螺旋。
在团队中实践精益看板,可以分为五个步骤,分别是:可视化流程、定义清晰的规则、限制在制品数量、管理工作流程和建立反馈并持续改进。今天我给你介绍了第一个步骤,也就是可视化流程,通过价值流分析将团队的交付路径可视化,建立起看板的主要结构,那么接下来就是开始应用看板了。下一讲,我会跟你聊聊其余的四个步骤,敬请期待。
## 思考题
最后,给你留一个思考题:你所在的公司是否也在实践敏捷呢?在敏捷转型的过程中,你遇到的最大问题、踩过的最大的坑是什么呢?
欢迎在留言区写下你的思考和答案,我们一起讨论,共同学习进步。如果你觉得这篇文章对你有所帮助,欢迎你把文章分享给你的朋友。

View File

@@ -0,0 +1,126 @@
<audio id="audio" title="09 | 精益看板(下):精益驱动的敏捷开发方法" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/9b/5c/9b5da1533c5d4de6a754f10f764c205c.mp3"></audio>
你好我是石雪峰。在上一讲中我给你介绍了两种常见的敏捷框架Scrum和精益看板。我重点提到关注价值流动是精益的核心理念限制在制品数量则是核心实践。此外我还给你介绍了实施精益看板第一步可视化流程。那么今天我会继续介绍剩余的四个步骤。
先提一句,如果你比较关心工具使用方面的问题,我给你分享一份有关常见的工具配置和使用方面的资料,你可以点击[网盘](https://pan.baidu.com/s/1SAmWYv7WeYgM6yZSRs5nag)下载提取码是mrtd。
好了,现在正式开始今天的内容。
## 第二步:定义清晰的规则
在完成可视化流程之后,看板的雏形就出来啦。接下来你要做的,就是定义清晰的规则。
可视化的意义不仅在于让人看得见,还在于让人看得懂。工作时间久了,我们很容易产生一种感觉,那就是**沟通的成本甚至要大于工作的成本**。沟通的最主要目的就是同步和传递信息,如果有一种途径可以提升信息传递的效率,那岂不是很好吗?
而看板恰恰有一个重要的意义,就是状态可视化。团队的所有成员可以通过看板了解当前在进行的任务状态、流程中的瓶颈点、任务与任务之间的依赖关系等信息,从而自发地采取相应的活动,来保证价值交付的顺畅,使整个项目能够有条不紊地交付。
当然,如果想要做到这点,光靠可视化流程还远远不够,你还需要在看板的设计中融入一定的规则。这些规则可以大大地降低团队成员之间的沟通成本,统一团队的沟通语言,形成团队成员之间的默契。看板的规则包含两个方面,一个是可视化规则,另一个是显式化规则,我分别来介绍一下。
**1.可视化规则。**
在上一讲中我们提到看板中的主要构成元素是“一列一行”。实际上看板中卡片的设计也有讲究主要有3点。
- 卡片的颜色:用于区分不同的任务类型,比如需求(绿色)、缺陷(红色)和改进事项(蓝色);
- 卡片的内容用于显示任务的主要信息比如电子看板ID号需求的名称、描述、负责人、预估工作量和停留时长等
- 卡片的依赖和阻塞状态:用于提起关注,比如在卡片上通过张贴不同的标志,表示当前卡片的健康程度,对于存在依赖和阻塞状态的卡片,需要团队高优先级协调和处理。这样一来,看板就显得主次分明啦。
**2.显式化规则。**
**看板除了要让人看得懂,还要让人会操作,这一点非常重要**。尤其是在引入看板的初期,大家对这个新鲜事物还比较陌生,所以,定义清晰的操作规则就显得格外重要了。而且,在团队习惯操作之前,需要反复地强调以加深团队的印象,慢慢培养团队的习惯。当团队习惯了使用看板之后,效率就会大大提升。这些规则包括:
- 谁来负责整理和移动卡片?
- 什么时间点进行卡片操作?
- 卡片的操作步骤是怎样的?(比如,卡片每停留一天需要做一次标记。)
- 什么时候需要线下沟通?(比如缺陷和阻塞)
- 哪些标识代表当前最高优先级的任务?
- 看板卡片的填充规则是怎样的?
- 谁来保障线下和线上看板的状态一致性?
还是那句话,这些规则在团队内部可能一直都存在,属于心照不宣的那种类型,但是,通过看板将规则显示化,无论是对于规则的明确,新人的快速上手,还是团队内部的持续改进,都有着非常大的好处。
## 第三步:限制在制品数量
**限制在制品数量是看板的核心,也是最难把握的一个环节,主要问题就在于把数量限制为多少比较合适的呢?**
要回答这个问题,首先要明确一点:**应用看板方法只能暴露团队的现有问题,而不能解决团队的现有问题。**
怎么理解这句话呢?这就是说,当在制品数量没有限制的时候,团队的交付时间和交付质量都会受到影响,这背后的原因可能是需求把控不到位,发布频率不够高,自动化程度不足以支撑快速交付,组织间的依赖和系统架构耦合太强……这些都是团队的固有问题,并非是使用看板方法就能统统解决掉的。
**但看板方法的好处在于,通过降低在制品数量,可以将这些潜在的问题逐步暴露出来。**比如在极端情况下假设我们将在制品数量设置为1也就是说团队当前只工作在一个需求上按道理来说交付的前置时间会大大缩短。但实际上团队发现由于测试环境不就绪导致无法验收交付或者交付窗口过长错过一个窗口就要再等2周的时间到头来还是不能达到快速交付价值的目标。那么这里的原因就在于测试环境初始化问题和交付频率的问题。这些都是团队固有的问题只不过在没有那么高的交付节奏要求时并没有显现出来而已。
所以,如果你能够摆正心态,正视团队的固有问题,你就会明白,限制在制品数量绝不仅仅是纠结一个数字这么简单的。在我看来,限制在制品数量有两个关键节点:一个是需求流入节点,一个是需求交付节点。
**1.需求流入节点。**
这里的关键是限制需求的流入。你可能就会说这太不靠谱了面对如狼似虎的业务方研发团队只能做个小绵羊毕竟只要你敢say“no”业务方就直接立刻写邮件抄送老板了。
其实需求的PK是个永恒的话题敢问哪个研发经理没经历过几十、上百次需求PK的腥风血雨呢我之前就因为同项目团队需求PK得过于激烈一度做好了被扫地出门的准备。但是后来我们发现到头来大家还是一根绳子上的蚂蚱在资源有限的前提下一次提100个需求和提10个需求从交付时长来看其实并没有什么区别。所以限制在制品数量只是换了一个方式PK需求从之前业务方提供一大堆需求让研发团队给排期的方式变成了根据需求的优先级限制并行任务数量的方式。
当然,研发团队需要承诺业务方以最快的速度交付最高优先级的需求。如果业务方看到需求的确按照预期的时间上线甚至是提前上线,他们就会慢慢习惯这种做法,团队之间的信任也就一点点建立起来了。
**2.需求流出节点。**
这里的关键在于加速需求的流出。在一般的看板中,最容易出现堆积的就是待发布的状态列,因为发布活动经常要根据项目的节奏安排,由专门团队在专门的时间窗口进行。如果发现待发布需求大量堆积,这时候就有理由推动下游加快发布节奏,或者以一种更加灵活的方式进行发布。
毕竟DevOps所倡导的是“You build ityou run it”的理念这也是亚马逊公司最为经典的团队理念意思是开发团队自己负责业务的发布每个发布单元都是独立的彼此没有强依赖关系从而实现团队自制。通过建立安全发布的能力将发布变成一件平常的事情这才真正有助于需求价值的快速交付。说白了要想做到业务敏捷就得想发就发做完一个上一个。
至于要将在制品数量限制为多少,我的建议是采用渐进式优化的方式。你可以从团队人数和需求的现状出发,在每个开发人员不过载的前提下,比如并行不超过三件事,根据当前处理中的任务数量进行约定,然后观察各个环节的积压情况,再通过第四步实践进行调整,最终达到一个稳定高效的状态。
## 第四步:管理工作流程
在专栏[第5讲](https://time.geekbang.org/column/article/152806)中,我提到过精益理论中的增值环节和不增值环节,而会议一般都会被归为不增值环节。于是,有人就会产生这样一种误解:“那是不是所有不增值的环节都要被消除掉,以达到最高的流动效率呢?”
如果这么想的话,那是不是类似项目经理这样的角色也就不需要了呢?毕竟,他们看起来并没有直接参与到软件开发的活动中。显然,这是很片面的想法。实际上,在精益的不增值活动中,还可以进一步划分出必要不增值活动和不必要不增值活动,有些会议虽然不直接增值,但却是非常必要的。所以,我们不能简单地认为精益就等于不开会、不审批。
看板方法同样根植于组织的日常活动之中,所以,同样**需要配套的管理流程,来保障看板机制的顺畅运转**。在看板方法中,常见的有三种会议,分别是每日站会、队列填充会议和发布规划会议。
**1.每日站会。**
接触过敏捷的团队应该都非常熟悉每日站会。但是与Scrum方法的“夺命三连问”昨天做了什么今天计划做什么有什么困难或者阻塞相比看板方法的站会则略有不同。因为我们在第二步制定了清晰的规则团队的现状已经清晰可见只需要同步下重点任务就可以了。看板方法更加关注两点
- 待交付的任务。看板追求价值的快速流动,所以,对于在交付环节阻塞的任务,你要重点关注是什么原因导致的。
- 紧急、缺陷、阻塞和长期没有更新的任务。这些任务在规则中也有相应的定义如果出现了这些问题团队需要最高优先级进行处理。这里有一个小技巧就是当卡片放置在看板之中时每停留一天卡片的负责人就会手动增加一个小圆点标记通过这个标记的数量就可以看出哪些任务已经停留了太长时间。而对于使用电子看板的团队来说这就更加简单了。比如Jira本身就支持停留时长的显示。当然你也可以自建过滤器按照停留时长排序重点关注Top问题的情况。
每日站会要尽量保持高效,对于一些存在争议的问题,或者是技术细节的讨论,可以放在会后单独进行。同时,会议的组织者也要尽量观察每日站会的执行效果,如果出现停顿或者不顺畅的情况,那就意味着规则方面有优化空间。比如,如果每日站会依赖一名组织者来驱动整个过程,只要这个人不发问,团队就不说话,这就说明规则不够清晰。另外,对于站会中迸发出来的一些灵感或者好点子,可以都记录下来,作为优化事项跟进解决。
**2.队列填充会议。**
队列填充会议的目标有两点:一个是对任务的优先级进行排序,一个是展示需求开发的状态。一般情况下,队列填充会议需要业务方、技术方和产品项目负责人参与进来,对需求的优先级达成一致,并填充到看板的就绪状态中。
在初期,我建议在每周固定时间举行会议,这样有助于整个团队共享需求交付节奏,了解需求交付状态,帮助业务方和技术方建立良好的合作和信任关系,在会议上也可以针对在制品数量进行讨论和调整。
**3.发布规划会议。**
发布规划会议以最终交付为目标。一般情况下,项目的交付节奏会影响队列填充的节奏,二者最好保持同步。另外,随着部署和发布的分离,研发团队越来越趋近于持续开发持续部署,而发布由业务方统一规划把控,发布规划会议有助于研发团队和业务方的信息同步,从而实现按节奏部署和按需发布的理想状态。
## 第五步:建立反馈和持续改进
实际上无论是DevOps还是精益看板任何一套方法框架的终点都是持续改进。因为作为一种新的研发思想和研发方法只有结合业务实际并根据自身的情况持续优化规则、节奏、工具和流程才能更好地为业务服务。关于这部分的内容我会在度量和持续改进中进行详细介绍。你要始终记得没有天然完美的解决方案只有持续优化的解决方案。看板方法的实践是一个循序渐进的过程。为此看板创始人David J Anderson总结了看板方法的成熟度模型用于指导中大型团队实践看板方法如下图所示
<img src="https://static001.geekbang.org/resource/image/ae/3c/ae98048d5805b01f3040ef2d4216393c.png" alt="">
>
图片来源:[http://leankanban.com/kmm/](http://leankanban.com/kmm/)
这个模型将看板的成熟度划分为7个等级。除此之外它还针对每一级的每一个实践维度给出了具体的能力参考对看板方法的实施有非常强的指导作用可以用于对标现有的能力图谱。
如果你想获取更加详细的信息,可以点击在这一讲的开头我分享给你的链接,作为补充参考。
## 总结
好啦,回顾一下,在这两讲中,我先给你介绍了看板的背景和起源。看板来源于生产制造行业,是一种常用的生产信号传递方式,同时,看板也是以丰田生产系统为代表的精益生产的核心工具,也就是以拉动为核心的按需生产方式。
接着我跟你探讨了为什么要限制在制品数量以及背后的理念也就是缩短交付前置时长以快速、高质量、可预期的交付方式在业务方和IT部门之间建立起合作信任关系。
除此之外我还给你介绍了精益看板的5个核心实践包括可视化流程定义清晰的规则约束在制品数量管理工作流程和建立反馈持续改进。掌握了这些你就获取了开启精益看板之旅的钥匙。在真正进行实践之后相信你会有更多的收获和感悟。
需要提醒你的是,僵化的实践方法,脱离对人的关注,可以说是影响精益看板在组织内落地的最大障碍。就像《丰田之道》中提到的那样,持续改进和对人的尊重,才是一切改进方法的终极坐标,这一点是我们必须要注意的。
## 思考题
最后,给你留一个思考题:如果让你现在开始在团队中推行精益看板方法,你觉得有哪些挑战吗?
欢迎在留言区写下你的思考和答案,我们一起讨论,共同学习进步。如果你觉得这篇文章对你有所帮助,欢迎你把文章分享给你的朋友。

View File

@@ -0,0 +1,142 @@
<audio id="audio" title="10 | 配置管理最容易被忽视的DevOps工程实践基础" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/8a/f0/8ac56b053a9670ed8ee823dfe5d21ef0.mp3"></audio>
你好我是石雪峰。从今天开始专栏正式进入了工程实践的部分。在DevOps的体系中工程实践所占的比重非常大而且和我们的日常工作息息相关。正因为如此DevOps包含了大量的工程实践很多我们都耳熟能详比如持续集成、自动化测试、自动化部署等等这些基本上是实践DevOps的必选项。
可是还有一些实践常常被人们所忽视但这并不代表它们已经被淘汰或者是不那么重要了。恰恰相反它们同样是DevOps能够发挥价值的根基配置管理Configuration Management就是其中之一。它的理念在软件开发过程中无处不在可以说是整个DevOps工程实践的基础。所以今天我们就来聊一聊配置管理。
说了这么多,那软件配置管理到底是个啥呢?
熟悉运维的同学可能会说不就是类似Ansible、Saltstack的环境配置管理工具吗还有人会说CMDB配置管理数据库也是配置管理吧这些说法都没错。配置管理这个概念在软件开发领域应用得非常普遍几乎可以说无处不在但是刚刚提到的这些概念都是细分领域内的局部定义。
我今天要讲到的配置管理,是一个宏观的概念,是站在软件交付全生命周期的视角,对整个开发过程进行规范管理,控制变更过程,让协作更加顺畅,确保整个交付过程的完整、一致和可追溯。
看到这里,我估计你可能已经晕掉了。的确,配置管理的理论体系非常庞大。但是没关系,你只需要把四个核心理念记在心中就足够了。这四个理念分别是:**版本变更标准化,将一切纳入版本控制,全流程可追溯和单一可信数据源**。
## 1. 版本变更标准化
**版本控制是配置管理中的一个非常核心的概念,而对于软件来说,最核心的资产就是源代码**。现在很多公司都在使用类似Git、SVN之类的工具管理源代码这些工具其实都是版本控制系统。版本描述了软件交付产物的状态可以说从第一行软件代码写下开始版本就已经存在了。
现代软件开发越来越复杂,往往需要多人协作,所以,如何管理每个开发者的版本,并把它们有效地集成到一起,就成了一个难题。实际上,版本控制系统就是为了解决这个问题的。试想一下,如果没有这么一套系统的话,所有代码都在本地,不要说其他人了,就连自己都会搞不清楚哪个是最新代码。那么,当所有人的代码集成到一起的时候,那该是多么混乱啊!
不仅如此,如果线上发生了严重问题,也找不到对应的历史版本,只能直接把最新的代码发布上去,简直就是灾难。
**配置管理中的另一个核心概念是变更**。我们对软件做的任何改变都可以称之为一次变更,比如一个需求,一行代码,甚至是一个环境配置。**版本来源于变更**。对于变更而言,核心就是要记录:**谁,在什么时间,做了什么改动,具体改了哪些内容,又是谁批准的**。
这样看来,好像也没什么复杂的,因为现代版本控制系统基本都具备记录变更的功能。那么,是不是只要使用了版本控制系统,就做到变更管理了呢?
的确,版本控制系统的出现,大大简化了管理变更的成本,至少是不用人工记录了。但是,从另一方面来看,用好版本控制系统也需要有一套规则和行为规范。
比如版本控制系统需要打通公司的统一认证系统也就是任何人想要访问版本控制系统都需要经过公司统一登录的认证。同时在使用Git的时候你需要正确配置本地信息尤其是用户名和邮箱信息这样才能在提交时生成完整的用户信息。另外系统本身也需要增加相关的校验机制避免由于员工配置错误导致无效信息被提交入库。
改动说明一般就是版本控制系统的提交记录,一个完整的提交记录应该至少包括以下几个方面的内容:
- **提交概要信息**:简明扼要地用一句话说明这个改动实现了哪些功能,修复了哪些问题;
- **提交详细信息**:详细说明改动的细节和改动方式,是否有潜在的风险和遗留问题等;
- **提交关联需求**:是哪次变更导致的这次提交修改,还需要添加上游系统编号以关联提交和原始变更。
这些改动应该遵循一种标准化的格式,并且有相关的格式说明和书写方式,比如有哪些关键字,每一行的长度,变更编号的区隔是使用逗号、空格还是分号等等。如果按照这个标准来书写每次的变更记录,其实成本还是很高的,更不要说使用英文来书写的话,英文的表达方式和内容展现形式又是一个难题。
我跟你分享一个极品的提交注释,你可以参考一下。
>
switch to Flask-XML-RPC dependency
CR: PBX-2222
The Flask-XML-RPC-Re fork has Python 3 support, but it has a couple
other problems.
<ol>
<li>
test suite does not pass
</li>
<li>
latest code is not tagged
</li>
<li>
uncompiled source code is not distributed via PyPI
</li>
</ol>
The Flask-XML-RPC module is essentially dead upstream, but it is
<p>packaged in EPEL 7 and Fedora. This module will get us far enough to<br>
the</p>
point that we can complete phase one for this project.
When we care about Python 3, we can drop XML-RPC entirely and get the
service consumers to switch to a REST API instead.
<p>(Note, with this change, the Travis CI tests will fail for Python 3.<br>
The</p>
solution is to drop XML-RPC support.)
这时,肯定有人会问,花这么大力气做这个事情,会不会有点得不偿失呢?从局部来看,的确如此。但是,换个角度想,当其他人看到你的改动,或者是评审你的代码的时候,如果通过提交记录就能清晰地了解你的意图,而不是一脸蒙地把你叫过来,让你再讲一遍,这样节约的时间比当时你书写提交记录的时间要多得多。
**所以你看,一套标准化的规则和行为习惯,可以降低协作过程中的沟通成本,一次性把事情做对,这也是标准和规范的重要意义**
当然,如果标准化流程要完全依靠人的自觉性来保障,那就太不靠谱了。毕竟,人总是容易犯错的,会影响到标准的执行效果。所以,当团队内部经过不断磨合,逐步形成一套规范之后,最好还是用自动化的手段保障流程的标准化。
这样做的好处有两点:一方面,可以降低人为因素的影响,如果你不按标准来,就会寸步难行,也减少了人为钻空子的可能性。比如,有时候因为懒,每次提交都写同样一个需求变更号,这样的确满足了标准化的要求,但是却产生了大量无效数据。这时候,你就可以适当增加一些校验机制,比如只允许添加你名下的变更,或者是只允许开放状态的变更号等等。另一方面,在标准化之后,很多重复性的工作就可以自动化完成,标准化的信息也方便计算机分析提取,这样就可以提升流程的流转效率。
**可以说标准化是自动化的前提自动化又是DevOps最核心的实践**。这样看来说配置管理是DevOps工程实践的基础就一点不为过了吧。
## 2. 将一切纳入版本控制
如果说,今天这一讲的内容,你只需要记住一句话,那就是将一切纳入版本控制,这是配置管理的金科玉律。你可能会问,需要将什么样的内容纳入版本控制呢?我会毫不犹豫地回答你:“一切都需要!”比如软件源代码、配置文件、测试编译脚本、流水线配置、环境配置、数据库变更等等,你能想到的一切,皆有版本,皆要被纳入管控。
这是因为,软件本身就是一个复杂的集合体,任何变更都可能带来问题,所以,全程版本控制赋予了我们全流程追溯的能力,并且可以快速回退到某个时间点的版本状态,这对于定位和修复问题是非常重要的。
之前我就遇到过一个问题。一个iOS应用发灰度版本的时候一切正常但是正式版本就遇到了无法下载的情况。当时因为临近上线为了查这个问题可以说是全员上阵团队甚至开始互相抱怨研发说代码没有变化所以是运维的问题运维说环境没动过所以是研发的问题。结果到最后才发现这是由于一个工具版本升级某个参数的默认值从“关闭”变成了“打开”导致的。
所以你看,如果对所有内容都纳入版本控制,快速对比两个版本,列出差异点,那么,解决这种问题也就是分分钟的事情,大不了就把所有改动都还原回去。
纳入版本控制的价值不止如此。实际上很多DevOps实践都是基于版本控制来实现的比如环境管理方面推荐采用基础设施即代码的方式管理环境也就是说把用代码化的方式描述复杂的环境配置同时把它纳入版本控制系统中。这样一来任何环境变更都可以像提交代码一样来完成不仅变更的内容一目了然还可以很轻松地实现自动化。**把原本复杂的事情简单化,每一个人都可以完成环境变更**。
这样一来开发和运维之间的鸿沟就被逐渐抹平了DevOps的真谛也是如此。所以现在行业内流行的“什么什么即代码”其背后的核心都是版本控制。
不过这里我需要澄清一下纳入版本控制并不等同于把所有内容都放到Git中管理。有些时候我们很容易把能力和工具混为一谈。Git只是一种流行的版本控制系统而已而这里强调的其实是一种能力工具只是能力的载体。比如Git本身不擅长管理大文件那么可以把这些大文件放到Artifactory或者其他自建平台上进行管理。
对自建系统来说实现版本控制的方式有很多种比如可以针对每次变更插入一组新的数据或者直接复用Git这种比较成熟的工具作为后台。唯一不变的要求就是无论使用什么样的系统和工具都需要把版本控制的能力考虑进去。
另外,在实践将一切纳入版本控制的时候,你可以参考一条小原则。如果你不确定是否需要纳入版本控制,有一个简单的判断方法就是:**如果这个产物可以通过其他产物来重现,那么就可以作为制品管理,而无需纳入版本控制**。
举个例子,软件包可以通过源代码和工具重新打包生成,那么,代码、工具和打包环境就需要纳入管控,而生成的软件包可以作为制品;软件的测试报告如果可以通过测试管理平台重新自动化生成,那么同样可以将其视为制品,但前提是,测试管理平台可以针对每一个版本重新生成测试报告。
## 3. 全流程可追溯
对传统行业来说,全流程可追溯的能力从来不是可选项,而是必选项。像航空航天、企业制造、金融行业等,对变更的管控都是非常严谨的,一旦出现问题,就要追溯当时的全部数据,像软件源代码、测试报告、运行环境等等。如果由于缺乏管理,难以提供证据证明基于当时的客观情况已经做了充分的验证,就会面临巨额的罚款和赔偿,这可不是闹着玩的事情。像最近流行的区块链技术,除了发币以外,最典型的场景也是全流程可追溯。所以说,**技术可以日新月异,但很多理念都是长久不变的**。
**对于配置管理来说,除了追溯能力以外,还有一个重要的价值,就是记录关联和依赖关系**。怎么理解这句话呢?我先提个问题,在你的公司里面,针对任意一个需求,你们是否能够快速识别出它所关联的代码、版本、测试案例、上线记录、缺陷信息、用户反馈信息和上线监控数据呢?对于任意一个应用,是否可以识别出它所依赖的环境,中间件,上下游存在调用关系的系统、服务和数据呢?
如果你的回答是“yes”那么恭喜你你们公司做得非常好。不过绝大多数公司都是无法做到这一点的。因为这不仅需要系统与系统之间的关联打通、数据联动也涉及到一整套完整的管理机制。
DevOps非常强调价值导向强调团队内部共享目标这个目标其实就是业务目标。但实际情况是业务所关注的维度和开发、测试、运维所关注的维度都各不相同。业务关心的是提出的需求有没有上线而开发关心的是这个需求的代码有没有集成运维关心的是包含这个代码的版本是否上线。所以如果不能把这些信息串联打通就没有真正做到全流程可追溯。
关于这个问题,我给你的建议是**把握源头,建立主线**。所谓源头,对于软件开发而言,最原始的就是需求,**所有的变更都来源于需求**。所以,首先要统一管理需求,无论是开发需求、测试需求还是运维需求。
接下来要以需求作为抓手去关联下游环节打通数据这需要系统能力的支持也需要规则的支持。比如每次变更都要强制关联需求编号针对不同的需求等级定义差异化流程这样既可以减少无意义的审批环节给予团队一定的灵活性也达到了全流程管控的目标。这是一个比较漫长的过程但不积跬步无以至千里DevOps也需要一步一个脚印地建设才行。
## 4. 单一可信数据源
最后,我想单独谈谈单一可信数据源。很多人不理解这是什么东西,我举个例子你就明白了。
有一个网络热词叫作“官宣”,也就是官方宣布的意思。一般情况下,官宣的信息都是板上钉钉的,可信度非常高。可问题是,如果有多个官宣的渠道,信息还都不一样,你怎么知道要相信哪一个呢?这就是单一可信数据源的意义。
试想一下,我们花了很大力气来建设版本控制的能力,但如果数据源本身不可靠,缺乏统一管控,那岂不是白忙一场吗?所以,对于软件开发来说,必须要有统一的管控:
- 对于代码来说,要有统一的版本控制系统,不能代码满天飞;
- 对于版本来说,要有统一的渠道,不能让人随便本地打个包就传到线上去了;
- 对于开发依赖的组件来说,要有统一的源头,不能让来路不明的组件直接集成到系统中。这不仅对于安全管控来说至关重要,对于企业内部的信息一致性也是不可或缺的。
**同时,单一可信数据源也要能覆盖企业内部元数据的管控**。比如企业内部经常出现这种情况同样是应用在A部门的系统中叫作123在B部门的系统中叫作ABC在打通两边平台的时候这就相当于“鸡同鸭讲”完全对不上。再比如信息安全团队维护了一套应用列表但实际上在业务系统中很多应用都已经下线且不再维护了这样一来不仅会造成资源浪费还伴随着非常大的安全风险。
很多时候,类似的这些问题都是因为缺乏统一的顶层规划和设计导致的,这一点,在建立配置管理能力的时候请你格外关注一下。
## 总结
今天我给你介绍了DevOps工程实践的基础配置管理以及配置管理的四大理念分别是版本变更标准化、将一切纳入版本控制、全流程可追溯和单一可信数据源希望能帮你掌握配置管理的全局概念。
虽然配置管理看起来并不起眼,但是就像那句经典的话一样:“岁月静好,是因为有人替你负重前行。” 对于任何一家企业来说,信息过载都是常态,而**配置管理的最大价值正是将信息序列化**,对信息进行有效的整理、归类、记录和关联。而软件开发标准和有序,也是协同效率提升的源头,所以,配置管理的重要性再怎么强调都不为过。
## 思考题
你在企业中遇到过哪些配置管理方面的难题呢?你们的配置管理体系又是如何建立的呢?你遇到过因为缺乏单一可信数据源而导致“鸡同鸭讲”的有趣故事吗?
欢迎在留言区写下你的思考和答案,我们一起讨论,共同学习进步。如果你觉得这篇文章对你有所帮助,欢迎你把文章分享给你的朋友。

View File

@@ -0,0 +1,175 @@
<audio id="audio" title="11 | 分支策略:让研发高效协作的关键要素" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/fe/23/fe70df33608b2f49ebcad1498d9f8623.mp3"></audio>
你好,我是石雪峰。今天我们来聊聊分支策略。
在上一讲中,我反复强调过一个理念,那就是将一切纳入版本控制。其实,现代版本控制系统不仅可以记录版本和变更记录,还有一个非常重要的功能,那就是**分支管理**。
现代软件开发讲究效率和质量,大多依赖于多团队间的协作来实现。对于一些大型软件来说,即便是百人团队规模的协作也没什么奇怪的。如果软件架构没有良好的拆分,很有可能出现几百人在一个代码仓库里面工作的情况。这时,分支管理就成了不可或缺的功能。
一方面,分支可以隔离不同开发人员的改动,给他们提供一个相对独立的空间,让他们能够完成自己的开发任务。另一方面,整个团队也需要根据软件的发布节奏来完成代码提交、审核、集成、测试等工作。
所以,如果说多人软件协作项目中有一个灵魂的话,我认为,这个灵魂就是分支策略。可以说,**分支策略就是软件协作模式和发布模式的风向标**。选择一种符合DevOps开发模式的分支策略对于DevOps的实践落地也会大有帮助。
今天,我会给你拆解一些常见的分支策略,帮你了解这些策略的核心流程、优缺点,以及适用的场景和案例。
## 主干开发,分支发布
<img src="https://static001.geekbang.org/resource/image/71/85/717a85f005b8da0b593d6376db679685.png" alt="">
>
<p>图片来源:<br>
[https://paulhammant.com/2013/12/04/what_is_your_branching_model/](https://paulhammant.com/2013/12/04/what_is_your_branching_model/)</p>
在这种分支策略下,开发团队共享一条主干分支,所有的代码都直接提交到主干分支上,主干分支就相当于是一个代码的全量合集。**在软件版本发布之前,会基于主干拉出一条以发布为目的的短分支**。
你需要注意一下这句话里的两个关键词:
1. **以发布为目的**。这条分支存在的意义不是开发新功能而是对现有功能进行验收并在达到一定的质量标准后对外发布。一般来说新功能不会基于这条分支提交只有一些Bugfix会集成进来。所以对于这种发布分支会有比较严格的权限管控。毕竟谁都不想让那些乱七八糟、未经验证的功能跑到发布分支上来。
1. **短分支**。这条发布分支一般不会存在太长时间,只要经过回归验证,满足发布标准后,就可以直接对外发布,这时,这条分支的历史使命也就结束了。除非上线之后发现一些紧急问题需要修复,才会继续在这条分支上修改验证,并将改动同步回主干分支。所以,只要在主干分支和发布分支并行存在的时间段内,所有发布分支上的改动都需要同步回主分支,这也是我们不希望这条分支存在时间过长的原因,因为这会导致重复工作量的线性累计。
对于以版本节奏驱动的软件项目来说,这种分支策略非常常见,比如客户端产品,或者是那种需要在客户终端升级的智能硬件产品,像智能手机、智能电视等。
早在很多年前,乐视刚刚推出超级电视的时候,喊过一个口号叫“周周更新”。要知道,当时智能电视产品的更新频率普遍是几个月一次。
其实,如果你了解分支策略的话,你就会发现,“周周更新”的背后也没什么特别的。当时,我所在的团队恰好负责智能电视产品线的分支策略,采用的就是主干开发、分支发布的模式。其中基于主干的发布分支提前两周拉出,然后在发布分支上进行回归验证,并在第一周发出体验版本给喜欢尝鲜的用户试用。然后,根据用户反馈和后台收集的问题进行进一步修正,并最终发布一个稳定版本。我把当时的分支策略图分享给你,你可以参考一下。
<img src="https://static001.geekbang.org/resource/image/e0/46/e05c3b28341b3c99cceb3b916f5e7046.jpg" alt="">
这种模式的优势有三个:
1. 对于研发团队来说,只有一条主线分支,不需要在多条分支间切换。
1. 在发布分支拉出之后,主干分支依然处于可集成状态,研发节奏可以保持在一个相对平稳的状态。
1. 发布分支一般以版本号命名,清晰易懂,线上哪个版本出了问题,就在哪个分支上修复。
不过,这种模式也存在着缺点和挑战:
1. **它对主线分支的质量要求很高**。如果主线分支出了问题就会block所有开发团队的工作。对于一个百人团队、每日千次的提交规模来说如果不对提交加以约束这种情况的发生频率就会非常高。
1. **它对团队协作的节奏要求很高**。如果主线分支上的功能没有及时合入,但是业务方又坚持要在指定版本上线这个功能,这就会导致发布分支“难产”。甚至有些时候,会被迫允许部分未开发完成的功能在发布分支上继续开发,这会给发布分支的质量和稳定性造成很大的挑战。
1. **在主线和发布分支并存期间,有可能会导致两边提交不同步的情况**。比如,发布分支修复了一个线上问题,但是由于没有同步回主线,导致同样的问题在下一个版本中复现。测试出来的问题越多,这种情况出现的概率就越大,更不要说多版本并存的情况了。
这些问题的解决方法包括以下几点:
1. 建立提交的准入门禁,不允许不符合质量标准的代码合入主线。
1. 采用版本火车的方式,加快版本的迭代速度,功能“持票上车”,如果跟不上这个版本就随下个版本上线。另外,可以采用功能开关、热修复等手段,打破版本发布的固定节奏,以一种更加灵活的方式对外发布。
1. 通过自动化手段扫描主线和发布分支的差异建立一种规则。比如Hotfix必须主线和发布分支同时提交或者发布分支上线后由专人反向同步等。
## 分支开发,主干发布
<img src="https://static001.geekbang.org/resource/image/b9/69/b956a9dc626cad58976b55c5cb773169.png" alt="">
>
图片来源:[https://paulhammant.com/2013/12/04/what_is_your_branching_model/](https://paulhammant.com/2013/12/04/what_is_your_branching_model/)
当开发接到一个任务后会基于主干拉出一条特性开发分支在特性分支上完成功能开发验证之后通过Merge request或者Pull request的方式发起合并请求在评审通过后合入主干并在主干完成功能的回归测试。开源社区流行的GitHub模式其实就是属于这种。
根据特性和团队的实际情况,还可以进一步细分为两种情况:
- 每条特性分支以特性编号或需求编号命名,在这条分支上,只完成一个功能的开发;
- 以开发模块为单位,拉出一条长线的特性分支,并在这条分支上进行开发协作。
**两者的区别就在于特性分支存活的周期,拉出时间越长,跟主干分支的差异就越大,分支合并回去的冲突也就越大**。所以,对于长线模式来说,要么是模块拆分得比较清晰,不会有其他人动这块功能,要么就是保持同主干的频繁同步。**随着需求拆分粒度的变小,短分支的方式其实更合适**。
这种模式下的优势也有两点:
1. **分支开发相对比较独立,不会因为并行导致互相干扰**。同时,特性只有在开发完成并验收通过后才会合入主干,对主干分支的质量起到了保护作用;
1. 随着特性分支的流行,在这种模式下,分支成了特性天然的载体。一个特性所关联的所有代码可以保存在一条特性分支上,这为以特性为粒度进行发布的模式来说提供了一种新的可能性。也就是说,如果你想要发布哪个特性,就可以直接将特性分支合并到发布分支上,这就让某一个特性变得“可上可下”,而不是混在一大堆代码当中,想拆也拆不出来。
关于这种特性分支发布的方法,我给你提供一份[参考资料](https://mp.weixin.qq.com/s/JsBX3UPgZL_HUOTCIopr_A),你可以了解一下。不过,我想提醒你的是,特性发布虽然看起来很好,但是有三个前置条件:第一个是**特性拆分得足够小**,第二是**有强大的测试环境作支撑**,可以满足灵活的特性组合验证需求,第三是**要有一套自动化的特性管理工具**。
当然,分支开发、主干发布的模式也有缺点和挑战:
1. 非常考验团队特性拆分的能力。如果一个特性过大,会导致大量并行开发的分支存在,分支的集成周期拉长,潜在的冲突也会增多。另外,分支长期存在也会造成跟主线差异过大的问题。所以,**特性的粒度和分支存活的周期是关键要素。根据经验来看,分支存活的周期一般不要超过一周**。
1. 对特性分支的命名规范要求很高。由于大量特性分支的拉出,整个代码仓库会显得非常乱。面对一大堆分支,谁也说不清到底哪个还活着,哪个已经没用了。所以,如果能够跟变更管理系统打通,自动化创建分支就最好了。
1. 特性分支的原子性和完整性,保证一个特性的关联改动需要提交到一条分支上,而不是到处都是。同时,特性分支上的提交也需要尽量清晰,典型的就是原子性提交。
我之前所在的一个团队就是采用的这种分支策略。有一次,我为了分支策略的执行细节跟研发负责人争得面红耳赤,争论的核心点就是:当特性分支合并回主干的时候,到底要不要对特性分支上的代码进行整理?
只要做过开发,你就会知道,很少有人能只用一次提交就把代码写对的,因为总是会有这样那样的问题,导致特性分支上的提交乱七八糟。
在合入主干的时候为了保证代码的原子性其实是有机会对代码提交进行重新编排的Git在这方面可以说非常强大。如果你熟练掌握git rebase命令就可以快速合并分拆提交将每一个提交整理为有意义的原子性的提交再合入主干或者干脆把特性分支上的改动压合成一个提交。当然这样做的代价就是不断重写特性分支的历史给研发团队带来额外的工作量。我跟你分享一些常见的命令。
>
比如当前特性分支feature1主分支master那么你可以执行以下命令整理提交历史
>
git checkout feature1 &amp;&amp; git fetch origin &amp;&amp; git rebase -i origin/master
>
<img src="https://static001.geekbang.org/resource/image/b7/1b/b709ba3701064f950534eb93d822731b.png" alt="">
>
<p>最常见的操作包括:<br>
p选择提交<br>
r更新提交的注释信息<br>
e编辑提交可以将一个提交拆分成多个<br>
s压合提交将多个提交合并成一个<br>
f类似压合提交但是放弃这个提交的注释信息直接使用合并提交的注释信息<br>
当然在git rebase的交互界面中你也可以调整提交的顺序比如将特性功能和关联的Bugfix整合在一起。</p>
**需要提醒你的是,分支策略代表了研发团队的行为准则,每个团队都需要磨合出一套适合自己的模式来**
## 主干开发,主干发布
<img src="https://static001.geekbang.org/resource/image/8f/b0/8f1b96d9847430effaba8d5ee45d8bb0.png" alt="">
>
图片来源:[https://paulhammant.com/2013/12/04/what_is_your_branching_model/](https://paulhammant.com/2013/12/04/what_is_your_branching_model/)
今天给你介绍的第三种分支策略是主干开发、主干发布。武学高手修炼到一定境界之后,往往会发现大道至简,分支策略也是如此。所以,第三种分支策略可以简单理解为没有策略。**团队只有一条分支,开发人员的代码改动都直接集成到这条主干分支上,同时,软件的发布也基于这条主干分支进行**。
对于持续交付而言,最理想的情况就是,每一次提交都能经历一系列的自动化环境并部署到生产环境上面,而这种模式距离这个目标就更近了一点。
可想而知,如果想要做到主干分支在任何时间都处于可发布状态,那么,这就对每一次提交的代码质量要求非常高。
在一些追求工程卓越的公司里你要提交一行代码就必须经历“九九八十一难”因为有一系列的自动化验收手段还有极为严格的代码评审机制来保证你的提交不会把主干分支搞挂掉。当然即便如此问题也是难以避免的那我们该怎么做呢这里我就要给你介绍下Facebook的分支策略演进案例了。
Facebook最早采用的也是主干开发、分支发布的策略每天固定发布两次。但是随着业务发展的压力增大团队对于发布频率有了更高的要求这种分支策略已经无法满足每天多次发布的需求了。于是他们开始着手改变分支策略从主干开发、分支发布的模式演变成了主干开发、主干发布的模式。
为了保证主干分支的质量自动化验收手段是必不可少的因此每一次代码提交都会触发完整的编译构建、单元测试、代码扫描、自动化测试等过程。在代码合入主干后会进行按需发布先是发布到内部环境也就是只有Facebook的员工才能看到这个版本如果发现问题就立刻修复如果没有问题再进一步开放发布给2%的线上生产用户,同时自动化检测线上的反馈数据。直到确认一切正常,才会对所有用户开放。
最后通过分支策略和发布策略的整合注入自动化质量验收和线上数据反馈能力最终将发布频率从固定的每天2次提升到每天多次甚至实现了按需发布的模式。Facebook最新的分支策略如图所示
<img src="https://static001.geekbang.org/resource/image/b2/64/b2a7a2d841e5b95d1fbf83d286d42364.jpg" alt="">
>
图片来源:[https://engineering.fb.com/web/rapid-release-at-massive-scale/](https://engineering.fb.com/web/rapid-release-at-massive-scale/)
看到这里,你可能会问:“在这三种典型策略中,哪种策略是最好的?我应该如何选择呢?”其实,这个问题也困扰着很多公司。
的确,不同类型、规模、行业的软件项目采用的分支策略可能都不尽相同,同时,发布频率、软件架构、基础设施能力、人员能力水平等因素也在制约着分支策略的应用效果。
所以很难说有一种通用的分支策略可以满足所有场景的需求。但是有些分支策略的原则更加适合于快速迭代发布的场景也就更加适合DevOps的发展趋势。所以我个人比较推荐的是**主干开发结合特性分支的模式**,也就是团队共享一条开发主干,特性开发基于主干拉出特性分支,快速开发验收并回归主干,同时,在特性分支和主干分别建立不同的质量门禁和自动化验收能力。
这样做的好处在于,**可以加快代码集成频率,特性相对独立清晰**,并且主干分支又可以保持一定的质量水平。不过,在执行的过程中,你需要遵守以下原则:
1. 团队共享一条主干分支;
1. 特性分支的存活周期要尽量短最好不要超过3天
1. 每天向主干合并一次代码如果特性分支存在超过1天那么每天都要同步主干代码
1. 谨慎使用功能开关等技术手段,保持代码干净和历史清晰;
1. 并行分支越少越好,如果可能的话,尽量采用主干发布。
关于最后一条,你需要注意的是,**是否需要发布分支,主要取决于项目的发布模式**。对于按照版本方式发布的项目来说比如App、智能硬件系统以及依赖大量外部系统联调的核心系统可以按照发布固定的节奏拉出发布分支对于发布节奏较快、系统架构拆分后相对独立的应用来说可以直接采用主干发布的模式并结合安全发布策略把控整体的发布质量。
这种分支发布的策略图如下所示:
<img src="https://static001.geekbang.org/resource/image/16/5e/165381a31f212516ee92fd295040465e.jpg" alt="">
## 总结
今天,我给你介绍了三种分支策略,建议你对照我给你分享的分支策略图,好好理解一下。另外, 我还介绍了适合DevOps模式的分支策略以及一些使用原则。还记得我最开始说的吗分支策略就是研发协作和发布模式的风向标分支策略的变化对整个研发团队的习惯和节奏都是一个非常大的调整找到适合当前团队的分支策略才是最重要的。
## 思考题
你目前所在的团队采用的是哪种分支策略?你觉得当前的分支策略有哪些问题或改进空间吗?你是否经历过分支策略的调整呢?如果有的话,你在这个过程中踩过什么“坑”吗?有没有什么心得呢?
欢迎在留言区写下你的思考和答案,我们一起讨论,共同学习进步。如果你觉得这篇文章对你有所帮助,欢迎你把文章分享给你的朋友。

View File

@@ -0,0 +1,145 @@
<audio id="audio" title="12 | 持续集成你说的CI和我说的CI是一回事吗" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/99/15/99b9c51a177216d667d2cb27e5f8e015.mp3"></audio>
你好我是石雪峰。今天我来跟你聊聊CI。
之前我曾应邀参加某公司的DevOps交流活动他们质量团队的负责人分享了DevOps平台建设方面的经验其中有一大半时间都在讲CI。刚开始还挺好的可是后来我越听越觉得奇怪以至于在交流环节我只想提一个问题“你觉得CI是个啥意思”后来为了不被主办方鄙视话到嘴边我又努力憋回去了。
回来的路上我就一直在思考这个问题。很多时候人们嘴上总是挂着CI但是他们说的CI和我理解的CI好像并不是一回事。比如有时候CI被用来指代负责内部工具平台建设的团队有时候CI类似一种技术实践间接等同于软件的编译和打包有时候CI又成了一种职能和角色指代负责版本的集成和发布的人。可见CI的定义跟DevOps一样每个人的理解都千差万别。
可问题是如果不能理解CI原本的含义怎么发挥CI真正的价值呢以CI的名义打造的平台又怎么能不跑偏并且解决真正的问题呢
所以,今天,就让我们一起重新认识下这个“最熟悉的陌生人”。
CI是Continuous Integration的缩写也就是我们熟悉的持续集成顾名思义这里面有两个关键的问题集成什么东西为什么要持续要回答这两个问题就得从CI诞生的历史说起了。
在20世纪90年代软件开发还是瀑布模式的天下人们发现在很长一段时间里软件是根本无法运行的。因为按照项目计划软件的功能被拆分成各个模块由不同的团队分别开发只有到了开发完成之后的集成阶段软件才会被真正地组装到一起。可是往往几个月开发下来到了集成的时候大量分支合并带来的冲突和功能问题集中爆发团队疲于奔命各种救火甚至有时候发现压根集成不起来。
我最初工作的时候做的就是类似这样的项目。我们负责客户端程序的开发到了集成的时候才发现客户的数据库使用的是Oracle而我们为了省事使用的是微软Office套件中的Access估计现在很多刚工作的年轻工程师都没听说过这个数据库这就导致客户下发的数据没法导入到本地数据库中。结果整整一个元旦假期我们都在加班加点好不容易赶工了一个数据中间层这才把两端集成起来。
所以,软件集成是一件高风险的、不确定的事情,国外甚至有个专门的说法,叫作“集成地狱”。也正因为如此,人们就更倾向于不做集成,这就导致开发末端的集成环节变得更加困难,从而形成了一个恶性循环。
为了解决这个问题CI的思想应运而生。CI本身源于肯特·贝克Kent Beck在1996年提出的极限编程方法ExtremeProgramming简称XP。顾名思义极限编程是一种软件开发方法作为敏捷开发的方法之一目的在于通过缩短开发周期提高发布频率来提升软件质量改善用户需求响应速度。
不知道为什么,每次听到极限编程,我心中都热血沸腾。不管在任何时代,总有那么一群程序员走在时代前沿,代表和传承着极客精神,就像咱们平台的名字极客时间,就代表了不甘于平庸、追求极致的精神,特别好。
扯远了让我们回归正题。极限编程方法中提出的实践现在看来依然相当前沿比如结对编程、软件重构、测试驱动开发、编程规范等这些词我们都耳熟能详但是真正能做到的却是凤毛麟角。其中还有一个特别有意思的实践规范叫作每周40小时工作制也就是一周工作5天每天工作8小时。联想到前些日子在网络上引发激烈争论的“996”就可以看出极限编程方法在国内的发展还是任重而道远啊。
当然,在这么多实践中,持续集成可以说是第一个被广泛接受和认可的。
关于CI的定义我在这里引用一下马丁·福勒Martin Fowler的一篇博客中的内容这也是当前最为业界公认的定义之一
>
CI是一种软件开发实践团队成员频繁地将他们的工作成果集成到一起通常每人每天至少提交一次这样每天就会有多次集成并且在每次提交后自动触发运行一次包含自动化验证集的构建任务以便尽早地发现集成问题。
CI采用了一种反常规的思路来解决软件集成的困境其核心理念就是越是痛苦的事情就要越频繁地做。很多人不理解为什么举个例子你就明白了。我小时候身体非常不好经常要喝中药第一次喝的时候每喝一口都想吐可是连续喝了一个星期之后我发现中药跟水的味道也没什么区别。这其实是因为人的适应力很强慢慢就习惯了中药的味道。对于软件开发来说也是这个道理。
如果开发周期末端的一次性集成有这么大的风险和不确定性,那不如把集成的频率提高,让每次集成的内容减少,这样即便失败,影响的也仅仅是一次小的集成内容,问题定位和修复都可以更加快速地完成。这样一来,不仅提高了软件的质量,也大大降低了最后阶段的返工所带来的浪费,还提升了软件交付效率。
你可能会说,这个道理我也懂啊,我们的持续集成就是这样的。别急,我们一起来测试一下。
假如你认为自己所在的项目和团队在践行CI那么你可以思考3个问题看看你们是否做到了。
>
<ol>
- 每一次代码提交,是否都会触发一次完整的流水线?
</ol>
>
<ol start="2">
- 每次流水线是否会触发自动化的测试环节?
</ol>
>
<ol start="3">
- 如果流水线出现了问题是否能够在10分钟之内修复
</ol>
我曾在现场做过很多次这个测试如果参与者认为做到了就会举手表示如果没有做到就会把手放下。每次面对一群自信满满的CI“信徒们”三连问的结果总会让人“暗爽”因为最开始几乎所有人都会举手他们坚信自己在实践持续集成。但接下来我每问一个问题就会有一半的人把手放下坚持到最后的人寥寥无几这几个人面对周边人的目光内心也开始怀疑起来如果我再适时地追问两下基本就都放下了。
这么看来CI听起来简单易懂但实施起来并没有那么容易。可以说CI涵盖了三个阶段每个阶段都蕴含了一组思想和实践只有把这些都做到了那才是真正地在实施CI。接下来让我们逐一看下这三个阶段。
## 第一阶段:每次提交触发完整的流水线
第一个阶段的关键词是:**快速集成**。这是对CI核心理念的最好诠释也就是集成速度做到极致每次变更都会触发CI。
当然,这里的变更有可能是代码变更,也有可能是配置、环境、数据变更。我之前强调过,**要将一切都纳入版本控制**这样所有的元数据变更都会被版本管理系统捕获并通过事件或者Webhook的方式通知持续集成平台。
对于现代的持续集成平台比如大家常用的Jenkins默认支持多种触发方式比如定时触发、轮询触发或者Webhook触发。那么**如果想做到每次提交都触发持续集成的话,首先就需要打通版本控制系统和持续集成系统**比如GitLab和Jenkins的集成网上已经有很多现成的材料大家照着操作一般都不会有太多问题。但是只要打通两个系统就足够了吗显然没有这么简单。实施提交触发流水线还需要一些前置条件。
1.**统一的分支策略**。
既然CI的目的是集成那么首先就需要有一条以集成为目的的分支。这条分支可以是研发主线也可以是专门的集成分支一旦这条分支上发生任何变更就会触发相应的CI过程。那么可能有人会问很多时候开发都是在特性分支或者版本分支上进行的难道这些分支上的提交就不要经过CI环节了吗这就引出了第2个前置条件。
2.**清晰的集成规则**。
对于一个大中型团队来说,每天的提交量是非常惊人的,这就要求持续集成具备足够的吞吐率,能够及时处理这些请求。而对于不同分支来说,持续集成的步骤和要求也不尽相同。不同分支的集成目的不同,相应的环节自然也不相同。
比如,对于研发特性分支而言,目的主要是快速验证和反馈,那么速度就是不可忽视的因素,所以这个层面的持续集成,主要以验证打包和代码质量为主;而对于系统集成分支而言,它的目的不仅是验证打包和代码质量,还要关注接口和业务层面的正确性,所以集成的步骤会更加复杂,成本也会随之上升。所以,**根据分支策略选择合适的集成规则对于CI的有效运转来说非常重要**。
3.**标准化的资源池**。
资源池作为CI的基础设施重要性不言而喻。
首先,**资源池需要实现环境标准化**也就是任何任务在任何节点都具备可运行的能力这个能力就包括了工具、配置等一系列要素。如果CI任务在一个节点可以运行跑到另外一个节点就运行失败那么CI的公信力就会受到影响。
另外,**资源池的并发吞吐量应该可以满足集中提交的场景,可以动态按需初始化的资源池就成了最佳选择**。当然,同时还要兼顾**成本因素**,因为大量资源的投入如果没有被有效利用,那么造成的浪费是巨大的。
4.**足够快的反馈周期**。
越是初级CI对速度的敏感性就越强。一般来讲如果CI环节超过1015分钟还没有反馈结果那么研发人员就会失去耐心所以CI的运行速度是一个需要纳入监控的重要指标。对于不同的系统而言要约定能够容忍的CI最大时长如果超过这个时长同样会导致CI失败。所以这就需要环境、平台、开发团队共同维护。
你看一套基本可用的CI所依赖的条件远不止这些核心还是为了能够在最短的时间内完成集成动作并给出反馈。如果你们公司已经实现了代码提交的CI并且不会有大量失败和排队的情况发生那么恭喜你第一阶段就算通过了。
## 第二阶段:每次流水线触发自动化测试
第二个阶段的关键词是:**质量内建**。关于质量内建我会在专栏后面的内容中详细介绍。实际上CI的目的是尽早发现问题这些问题既包括构建失败也包括质量不达标比如测试不通过或者代码规约静态扫描等不符合标准。
我见过的很多CI都是“瘸腿”CI因为缺失了自动化测试的能力注入或者自动化测试的能力很差基本无法发现有效问题。这里面有几个重要的关注点我们来看一下。
1.**匹配合适的测试活动**。
对于不同层级的CI而言同样需要根据集成规则来确定需要注入的质量活动。比如最初级的提交集成就不适合那些运行过于复杂、时间太长的测试活动快速的代码检查和冒烟测试就足以证明这个版本已经达到了最基本的要求。而对于系统层的集成来说质量要求会更高这样一来一些接口测试、UI测试等就可以纳入到CI里面来。
2.**树立测试结果的公信度**。
自动化测试的目标是帮助研发提前发现问题但是如果因为自动化测试能力自身的缺陷或者环境不稳定等因素造成了CI的大量失败那么这个CI对于研发来说就可有可无了。所以**我们要对CI失败进行分类分级重点关注那些异常和误报的情况并进行相应的持续优化和改善**。
3.**提升测试活动的有效性**。
考虑到CI对于速度的敏感性那么如何在最短的时间内运行最有效的测试任务就成了一个关键问题。显然大而全的测试套件是不合时宜的只有在基础功能验证的基础上结合与本次CI的变更点相关的测试任务发现问题的概率才会大大提升。所以根据CI变更自动识别匹配对应的测试任务也是一个挑战。
当你的CI已经集成了自动化验证集并且该验证集可以有效地发现问题那么恭喜你第二阶段也成功了。但这并不是“一锤子买卖”毕竟由于业务需求的不断变化自动化测试要持续更新才能保证始终有效。
## 第三阶段:出了问题可以在第一时间修复
到现在为止我们已经做到了快速集成和质量内建说实话利用现有的开源工具和框架快速搭建一套CI平台并不困难**真正让CI发挥价值的关键还是在于团队面对持续集成的态度以及团队内是否建立了持续集成的文化**。
硅谷的很多公司都有一种不成文的规定,那就是员工每天下班前要先确认持续集成是正常的,然后再离开公司,同时,公司也不建议在深夜或者周末上线代码,因为一旦出了问题,很难在第一时间修复,造成的影响难以估计。
其实很多企业并不知道他们花费大量人力、物力建设CI的平均修复时长是多少也缺乏这方面的数据统计。就现状而言有些时候他们可以做到在10分钟内修复而有些时候就需要几个小时原因可能是负责人出去开会了或者是赶上了午休的时间。
当然也有一些企业质疑10分钟这个时间长度因为软件项目的特殊性很有可能每次集成周期就远大于10分钟。如果你也是这样想的那你可能就误解CI的理念和初衷了毕竟我也不相信马丁·福勒能够保证在10分钟内修复问题。在这么短的时间里人为因素其实并不可控所以**人不是关键,建立机制才是关键**。
什么是机制呢?**机制就是一种约定,人们愿意遵守这样的行为,并且做了会得到好处**。对于CI而言保证集成主线的可用性其实就是团队成员间的一种约定。这不在于谁出的问题谁去修复而在于我们是否能够保证CI的稳定性足够清楚问题的降级路径并且主动关注、分析和推动问题解决。
另外团队要建立清晰的规则比如10分钟内没有修复则自动回滚代码比如当CI“亮红灯”的时候团队不再提交新的代码因为在错误的基础上没有办法验证新的提交这时需要集体放下手中的工作共同恢复CI的状态。
只有团队成员深信CI带给团队的长期好处远大于短期投入并且愿意身体力行地践行CI这个“10分钟”规则才有可能得到保障并落在实处。
## 总结
在这一讲中我们回顾了CI诞生的历史和CI试图解决的根本问题。同时我们也介绍了CI落地建设的三个阶段和其中的核心理念即快速集成、质量内建和文化建立。
最后我特别想再提一点很多人经常会把工具和实践混为一谈一旦结果没有达到预期就会质疑实践是否靠谱工具是否好用很容易陷入工具决定论的怪圈。实际上CI的核心理念从未有过什么改变但工具却一直在升级换代。工具是实践的载体实践是工具的根基单纯的工具建设仅仅是千里之行的一小步这一点我们必须要明白。
## 思考题
可以说一个良好的CI体现了整个研发团队方方面面的能力那么你对企业内部实践CI都有哪些问题和心得呢
欢迎在留言区写下你的思考和答案,我们一起讨论,共同学习进步。如果你觉得这篇文章对你有所帮助,欢迎你把文章分享给你的朋友。

View File

@@ -0,0 +1,159 @@
<audio id="audio" title="13 | 自动化测试DevOps的阿克琉斯之踵" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/81/e0/812614c1d697ee2f88374a1425915ce0.mp3"></audio>
你好,我是石雪峰。
在古希腊神话中战神阿克琉斯英勇无比浑身刀枪不入唯独脚后跟是他的致命弱点。在特洛伊战争中他的脚后跟被一箭射中倒地身亡从此阿克琉斯之踵就被用来形容致命的缺陷。我今天要跟你聊的自动化测试就是DevOps的阿克琉斯之踵。
我之前走访过很多公司,我发现,在工程实践领域,比如配置管理、持续集成等,他们实践得还不错,但是却有两大通病,一个是研发度量,另一个就是自动化测试。
没有人会否认自动化测试的价值而且很多公司也都或多或少地在实践自动化测试。但从整体来看自动化测试的实施普遍不成体系大多都在关注单点工具。另外团队对自动化测试的真实效果也存在疑惑。如果不能解决这些问题就很难突破实践DevOps的天花板。
那么,自动化测试究竟要解决什么问题,又适合哪些业务形态和测试场景呢?我们该如何循序渐进地推进建设,并且正确地度量效果以免踩坑呢?这些问题,就是我要在这一讲中跟你分享的重点内容。
## 自动化测试要解决什么问题?
产品交付速度的提升,给测试工作带来了很大的挑战。一方面,测试时间被不断压缩,以前三天的测试工作要在一天内完成。另一方面,需求的变化也给测试工作的开展带来了很大的不确定性。这背后核心的问题是,**业务功能的累加导致测试范围不断扩大,但这跟测试时长的压缩是矛盾的**。说白了,就是要测试的内容越来越多,但是测试的时间却越来越短。
全面测试会带来相对更好的质量水平,但是投入的时间和人力成本也是巨大的,而快速迭代交付就意味着要承担一定的风险。那么,究竟是要速度,还是要质量,这是一个很难回答的问题。
所以,要想提升测试效率,自然就会联想到自动化手段。实际上,自动化测试适用于以下几种典型场景:
1. 有大量机械的重复操作,并且会反复执行的场景,比如批量的回归测试;
1. 有明确的设计规范且相对稳定的场景,比如接口测试;
1. 大批量、跨平台的兼容性测试,比如覆盖多种版本和多种机型的测试,几十个机型还可以接受,如果覆盖成百上千个机型,就只能依靠自动化了;
1. 长时间不间断执行的测试,比如压力测试、可用性测试等。
这些典型场景往往都具备几个特征:设计明确、功能稳定、可多次重复、长期大批量执行等,核心就是通过自动化手段来解决测试成本的问题,也就是人的问题。但这并不意味着手工测试就没有价值了。相反,当人从重复性劳动中解放出来后,就可以投入到更有价值的测试活动中,比如探索性测试、易用性测试、用户验收测试等,这些都属于手工测试的范畴。
这听上去还挺合理的,可是,为什么很多公司还是倾向于采用手工测试的方式呢?实际上,并非所有的测试活动都适合自动化,而且,自动化测试建设也面临着一些问题。
1. **投入产出比**:很多需求基本上只会上线一次(比如促销活动类需求),那么,实现自动化测试的成本要比手动测试高得多,而且以后也不会再用了,这显然有点得不偿失。
1. **上手门槛**:自动化测试依赖代码方式实现,要开发一套配置化的测试框架和平台,对架构设计和编码能力都有很大的要求。但是,测试人员的编码能力一般相对较弱。
1. **维护成本高**:无论是测试环境、测试用例还是测试数据,都需要随着需求的变化不断进行调整,否则就很容易因为自动化测试过时,导致执行失败。
1. **测试设备投入高**比如移动App的测试需要有大量的手机资源想要覆盖所有的手机型号、操作系统版本本身就不太现实。更何况有限的机器还经常被测试人员拿去做本地调试这就进一步加剧了线上测试没有可用资源的情况。
## 自动化测试的设计
这么看来,自动化测试并不是一把万能钥匙,我们也不能指望一切测试都实现自动化。只有在合适的领域,自动化测试才能发挥出最大价值。那么,你可能就要问了,面对这么多种测试类型,到底要从哪里启动自动化测试的建设呢?
首先我来给你介绍一下经典的测试三角形。这个模型描述了从单元测试、集成测试到UI测试的渐进式测试过程。越是靠近底层用例的执行速度就越快维护成本也越低。而在最上层的UI层执行速度要比单元测试和接口测试要慢比手工测试要快相应的维护成本要远高于单元测试和接口测试。
<img src="https://static001.geekbang.org/resource/image/28/6f/28d6b53907036a38d5649a673664006f.png" alt="">
>
图片来源“DevOps Handbook"
这样看来从靠近底层的单元测试入手是一个投入产出相对比较高的选择。但实际上单元测试的执行情况因公司而异有的公司能做到80%的覆盖率,但有的公司却寸步难行。毕竟,单元测试更多是由开发主导的,开发领导的态度就决定了运行的效果。但不可否认的是,单元测试还是非常必要的,尤其是针对核心服务,比如核心交易模块的覆盖率。当然,好的单元测试需要研发投入大量的精力。
对于UI层来说执行速度和维护成本走向了另外一个极端这也并不意味着就没有必要投入UI自动化建设。**UI层是唯一能够模拟用户真实操作场景的端到端测试**页面上的一个按钮可能触发内部几十个函数调用和单元测试每次只检查一个函数的逻辑不同UI测试更加关注模块集成后的联动逻辑**是集成测试最有效的手段**。
另外很多测试人员都是从UI开始接触自动化的再加上相对成熟的测试工具和框架实施不依赖于源码也是一种比较容易上手的自动化手段。在实际应用中UI自动化可以帮助我们节省人工测试成本提高功能测试的测试效率。不过它的缺点也是比较明显的**随着敏捷迭代的速度越来越快UI控件的频繁变更会导致控件定位不稳定提高了用例脚本的维护成本**。
综合考虑投入产出比和上手难度的话,位于中间层的接口测试就成了一种很好的选择。一方面,现代软件架构无论是分层还是服务调用模式,对接口的依赖程度都大大增加。比如典型的前后端分离的开发模式,前后端基本都是在围绕着接口进行开发联调。另一方面,与单元测试相比,接口测试调用的业务逻辑更加完整,并且具备清晰的接口定义,适合采用自动化的方式执行。
正因为如此对于基于Web的应用来说我更推荐椭圆形模型也就是以中间层的API接口测试为主以单元测试和UI测试为辅。你可以参考一下分层自动化测试模型图。
<img src="https://static001.geekbang.org/resource/image/14/9b/140a33713f7332277c8d2114d050d39b.png" alt="">
## 自动化测试的开发
**有效的自动化测试离不开工具和平台的支持**。以接口测试为例最早都是通过cURL、Postman、JMeter等工具单机执行的。但是一次成功的接口测试除了能够发起服务请求之外还需要前置的测试数据准备和后置的测试结果校验。对于企业的实际业务来说不仅需要单接口的执行还需要相对复杂的多接口而且带有逻辑的执行这就依赖于调用接口的编排能力甚至是内建的Mock服务。
不仅如此,测试数据、用例、脚本的管理,测试过程中数据的收集、度量、分析和展示,以及测试报告的发送等,都是一个成熟的自动化测试框架应该具备的功能。
比如对于UI自动化测试来说最让人头疼的就是UI控件变化后的用例维护成本问题。**解决方法就是操作层获取控件和控件本身的定位方法,进行解耦,这依赖于框架的设计与实现**。在实际操作控件时,你可以通过自定义名称的方式来调用控件,自定义名称在控件相关配置文件中进行定义。在具体操作时,可以通过操作层之下的代理层来处理。示例代码如下:
```
public void searchItem(String id) {
getTextBox(&quot;SearchBar&quot;).clearText();
getTextBox(&quot;SearchBar&quot;).setText(id);
getButton(&quot;Search&quot;).click();
}
```
在代码中搜索条控件被定义为SearchBar通过调用代理层的getTextBox方法得到一个文本输入框类型对象并调用该对象的清除方法。然后在对应的控件配置文件中添加对应的自定义名称和控件的定位方法。
这样一来,即便控件发生改变,对于实际操作层的代码来说,由于采用的是自定义名称,所以你不需要修改逻辑,只要在对应的控件配置文件中,替换控件的定位方法就行了。关于具体的控件配置文件,示例代码如下:
```
&lt;TextBox comment=&quot;首页搜索框&quot; id=&quot;SearchBar&quot;&gt;
&lt;iOS&gt;
&lt;appium&gt;
&lt;dependMethod methodName=&quot;findElementByXPath&quot;&gt;
&lt;xpath&gt;
//XCUIElementTypeNavigatorBar[@name=&quot;MainPageView&quot;]/XCUIElementTypeOther/...
&lt;/xpath&gt;
&lt;/dependMethod&gt;
&lt;/appium&gt;
&lt;/iOS&gt;
&lt;/TextBox&gt;
```
当然为了简化测试人员的编写用例成本你可以在操作层使用Page-Object模式针对页面或模块封装操作方式通过一种符合认知的方式来实现具体的功能操作。这样一来在实际编写用例的时候你就可以非常简单地调用操作层的接口定义。示例代码如下
```
@TestDriver(driverClass = AppiumDriver.class)
public void TC001() {
String id='10000'
page.main.switchView(3);
page.cart.clearShoppingCart();
page.main.switchView(0);
page.search.searchProduct(id);
page.infolist.selectlist(0);
page.infodetail.clickAddCart();
Assert.assertTrue(page.cart.isProductCartExist(), &quot;商品添加成功&quot;)
}
```
从这些示例中我们可以看出一个良好的自动化测试框架可以显著降低测试人员编写测试用例的门槛以及测试用例的维护成本。对于一个成熟的平台来说平台易用性是非常重要的能力通过DSL方式来声明测试过程可以让测试人员聚焦在测试业务逻辑的设计和构建上大大提升自动化测试的实现效率。
关于自动化测试框架的能力模型,我给你分享你一份资料,你可以点击[网盘](https://pan.baidu.com/s/1E3xAHgcehW9NyWKVgTXxFQ)获取提取码是gk9w。这个能力模型从测试脚本封装、测试数据解耦、测试流程编排、报告生成等多个方面展示了框架建设的各个阶段应该具备的能力。
## 自动化测试结果分析
那么,我们该如何衡量自动化测试的结果呢?当前比较常用的方式是**覆盖率**,不过问题是,测试覆盖率提升就能发现更多的缺陷吗?
一家大型金融公司的单元测试覆盖率达到了80%接口覆盖率更是达到了100%从这个角度来看他们的自动化测试做得相当不错。但是当我问到自动化测试发现的问题数量占到整体问题的比例时他们的回答有点出人意料。在这么高的覆盖率基础上自动化测试发现的问题占比仅仅在5%左右。那么花了这么大力气建设的自动化测试最后仅仅发现了5%的有效问题,这是不是说明自动化测试的投入产出比不高呢?
实际上,说自动化测试是为了发现更多的缺陷,这是一个典型的认知误区。在实际项目中,手工测试发现的缺陷数量要比自动化测试发现的缺陷数量多得多。自动化测试更多是在帮助守住软件质量的底线,尤其是应用在回归测试中,自动化测试可以确保工作正常的已有功能不会因为新功能的引入而带来质量回退。可以这么说,**如果自动化测试覆盖率足够高,那么软件质量一定不会差到哪儿去**。
在自动化测试领域,除了追求覆盖率一个指标以外,自动化测试的结果分析也值得重点关注一下。如果自动化测试的结果并不准确,甚至带来大量误报的话,这对团队来说反而是一种干扰。关于测试误报,是指由于非开发代码变更导致的自动化测试用例执行失败的情况。业界对于误报率的普遍定义是:
>
自动化测试误报率=非开发变更引入的问题用例数量/测试失败的用例数量
>
比如单次自动化测试执行了100个用例其中有20个用例失败这20个失败用例有5个是由于本次功能或代码变更引入的也就是真实的缺陷那么误报率就等于20 - 5/20 = 75%
**测试误报率是体现自动化测试稳定性的一个核心指标**。对于不同测试类型和产品形态,误报的的原因有很多。比如测试环境的网络不稳定导致的连接超时、测试脚本和测试工具本身的固有缺陷导致的执行失败、测试数据不齐备、测试资源不可用等等。
由于测试误报的客观存在,即便执行了自动化测试并给出了测试结果,但还是需要人工审查判断之后,才能将真正的问题上报缺陷系统。这样一来,在自动化执行末端加入了人工处理,就导致自动化测试难以大规模推行,这也是自动化测试略显“鸡肋”的原因之一。
那么,要如何解决这个问题呢?这就要依赖于自动化测试结果的分析啦。
1. 对自动化测试的问题进行分类。你要弄清楚一次失败是环境问题、网络问题、功能变更,还是系统缺陷?你需要将失败的用例归纳到这些分类之中。当一个类别的问题非常多的时候,你可以考虑进行拆分,比如网络问题,你可以拆分为网络不可达、延迟超时、域名解析错误等等。
1. 增加已有分类的自动识别能力。比如,对于捕获到的常见异常,可以根据异常信息自动上报到对应的错误分类,从而简化人工识别和归类错误的工作量。
1. 提升自动化测试工具和环境的健壮性,对已知问题增加一定的重试机制。
1. 持续积累和丰富错误分类,有针对性地开展改进工作,从而不断提升自动化测试的稳定性。
我跟你分享一幅某公司的自动化测试结果分析示意图。通过统计错误的分类,可以看出错误的占比情况,并且针对常见的误报类型进行有针对性的优化,并建立度量指标来跟踪长期结果,从而保证自动化测试结果的整体可信度。这些工作都需要长期的投入才能看出成效,这也是让自动化测试价值最大化和团队能力提升的必经之路。
<img src="https://static001.geekbang.org/resource/image/70/07/70445e2161b3c447c7d21384da947e07.png" alt="">
## 总结
总结一下,这一讲我给你介绍了有关自动化测试的四个方面,包括自动化测试要解决的问题和适用场景、实施的路径、框架工具开发的典型思路以及结果分析的要点。希望能够帮你建立起对自动化测试这个“老大难”问题的全面认知,让你在推进自动化测试能力建设的时候有迹可循。
## 思考题
你所在的企业在进行自动化建设时,有哪些困境和问题,你们是如何解决的呢?
欢迎在留言区写下你的思考和答案,我们一起讨论,共同学习进步。如果你觉得这篇文章对你有所帮助,欢迎你把文章分享给你的朋友。

View File

@@ -0,0 +1,134 @@
<audio id="audio" title="14 | 内建质量:丰田和亚马逊给我们的启示" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/00/b9/0038b70c49ff029ad8203f1f490f36b9.mp3"></audio>
你好,我是石雪峰,今天我来跟你聊一个非常重要的话题:内建质量。
我之前给你讲过一个故事,说的是在美国汽车工厂装配流水线的末端,总是有个人在拿着橡胶锤子敲打车门,以检查车门是否安装良好。我还说,如果一个公司要靠“拿锤子的人”来保证质量,这就说明,这个公司的流程本身可能就有问题。
这个观点并不是我凭空捏造出来的而是来自于质量管理大师爱德华·戴明博士经典的质量管理14条原则。其中第3条指出**不应该将质量依赖于检验工作,因为检验工作既昂贵,又不可靠。最重要的是,检验工作并不直接提升产品质量,只是为了证明质量有缺陷**。而正确的做法是将质量内建于整个流程之中,并通过有效的控制手段来证明流程自身的有效性。
## 为什么内建质量如此重要?
在传统的软件开发过程中,检验质量的“锤子”往往都握在测试团队的手中。他们在软件交付的末端,通过一系列的“锤子”来“敲打”软件产品的方方面面,试图找到一些潜在的问题。
这样做的问题是,测试通过尽可能全面的回归测试来验证产品质量符合预期,成本是巨大的,但是效果却不见得有多好。
因为测试只能基于已知的产品设计进行验证,但那些潜在的风险有可能连开发自己都不知道。比如,开发引入了一些第三方的类库,但这些库本身存在缺陷,那么,如果测试没有回归到这个场景,就很有可能出现漏测和生产事故。
另外由于测试存在的意义在于发现更多的缺陷有些团队的考核指标甚至直接关联缺陷提交数量以及缺陷修复数量。那么这里的前提就是假设产品是存在缺陷的。于是测试团队为了发现问题而发现问题在研发后面围追堵截这也造成了开发和测试之间的隔阂和对立这显然不是DevOps所倡导的状态。
那么,解决这个问题的正确“姿势”,就是内建质量啦!
关于内建质量,有个经典的案例就是丰田公司的安灯系统,也叫作安灯拉绳。丰田的汽车生产线上方有一条绳子,如果生产线上的员工发现了质量问题,就可以拉动安灯系统通知管理人员,并停止生产线,以避免带有缺陷的产品不断流向下游。
要知道在生产制造业中生产线恨不得24小时运转因为这样可以最大化地利用时间生产更多的产品。可是现在随随便便一个员工就可以让整条生产线停转丰田公司是怎么想的呢
其实这背后的理念就是“Fail fast”即快速失败。如果工人发现了有缺陷的产品却要经过层层审批才能停止生产线就会有大量带有缺陷的产品流向下游所以停止生产线并不是目的及时发现问题和解决问题才是目的。
当启动安灯系统之后,管理人员、产线质量控制人员等相关人员会立刻聚集到一起解决这个问题,并尽快使生产线重新恢复运转。更重要的是,这些经验会被积累下来,并融入组织的能力之中。
内建质量扭转了看待产品质量的根本视角,也就是说,**团队所做的一切不是为了验证产品存在问题,而是为了确保产品没有问题**。
几年前我在华为参加转正答辩的时候被问到一个问题“华为的质量观是怎样的”答案是三个字“零缺陷。”我当时并不理解人非圣贤孰能无过产品零缺陷简直就是反常理。但是后来我慢慢明白所谓零缺陷并不是说产品的Bug数量等于零这其实是一种质量观念倡导全员质量管理构建质量文化。每一个人在工作的时候都要力争第一时间发现和解决缺陷。
所以,总结一下,内建质量有两个核心原则:
- 问题发现得越早,修复成本就越低;
- 质量是每个人的责任,而不是质量团队的责任。
说了这么多,你应该已经对内建质量有了初步的认识。那么接下来,我来给你介绍下内建质量的实践思路、操作步骤、常见问题以及应对方法。
## 内建质量的实施思路
既然是内建质量,那么,我们就应该在软件交付的各个环节中注入质量控制的能力。
在需求环节,可以定义清晰的需求准入规则,比如需求的价值衡量指标是否客观、需求的技术可行性是否经过了验证、需求的依赖是否充分评估、需求描述是否清晰、需求拆分是否合理、需求验收条件是否明确等等。
通过前置需求质量控制,可以减少不靠谱的需求流入。在很多公司,“一句话需求”和“老板需求”是非常典型的例子。由于没有进行充分沟通,研发就跟着感觉走,结果交付出来的东西完全不是想要的,这就带来了返工浪费。
**在开发阶段,代码评审和持续集成就是一个非常好的内建质量的实践**。在代码评审中,要尽量确认编码是否和需求相匹配,业务逻辑是否清晰。另外,通过一系列的自动化检查机制,来验证编码风格、风险、安全漏洞等。
在测试阶段,可以通过各类自动化测试,以及手工探索测试,覆盖安全、性能、可靠性等,来保障产品质量;在部署和发布阶段,可以增加数据库监控、危险操作扫描、线上业务监控等多种手段。
从实践的角度来说,每个环节都可以控制质量,那么,我们要优先加强哪个环节呢?
根据内建质量的第一原则,我们知道,如果可以在代码刚刚提交的时候就发现和修复缺陷,成本和影响都是最低的。如果等到产品上线后,发现了线上质量问题,再回过头来定位和修复问题,并重新发布软件,成本将会呈指数级增长。
所以,**研发环节作为整个软件产品的源头,是内建质量的最佳选择**。那么,具体要怎么实施呢?
## 内建质量的实施步骤
**第一步:选择适合的检查类型**
以持续集成阶段的代码检查为例,除了有单元测试、代码风格检查、代码缺陷和漏洞检查、安全检查等等,还有各种各样的检查工具。但实际上,这些并不是都需要的。至少在刚开始实践的时候,如果一股脑全上,那么研发基本上就不用干活了。
所以,**选择投入产出比相对比较高的检查类型,是一种合理的策略**。比如代码风格与缺陷漏洞相比检查缺陷漏洞显然更加重要因为一旦发生代码缺陷和漏洞就会引发线上事故。所以这么看来如果是客户端业务Infer扫描就可以优先实施起来。虽然我们不能忽视编码风格问题但这并不是需要第一时间强制执行的。
**第二步:定义指标并达成一致**
确定检查类型之后,就要定义具体的质量指标了。质量指标分两个层面,一个是指标项,一个是参考值,我分别来介绍一下。
**指标项是针对检查类型所采纳的具体指标**,比如单元测试覆盖率这个检查项,可采纳的指标就包括行、指令、类、函数等。那么,我们要以哪个为准呢?这个一般需要同研发负责人达成一致,并兼顾行业的一些典型做法,比如单测行覆盖率就是一个比较好的选择。
另外,很多时候,在既有项目启用检查的时候,都会有大量的技术债。关于技术债,我会在下一讲展开介绍。简单来说,就是欠了一堆债,一时半会儿又还不了,怎么办呢?这个时候,比较合适的做法就是选择动态指标,比如增量代码覆盖率,也就是只关注增量代码的情况,对存量代码暂不做要求。
指标项定义明确之后,就要定义参考值了。这个参考值会直接影响质量门禁是否生效,以及生效后的行为。
我简单介绍下质量门禁。质量门禁就类似一道安全门,通过门禁时进行检查,如果不满足指标,则门禁报警,禁止通过。这就跟交警查酒驾一样,酒精含量如果超过一定的指标,就会触发报警。
**参考值的定义是一门艺术**。对于不同的项目,甚至是同一个项目的不同模块来说,我们很难用“一刀切”的方式定义数值。我比较推荐的做法是**将静态指标和动态指标结合起来使用**。
**静态指标就是固定值**,对于漏洞、安全等问题来说,采取零容忍的态度,只要存在就绝不放过。而**动态指标是以考查增量和趋势为主**比如基线值是100你就可以将参考值定义成小于等于100也就是不允许增加。你还可以根据不同的问题等级定义不同的参考值比如严格检查致命和阻塞问题其余的不做限制。
最后,对于这个指标,你一定要跟研发团队达成共识,也就是说,团队要能够认可并且执行下去。所以,定义指标的时候要充分采纳对方的建议。
**第三步:建立自动化执行和检查能力**
无论公司使用的是开源工具还是自研工具,都需要支持自动化执行和检查的能力。根据检查时机的不同,你也可以在提测平台、发布平台上集成质量门禁的功能,并给出检查结果的反馈。
**按照快速失败的原则,质量门禁的生效节点要尽量靠近指标数据的产生环节**。比如如果要检查编码风格最佳的时间点是在研发本地的IDE中进行其次是在版本控制系统中进行并反馈结果而不是到了最后发布的时间点再反馈失败。
现代持续交付流水线平台都具备质量门禁的功能,常见的配置和生效方式有两种:
1. 在持续交付平台上配置规则,也就是不同指标和参考值组合起来,形成一组规则,并将规则关联到具体的执行任务中。这样做的好处是,各个生成指标数据的子系统只需要将数据提供给持续交付平台就行了,至于门禁是否通过,完全依靠持续交付平台进行判断。另外,一般配置规则的都是质量人员,提供这样一个单独的入口,可以简化配置成本。具体的实现逻辑,如图所示:
<img src="https://static001.geekbang.org/resource/image/16/fb/16168a5d172c4839ef98b201fcdd5dfb.png" alt="">
1. 在各个子系统中配置质量门禁。比如在UI自动化测试平台上配置门禁的指标当持续交付平台调用UI自动化测试的时候直接反馈门禁判断的结果。如果检查不通过则流水线直接失败。
**第四步:定义问题处理方式**
完成以上三步之后,就已经开始进行自动化检查了,而检查的结果和处理方式,对质量门禁能否真正起到作用非常重要。一般来说,质量门禁都具有强制属性,也就是说,如果没有达到检查指标,就会立即停止并给予反馈。
在实际执行的过程中,质量门禁的结果可能存在多种选项,比如失败、告警、人工确认等。这些都需要在制定规则的时候定义清楚,通过一定的告警值和人工确认方式,可以对质量进行渐进式管控,以达到持续优化的目标。
另外,你需要对所有软件交付团队成员宣导质量规则和门禁标准,并明确通知方式、失败的处理方式等。否则,检查出问题却没人处理,这个门禁就形同虚设了。
**第五步:持续优化和改进**
无论是检查能力、指标、参考值,还是处理方式,只有在运行起来后才能知道是否有问题。所以,在推行的初期,也应该具备一定程度的灵活性,比如对指标规则的修订、指标级别和参考值的调整等,**核心目标不是为了通过质量门禁,而是为了质量提升,这才是最重要的**。
## 内建质量的常见问题
内建质量说起来并不复杂,但想要执行到位却很困难,那么,到底有哪些常见的问题呢?我总结了一些常见问题和处理建议,做成了表格,你可以参考一下。
<img src="https://static001.geekbang.org/resource/image/5f/fe/5fe50bad00fced809adcbd31775ed3fe.jpg" alt="">
最后我再给你分享一个亚马逊的故事。2012年安灯系统被引入亚马逊公司一线客服如果收到客户反馈或者观察到商品有潜在的质量和安全风险就可以发出告警邮件并将商品设置为“不可购买”的状态说白了就是强制下架。客服居然可以不经过任何审批直接把商品下架不怕遭到供应商的投诉吗
实际上,这正是亚马逊践行以客户为中心的理念和原则的真实写照,**每个人都为最终质量负责,没有例外**。当员工得知自己被赋予了这样大的权限时,每个人都会尽自己的力量为质量工作加分。即便偶尔会有错误操作,这也是团队内部难能可贵的学习经验。
在公司中,无论是建立质量门禁的规则,还是开发一套平台系统,其实都不是最困难的事情,难的是,在实际过程中,有多少正常流程走了特殊审批?有多少发布是走的紧急通道?又有多少人会说开启了质量门禁,就会阻碍业务交付?
说到底,还是要问问自己,你愿意付出多少代价,来践行自己的理念和原则,先上再说?我想,能在这一点上达成共识,才是内建质量落地的终极要素吧。
## 总结
总结一下在这一讲中我通过两个故事给你介绍了内建质量的背景和原则那就是尽早发现问题尽早修复以及每个人都是质量的负责人。另外我还给你介绍了实施内建质量的五个常见步骤。希望你始终记得质量是生产出来的而不是测试出来的。掌握了内建质量你就揭开了DevOps高效率和高质量并存的秘密。
## 思考题
你所在的企业中是否启用了强制的质量门禁呢?可以分享一些你觉得效果良好的规则吗?
欢迎在留言区写下你的思考和答案,我们一起讨论,共同学习进步。如果你觉得这篇文章对你有所帮助,欢迎你把文章分享给你的朋友。

View File

@@ -0,0 +1,144 @@
<audio id="audio" title="15 | 技术债务:那些不可忽视的潜在问题" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/55/74/5544bb6bf642d02942974dc5ad3a1a74.mp3"></audio>
你好,我是石雪峰,今天我来跟你聊聊技术债务。
如果要问软件开发人员在项目中最不愿意遇到的事情,答案很可能是接手了一个别人开发了一半的系统。而且,系统开发的时间越长,开发人员的抵触情绪也就越大。那么,既然是同一种代码语言,同一种语法规则,至少还是一个能运行的东西,开发人员为什么要发自内心地抵触呢?我猜,很可能是不想看别人写的代码。之所以会这样,看不懂和怕改错是一个非常重要的原因,而这些,其实都是技术债务的结果。
## 什么是技术债务?
那么,究竟什么是技术债务呢?它是从哪里来的呢?好好地写个代码,咋还欠债了呢?
试想这样一种场景老板拍下来一个紧急需求要求你在3天内开发完成上线。在评估需求和设计的时候你发现要实现这个功能有两种方案
- 方案1采用分层架构引入消息队列。这样做的好处是结构清晰功能解耦但是需要1周的时间
- 方案2直接在原有代码的基础上修修补补硬塞进去一块逻辑和页面这样做需要2天时间还有1天时间来测试。
那么,你会选择哪个方案呢?
我想在大多数情况下你可能都会选择方案2因为业务的需求优先级始终是最高的。尤其是当下市场竞争恨不得以秒来计算先发优势非常明显。
而技术债务,就是指团队在开发过程中,为了实现短期目标选择了一种权宜之计,而非更好的解决方案,所要付出的代价。这个代价就是团队后续维护这套代码的额外工作成本,并且只要是债务就会有利息,债务偿还得越晚,代价也就越高。
实际上,带来技术债务的原因有很多,除了压力之下的快速开发之外,还包括不明真相的临时解决方案、新员工技术水平不足,和历史债务累积下来的无奈之举等。总之,代码维护的时间越长,引入的技术债务就会越多,从而使团队背上沉重的负担。
## 技术债务长什么样?
简单来说,你可以把技术债务理解为不好的代码。但是这里的“不好”,究竟是哪里不好呢?我相信,写过代码的人,或多或少都有过这样的经历:
- 一份代码里面定义了一堆全局变量,各个角落都在引用;
- 一个脚本仓库里面,一大堆名字看起来差不多的脚本,内容也都差不多;
- 一个函数里面修修补补写了上千行;
- 数据表查询各种神奇的关联;
- 参数传递纯靠肉眼计算顺序;
- 因为修改一段代码引发了一系列莫名其妙的问题;
- ……
那么究竟要如何对代码的技术债务进行分类呢我们可以借用“Sonar Code Quality Testing Essentials”一书中的代码“七宗罪”也就是复杂性、重复代码、代码规范、注释有效性、测试覆盖度、潜在缺陷和系统架构七种典型问题。你可以参考一下这七种类型对应的解释和描述
<img src="https://static001.geekbang.org/resource/image/a8/ac/a8053cf56a473c22100dca9032bae9ac.jpg" alt="">
除了低质量的代码问题之外,还有很多其他类型的技术债务,比如不合理的架构、过时的技术、冷门的技术语言等等。
比如我们公司之前基于Ruby语言开发了一套系统但是与Java、Python等流行语言相比Ruby比较小众所以很难找到合适的工程师也影响了系统的进一步发展。再比如到2020年元旦官方即将停止为Python 2.x分支提供任何支持如果现在你们的新系统还在采用Python 2进行开发那么很快就将面对升级大版本的问题。虽然官方提供了一些减少迁移成本的方案但是从系统稳定性等方面来讲依然有着非常大的潜在工作量。
## 为什么要重视技术债务?
那么问题来了,为什么要重视技术债务呢?或者说,烂代码会有什么问题呢?
从用户的角度来说技术债务的多少好像并不影响用户的直观体验说白了就是不耽误使用应该有的功能都很正常。那么回到最开始的那个例子既然2天开发的系统和1周开发的系统从使用的角度来说并没有什么区别那是不是就意味着理应选择时间成本更低的方案呢
显然没有这么简单。举个例子,一个人出门时衣着得体,但是家里却乱成一团,找点东西总是要花很长时间,这当然不是什么值得骄傲的事情。对于软件来说,也是如此。**技术债务最直接的影响就是内部代码质量的高低**。如果软件内部质量很差会带来3个方面的影响
**1.额外的研发成本**
对一个架构清晰、代码规范、逻辑有序、注释全面的系统来说新增一个特性可能只需要12天时间。但是同样的需求在一个混乱的代码里面可能要花上1周甚至是更长的时间。因为单是理解原有代码的逻辑、理清调用关系、把所有潜在的坑趟出来就不是件容易的事情。更何况还有大量重复的代码每个地方都要修改一遍一不小心就会出问题。
**2.不稳定的产品质量**
代码质量越差,修改问题所带来的影响可能就越大,因为你不知道改了一处内容,会在哪个边缘角落引发异常问题。而且,这类代码往往也没有可靠的测试案例,能够保证修改前和修改后的逻辑是正确的。如果新增一个功能,导致了严重的线上问题,这时就要面临是继续修改还是回滚的选择问题。因为如果继续修改,可能会越错越多,就像一个无底洞一样,怎么都填不满。
**3.难以维护的产品**
正是由于以上这些问题,研发人员在维护这种代码的时候往往是小心加谨慎,生怕出问题。这样一来,研发人员宁愿修修补补,也不愿意改变原有的逻辑,这就会导致代码质量陷入一种不断变坏的向下螺旋,越来越难以维护,问题越积累越多,直到再也没办法维护的那一天,就以重构的名义,推倒重来。其实这压根就不是重构,而是重写。
另外,如果研发团队整天跟这样的项目打交道,团队的学习能力和工作积极性都有可能受到影响。可见,技术债务的积累就像真的债务一样,属于“出来混,迟早要还”的那种,只不过是谁来还的问题而已。
## 如何量化技术债务?
软件开发不像是银行贷款,技术债务看不见摸不着,所以,我们需要一套计算方法把这种债务量化出来。**目前业界比较常用的开源软件就是SonarQube**。在SonarQube中技术债是基于SQALE方法计算出来的。关于[SQALE](http://www.sqale.org/)全称是Software Quality Assessment based on Lifecycle Expectations这是一种开源算法。当然今天的重点不是讲这个算法你可以在[官网](http://www.sqale.org/)查看更多的内容。同时我再跟你分享一篇关于SQALE算法的[文章](https://blog.sonarsource.com/sqale-the-ultimate-quality-model-to-assess-technical-debt/),它可以帮你更深入地研究代码质量。
Sonar通过将不同类型的规则按照一套标准的算法进行识别和统计最终汇总成一个时间也就是说要解决扫描出来的这些问题需要花费的时间成本大概是多少从而对代码质量有一种直观的认识。
Sonar提供了一种通用的换算公式。举个例子如下图所示在Sonar的默认规则中数据越界问题被定义为严重级别的问题换算出来的技术债务等于15分钟。这里的15分钟就是根据前面提到的SQALE分析模型计算得出的。当然你也可以在规则配置里面对每一条规则的预计修复时间进行自定义。
<img src="https://static001.geekbang.org/resource/image/d1/09/d1b393d5d6744f478fb16a73631f6109.png" alt="">
**计算出来的技术债务会因为开启的规则数量和种类的不同而不同**。就像我在上一讲中提到的那样,团队内部对规则达成共识,是非常重要的。因为只有达成了共识,才能在这个基础上进行优化。否则,如果规则库变来变去,技术债务指标也会跟着变化,这样就很难看出团队代码质量的长期走势了。
另外在Sonar中还有一个更加直观的指标来表示代码质量这就是**SQALE级别**。SQALE的级别为A、B、C、D、E其中A是最高等级意味着代码质量水平最高。级别的算法完全是基于技术债务比例得来的。简单来说就是**根据当前代码的行数,计算修复技术债务的时间成本和完全重写这个代码的时间成本的比例**。在极端情况下一份代码的技术债务修复时长甚至比完全推倒重写还要长这就说明代码已经到了无法维护的境地。所以在具体实践的时候也会格外重视代码的SQALE级别的健康程度。
>
技术债务比例 = 修复已有技术债务的时间 / 完全重写全部代码的时间
将代码行数引入进来可以更加客观地计算整体质量水平。毕竟一个10万行的代码项目和一个1千行的代码项目比较技术债务本身就没有意义。其实这里体现了一种更加可视化的度量方式。比如现在很多公司在做团队的效能度量时往往会引入一大堆的指标来计算根本看不懂。更加高级的做法是将各种指标汇总成一组算法并根据算法给出相应的评级。
当然,如果你想知道评级的计算方法,也可以层层展开,查看详细的数据。比如,持续集成能力,它是由持续集成频率、持续集成时长、持续集成成功率、问题修复时长等多个指标共同组成的。如果在度量过程中,你发现持续集成的整体评分不高,就可以点击进去查看每个指标的数据和状态,以及详细的执行历史。这种数据关联和下钻的能力对构建数据度量体系而言非常重要。
通过将技术债务可视化,团队会对代码质量有更直观的认识,那么接下来,就要解决这些问题了。
## 解决方法和原则
我走访过很多公司他们都懂得技术债务的危害不仅把Sonar搭建起来了还定时执行了但问题是没时间。的确很多时候我们没时间做单测没时间做代码评审没时间解决技术债务但是这样一路妥协啥时候是个头儿呢
前几天,我去拜访一家国内最大的券商公司,眼前一亮。这样一家所谓的传统企业,在研项目的技术债务居然是个位数。在跟他们深入交流之后,我发现,公司在这方面下了大力气,高层领导强力管控,质量门禁严格执行,所以才获得了这样的效果。
所以,从来没有一切外部条件都具备的时候,要做的就是先干再说。那么,要想解决技术债务,有哪些步骤呢?
1. 共识:团队内部要对技术债务的危害、解决项目的目标、规则的选择和制定达成一致意见。
1. 可见通过搭建开源的Sonar平台将代码扫描整合进持续交付流水线中定期或者按需执行让技术债务变得可视化和可量化。不仅如此Sonar平台还能针对识别出来的问题给出建议的解决方法这对于团队快速提升编码水平大有帮助。
1. 止损针对核心业务模块对核心指标类型比如vulnerability缺陷的严重和阻塞问题设定基线也就是控制整体数量不再增长。
1. 改善:创建技术优化需求,并在迭代中留出一定的时间修复已有问题,或者采用集中突击的方式搞定大头儿,再持续改进。
在解决技术债务的过程中要遵循4条原则。
1. **让技术债务呈良性下降趋势**。一种好的趋势意味着一个好的起点,也是团队共同维护技术债务的一种约定。
1. **优先解决高频修改的问题**。技术债务的利息就是引入新功能的额外成本,那么对于高频修改的模块来说,这种成本会快速累积,这也就意味着修复的产出是最大的。至于哪些代码是高频修改的,只要通过**分析版本控制系统**就可以看出来。
1. **在新项目中启动试点**。如果现有的代码过于庞大不可能在短时间内完成修复那么你可以选择控制增长同时在新项目中试点执行一方面磨合规则的有效性另一方面也能试点质量门禁、IDE插件集成等自动化流程。
1. **技术债务无法被消灭,也不要等到太晚**。只要还在开发软件项目,技术债务就基本上无法避免,所以不需要一下子把目标定得太高,循序渐进就行了。但同时,技术债务的累积也不是无穷无尽的,等到再也无法维护的时候就太迟了。
在刚开始解决技术债务的时候最大的问题不是参考指标太少而是太多了。所以团队需要花大量时间来Review规则。关于这个问题我给你两条建议第一参考代码质量平台的默认问题级别。一般来说阻塞和严重的问题的优先级比一般问题更高这也是基于代码质量平台长时间的专业积累得出的结论。第二你可以参考业界优秀公司的实践经验比如很多公司都在参考阿里巴巴的Java开发手册京东也有自己的编码规约。最后我总结了一些影响比较大的问题类型建议你优先进行处理。
- 大量重复代码;
- 类之间的耦合严重;
- 方法过于复杂;
- 条件判断嵌套太多;
- 缺少必要的异常处理;
- 多表关联和缺少索引;
- 代码风险和缺陷;
- 安全漏洞。
## 总结
在这一讲中,我给你介绍了什么是技术债。而技术债的成本,就是团队后续开发新功能的额外成本。技术债务有很多形态,典型的就是代码“七宗罪”。除此之外,我还跟你聊了下技术债的影响,以及量化技术债务的方法。最后,我给出了一些解决方法和原则,希望能帮你攻克技术债这个难题。
<img src="https://static001.geekbang.org/resource/image/21/97/21932cb077d7b910588ef291ee028597.jpeg" alt="">
最近这两年,智能研发的声音不绝于耳,其中关于使用人工智能和大数据技术提升代码质量的方法,是目前的一个热门研究领域。通过技术手段,辅助研发解决技术问题,在未来是一种趋势。如果你在公司中从事的是研发辅助和效率提升类的工作,建议你深入研究下相关的学术文章,这对你的工作会大有裨益。
>
参考资料:
<ol>
- [通过持续监控实现代码克隆的定制化管理](https://mp.weixin.qq.com/s/e4B0PsyUPCD2FAJBL0HNbQ)
- [基于代码大数据的软件开发质量追溯体系](https://mp.weixin.qq.com/s/oPYiFCYj1l4XKfTyNj8zEA)
- [代码克隆那点事:开发人员为何克隆?现状如何改变?](https://mp.weixin.qq.com/s/iGQsMJP-6eusfJX8Q66kaQ)
</ol>
## 思考题
你遇到过印象深刻的烂代码吗?
欢迎在留言区写下你的思考和答案,我们一起讨论,共同学习进步。如果你觉得这篇文章对你有所帮助,欢迎你把文章分享给你的朋友。

View File

@@ -0,0 +1,169 @@
<audio id="audio" title="16 | 环境管理:一切皆代码是一种什么样的体验?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/32/9a/32ed94a9960fd6d4e8bb6c6ad0d97b9a.mp3"></audio>
你好,我是石雪峰。
网上经常流传着一些有关偏见地图的段子,通俗点说,“偏见地图”就是说网友对世界其他地方的印象,比如很多人认为天津人都会说相声。
如果软件开发中也有偏见地图的话那么对不熟悉运维的人来说提到运维团队可能就觉得是维护环境的那帮人。于是环境就成了软件行业的“头号背锅侠”。比如线上出故障了可以是环境配置错误测试有些功能没测到可以是没有测试环境开发出Bug了也不管三七二十一先甩给环境再说……所以你看好像什么问题都可能跟环境相关。这种没来由的偏见也加剧了开发和运维之间的不信任。
## 环境管理的挑战
那么为啥环境总是让人这么不放心呢其实这是因为现代企业所面对的业务复杂性很大程度上都可以直观地体现在环境管理的方方面面上。总结起来我认为一共有5点
1.**环境种类繁多**
首先软件关联的环境种类越来越多比如开发环境、测试环境、UAT用户验收测试环境、预发布环境、灰度环境、生产环境等。光是分清这些环境的名字和作用就不是件容易的事情。
2.**环境复杂性上升**
现代应用的架构逐渐从单体应用向微服务应用转变。随着服务的拆分,各种缓存、路由、消息、通知等服务缺一不可,任何一个地方配置出错,应用都有可能无法正常运行。这还不包括各种服务之间的依赖和调用关系,这就导致很多企业部署一套完整环境的代价极高,甚至变成了不可能完成的任务。
3.**环境一致性难以保证**
比如,那句经典的甩锅名言“在我的机器上没问题”说的就是环境不一致的问题。如果无法保证各种环境配置的一致性,那么类似的问题就会无休止地发生。实际上,在很多企业中,生产环境由专门的团队管理维护,管理配置还算受控。但是对于开发环境来说,基本都属于一个黑盒子,毕竟是研发本地的电脑,即便想管也管不到。
4.**环境交付速度慢**
由于职责分离环境的申请流程一般都比较冗长从提起申请到交付可用的环境往往需要2周甚至更长的时间。
一方面这跟公司内部的流程审批有关。我见过一家企业申请一套环境需要5级审批想象一下于一家扁平化组织的公司从员工到CEO之间的层级可能也没有5级。另一方面环境配置过程依赖手动完成过程繁琐效率也不高大多数情况下环境配置文档都属于过时状态并不会根据应用升级而动态调整这么一来二去几天就过去了。
5.**环境变更难以追溯**
产品上线以后出现问题,查了半天才发现,原来是某个环境参数的配置导致的。至于这个配置是谁改的,什么时间改的,为什么修改,经过了哪些评审,一概不知,这就给线上环境的稳定性带来了极大的挑战和潜在的风险。要知道,**环境配置变更的重要性,一点也不亚于代码变更,通常都需要严格管控**。
## 基础设施即代码
你可能会问有没有一种方法可以用来解决这些问题呢还真有这就是基础设施即代码。可以这么说如果没有采用基础设施即代码的实践DevOps一定走不远。那么到底什么是基础设施即代码呢
**基础设施即代码就是用一种描述性的语言通过文本管理环境配置并且自动化完成环境配置的方式。典型的就是以CAPS为代表的自动化环境配置管理工具**也就是Chef、Ansible、Puppet和Saltstacks四个开源工具的首字母缩写。
这个概念听起来比较抽象那么所谓基础设施即代码这个描述基础设施的代码长什么样子呢我给你分享一段Ansible的配置示例你可以参考一下。
```
---
- name: Playbook
hosts: webservers
become: yes
become_user: root
tasks:
- name: ensure apache is at the latest version
yum:
name: httpd
state: latest
- name: ensure apache is running
service:
name: httpd
state: started
```
无论你是否了解Ansible单就这段代码而言即便你不是专业运维或者工具专家在注释的帮助下你也大概能理解这个环境配置过程。实际上这段代码就做了两件事安装http的软件包并启动相关服务。
为什么基础设施即代码能够解决以上问题呢?
首先,对于同一个应用来说,各种环境的配置过程大同小异,只是在一些配置参数和依赖服务方面有所差别。**通过将所有环境的配置过程代码化,每个环境都对应一份配置文件,可以实现公共配置的复用**。当环境发生变更时,就不再需要登录机器,而是直接修改环境的配置文件。这样一来,环境配置就成了一份活的文档,再也不会因为更新不及时而失效了。
其次,**环境的配置过程,完全可以使用工具自动化批量完成**。你只需要引用对应环境的配置文件即可,剩下的事情都交给工具。而且,即便各台机器的初始配置不一样,工具也可以保证环境的最终一致性。由于现代工具普遍支持幂等性原则,即便执行完整的配置过程,工具也会自动检测哪些步骤已经配置过了,然后跳过这个步骤继续后面的操作。这样一来,大批量环境的配置效率就大大提升了。
最后既然环境配置变成了代码自然可以直接纳入版本控制系统中进行管理享受版本控制的福利。任何环境的配置变更都可以通过类似Git命令的方式来实现不仅收敛了环境配置的入口还让所有的环境变更都完全可追溯。
基础设施即代码的实践通过人人可以读懂的代码将原本复杂的技术简单化这样一来即便是团队中不懂运维的角色也能看懂和修改这个过程。这不仅让团队成员有了一种共同的语言还大大减少了不同角色之间的依赖降低了沟通协作成本。这也是基础设施即代码的隐形价值所在特别符合DevOps所倡导的协作原则。
看到这儿你可能会说这不就是一种自动化手段吗好像也没什么特别的呀。回头想想DevOps的初衷就是打破开发和运维的隔阂但究竟要如何打通呢
在大多数公司,部署上线的工作都是由专职的运维团队来负责,开发团队只要将测试通过的软件包提供给运维团队就行了。所以,**开发和运维的自然边界就在于软件包交付的环节只有打通开发环节的软件集成验收的CI流水线和运维环节的应用部署CD流水线上线才能真正实现开发运维的一体化**。而当版本控制系统遇上基础设施即代码,就形成了一种绝妙的组合,那就是**GitOps**。
### 开发运维打通的GitOps实践
顾名思义GitOps就是基于版本控制系统Git来实现的一套解决方案核心在于基于Git这样一个统一的数据源通过类似代码提交过程中的拉取请求的方式也就是Pull Request来完成应用从开发到运维的交付过程让开发和运维之间的协作可以基于Git来实现。
虽然GitOps最初是基于容器技术和Kubernetes平台来实现的但它的理念并不局限于使用容器技术实际上**它的核心在于通过代码化的方式来描述应用部署的环境和部署过程**。
在GitOps中每一个环境对应一个环境配置仓库这个仓库中包含了应用部署所需要的一切过程。比如使用Kubernetes的时候就是应用的一组资源描述文件比如部署哪个版本开放哪些端口部署过程是怎样的。
当然你也可以使用Helm工具来统一管理这些资源文件。如果你还不太熟悉Kubernetes可以简单地把它理解为云时代的Linux而Helm就是RPM或者APT这些包管理工具通过应用打包的方式来简化应用的部署过程。
除了基于Kubernetes的应用你也可以使用类似Ansible Playbook的方式。只不过与现成的Helm工具相比使用Ansible时需要自己实现一些部署脚本不过这也不是一件复杂的事情。
你可以看看下面的这段配置文件示例。这些配置文件采用了yml格式它描述了应用部署的主要信息其中镜像名称使用参数形式会有一个独立的文件来统一管理这些变量你可以根据应用的实际版本进行替换以达到部署不同应用的目标。
```
apiVersion: extensions/v1beta1
kind: Deployment
spec:
replicas: 1
template:
metadata:
labels:
app: demo
spec:
containers:
- name: demo
image: &quot;{{ .Values.image.tag }}&quot;
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
```
现在,我们来看看这个方案是如何实现的。
首先开发人员提交新的代码改动到Git仓库这会自动触发持续集成流水线对于常见的版本控制系统来说配置钩子就可以实现。当代码经过一系列的构建、测试和检查环节并最终通过持续集成流水线之后就会生成一个新版本的应用并上传到制品库中典型的就是Docker镜像文件或者war包的形式。
以上面的配置为例假如生成了应用的1.0版本镜像接下来会自动针对测试环境的配置仓库创建一个代码合并请求变更的内容就是修改镜像名称的版本号为1.0。这个时候,开发或者测试人员可以通过接受合并的方式,将这段环境变更配置合入主干,并再一次自动化地触发部署流水线,将新版本的应用部署到测试环境中。每次应用的部署采用相同的过程,一般就是将最新版本的应用制品拷贝到服务器并且重启,或者更新容器镜像并触发滚动升级。
这个时候测试环境就部署完成了当然如果使用Kubernetes可以利用**命名空间的特性**,快速创建出一套独立的环境,这是使用传统部署的应用所不具备的优势。在测试环境验收通过后,可以将代码合并到主分支,再一次触发完整的集成流水线环节,进行更加全面的测试工作。
当流水线执行成功后,可以自动针对预发布环境的配置仓库创建一个合并请求,当评审通过后,系统自动完成预发布环境的部署。如果职责分离要求预发布环境的部署必须由运维人员来操作,把合并代码的权限只开放给运维人员就行了。当运维人员收到通知后,可以登录版本控制系统,查看本次变更的范围,评估影响,并按照部署节奏完成部署。而这个操作,只需要在界面点击按钮就可以实现了。这样一来,开发和运维团队的协作就不再是一个黑盒子了。大家基于代码提交评审的方式完成应用的交付部署,整个过程中的配置过程和参数信息都是透明共享的。
我跟你分享一幅流程图,希望可以帮你充分地理解这个分层部署的过程。
<img src="https://static001.geekbang.org/resource/image/2d/fc/2de091bea58d1c4f376a26fa61c8f0fc.png" alt="">
那么GitOps的好处究竟有哪些呢
首先,就是**环境配置的共享和统一管理**。原本复杂的环境配置过程通过代码化的方式管理起来,每个人都能看懂。这对于开发自运维来说,大大地简化了部署的复杂度。
另外所有最新的环境配置都以Git仓库中为准每一次的变更和部署过程也同样由版本控制系统进行记录。即便仅仅是环境工具的升级也需要经过以上的完整流程从而实现了环境和工具升级的层层验证。所以这和基础设施即代码的理念可以说有异曲同工之妙。
### 开发环境的治理实践
关于开发环境的治理,我再给你举一个实际的案例。对于智能硬件产品开发来说,最大的痛点就是各种环境和工具的配置非常复杂,每个新员工入职,配置环境就要花上几天时间。另外,由于工具升级频繁和多平台并行开发的需要,开发经常需要在多种工具之间进行来回切换,管理成本很高。
关于这个问题,同样**可以采用基础设施即代码的方法生成一个包含全部工具依赖的Docker镜像并分发给开发团队**。在开发时仅需要拉起一个容器,将代码目录挂载进去,就可以生成一个完全标准化的研发环境。当工具版本升级时,可以重新制作一个新的镜像,开发本地拉取后,所有的工具就升级完成了,这大大简化了研发环境的维护成本。
其实,我们也可以发挥创新能力,**把多种工具结合起来使用,以解决实际问题**。比如我们团队之前要同时支持虚拟化设备和容器化两种环境虚拟化可以采用传统的Ansible方式完成环境部署但容器化依赖于镜像的Dockerfile。这就存在一个问题要同时维护两套配置每次升级的时候也要同时修改虚拟化和容器化的配置文件。于是为了简化这个过程就可以把两者的优势结合起来使用单一数据源维护标准环境。
具体来说在Dockerfile中除了基础环境和启动脚本环境配置部分同样采用Ansible的方式完成这样每次在生成一个新的镜像时就可以使用相同的方式完成环境的初始化过程配置示例如下
```
FROM harbor.devops.com:5000/test:ansible
MAINTAINER XX &lt;xx@devops.com&gt;
ADD ./docker /docker
WORKDIR /docker
RUN export TMPDIR=/var/tmp &amp;&amp; ansible-playbook -v -i playbooks/inventories/docker playbooks/docker_container.yml
```
### 开发本地测试的实践
其实我始终认为环境管理是DevOps推行过程中的一个潜在“大坑”。为了提升开发者的效率业界也在探索很多新的实践方向。我在前面也给你介绍过快速失败的理念只有在第一时间反馈失败才能最小化问题修复成本。而对于研发来说由于测试环境的缺失往往要等到代码提交并部署完成之后才能获取反馈这个周期显然是可以优化的。关于如何解决开发本地测试的问题在Jenkins社区也有一些相关的实践。
比如你基于Kubernetes创建了一套最小测试环境按照正常过程来说如果改动一行代码你需要经过代码提交、打包镜像、上传制品、更新服务器镜像等才能开始调试。但如果你使用[KSync](https://github.com/ksync/ksync)工具这些过程统统可以省略。KSync可以帮你建立本地工作空间和远端容器目录的关联并自动同步代码。也就是说只要在本地IDE里面修改了一行代码保存之后KSync就可以帮你把本地代码传到线上的容器中对于类似Python这样的解释型语言来说特别省事。
谷歌也开源了一套基于容器开发自动部署工具[Skaffold](https://github.com/GoogleContainerTools/skaffold)跟KSync类似使用Skaffold命令就可以创建一套Kubernetes环境。当本地修改一行代码之后Skaffold会自动帮你重新生成镜像文件推送远端并部署生效让代码开发变得所见即所得。研发只需要专注于写代码这件事情其余的全部自动化这也是未来DevOps工程实践的一个发展方向。
## 总结
今天,我给你介绍了企业环境管理的五个难题:种类多,复杂性,一致性,交付速度和变更追溯,并解释了为什么基础设施即代码是解决环境管理问题的最佳实践,还跟你分享了三个基础设施即代码的案例,希望能够帮助你理解这个过程。
如果你不太了解Kubernetes和容器可能会有些内容难以消化。我想跟你说的是**无论采用什么技术,代码化管理的方式都是未来的发展趋势**建议你结合文章中的代码和流程图仔细梳理一下并且尝试使用CAPS工具重新定义环境部署过程将环境配置过程实现代码化。如果有问题可以及时在留言区提问。
## 思考题
你认为推行开发自运维的最大难点是什么?关于解决这些难点,你有什么建议吗?
欢迎在留言区写下你的思考和答案,我们一起讨论,共同学习进步。如果你觉得这篇文章对你有所帮助,欢迎你把文章分享给你的朋友。

View File

@@ -0,0 +1,151 @@
<audio id="audio" title="17 | 部署管理:低风险的部署发布策略" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/fd/f9/fd902c2ae2c4a53325cb631ad7bd86f9.mp3"></audio>
你好,我是石雪峰,今天我来跟你聊聊部署管理。
在DevOps年度状态报告中有四个核心的结果指标其中仅“部署”这一项就占了两个关键指标分别是**部署频率**和**部署失败率**。顺便提一下,另外两个指标是**前置时长**和**平均故障修复时长**。
对DevOps来说部署活动就相当于软件交付最后一公里的最后一百米冲刺。只有通过部署发布软件真正交付到最终用户手中的时候前面走过的路才真正创造了价值。
部署和发布这两个概念,经常会被混用,但严格来说,部署和发布代表两种不同的实践。**部署是一组技术实践,表示通过技术手段,将本次开发测试完成的功能实体**(比如代码、二进制包、配置文件、数据库等)**应用到指定环境的过程**,包括开发环境、预发布环境、生产环境等。部署的结果是对服务器进行变更,但是这个变更结果不一定对外可见。
发布也就是Release更偏向一种业务实践也就是**将部署完成的功能正式生效,对用户可见和提供服务的过程**。发布的时机往往同业务需求密切相关。很多时候部署和发布并不是同步进行的比如对于电商业务来说要在0点上线新的活动那么如果部署和发布不分离就意味着要在0点的前1秒完成所有服务器的变更这显然是不现实的。
那么,我想请你思考这样一个问题:所谓的低风险发布,是不是要在发布之前确保本次变更的功能万无一失了,才会真正地执行发布动作呢?
事实上即使没这么说很多公司也都是这样做的。传统软件工程在流程设计的时候也是希望通过层层的质量手段来尽可能全面地验证交付产品的质量。典型的应用就是测试的V模型从单元测试、集成测试、系统测试到用户验收还有各类专项测试其实都是为了在发布之前发现更多的问题以此来保障产品的质量。
那么在DevOps模式下是否也倡导同样的质量思想呢我觉得这是一个有待商榷的问题。
实际上随着发布频率的加速留给测试活动的时间越来越有限了。与此同时现在业务的复杂度也比十年前高了不知道多少个等级。每次发布涉及PC端、移动端还有小程序、H5等多种形态更别提成百上千的终端设备了。要在有限的时间里完成所有的测试活动本来就是件很有挑战的事情。而且各个公司都在衡量测试开发比更是限制了测试人力投入的增长甚至还要不断下降。
你当然可以通过自动化手段来提升测试活动的效率但穷尽测试本来就是个伪命题。那么明明说了DevOps可以又快又好难道是骗人的吗
当然不是。这里的核心就在于DevOps模式下质量思想发生了转变。简单概括就是**要在保障一定的质量水平的前提下,尽量加快发布节奏,并通过低风险发布手段,以及线上测试和监控能力,尽早地发现问题,并以一种最简单的手段来快速恢复。**
这里面有几个关键词:**一定的质量水平****低风险发布手段****线上测试和监控**,以及**快速恢复**。我分别来给你解释一下。
### 一定的质量水平
这个“一定”要怎么理解呢?对于不同形态的软件来说,质量标准的高低自然是不相同的。比如,我有一个制造卫星的同学,他们对于软件质量的要求就是要做到几年磨一剑,甚至是不计成本的。但对于互联网这种快速迭代的业务来说,大家都习惯了默认会出问题,所以在圈定测试范围和测试覆盖的基础上,只要完成严重问题的修复即可发布,低级别的问题可以在后续的众测和灰度的环节继续处理。
所以与定义一个发布质量标准相比更重要的随着DevOps的推广扭转团队的质量观念。**质量不再是测试团队自身的事情,而是整个交付团队的事情**。如果出现了线上问题,团队要一起来定位和修复,并且反思如何避免类似的问题再次发生,从失败中学习。
而测试能力的向前、向后延伸,一方面,提供了工具和平台以帮助开发更容易地进行自测;另一方面,加强针对线上监控埋点等类型的测试,可以保证线上问题可以快速暴露,正常获取辅助分析用户行为的数据,这会全面提升整体的发布质量。
### 低风险的发布手段
既然发布是一件不可回避的高风险事情,那么,为了降低发布活动的风险,就需要有一些手段了。典型的包括以下几种:蓝绿部署,灰度发布和暗部署。
**1.蓝绿部署**
蓝绿部署就是为应用准备两套一模一样的环境,一套是蓝环境,一套是绿环境,每次只有一套环境提供线上服务。这里的蓝和绿,只是用于区分两套环境的标志而已。在新版本上线时,先将新版本的应用部署到没有提供线上服务的环境中,进行上线前验证,验证通过后就达到了准备就绪的状态。在发布时间点,只要将原本指向线上环境的路由切换成另外一套环境,整个发布过程就完成了。
一般来说,**这种方式的实现成本比较高**。因为有两套一模一样的环境,只有一套用于真正地提供线上服务。为了减少资源浪费,在实际操作中,另外一套环境可以当作预发布环境使用,用来在上线之前验证新功能。另外,在这种模式下,数据库普遍还是采用同一套实例,通过向下兼容的方式支持多个版本的应用。
<img src="https://static001.geekbang.org/resource/image/47/27/47931f5ea26ae8fe57dee79022046527.png" alt="">
>
图片来源:[https://www.gocd.org/2017/07/25/blue-green-deployments.html](https://www.gocd.org/2017/07/25/blue-green-deployments.html)
**2.灰度发布**
灰度发布,也叫金丝雀发布。与蓝绿部署相比,灰度发布更加灵活,成本也更低,所以,在企业中是一种更为普遍的低风险发布方式。
**灰度发布有很多种实现机制,最典型的就是采用一种渐进式的滚动升级来完成整个应用的发布过程**。当发布新版本应用时,根据事先设计好的灰度计划,将新应用部署到一定比例的节点上。当用户流量打到这部分节点的时候,就可以使用新的功能了。
值得注意的是要保证同一个用户的行为一致性不能时而看到新功能时而看到老功能。当然解决办法也有很多比如通过用户ID或者cookie的方式来识别用户并划分不同的组来保证。
新版本应用在部分节点验证通过后,再逐步放量,部署更多的节点,依次循环,最终完成所有节点的部署,将所有应用都升级到新版本。分批部署只是实现灰度发布的方法之一,利用配置中心和特性开关,同样可以实现指向性更强的灰度策略。比如,针对不同的用户、地域、设备类型进行灰度。
对于移动端应用来说灰度发布的过程也是必不可少的。我以iOS平台应用为例带你梳理下发布的步骤。首先公司的内部用户可以自行下载安装企业包进行新版本验证和试用。试用OK后再通过官方的Testflight平台对外开启灰度这样只有一部分用户可以收到新版本通知并且在Testflight中安装新版本。灰度指标符合预期后再开启全量用户升级。
现在很多应用都采用了动态下发页面的方法,同样可以使用特性开关,来控制不同用户看到不同的功能。
<img src="https://static001.geekbang.org/resource/image/65/5c/65b39fae9bece629c567d35055ac7f5c.png" alt="">
>
图片来源:[https://www.gocd.org/2017/07/25/blue-green-deployments.html](https://www.gocd.org/2017/07/25/blue-green-deployments.html)
**3.暗部署**
随着A/B测试的兴起暗部署的方式也逐渐流行起来。**所谓暗部署,就是在用户不知道的情况下进行线上验证的一种方法**。比如后端先行的部署方式,把一个包含新功能的接口发布上线,这个时候,由于没有前端导向这个接口,用户并不会真实地调用到这个接口。当用户进行了某些操作后,系统会将用户的流量在后台复制一份并打到新部署的接口上,以验证接口的返回结果和性能是否符合预期。
比如,对于电商业务场景来说,当用户搜索了一个关键字后,后台有两种算法,会给出两种返回结果,然后可以根据用户的实际操作,来验证哪种算法的命中率更高,从而实现了在线的功能验证。
<img src="https://static001.geekbang.org/resource/image/0b/88/0b723413da42fd5327523ba115d0f088.png" alt="">
>
图片来源:[https://www.gocd.org/2017/07/25/blue-green-deployments.html](https://www.gocd.org/2017/07/25/blue-green-deployments.html)
以上这三种低风险发布手段如果应用规模整体不大蓝绿部署是提升系统可用性的最好手段比如各类Hot-standby的解决方案其实就是蓝绿部署的典型应用。而对于大规模系统来说考虑到成本和收益灰度发布显然就成了性价比最高的做法。如果想要跑一些线上的测试收集真实用户反馈那么暗部署是一种不错的选择。
### 线上测试和监控
那么如何验证多种发布模式是正常的呢核心就在于线上测试和监控了。实际上在DevOps中有一种全新的理念那就是**监控就是一种全量的测试**。
你可能会问,为什么要在线上进行测试?这岂不是非常不安全的行为吗?如果按照以往的做法,你应该做的就是花费大量精力来建立一个全仿真的预发布环境,尽可能地模拟线上环境的内容,以达到验证功能可用性的目标。但只要做过测试的团队就知道,测试环境永远不能替代生产环境,即便在测试环境做再多的回归,到了生产环境,依旧还是会有各种各样的问题。
关于测试环境和生产环境,有一个特别有趣的比喻:测试环境就像动物园,你能在里面看到各种野生动物,它们都活得都挺好的;生产环境就像大自然,你永远无法想象动物园里的动物回到大自然之后会有什么样的行为,它们面临的就是一个完全未知的世界。产生这种差异的原因有很多,比如环境设备的差异、用户行为和流量的差异、依赖服务的差异等,每一个变量都会影响组合的结果。
那么,既然无法事先模拟发布后会遇到的所有场景,该如何做线上验证呢?比较常见的,有三种手段。
**1.采用灰度发布、用户众测等方式,逐步观察用户行为并收集用户数据,以验证新版本的可用性是否符合预期。**
这里的主要实践之一就是**埋点功能**。在互联网产品中,埋点是一种最常用的产品分析和数据采集方法,也是数据驱动决策的主要依据之一。它的价值就在于,根据预先设计的收集和监控数据的方法,采集用户的行为、产品质量、运营数据等多维度的数据。
大型公司一般都实现了自己的埋点SDK根据产品设计需求可以自动化地采集数据并配置采集粒度对于小公司来说像**友盟**这种第三方统计工具,就可以满足绝大多数情况的需求了。
**2.用户反馈。**
除了自动化的采集数据之外,用户主动的反馈也是获取产品信息的第一手资料。而用户反馈的渠道有很多,公司里面一般都有**用户运营和舆情监控系统**,用于按照“关键字”等自动爬取各个主流渠道的产品信息。一旦发现负面的反馈,就第一时间进行止损。
**3.使用线上流量测试。**
这一点在讲暗部署时我也提到过,最典型的实践就是**流量镜像**。除了做线上的A/B测试最常用的就是将线上真实的用户流量复制下来以实时或者离线的方式回放到预发布环境中用于功能测试。
除此之外,流量镜像还有很多高级的玩法。像是根据需求选择性地过滤一些信息,比如使用只读的查询内容来验证搜索接口。另外,还可以按照倍数放大和缩小流量,以达到服务压测的目的。还有,可以自动比对线上服务和预发布服务的返回结果,以验证相同的流量过来时,两个版本之间系统的行为是否一致。另外,流量镜像的数据可以离线保存,这对于一些偶发的、难以复现的用户问题,提供了非常难得的数据积累,可以帮助研发团队进一步分析,以避免此类问题的再次发生。
在工具层面,我推荐你使用开源的**GoReplay工具**。它基于Go语言实现作用于HTTP层不需要对系统进行大量改造并且能很好地支持我刚才提到的功能。
### 快速恢复
一旦发现新版本发布后不符合预期,或者有严重的缺陷,最重要的就是尽快控制局面,解决故障。**平均故障修复时长**MTTR是DevOps的四个核心指标之一DevOps的质量信心不仅来源于层层的质量门禁和自动化验证出现问题可以快速定位和修复也是不可忽视的核心能力之一。
平均故障修复时长可以进一步拆解为平均故障检测时长MTTD、平均故障识别诊断时长MTTI以及平均故障修复时长MTTR。在故障发生后根据服务可用性指标SLA对问题进行初步分析定位明确解决方案。在这个领域一款好用的线上诊断工具可以大大地帮助你缓解燃眉之急。比如**阿里的开源工具Arthas**就可以实时监控堆栈信息、JVM信息调用参数查看返回结果跟踪节点耗时等甚至还能查看内存占用、反编译源码等堪称问题诊断利器。
<img src="https://static001.geekbang.org/resource/image/6a/0f/6aca9b3215235e21bdd4a87e8e607e0f.jpg" alt="">
初步对问题进行分析定位后,你可以有两种选择:**向前修复和向后回滚**。
**向前修复就是快速修改代码并发布一个新版本上线,向后回滚就是将系统部署的应用版本回滚到前一个稳定版本**。无论选择哪一种考验的都是自动化的部署流水线和自动化的回滚能力这也是团队发布能力的最佳体现。而在DevOps的结果指标中部署前置时长描述的恰恰就是这段时长。当然最佳实践就是自动化的流水线。往往在这个时候你就会希望流水线更快一些更自动化一些。
<img src="https://static001.geekbang.org/resource/image/46/7c/467adeb8aa1afc297b7009217c8a627c.png" alt="">
最后,再提一点,你可能在很多大会上听过“故障自愈”,也就是出现问题系统可以自动修复。这听起来有点神奇,但实际上,故障自愈的第一步,就要做好**服务降级和兜底策略**。这两个听起来很专业的词是啥意思呢?别着急,我给你举个例子,你就明白了。
我给你截了两张某购物App的图片你可以对比看下有什么不同。
<img src="https://static001.geekbang.org/resource/image/ea/65/eaedb72bd38b7811e2af44c2047c2165.png" alt="">
如果你仔细看的话你会发现单这一个页面就有大大小小8个差异。所以**服务降级就是指,在流量高峰的时候,将非主路径上的功能进行临时下线,保证业务的可用性**。典型的做法就是通过**功能开关的方式**来手动或自动地屏蔽一些功能。
<img src="https://static001.geekbang.org/resource/image/e6/ce/e611e299e35d831ce705bb0c7ef17dce.png" alt="">
而兜底策略是指,当极端情况发生时,比如服务不响应、网络连接中断,或者调用服务出现异常的时候,也不会出现崩溃。常见的做法就是缓存和兜底页面,以及前端比较流行的骨架屏等。
## 总结
在这一讲中我给你介绍了DevOps模式下质量思想的转变那就是要在保障一定的质量水平的前提下尽量加快发布节奏并通过低风险发布手段以及线上测试和监控能力尽早地发现问题并以一种最简单的手段来快速恢复。
质量活动是有成本的,为了保证快速迭代发布,一定程度的问题发生并不是末日,更重要的是通过质量活动向前向后延伸,并在生产环境加强监控和测试。同时,三种典型的低风险发布方式可以满足不同业务场景的需求。当问题发生时,不仅要做到快速识别,快速修复,还要提前通过服务降级、兜底策略等机制保证系统服务的连续性。
## 思考题
你所在的企业采用了哪些手段来保障部署活动是安全可靠的呢?
欢迎在留言区写下你的思考和答案,我们一起讨论,共同学习进步。如果你觉得这篇文章对你有所帮助,欢迎你把文章分享给你的朋友。

View File

@@ -0,0 +1,183 @@
<audio id="audio" title="18 | 混沌工程:软件领域的反脆弱" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/bd/c7/bde3c40d5d2f4d2425639a87c7ab63c7.mp3"></audio>
你好,我是石雪峰。
经济学领域有一本特别有名的书,叫作《反脆弱》。它的核心理念就是,在面对普遍存在又不可预估的不确定性时,通过一种行之有效的方法,不仅可以规避重大风险,还能够利用风险获取超出预期的回报。另外,通过积极地试错,控制损失成本,还能不断提升在不确定性事件发生时的收益。
不仅仅要规避风险,还要在风险中受益,这听起来是不是很神奇?其实,在软件工程领域,也有类似的思想和实践,可以帮助我们在面对极其复杂且规模庞大的分布式系统时,有效地应对不可预见的故障,不仅可以从容不迫地应对,还能从中获益,并且通过频繁、大量地实验,识别并解决潜在的风险点,从而提升对于复杂系统的信心。这就是今天我要给你分享的主题:混沌工程。
## 什么是混沌工程?
混沌工程作为软件领域的一门新兴学科,就和它的名字一样,让很多人感到非常“混沌”。那么,混沌工程究竟是从何而来,又是要解决什么问题呢?
我们先来看看混沌原则网站对混沌工程的定义:
>
Chaos Engineering is the discipline of experimenting on a distributed system in order to build confidence in the systems capability to withstand turbulent conditions in production.
>
混沌工程是一门在分布式系统上进行实验的学科,目的是建立人们对于复杂系统在生产环境中抵御突发事件的信心。
简单来说,混沌工程要解决的,就是复杂环境下的分布式系统的反脆弱问题。那么,我们所要面对的“复杂的分布式”的真实世界是怎样的呢?
我给你举个例子。对于一个大型的平台来说每日在线的活动数以万计服务的用户可以达到千万级别。为了满足这种规模的业务量级仅客户端就有300多个组件后端服务更是不计其数。
可以想象,这样一套复杂的系统,任何一个地方出了一点小问题,都有可能带来线上事故。
另外,随着微服务、容器化等技术的兴起,业务驱动自组织团队独立发布的频率越来越高,再加上架构的不断更新演进,可以说,**几乎没有人能完整地梳理清楚一套系统的服务间调用关系**,这就让复杂系统变成了一个“黑洞”。不管外围如何敲敲打打,都很难窥探到核心问题。
为了让你对复杂的真实系统有更加直观的认识我跟你分享一张Netflix公司在2014年公开的微服务调用关系图你可以参考一下。
<img src="https://static001.geekbang.org/resource/image/fc/db/fc2a435fcba0551bf2b072fa48155edb.jpeg" alt="">
>
图片来源:[https://www.slideshare.net/BruceWong3/the-case-for-chaos?from_action=save](https://www.slideshare.net/BruceWong3/the-case-for-chaos?from_action=save)
面对这样复杂的分布式系统,想要通过穷尽全面的测试来保障质量,不出线上问题几乎是不可能的事情。因为测试的假设前提都是为了验证软件的预期行为,而**真实世界的问题却从来不按套路出牌,被动遵循已有的经验并不能预防和解决未知的问题**。
尤其是,如果系统的可用性是基于某一个服务不会出问题来设计的话,那么,这个服务十有八九会出问题。
比如前不久我们内部的平台就出现了一次宕机原因是依赖的一个基础服务的认证模块出现了异常从而导致存储数据失败。因为平台的所有基础数据都在这个看似万无一失的服务上保存即便监控第一时间发现了这个问题但是除了等待之外我们什么都做不了。结果平台的可用性直接从4个9掉到了3个9。
既然面对复杂的分布式系统我们无法避免异常事件的发生那么有什么更好的办法来应对这种不确定性吗Netflix公司给出了他们的回答而这正是混沌工程诞生的初衷。
区别于以往的方式,混沌工程采取了一种更加积极的方式,换了一个思路主动出击。那就是,**尽可能在这些故障和缺陷发生之前,通过一系列的实验,在真实环境中验证系统在故障发生时的表现**。根据实验的结果来识别风险问题,并且有针对性地进行系统改造和安全加固,从而提升对于整个系统可用性的信心。
## 服务可用性实践
看到这儿,你可能就要问了,这不就是日常的系统可用性保障活动吗?我们公司也有类似的实践呀,比如故障演练、服务降级方案、全链路压测等,这些基本都是大促活动到来前必需的备战活动。
的确,这些实践与混沌工程有相似之处,毕竟,混沌工程就是从这些实践中发展起来的,但是,思路又略有不同。
比较正规的公司基本上都会有一套完整的数据备份机制和服务应急响应预案,就是为了当灾难发生时,可以保证系统的可用性和核心数据的安全。
比如,**故障演练就是针对以往发生过的问题进行有针对性地模拟演练**。通过事先定义好的演练范围,然后人为模拟事故发生,触发应急响应预案,快速地进行故障定位和服务切换,并观察整个过程的耗时和各项数据指标的表现。
故障演练针对的大多是可以预见到的问题比如机器层面的物理机异常关机、断电设备层面的磁盘空间写满、I/O变慢网络层面的网络延迟、DNS解析异常等。这些问题说起来事无巨细但基本上都有一条清晰的路径有明确的触发因素监控事项和解决方法。
另外,在故障演练的过程中,很难覆盖所有的故障类型,只能选择典型的故障进行验证。但是实际问题发生时,往往是多个变量一起出问题,逐个排查下来非常耗时耗力。
很多公司为了模拟线上的真实场景,于是就引入了全链路压测的技术。对于大促密集的电商行业来说,尤为重要。
对于一次完整的压测来说,大致的过程是这样的:
- 首先,准备压测计划,调试压测脚本和环境,对压测容量和范围进行预估;
- 然后,为了保证线上流量不受影响完成机房线路切换,确保在压测过程中没有线上真实流量的引入;
- 接着,根据预定义的压测场景执行压测计划,观察流量峰值并动态调整;
- 最后在压测完成后再次进行流量切换并汇总压测结果识别压测问题。在压测过程中除了关注QPS指标之外还要关注TP99、CPU使用率、CPU负载、内存、TCP连接数等从而客观地体现出大流量下服务的可用性。
**从业务层面来说,面对多变的环境因素,完善的服务降级预案和系统兜底机制也是必不可少的**。在业务压力比较大的时候,可以适当地屏蔽一些对用户感知不大的服务,比如推荐、辅助工具、日志打印、状态提示等,**保证最核心流程的可用性**。另外,**适当地引入排队机制**也能在一定程度上分散瞬时压力。
好啦,说了这么多服务可用性的方法,是不是把这些都做到位就可以确保万无一失了呢?答案是否定的。这是因为,这些活动都是在打有准备之仗。但实际上,很多问题都是无法预知的。
既然现有的实践并不能帮助我们拓展对不可用性的认知,那么就需要一种有效的实验方法,帮助我们基于各种要素排列组合,从而在问题发生之前,发现这些潜在的风险。
比如Netflix公司著名的“混乱猴子Chaos Monkey就是用来随机关闭生产环境的实例的工具。在生产环境放任一个“猴子”乱搞事情这是疯了吗还真不是。Netflix的“猴子军团”的威力一个比一个巨大甚至可以直接干掉一个云服务可用区。
这背后的原因就是,即便是云服务上,也不能确保它们的服务是永远可靠的,所以,**不要把可用性的假设建立在依赖服务不会出问题上**。
当然Netflix并没有权限真正关闭云服务上的可用区他们只是模拟了这个过程并由此来促使工程团队建立多区域的可用性系统促进研发团队直面失败的架构设计不断磨练工程师对弹性系统的认知。
引用Netflix的混沌工程师Nora Jones的话来说
>
混沌工程不是为了制造问题,而是为了揭示问题。
**必须要强调的是,在引入混沌工程的实践之前,首先需要确保现有的服务已经具备了弹性模式,并且能够在应急响应预案和自动化工具的支撑下尽早解决可能出现的问题**
如果现有的服务连基本的可恢复性这个条件都不具备的话,那么这种混沌实验是没有意义的。我跟你分享一幅混沌工程的决策图,你可以参考一下:
<img src="https://static001.geekbang.org/resource/image/77/e3/770700502eb079f09dc0cba03eafc0e3.png" alt="">
>
图片来源:[https://blog.codecentric.de/en/2018/07/chaos-engineering/](https://blog.codecentric.de/en/2018/07/chaos-engineering/)
## 混沌工程的原则
混沌工程不像是以往的工具和实践,作为一门学科,它具有非常丰富的内涵和外沿。你在进入这个领域之前,有必要了解下混沌工程的五大原则:**建立稳定状态的假设、真实世界的事件、在生产中试验、持续的自动化实验、最小影响范围。**
我们分别来看一下这五条原则要如何进行实践。
**1.建立稳定状态的假设**
关于系统的稳定状态,就是说,有哪些指标可以证明当前系统是正常的、健康的。实际上,无论是技术指标,还是业务指标,现有的监控系统都已经足够强大了,稍微有一点抖动,都能在第一时间发现这些问题。
比如对于技术指标来说前面在压测部分提到的指标就很有代表性QPS、TP99、CPU使用率等而对于业务指标来说根据公司具体业务的不同会有所不同。
举个例子对于游戏来说在线用户数和平均在线时长就很重要对于电商来说各种到达率、结算完成率以及更加宏观的GMV、用户拉新数等都能表现出业务的健康程度。
**与技术指标相比,业务指标更加重要**,尤其是对电商这种活动密集型的行业来说,业务指标会受到活动的影响,但基于历史数据分析,总体趋势是比较明显的。
当业务指标发生大量的抖动时(比如瞬时降低提升),就意味着系统出现了异常。比如,几天前微信支付出现问题,从监控来看,支付的成功率就受到了比较明显的影响。
在真实世界中,为了描述一种稳定状态,需要一组指标构成一种模型,而不是单一指标。**无论是否采用混沌工程,识别出这类指标的健康状态都是至关重要的**。而且,还要围绕它们建立一整套完善的数据采集、监控、预警机制。
我给你提供了一些参考指标,汇总在了下表中。
<img src="https://static001.geekbang.org/resource/image/68/3d/68103ce85d10ebaba0a1f9278063f63d.jpg" alt="">
2.**真实世界的事件**
真实世界的很多问题都来源于过往踩过的“坑”,即便是特别不起眼的事件,都会带来严重的后果。
比如我印象比较深的一次故障就是服务器在处理并发任务的时候CPU跑满系统直接卡死。通过调查发现在出现问题的时候系统的I/O Wait很高这就说明磁盘发生了I/O瓶颈。经过仔细地分析最终发现是磁盘Raid卡上的电池没电了从而导致磁盘Raid模式的降级。
像这种事情你很难通过监控所有Raid卡的电池容量来规避问题也不可能在每次模拟故障的时候故意换上没电的电池来进行演练。
所以,既然我们无法模拟所有的异常事情,**投入产出比最高的就是选择重要指标**(比如设备可用性、网络延迟,以及各类服务器问题),**进行有针对性地实验**。另外,可以结合类似全链路压测等手段,从全局视角测试系统整体运作的可用性,通过和稳定状态的假设指标进行对比,来识别潜在的问题。
3.**在生产中实验**
跟测试领域的“质量右移理念”一样,混沌工程同样鼓励在靠近生产环境的地方进行实验,甚至直接在生产环境中进行实验。
这是因为,**真实世界的问题,只有在生产环境中才会出现**。一个小规模的预发布环境更多的是验证系统行为和功能符合产品设计,也就是从功能的角度出发,来验证有没有新增缺陷和质量回退。
但是,系统的行为会根据真实的流量和用户的行为而改变。比如,流量明星的一则消息就可能导致微博的系统崩溃,这是在测试环境很难复现的场景。
但客观来说,在生产环境中进行实验,的确存在风险,这就要求**实验范围可控,并且具备随时停止实验的能力**。还是最开始的那个原则,**如果系统没有为弹性模式做好准备,那么就不要开启生产实验**。
还以压测为例,我们可以随机选择部分业务模块,并圈定部分实验节点,然后开启常态化压测。通过定期将线上流量打到被测业务上,观察突发流量下的指标表现,以及是否会引发系统雪崩,断路器是否生效等,往往在没有准备的时候才能发现真实问题。这种手段作为混沌工程的一种实践,已经普遍应用到大型公司的在线系统之中了。
4.**持续的自动化实验**
**自动化是所有重复性活动的最佳解决方案**。通过自动化的实验和自动化结果分析,我们可以保证混沌工程的诸多实践可以低成本、自动化地执行。正因为如此,以混沌工程为名的工具越来越多。
比如商业化的混沌工程平台Gremlins就可以支持不可用依赖、网络不可达、突发流量等场景。今年阿里也开源了他们的混沌工具[ChaosBlade](https://github.com/chaosblade-io/chaosblade),缩短了构建混沌工程的路径,引入了更多的实践场景。另外,开源的[Resilience4j](https://github.com/resilience4j/resilience4j)和[Hystrix](https://github.com/Netflix/Hystrix)也都是非常好用的工具。无论是自研,还是直接采用,都可以帮助你快速上手。
我相信随着越来越多工具的成熟未来混沌工程也会成为CI/CD流水线的一部分被纳入到日常工作中来。
5.**最小的影响范围**
混沌工程实践的原则就是不要干扰真实用户的使用,所以,在一开始将实验控制在一个较小的范围内,是非常有必要的,这样可以避免由于实验失控带来的更大问题。
比如圈定一小部分用户或者服务范围可以帮助我们客观地评估实验的可行性。假设要实验一个API对错误的处理能力我们可以部署一个新的API实验集群并修改路由导流0.5%的流量用于线上实验。在这个集群中通过故障注入的方式验证API是否能够处理流量带来的错误场景。这有点类似于一个灰度实验环境或者暗部署的方式。
除了可以用于验证新功能做线上的A/B测试同样适用于混沌工程的故障注入。
这五大原则共同勾勒出了混沌工程的全景图,描述系统稳定状态的前提下,将真实世界的事件在生产环境中进行实验,并控制最小影响范围,引入自动化方式持续进行。作为一种全新的工程领域,混沌工程还要走很长的路,才能跨越技术演进的鸿沟。
>
<p>参考资料:<br>
[Netflix混沌工程成熟度模型](https://www.infoq.cn/article/M3EktXxYGRYYm*t5vKga)<br>
[混沌工程资料集](https://github.com/dastergon/awesome-chaos-engineering)<br>
[Netflix混沌工程手册](https://www.oreilly.com/library/view/chaos-engineering/9781491988459/)</p>
## 总结
在这一讲中我给你介绍了一个应对复杂分布式系统可用性挑战的新学科——混沌工程。实际上混沌工程采用了一种全新的思路在系统中主动注入混沌进行实验以此来发现潜在的真实世界的问题。在服务可用性方面我们一直在努力实践比如故障演练、服务降级、全链路压测已经成为了大型系统的标配。最后我给你介绍了混沌工程的5个实践原则希望可以帮助你建立更加全面的认知。
不可否认,目前国内在混沌工程领域的实践还处于摸索实验阶段,但是随着系统的复杂性越来越高,混沌工程也注定会跨越技术发展的鸿沟,成为解决复杂系统可用性问题的利器。
## 思考题
关于真实世界中发生的异常事件,你有哪些独特的经历呢?结合混沌工程的实践,你有什么新的思路吗?
欢迎在留言区写下你的思考和答案,我们一起讨论,共同学习进步。如果你觉得这篇文章对你有所帮助,也欢迎你把文章分享给你的朋友。

View File

@@ -0,0 +1,154 @@
<audio id="audio" title="19 | 正向度量如何建立完整的DevOps度量体系" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/e2/da/e28631fd0f6eb29a47f5b2ad366018da.mp3"></audio>
你好我是石雪峰。到今天为止我用14讲的篇幅给你通盘梳理了DevOps的工程实践基本涵盖了工程实践的方方面面。但是就像那句经典的“不仅要低头看路还要抬头看天”说的一样我们花了这么大的力气投入工程实践的建设结果是不是符合我们的预期呢
所以在工程实践的最后两讲我想跟你聊聊度量和持续改进的话题今天先来看看DevOps的度量体系。
我相信对于每个公司来说度量都是必不可少的实践也是管理层最重视的实践。在实施度量的时候很多人都把管理学大师爱德华·戴明博士的“If you cant measure it, you cant manage it”奉为实践圭臬。
但是,回过头来想想,有多少度量指标是为了度量而度量的?花了好大力气度量出来的数据会有人看吗?度量想要解决的,到底是什么问题呢?
所以,**度量不是目的,而是手段,也就是说度量的目标是“做正确的事”,而度量的手段是“正确地做事”**。
那么什么才是度量领域正确的事情呢如果想要弄清楚DevOps中的度量长什么样子关键就是要回到**DevOps对于软件交付的核心诉求**上。
简而言之对于IT交付来说DevOps希望做到的就是**持续、快速和高质量的价值交付**。价值可以是一个功能特性,可以是用户体验的提升,也可以是修复阻塞用户的缺陷。
明确了这一点也就明确了DevOps的度量想要达到的目标就是为了证明经过一系列的改进工作与过去相比**团队的交付速度更快了,交付质量更高了**。如果度量的结果不能导向这两个核心目标,那么显然就走错了方向,也就得不到实际想要的结果了。
如果只有大方向,往往还是不知道具体要怎么做。这个时候,就需要把目标和方向拆解成一系列的度量指标了。那么,怎样定义好的度量指标和不好的度量指标呢?
## 如何定义指标?
前几天,我被派到某仓库做流水线工人,这个经历让我深刻地理解了工业制造和软件行业的巨大差异。
如果你现在问我,决定工业生产流水线速度的是什么?我可以告诉你,答案就是,流水线本身。因为流水线的传送带的速度是一定的,产线速度也就可以直观地量化出来。
但是,软件开发不像工业制造,开发的过程看不见摸不着,除了工程师真正编写代码的时间,还要包括构思、设计和测试的时间,以及完成各类流程的时间等等。这个过程中可能还存在着各种并行工作的切换和打断,所以,没法用工业流水线的方式来衡量开发人员的效率。
于是,为了达到量化的目的,很多指标就被人为地设计出来了。
比如以准时提测率这个指标为例这个指标采用的是百分制的形式按时提测得100分延期一天得90分延期两天得70分以此类推要是延期五天及以上就只能0分了。这样的指标看起来似乎足够客观公平但是仔细想想延期1天1小时和延期1天23小时似乎也没有太大区别得分的高低并不能反映真实的情况。
在各个公司的度量体系中,类似的人造指标可谓比比皆是。可见,不好的指标总是五花八门,各有各的样子。不过,好的指标大多具备一些典型的特征。
**1.明确受众。**
指标不能脱离受众而单独存在,**在定义指标的同时,要定义它所关联的对象,也就是这个指标是给谁看**。
不同的人关注点自然也不一样,即便指标本身看起来没有什么问题,但是如果使用错位了,也很难产生预期的价值。比如,给非技术出身的老板看单元测试的覆盖率,就没有什么太大意义。
**2.直指问题。**
在NBA中优秀的球员总是自带体系的。所谓体系就是围绕这个球员的核心能力的一整套战术打法可以解决球队的实际问题所以这个球员的表现就成了整支球队的“晴雨表”。
而好的指标也应该是直指问题的,你一看到这个指标,就能意识到问题所在,并自然而然地进行改进,而不是看了跟没看见一样,也不知道具体要做什么。
比如,构建失败率很高,团队就会意识到代码的提交质量存在问题,需要加强事前的验证工作。
**3.量化趋势。**
按照SMART原则**好的指标应该是可以衡量的,而且是可以通过客观数据来自证的**。
比如,用户满意度这种指标看起来很好,但很难用数据衡量;再比如,项目达成率这个指标,如果只是靠手工填写,那就没啥说服力。
同时,**好的度量指标应该能展现趋势**。也就是说,经过一段时间的沉淀,指标是变好了,还是变坏了,距离目标是更近了,还是更远了,这些都应该是一目了然的。
**4.充满张力。**
指标不应该孤立存在,而是应该相互关联构成一个整体。好的指标应该具有一定的张力,**向上可以归并到业务结果,向下可以层层分解到具体细节**。这样通过不同维度的数据抽取,可以满足不同视角的用户需求。
比如,单纯地度量需求交付个数,就没有太大意义。因为需求的颗粒度会直接影响数量,如果只是把一个需求拆成两个,从而达到需求交付速度加倍的效果,这就失去了度量的意义。
## 定义指标有哪些原则?
明白了好的度量指标的典型特征接下来我们就来看看定义DevOps度量的五条原则
1. **全局指标优于局部指标**:过度的局部优化可能对整体产出并无意义,从而偏离了度量的核心,也就是**提升交付速度和交付质量**。
1. **综合指标优于单一指标**:从单一维度入手会陷入只见树木不见森林的困境,综合指标更加客观。所以,要解决一个问题,就需要一组指标来客观指引。
1. **结果指标优于过程指标**:首先要有结果指标,以结果为导向,以过程为途径,一切过程指标都应该归结到结果指标。
1. **团队指标优于个人指标**:优先考核团队指标而非个人指标,团队共享指标有助于形成内部合力,减少内部的割裂。
1. **灵活指标优于固化指标**:指标的设立是为了有针对性地实施改进,需要考虑业务自身的差异性和改进方向,而非简单粗暴的“一刀切”,并且随着团队能力的上升,指标也需要适当的调整,从而不断挑战团队的能力。
## 哪些指标最重要?
基于以上的指标特征和指导原则并结合业界大厂的一些实践我给你推荐一套DevOps度量体系。
虽然各个公司的度量指标体系都不尽相同,但是我认为这套体系框架足以满足大多数场景,如下图所示:
<img src="https://static001.geekbang.org/resource/image/e5/76/e5ee032923d611854e005bf392b24676.jpeg" alt="">
**1.交付效率**
- **需求前置时间**:从需求提出到完成整个研发交付过程,并最终上线发布的时间。对业务方和用户来说,这个时间是最能客观反映团队交付速度的指标。这个指标还可以进一步细分为需求侧,也就是从需求提出、分析、设计、评审到就绪的时长,以及业务侧,也就是研发排期、开发、测试、验收、发布的时长。对于价值流分析来说,这就代表了完整的价值流时长。
- **开发前置时间**:从需求进入排期、研发真正动工的时间点开始,一直到最终上线发布的时长。它体现的是研发团队的交付能力,也就是一个需求进来后,要花多久才能完成整个开发过程。
**2.交付能力**
- **发布频率**:单位时间内的系统发布次数。原则上发布频率越高,代表交付能力越强。这依赖于架构结构和团队自治、独立发布的能力。每个团队都可以按照自己的节奏安全地发布,而不依赖于关联系统和发布窗口期的约束。
- **发布前置时间**指研发提交一行代码到最终上线发布的时间是团队持续交付工程能力的最直观的考查指标依赖于全流程自动化的流水线能力和自动化测试能力。这也是DevOps状态报告中的核心指标之一。
- **交付吞吐量**:单位时间内交付的需求点数。也就是,单位时间内交付的需求个数乘以需求颗粒度,换算出来的点数,它可以体现出标准需求颗粒度下的团队交付能力。
**3.交付质量**
- **线上缺陷密度**:单位时间内需求缺陷比例,也就是平均每个需求所产生的缺陷数量,缺陷越多,说明需求交付质量越差。
- **线上缺陷分布**:所有缺陷中的严重致命等级缺陷所占的比例。这个比例的数值越高,说明缺陷等级越严重,体现了质量的整体可控性。
- **故障修复时长**:从有效缺陷提出到修复完成并上线发布的时间。一方面,这个指标考查了故障定位和修复的时间,另外一方面,也考查了发布前置时间,只有更快地完成发布上线过程,才能更快地修复问题。
这三组、八项指标体现了团队的交付效率、交付能力和交付质量从全局视角考查了关键的结果指标可以用于展现团队DevOps改进的效果和价值产出。不过定义指标只能说是DevOps度量的一小步只有让这些指标发挥价值才能说是有意义的度量。
## 如何开启度量工作?
在企业内部开启度量工作,可以分为四个步骤。
**第1步细化指标。**
一个完整的指标,除了定义之外,还需要明确指标名、指标描述、指标级别(团队级/组织级)、指标类型、适用场景范围及目标用户、数据采集方式和标准参考值。
以交付指标为例,我汇总了一份细化后的指标内容,你可以参考下表。其实不仅仅是核心结果指标,只要是在度量体系内定义的指标,都需要进行细化。
<img src="https://static001.geekbang.org/resource/image/81/cf/81227920cc306a7fae29afa3d77a02cf.jpg" alt="">
关于指标的参考值,对于不同的业务形态,参考值也有所不同。比如就单元测试覆盖率而言,无人车的业务和普通的互联网业务的差别可能会非常大。
所以参考值的选定,需要结合业务实际来分析并达成共识。而且,度量指标本身也需要建立定期更新的机制,以适应于整个团队的能力。
**第2步收集度量数据**
度量指标需要客观数据的支撑,而数据往往都来源于各个不同的平台。所以,在定义指标的时候,你需要评估是否有足够的客观数据来支撑这个指标的衡量。
在采集度量数据的初期,我们面临的最大问题不仅是系统众多、数据口径不一致,还包括数据的准确性。
举个例子,比如开发交付周期这个指标,一般都是计算一个需求从开始开发到线上发布的时间长度。但是,如果开发人员迟迟不把这个需求设置为“已解决”或者“待测试”状态,那么统计出来的开发周期就存在大量的失真,很难反映出客观、真实的情况。
这就需要从流程和平台两个层面入手解决。比如,一方面,从流程层面制定研发操作规范,让每一名研发人员都清楚在什么时间点需要改变需求卡片状态;另一方面,建设平台能力,提供易用性的方式辅助研发,甚至自动流转需求状态。
**第3步建立可视化平台。**
度量指标毕竟是要给人看的,度量数据也需要有一个地方可以收集和运算,这就依赖于度量可视化平台的建设了。关于如何建设一个支持多维度视图、对接多系统数据,以及灵活可编排的度量平台,我会在工具篇给你分享一个案例,帮助你破解度量平台建设的关键问题。
**第4步识别瓶颈并持续改进。**
当数据做到了可信和可视化之后,团队面临的问题和瓶颈会自然而然浮现出来。如何通过指标牵引并驱动团队实施改进,这也是下一讲我们要讨论的核心内容。
我给你提供一些常用的度量指标和相关定义,你可以点击[网盘链接](https://pan.baidu.com/s/1cZKd__yAhcvvrcYNZx9uAA)获取提取码是c7F3。需要注意的是指标宜少不宜多宜精不宜烂对于企业的DevOps度量而言这也是最常见的问题定义了一大堆的指标却不知道要拿来做什么。
只有将指标的定义细化,并在团队内部达成共识,仔细甄别数据的完整和有效性,并做到满足不同维度视角的可视化,才具备了驱动团队进行改进的基础,这一点请你一定要记住。
## 总结
总结一下DevOps度量想要达到的目标就是证明团队经过一系列的改进工作与过去相比交付速度更快了交付质量也更高了。所以交付效率和交付质量是最为核心的两个目标。只有围绕这两个目标建立的度量体系才没有走错方向。
好的指标一般都具备四种特性:明确受众、直指问题、量化趋势和充满张力。结合指标特征和指导原则,以及业界大厂的一些实践,我给你介绍了三组、八项核心结果指标,包括效率指标、能力指标和质量指标。最后,我给你介绍了建立度量体系的四个步骤,希望可以帮助你一步步地搭建持续改进的基石。
度量是把双刃剑,做得不好反而会伤害团队的士气。如果本末倒置,把度量结果跟个人的绩效相绑定,就很容易使度量这个事情变了味道。很多大公司反反复复地在建立度量体系,就是因为前一个体系被人摸透,变成了数字游戏,于是就失去了原有的目的,只能推倒重来。
还是那句话,度量只是一种手段,而非目的。归根结底,度量的真正目的还是团队效率的提升和业务的成功。只有通过度量激起团队自发的改进意愿,提升团队改进的创造性和积极性,才是所谓的“正向度量”,这也是我最想传达给你的理念。
## 思考题
你所在的企业是否也在建设DevOps的度量体系呢你觉得这些度量指标数据对改进当前的工作是否起到了正面作用呢
欢迎在留言区写下你的思考和答案,我们一起讨论,共同学习进步。如果你觉得这篇文章对你有所帮助,也欢迎你把文章分享给你的朋友。

View File

@@ -0,0 +1,143 @@
<audio id="audio" title="20 | 持续改进PDCA体系和持续改进的意义" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/f0/0b/f0c9f5f40ec94f0545b2707daf29700b.mp3"></audio>
你好,我是石雪峰。
今天是“工程实践篇”的最后一节课如果你现在问我在这么多的工程实践中什么能力是团队在推行DevOps时最应该具备的我会毫不犹豫地告诉你那就是**持续改进**。
很多同学在留言区问我“雪峰老师我们公司已经搭建了Gitlab也跟Jenkins实现了打通做到了自动化的编译打包和发布工作。可是接下来我们还有啥可以做的呢我感到很迷茫啊。”
所以这就引申出来一个问题“一个团队做到什么程度才算是达到了DevOps呢
每每遇到这样的问题,我就会回想起,几年前我去国内一家知名公司的杭州总部交流的经历。
当时负责跟我们对接的是这家公司DevOps的主要推动人可以说他见证了这家巨头公司的DevOps转型全过程。在交流时我问了他一个问题他的回答让我印象特别深刻。
我问他“你觉得你们公司是在什么时候实现DevOps转型的呢”他想了想“现在我们公司已经没有专职的测试和专职的运维了基础架构也早就容器化了。这些事情都是业务发展到一定阶段之后自然而然发生的只不过DevOps火起来以后我们才发现原来我们一直在做的就是DevOps。所以很难说在哪个时间点完成了DevOps转型。对我们来说最重要的就是团队具备了一种能力就是**始终能够找到新的突破,持续追求更好的状态**。”
我想这段话应该非常能够代表一个团队实施DevOps转型时期望达到的状态吧。
其实如果你有机会去跟谷歌、Netflix的工程师交流一下你就会发现这些业界DevOps做得特别牛的公司内部都不怎么提DevOps的概念。因为他们早就对DevOps的这些实践习以为常了。很多知名的工具平台都是内部员工自发地为了解决一些问题而开发出来的。
比如像Gerrit这种非常流行的代码在线评审和管理工具最开始就是为了解决谷歌内部缺少一种基于Git并且具备权限管控的代码评审工具的问题才被开发出来的你可以了解下这段[历史](https://www.gerritcodereview.com/about.html)。
你看,遇到一个钉子,从而造个锤子,和拿着一把锤子,满世界找钉子就是两种截然不同的做法。但很多时候,我们采用的都是后一种做法,手里拿着一堆锤子,却找不到钉子在哪里。
所以如果一定要让我来回答DevOps做到什么程度就算是实现转型落地了那么我的回答是**核心就是团队已经具备了持续改进的能力,而不只是简简单单地引入了几个工具,建立了几个度量指标而已**。
说到这儿,你可能会说,这个所谓的持续改进,怎么感觉无处不在呢?似乎很多工程实践的落地方法中,最后一步都是持续改进。那么,持续改进的意义到底是什么呢?为什么一切活动的终极目标都是持续改进呢?
这是因为每家公司面临的问题都不一样从0到1的过程相对比较简单可以对照着工程实践快速地引入工具建立流程补齐能力短板。但是**从1到N的过程就需要团队根据业务需要自行识别改进目标了**。
还以最开始那个问题为例基于Gitlab和Jenkins搭建了自动化构建和发布的能力之后你觉得还有哪些可行的改进方向呢比如测试是否注入其中了呢是否建立了质量门禁机制呢数据库变更是否实现了自动化呢构建发布的速度是否足够理想构建资源是否存在瓶颈
能想到的方向有很多,但哪个才是现阶段最重要、价值最大化的点,说到底,还是要看业务的需求,没办法泛泛而谈。
谈到持续改进有一个非常著名的方法体系叫作PDCA也称为戴明环。没错你从名称就能看出这套方法体系同样来自于质量管理大师戴明博士。PDCA是四个英文单词的缩写也就是Plan计划、Do实施、Check检查和Action行动
PDCA提供了一套结构化的实施框架任何一项改进类工作都可以划分为这四个实施阶段。**通过PDCA循环的不断迭代驱动组织进入一种良性循环不断识别出新的待改进问题**。针对这些问题,首先要进行根因分析,制定具体的实施计划。然后,不定期地检查实施的结果和预期目标是否一致。最后,要对改进结果进行复盘,把做得好的地方保留下来,把做得不好的地方纳入下一阶段的循环中,继续改进。
<img src="https://static001.geekbang.org/resource/image/60/39/605228cf06160834253f25b7801f6c39.png" alt="">
这个方法听起来也没什么复杂的,每个人都能够理解,关键在于是否真正地用心在做。
我再给你分享一个真实的例子。
大概两年前我参与到一家中型企业的DevOps转型工作当中。这家企业刚开始接触DevOps时的状态呢我就不细说了反正就是基本啥都没有。代码库使用的是SVN构建打包都在本地完成版本发布要两个月而且经常是多版本并行的节奏光同步代码就需要专人完成。
经过半年多的改造之后,团队内部的整体工具链体系初具规模,版本发布节奏也缩短到了一个月一次,团队对达到的成绩非常满意。
当然,这并不是重点,重点是,我上个月又碰到了这个项目的负责人。她跟我说,他们现在的发布节奏已经实现了两周一次,甚至不定期还有临时版本发布。我很好奇,他们究竟是怎么做到的。
原来最开始导入改进方案的时候我给项目组提到过容器化的思路但是因为当时客观条件不具备就没有继续推进下去。没想到在短短不到一年的时间里他们已经实现了容器化部署自建的PaaS平台也有模有样即便是跟很多大公司相比也毫不逊色。
她说“这段DevOps转型的过程带给我们的不仅仅是一些常见的工程实践和工具平台更重要的是一双总能发现不完美的眼睛和追求极致的态度以及对这类问题的认知方法。这些驱动我们不断地找到新的方法解决新的问题。”
的确,很多工程实践和工具平台,在公司内部其实只是一小步,之后遇到的问题和挑战还会有很多。这时候,我们能够依靠的终极奥义就是持续改进的思想,而**构建持续改进的核心,就在于构建一个学习型组织**。
那么,究竟要从哪里开始学习呢?在学习和改进的过程中又有哪些比较推荐的做法呢?我总结了四个实践,你可以参考一下。
## 鼓励正向回溯和总结
从失败中学习是我们从小就懂的道理。**一个团队对待故障的态度,很大程度上就反映了他们对于持续改进的态度**。系统出现故障是谁都不愿意遇到的事情,但在真实世界中,这是没法避免的。
在很多公司里面,出现故障之后,有几种常见的做法:
- 把相关方拉到一起,定级定责,也就是确定问题级别和主要的责任方;
- 轻描淡写地回个改进邮件,但是没有明确的时间节点,即便有,也没人跟踪;
- 把问题归结为不可复现的偶发事故,最后不了了之。
与这些做法相比,更好的方法是建立一种正向回溯和总结的机制。也就是说,当问题发生之后,事先准备一份详尽的故障分析报告,并拉上相关方一起彻底分析问题的根因,并给出改进任务的具体时间点。
**故障回溯并不一定以确定责任为第一要务,更重要的是,要识别系统流程中的潜在问题和漏洞,并通过后续机制来进行保障**,比如增加测试用例、增加产品走查事项等等。
**其实,大到线上故障,小到日常错误,都值得回溯和总结**
比如,我们每天都会遇到形形色色的编译错误,如果每个人遇到同样的问题,都要爬一次同样的坑,显然是非常低效的。
这就需要有团队来负责收集和总结这些常见的错误,并提取关键错误信息和常见解决方法,形成一个案例库。同时,在构建系统中嵌入一个自动化服务,下次再有人遇到编译错误的时候,就可以自动匹配案例库,并给他推送一个问题分析报告和解决建议,帮助团队成员快速解决问题。
这样随着团队智慧的不断积累越来越多的问题会被识别出来从而实现组织知识共享和研发辅助的能力这在很多大公司里面都是一个重点建设方向。仔细想想这本身就是一个PDCA的过程。
不过,这里要补充一点,团队实施持续改进的过程,不应该是一次大而全的变革,而应该是一系列小而高频的改进动作。因为大的变革往往影响众多,很容易半途而废,而小的改进更加温和,也更加容易成功。为了方便你理解,我跟你分享一张示意图。
<img src="https://static001.geekbang.org/resource/image/07/b4/076bbd81826e4f506232b4ec390899b4.png" alt="">
## 预留固定时间进行改进
很多时候团队都处于忙碌的状态时间似乎成了推行DevOps的最大敌人。于是团队就陷入了一种太忙以至于没时间改进的状态中。
如果团队选择在同等时间内去做更多的功能那就说明至少在当前这个阶段业务开发的重要性要高于DevOps建设的重要性。
可问题是业务的需求是没有止境的。有时候我去问一线员工“你觉得有什么地方是DevOps可以帮你的吗”要么大家会说“没什么特别的现在挺好”要么就是一些非常琐碎的点。实际上这只能说明要么是没想过这个事情要么就是不知道还有更好的做法。但是如果不能调动一线员工的积极性持续改进也就无从谈起了。
所以,正确的做法是,在团队的日常迭代中,事先给改进类工作预留一部分时间,或者是在业务相对不那么繁忙的时候(比如大促刚刚结束,团队在调整状态的时候),在改进工作上多花些时间。
这些工作量主要用于解决非功能需求、技术改进类问题,比如修复技术债务、单元测试用例补充、度量识别出来的改进事项等。通过将这部分改进时间固定下来,可以培养团队持续改进的文化。
我比较推荐的做法是,**在团队的Backlog中新增一类任务专门用于记录和跟踪这类持续改进的内容**。在迭代计划会议上,对这类问题进行分析,并预估工作量,保证团队有固定的时间来应对这些问题。
另外很多公司也开始流行举办Hackathon Day黑客马拉松是说在有限的时间里通过编程实现自身的想法和创意在这个过程中充满了积极探索的精神、自由散发的思维和挑战极限的理念通过团队协作与互相激发实现创意到开发的全过程。
我们团队最近也在准备参加今年的黑客马拉松希望通过这个途径寻求合作共建除了解决内部效率提升的“老大难”问题还能提升团队成员的积极性在更大的舞台上展现DevOps的价值一举两得。
## 在团队内部共享业务指标
很多时候团队成员都像是临时工一样,对于自己所负责的需求和业务的表现一概不知。如果团队成员对一件事情没有归属感,那么又如何激发他们的责任感和自我驱动意识呢?
所以,对于业务的指标和表现,需要尽可能地在团队内部做到透明,让团队成员可以接触真实世界的用户反馈和评价,以及业务的度量信息。
在一个新功能开发完成上线之后,要能实时查看这个需求的上线状态。如果需求分析时已经关联了业务考核指标,那么,同样可以将该业务关联的指标数据进行展示。这样,研发就会知道自己交付的内容有多少问题,用户的真实反馈是怎样的,从而促使团队更多地站在用户的视角思考问题。
**除了业务指标DevOps的指标体系也应该对内部公开透明**。大家可以查看自己所在团队的表现,以及在公司内部的整体水平。
适当的侧向压力,会促使大家更加主动地接受改进工作,并且通过度量数据展示改进的效果,从而形成正向的循环。
## 激励创造性,并将价值最大化
每个团队中都不乏有创新意愿和思想的员工,他们总是能从墨守成规的规范中找到可以进行优化的点。
比如,之前,我们团队的一个测试人员发现,日常埋点测试费时费力,而且没有数据统计。于是,她就自己利用业余时间开发了一个小工具,用工具来承载这部分工作,效率大幅提升。
如果更多人知道这样的创新,并且在更大范围内使用,不仅可以提升更多人的效率,让团队整体受益,而且还可以减少类似的重复建设,让有想法的员工一起参与工具优化。
比较好的做法是,**在团队成员的绩效目标中,增加对团队贡献和技术创新的要求,在团队内部鼓励创新类工作**。另外,在团队内部建立对应的选拔和激励机制,为好的想法投入资源,把它们变成可以解决类似问题的工具。
很多公司也开始注意到这种**内部知识复用**的重要性,所以,无论是代码库开源,还是公共基础组件的市的建设,甚至是公司级的平台治理系统,都可以帮助你快速地复用已有的能力,避免一直重复造轮子。
## 总结
就像每个工程实践的终点都是持续改进一样,我们专栏的“工程实践篇”同样以持续改进的实践作为收尾。
我始终认为团队是否建立了持续改进的文化是评估团队的DevOps实践效果的重要参考。在这一讲中我给你介绍了PDCA的持续改进方法体系也就是通过计划、实施、检查、行动这四个步骤的持续迭代不断把团队推向更优的状态促使团队进入正向发展的车道。
另外我给你介绍了四个持续改进落地的方法包括在失败中总结和学习建立固定的改进时间在团队内部共享指标、培养团队的责任感以及激发团队的创造力并将价值最大化。这些方法的核心就是想打造一个学习型的组织和文化给DevOps的生根发芽提供丰饶的养分。
从下一讲开始,我们将进入“工具实践篇”,我会给你介绍一些核心工具的设计思想、建设路径,以及一些常见开源工具的使用方法等,敬请期待。
## 思考题
除了我提到的这四种持续改进的手段,你所在的公司,有什么活动可以促进持续改进文化的建设吗?
欢迎在留言区写下你的思考和答案,我们一起讨论,共同学习进步。如果你觉得这篇文章对你有所帮助,也欢迎你把文章分享给你的朋友。

View File

@@ -0,0 +1,178 @@
<audio id="audio" title="29 | 向前一步万人规模企业的DevOps实战转型案例" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/1c/51/1c5bb812429cbde1fe16e6f49f0d8551.mp3"></audio>
你好,我是石雪峰。
“向前一步”这个名字来源于Facebook的首席运营官谢丽尔·桑德伯格的一本书《向前一步女性工作及领导意志》。她在书中鼓励女性在职场中向前一步勇于面对挑战追求自己的人生目标。
我之所以选择用这个名字作为案例的标题是因为在企业中DevOps转型并不是一件容易的事情我们也需要有勇气向前迈出一小步去承担这个使命。哪怕只是改变了一个小问题也是转型过程中不可忽视的力量源泉。
在专栏最后的案例环节我会用两讲给你介绍下微软这些年的DevOps转型故事以及我在国内企业中的实践总结和经验。
今天,我们先从**管理实践**和**文化层面**入手来看看这家传统的软件巨头是如何在经历了移动互联网时代的迷失之后在容器云和AI时代再一次独占鳌头的。
微软的DevOps转型并不是一个突然的决定**随着云服务的兴起,用户需求激增,对发布节奏的要求越来越高**。这些通过**需求的数量**就能体现出来。2016年的用户需求数量比过去4年的总量还要多到了2017年需求数量达到了2016年的2倍这就要求团队能够以更快的速度完成交付。
要知道如果你期望的优化水平是提升10%的交付能力那在原有的组织架构、流程规则下做局部优化就有可能实现。但是如果要达到200%的优化效果,就需要做出巨大的改变了。
## 建立面向交付的特性团队
微软之前的组织架构跟很多公司一样,也是按照职能划分的,比如分为项目管理团队、开发团队、测试团队和运维团队。每个团队都比较封闭,部门墙的问题非常严重,给团队内部的协作效率造成了很大的影响。
<img src="https://static001.geekbang.org/resource/image/32/68/326fa5282fc147f5d1ab5f8a90431868.png" alt="">
为了应对需求交付的压力,微软首先进行了一次组织架构调整,**将开发团队和测试团队整合为工程团队**。于是,测试的职能在团队中消失了,转而变成了面向开发的开发工程师和面向测试的开发工程师,他们和产品管理团队一起完成项目的敏捷推进。在敏捷的理念中,测试活动应该内嵌于开发环节之中,通过把两个部门整合起来,就完成了测试注入研发的工作。
<img src="https://static001.geekbang.org/resource/image/63/bc/630746e8acd92ec3ab7a83306e3493bc.png" alt="">
虽然开发和测试团队融合到了一起,但是交付工作依然依赖于独立的运维团队来完成,这就造成了一个问题:**即便开发效率再高,如果运维能力跟不上,那也是没有意义的**。
于是,微软开启了第二次组织变革,这一次的核心是**构建特性交付团队,并赋予团队自治的能力**。
所谓的特性交付团队,就是我们常说的“全功能团队”,实际上,这就是把横向的按照职能划分的组织变成垂直跨职能的组织。这个团队中包含了要完成功能交付的所有角色(比如产品、开发、测试和运维),可以闭环地完成整个交付工作。
在这个过程中,微软引入了一种叫作**自组织团队**的形式。与传统的管理层自上而下安排组织的方式不同的是,员工可以自由地选择想要加入的特性团队。这种新的自由组队的方式为每个人都提供了学习新知识的机会。
你可能觉得,这么搞的话,组织不是乱掉了?高手都希望跟高手在一起,那剩下的同学怎么办呢?其实,我在国内的一家公司也见过类似的玩法,他们解决这个问题的核心方法就是“**传帮带**”模式。
比如,一个职能依赖某种特殊技能,但这种技能在团队内部非常稀缺,无论拥有这种特殊技能的这名成员去到哪个小队,剩下的组都会出问题。所以,这家公司就强制采用“老带新”的模式,也就是师傅对新人进行集中培训,给新人快速赋能。而且,这种“师徒关系”会长期存在,如果新人遇到什么问题,都可以请教师傅。当然,对于新人来说,也会有相应的考查机制。这种模式就有助于公司达成内部成员互相学习的目标。
根据数据统计虽然只有不到20%的员工选择了岗位变化但是这种方式却给100%的员工提供了选择的可能性。对于一家官僚政治出名的公司来说,这就可以大大地调动员工的积极性。
<img src="https://static001.geekbang.org/resource/image/30/2f/30ef61022920bbc0eaa6cc7bf28d292f.png" alt="">
实际上,特性交付团队还有几个显著的特征:
1. 拥有团队独立的办公空间,大家都坐在一起,在沟通时基本可以靠“吼”;
1. 一般由1012个团队成员组成
1. 具有明确的工作目标和职责;
1. 为了保证稳定性一旦组队成功未来的1218个月不再改变
1. 自己管控特性向生产环境部署;
1. 团队自治。
无独有偶国内某大型公司在推进DevOps转型的初期也做了类似的事情。为了加速研发和运维的融合它们将一个大的应用运维团队拆分到了各个业务线里面。
不仅如此,研发开始向全栈转型,承接运维工作,而运维自身的工作释放出去后,就要求团队进行能力升级。运维团队需要具备研发能力,来不断地开发和优化运维工具,以降低研发、运维的成本。
这个过程说起来轻松但实际在做的时候就需要非常强的组织执行力甚至还需要高层背书自上而下地贯彻这样的要求。转型的过程对于每个人来说都是很痛苦的但也只有经过这样剧烈的变革才让DevOps转型成为了现实而不仅仅只是说说而已或者只是在几个小部门之间搞来搞去。
我经常说一句话:“**想在不改变流程的前提下实现企业的DevOps转型是不现实的**。”至于团队的组织架构是否要调整,还是由交付效率来决定的。
转型初期的引入工具和推广阶段对组织的冲击力没有那么大,但是,当转型到达了“深水区”之后,**组织的变革**就成了一个非常现实的问题。
根据“康威定律”,**一个团队交付的系统结构和他们的组织结构是相同的**。其实换个角度来说软件交付的流程也是跟当前的组织结构保持一致的。只要有一个独立的测试团队就总会有一个独立的测试阶段。而正是因为这样的一个个阶段才带来了内部协作的部门墙和效率瓶颈而这都是DevOps转型需要考虑的事情。
## 自组织敏捷团队
回到案例部分,为了促进特性交付团队的自治,微软在敏捷开发计划方面也进行了一定的调整。
首先,按照不同的维度,他们分为四种计划。
- 迭代维度设定为3周一个迭代
- 计划维度包含了3个迭代
- Season维度6个月包含了两个计划周期
- Scenario维度长达18个月的远景图。
<img src="https://static001.geekbang.org/resource/image/f4/6d/f4f990e10213aa0be6202d6ac643ba6d.png" alt="">
其中,管理层负责规划长期目标和全景图,也就是回答“我们要去哪里”的问题;而中短期目标,也就是迭代和计划,由自组织团队自行决定,这回答的就是“我们如何去到那里”的问题。
交付节奏按照迭代来进行每3周的迭代会有一部分价值产出。随着迭代的不断推进再逐步更新、优化计划目标并反馈给长期规划进行互动和调整。也就是说618个月的长期计划并不是一成不变的团队会基于每个迭代和计划的交付增量以及用户的反馈进行调整建立起一种“**计划 - 交付 - 学习**”的闭环路径,不断地校准产品目标和整体方向,保证长期规划的有效性,从而规避了原本瀑布模式下的在项目初期决定未来开发路径的潜在问题。
毕竟,在这个快速变化的时代,谁也无法保证你的计划是一成不变、永远有效的。
<img src="https://static001.geekbang.org/resource/image/cb/7d/cb84537437ba1cc7f62879a5019ea07d.png" alt="">
现在,特性交付团队的迭代和计划是由自己来决定了,但是你别忘了,每个成功的项目都需要成百上千人的协作。那么,如何保证团队目标的一致性和互相的配合度呢?
微软引入了三种实践方法,分别是**迭代邮件**、**团队交流**、**体验评审**。
**1.迭代邮件**
在每个迭代的开始和结束时,团队都会发出迭代计划和状态邮件。在邮件中,除了明确本次迭代的特性完成情况以及下个迭代的交付计划之外,为了帮助其他团队成员更好地了解这个迭代的功能,他们还将这些功能录制成视频附在邮件里。不仅如此,**待办事项的列表**和**看板状态**也都以链接的形式被附在了邮件中。
<img src="https://static001.geekbang.org/resource/image/40/de/403b15202f5ba2181cc8c0c583ed0ade.png" alt="">
**2.团队交流**
在每次迭代完成的时候,团队成员都要问自己三个问题:
- 下一步的待办事项中包含哪些内容?
- 有哪些技术债务的累积和非功能特性?
- 有哪些遗留问题?
团队中的每个成员都要亲自完成这项任务,这不仅是为了减少信息传递的损失,更重要的是建立一种仪式感,帮助大家更加理性地安排迭代计划。毕竟,一旦把任务安排好了,就要按时完成。
**3.体验评审**
在分析需求之初,采用用户故事的形式,站在用户的角度,以场景化的方式来描述用户所处的现状,以及这个特性想要解决的问题。那么,不同团队的成员就可以站在用户的视角来实现这个功能。
特别有意思的是,微软在管理特性的时候,**会尽量保持对原始用户需求的关联**。他们会在特性旁边附上原始的用户需求。
很多时候,开发要处理的任务都是**被产品人员翻译过的用户需求**,而并非原始的用户需求,以至于在开发的时候,**我们并不知道要解决的核心问题是什么**。通过关联原始用户需求,每个人都能在开发、测试、交付的过程中,站在用户的视角来重新审视一下,我们交付的功能到底是不是用户想要的。
这些环节的变化带来了一系列积极的影响。
首先,团队成员的积极性大大提高。因为他们觉得自己是用户体验的首要负责人,他们有责任自己修复并解决用户的实际问题。
其次,团队无需再等待领导的规划。在符合整体项目计划的前提下,他们可以自行制定计划。
最后,计划的更新是由持续学习来驱动的。比如,团队会给用户经常使用的功能添加埋点,观察用户使用的数据情况,定期关注和解决用户反馈信息。
**持续的增量交付和不断的反馈建议,也是现在保证产品需求有效性的最佳手段**。毕竟业务敏捷是DevOps的源头如果业务自己对需求都没有明确的衡量方法那么即便拥有了最强的持续交付能力也是跟“蒙眼狂奔”一样。所以想要推进DevOps**敏捷开发实践和需求价值分析**都是必不可少的要素。
在微软,为了促进有效反馈,他们的**度量体系**也很好,非常值得一说。对于微软来说,**获取用户的真实行为数据至关重要**。他们在建设指标体系的时候,出发点大多落脚在**考量哪些指标对业务衡量有直接作用**上,而不是衡量团队的产出以及个人的产出。
他们采用的指标包括以下几个方面:
- **使用维度**:用户增长、用户满意度、特性交付情况等;
- **效率维度**:构建时长、自测时长、部署时长等。
- **在线站点健康度**:错误定位时长、用户影响时长、线上问题的遗留时长等。
但是,某些国内流行的指标却并没有被纳入绩效考核,比如**完成时长**、**代码行数**、**缺陷数量**等。
<img src="https://static001.geekbang.org/resource/image/0d/a2/0d845455a931027e8a974bcd5ab5b7a2.png" alt="">
你可能会说,这也没什么特殊的啊,但是,你要知道,微软对于用户的关注不止如此。
我给你举个具体的例子。一般情况下我们在度量系统可用性的时候都是面向系统整体的比如保证整体可用性达到4个9也就是在99.99%的情况下是可用的。但是,微软认为,系统可用性应该更进一步,**要以账号的维度来进行度量和统计**。
当我们站在系统整体的视角时,很多个人用户的行为就被整体数据掩盖了,也就是我们常说的“被平均”了。但是,如果站在账号的视角,也就是每一个用户的视角来看待这个问题的时候,我们就会发现,用户是真真切切地遇到了一些问题。
比如,某一个账号下服务不可用的情况出现频率比较高,那么,与其等着用户上网吐槽,倒不如提前跟用户取得联系,主动帮助他们解决问题。在联系用户的邮件中,不仅要清楚地描述团队观察到的客观情况,还要提供建议的解决方案。如果用户无法自主完成定位和修复,还可以通过邮件中的联系方式和团队取得联系,寻求进一步的帮助。
微软对用户的关注不仅体现在系统可用性的度量方面,在特性开关方面也是如此。
特性开关是一种比较常见的在运行时控制特性是否对外可见的技术手段。在微软的产品中,也大量地使用到了特性开关的技术,但他们的特性开关可以**细化到用户级别**,也就是可以将用户添加到或者移出列表中,从而控制每一个用户的可见特性。
这样一来,如果某些新特性影响了特定用户的使用,就可以通过这种方式处理,无需部署,直接将特性下线。这不仅有助于问题的快速解决,还提供了一种更加精细化的实验机制。与灰度发布相比,基于特性的发布也更加灵活。
## 团队转型从中型团队入手
在转型团队的选择方面,微软的经历带给我们的启示是,**尽量避免从大型团队开始入手**。
在DevOps转型的过程中常见的思维方式是先把企业内部最核心和最大的团队搞定。只要把最复杂的部分搞定了其他中小团队的需求也就都可以满足了他们会自然而然地跟上转型的节奏。
但是事实上,这些大团队往往都有一些独特的流程以及特殊的需求,对系统工具和流程的定制化程度较高,实现起来也最复杂,甚至对他们来说,转型工作的优先级并不是最高的,总会因为这样那样的需求导致转型工作一拖再拖。这对于转型工作来说,并不是一件好事。
所以微软调整了他们的策略采用了“middle-out”的方法也就是**专注于中型团队**40到100人。这些团队由于资源不像大团队那样充足对外有充分的需求。而且这种规模的团队可以快速地评估现状收集团队的必要信息而不是猜测他们到底需要什么。
通过持续细小的改进,帮助这样的团队做得更好,内部的传播让更多的团队主动联系他们并寻求帮助,从而建立了一个有效的持续改进循环。
## 总结
今天我给你介绍了微软DevOps转型的上半部分内容。我们来简单总结一下。
- 为了满足快速交付的需求,他们打破组织的原有架构,建立了面向特性交付的跨职能组织;
- 通过团队自治,他们将计划分为短期目标和长期目标,短期目标(包括迭代和计划)都由特性团队来自主决定;
- 在度量方面,他们更加关注业务指标的表现。而且,无论是在系统可用性方面,还是在特性开关方面,他们都细化到了具体的用户级别,以保证每个用户的使用体验;
- 在选择转型团队方面,他们主动避开了最复杂的团队,而是从能够把握住的中型团队做起,积累成功经验,然后不断传播。
最后我再提一点自己的想法。这两年来在DevOps领域特性的出镜率越来越高。因为特性是更加符合DevOps快速交付原则的需求颗粒度。所以业界的各大公司在基于特性的需求管理、基于特性的分支策略、基于特性的发布和价值追踪策略等层面都有很多实践和思考。比如今年CloudBees公司发布的SDM产品就是基于特性维度的。
我相信未来的DevOps也会朝着这个方向发展。打造一整套基于特性开发的研发模式是一个值得我们花精力好好思考的点。
## 思考题
你认为,基于特性维度的开发和交付,有哪些流程、工具、规则是有效的呢?
欢迎在留言区写下你的思考和答案,我们一起讨论,共同学习进步。如果你觉得这篇文章对你有所帮助,也欢迎你把文章分享给你的朋友。

View File

@@ -0,0 +1,182 @@
<audio id="audio" title="30 | 向前一步万人规模企业的DevOps实战转型案例" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/94/8d/94e4d81db1e00f8c9b4ddfa77265e88d.mp3"></audio>
你好我是石雪峰。今天我们接着上一讲的内容继续来聊一聊微软DevOps转型的故事。
经常有人会问企业的DevOps转型应该由哪个团队来负责是否要组建一个全新的DevOps团队呢带着这个问题我们来看看微软是怎么做的。
## 1ES
微软有一个特殊的团队叫作1ES。1ES是One Engineering System的缩写直译过来就是“一套工程系统”的意思。从这个名字相信你就可以看出来**在微软内部,有一套统一的工程能力平台来支撑微软内部各种形态产品的研发交付工作**。没错这个1ES团队包含了近200名工程师作为组织级的研发效能团队他们的目标就是**通过一整套通用的工程能力平台,来提升内部的研发交付效率**。
1ES团队的工作职责可不仅仅是开发通用工具平台他们还要负责公司的文化转型、最新的工程方法导入试验、研发过程改进、安全合规性检查、内部研发效率咨询以及在工程团队推广最佳实践等等可以说是一个“全功能”的企业研发效能和生产力团队。截至2018年数据显示总共有近10万名用户在1ES提供的平台上协同办公。
<img src="https://static001.geekbang.org/resource/image/41/b8/41d63ec1588a2655d75d7f55cb8ffab8.png" alt="">
但国内的现状是很多企业对于研发效能的关注才刚刚起步。即便有人员负责类似的事情也大多分散在各个业务内部难以形成合力。组建了企业级统一的研发效能团队而且规模能够跟微软的1ES相提并论的企业基本上一只手就可以数得过来就更别提建立一套统一的工程能力平台了。我曾见过一家大型企业他们内部的工具平台有1700多个殊不知这里面有多少的重复建设和资源浪费。
那么你以为微软的1ES团队天生就是这样“一统天下”的吗还真不是这么回事。
事实上1ES团队的历史可以追溯到2014年。当时微软新上任的CEO萨提亚·纳德拉非常重视研发能力建设他致力于通过最好的工具来赋能研发团队。结果微软的每个部门都会根据自己的实际情况采购自己习惯的工具平台这就导致整个公司内部的工具、流程和成熟度差异巨大。差异化的工具和流程进一步增强了不同团队之间的共享和协作内部人员转岗的成本极高因为他们到了新团队以后要从头开始适应一切。
为了解决这个问题1ES团队识别了三大领域**工作计划管理**、**版本控制**和**构建能力**。他们先在企业内部识别哪些团队没有使用公司构建的统一工具然后自顶向下强推。这背后的核心理念就是“Use what we ship to ship what we use”也就是使用他们对外发布的工具来研发团队自己的工具。
不知道你发现没有,这三个领域都是软件交付的主路径,**需求和任务管理、版本控制和构建系统无一不是核心系统**。当你想要建立一个统一的效能平台的时候,最重要的就是抓住主路径上的核心系统。
关于“如何基于核心系统扩展一整套解决方案”我给你推荐一篇GitHub的[博客](https://github.blog/2019-11-13-universe-day-one/),你可以看看他们是如何思考这个问题的。
在接下来的几年里面1ES团队推动VSTS也就是现在的Azure DevOps成为了微软内部的工具平台标准平台的用户也从最开始的几千个人增长到了后来的10万多人。
正是从2010年开始至今150个迭代的千锤百炼才造就了后来Azure DevOps产品的大放异彩。可以说无论是从设计理念、功能还是用户体验等方面微软的Azure DevOps平台在当今业界都是首屈一指的。
<img src="https://static001.geekbang.org/resource/image/dd/ba/dd0189b0de10caf513fdd018e7fadbba.png" alt="">
## 持续交付
持续交付是DevOps转型的核心部分1ES提供的统一工程能力平台让这一切成为了可能。那么微软的持续交付做到了什么程度呢
从2019年3月份的数据来看他们每天部署82,000次、创建28,000个工作项每个月有44万个提交请求、460万次构建和240万次的提交数量。
无论把这些数据的哪一项拿出来,都是非常惊人的,这体现了微软卓越的工程能力水平。
<img src="https://static001.geekbang.org/resource/image/8c/c2/8c67f5153f568acd746021bbe918ebc2.png" alt="">
那么微软是如何一步步走到今天的呢我们先来看看DevOps中最重要的、也是“老大难”的测试部分看看微软是如何实现在6分钟内完成6万个测试用例的。
其实早在2014年微软在测试中遇到的问题跟大多数公司没什么两样测试耗时太长、测试频繁失败、主线质量不可靠、迭代周期末端的质量远远达不到发布门槛。
这些问题严重到什么程度呢?我给你列举几个数字,你就明白了。
- 每天的自动化测试耗时22个小时
- 全功能自动化测试长达2天
- 仅有60%的P0级别用例可以执行成功
- 在过往的8年里面甚至没有一次每日自动化测试是全部通过的。
不仅如此团队成员之间对单元测试存在着巨大的分歧研发不愿意花时间写单元测试团队不认为可以通过单元测试替代功能测试甚至连用不用Mock他们在理念上也存在着冲突。
历史总是惊人的相似。在我之前的公司里面,研发总能找到各种理由苦口婆心地说服你他们不需要写单元测试,或者是,各种环境问题导致单元测试压根没法执行完成,因为引用了大量的外部服务。
微软的解法是,**停止这种无意义的争论,为了达成预期目标前进**。他们**先从能达成共识的部分开始推进,并重新整理了内部的测试模型**,如下图所示:
<img src="https://static001.geekbang.org/resource/image/bf/da/bf6f84d0c3ecf36719c7d287f667a3da.png" alt="">
- L0级这是没有外部依赖的单元测试。这部分在代码合并请求中执行执行时长小于60ms
- L1级这是存在外部依赖的单元测试测试时间一般小于2秒平均400ms左右
- L2级是面向接口的功能测试在预发环境执行
- L3级也就是在生产环境下执行的线上测试。
在明确了整体策略之后,团队开始对测试活动进行改造。整个改造过程可以划分为四个阶段:
**阶段一从L0/L1级测试入手**
在这个阶段尽可能地简化L0/L1级测试的执行成本编写高质量的测试用例。
根据我在企业里面推行单测的经验,抛开“到底应不应该写单测”这个事情不说,最大的争议点就是**分工**的问题。从做事的角度来说,包含几个方面:工具和框架选型、规则整理输出、工具平台开发、数据的度量和可视化建设。
为了加快单测的推行我建议前期工具和框架选型由自身的开发和测试工程师或者有经验的DevOps工程师一起完成并在试点项目跑通。接下来研发完成规则的梳理包括单测的书写规则、工具环境配置规则等等平台方面启动单测相关的能力建设目的就是研发只需要写单测代码具体的执行、数据分析、报告统计都交给平台完成。最后在团队内部进行推广并持续更新迭代规则和工具。在这个阶段**尽量不要新增每日测试用例**。
**阶段二:分析已有的每日测试用例**
在这个阶段,重点要识别几个方面的内容:
- 哪些测试用例已经过时,可以删掉?
- 哪些测试用例可以转移到L0/L1级完成
- 哪些测试可以整合进SDK中专项进行比如性能测试
这一步骤的目的就是让每日测试用例集合尽可能地“瘦身”,加快执行速度。毕竟,每次跑几十个小时,一旦失败的话,就没有第二次机会了。
**阶段三将每日测试转化为L2级测试**
接口测试是一种性价比相对更高的测试类型,所以,推进面向接口的自动化测试建设可以兼顾测试的执行效率和业务的覆盖情况。
在这个阶段我们需要完善接口自动化测试框架提供代码、配置和多接口验证等多种测试类型。除此之外要集中统一的管理系统的API一方面进行API的治理另一方面加强研发和测试基于API的协作把所有的变更版本线上化。一旦研发更新了API定义测试可以在同一个地方更新他们的测试用例和Mock数据从而实现基于API的在线协同工作。
**阶段四建设L3级测试**
这就是在生产环境的线上测试,主要是通过监控机制来诊断系统的健康度。这部分内容我在[第17讲](https://time.geekbang.org/column/article/167353)中提到过,如果你不记得了,可以回去复习一下。
随着L0/L1级测试的不断增多这些测试都可以纳入到代码合并请求中自动执行。另外L2级的API接口测试同样可以纳入到流水线中。
通过40多个迭代的持续努力以及考核机制的促进作用整个测试的分布情况发生了明显的反转。
你可以看到每日测试的数量不断减少L0级别的测试不断增多到后来L1/L2级的测试也相对稳定下来。你要知道这40多个迭代可是花了将近3年的时间。如果以后谁再跟你说“3个月就能搞定单测”你可千万别跟他聊天。
<img src="https://static001.geekbang.org/resource/image/64/eb/6497a8b396e9b125b45934616a7f4beb.png" alt="">
## 持续部署
持续交付的终点是持续部署,那么,微软在部署层面又做了哪些事情呢?
首先,微软不承认半自动化部署这个事情。其实很多时候,部署动作都不是一次性完成的。有些命令或者步骤并没有线上化,或者就是非高频的动作没有做到工具里面,还是需要通过手动复制一段命令的方式来实现。
经常有人会问:“我们的大部分操作都实现了自动化,这算不算做得不错了呢?”我的回答也很简单:“对于一个没有基础或者非专业的人来说,他是否可以完成这项任务?”坦率地说,这有点“抬杠”的性质,但事实上,如果一个平台做完了,结果还是要依赖于指定人去操作,那你就得想想这个事情的意义和未来的价值了。
之前我在做一个项目的时候,就遇到过类似的案例。为了解决配置变更的问题,团队成员实现了一个非常复杂的任务,但是在评审的时候,我们发现,这个任务并不能解决所有问题,到头来还是需要他手动入库操作。手动入库的成本其实还好,但是为了自动而自动,结果得不偿失,这就有点浪费时间和精力了。
那么,**要想解决所有人都能部署的需求,要做的就是完全的自动化**。把所有的操作都内嵌于流水线之中,并且纳入版本控制,用于记录变更信息。使用同一套工具实现多环境部署,通过配置中心完成不同环境的配置下发。
这样做的好处有很多,一方面,可以在不同的环境中完善部署工具的健壮性,避免由于部署方式或者工具的差异带来的潜在风险。另一方面,与生产环境的部署相比,测试环境的部署心理压力没有那么大。当大家都熟悉测试环境的部署过程之后,对生产环境的部署就是小菜一碟了。
为了实现安全低风险的部署,微软引入了“部署环”的概念,你可以把部署环理解为**将部署活动拆分成了几个阶段**。每一次生产部署都需要经过五环验证过程,即便是配置变更,也是如此,不存在额外的紧急通道。这五个部署环分别是:
1. 金丝雀(内部用户)
1. 小批量外部用户
1. 大批量外部用户
1. 国际用户
1. 其他所有用户
通过渐进式的部署方式,每一个新的版本都缓慢地经过每一环的验证,并逐步放量,开放给所有用户。其中有几个点值得我们借鉴。
**1.通过流水线打通CI/CD**
我们可以这样理解CI/CD
- CI的目的是生成一个可以用于部署的包。这个包可以是war包、tar包、ear包也可以是镜像这**取决于系统的部署方式**。
- CD的目的是将这个包部署到生产环境并发布给用户。
所以CI和CD的结合点就在于**制品库**通过流水线调度部署包在制品库中的流转从而完成制品的晋级。我发现很多大厂都是用部署前重新打包的方式人为地将CI和CD的过程割裂开来这并不是一种好的处理方式。
**2.持续部署并不意味着全自动**
我们都知道持续部署能力是考查一个公司DevOps能力的最好指标比如前面我提到的微软每天能够部署8万多次。那么这是不是说每次变更都要经过自动化过程部署到生产环境呢答案是不一定。
你可以看一下这幅微软开发的全景图其中在CD过程中每一环的部署都需要人工确认来完成这背后的核心理念是控制“爆炸半径”。
<img src="https://static001.geekbang.org/resource/image/cb/42/cb221e6fd8e2e06b9cd1850dbf7e0e42.jpeg" alt="">
既然无法彻底阻止失败,那么是否能够控制影响范围呢?“部署环”的设计理念正是如此,为了做到这一点,**适当的人工管控还是很有必要的**。
那么,如何确认部署是成功的呢?
微软定义了非常详细的保障在线服务可用性的规则,其中最重要的就是,**明确线上服务状态永远处于第一优先级**。你可能觉得,本来不就应该是这样的吗?但是,在实际工作中,我们会发现,内部工具团队经常专注于实现新功能,而把线上的报警放在一边。
要想解决这个问题除了明确线上为先的理念之外制定相应的规则也是很重要的。比如微软的值班工程师叫作DRIDesignated Responsible Individual也就是“指定责任人”。微软明确要求每个在岗工程师必须在工作日5分钟内、休息日15分钟内响应问题并把这纳入到了人员和团队的考核之中。另外通过每周、每月的线上服务状态报告以及每次事故的详尽故障分析不断在内部强化线上为先的理念。
## 总结
在这个案例中我给你介绍了微软在转型过程中的几个重点包括自动化测试能力、统一工程平台和工程团队、分级持续部署、组织变革、团队自治和文化转变等。这些都是在实际的DevOps转型过程中企业所面对的最为头疼的事情。微软的经历是否给你带来了一些启发呢当然想要做好DevOps可绝对不只是做好这几点就够了的。
对于DevOps的转型过程微软的理念是
>
A journey of a thousand miles begins with a single sprint.
这就是咱们常说的“千里之行始于足下”。DevOps不是一种魔法可以立即见效而是每次变好一点点每个人都在不断地思考“我能为DevOps建设做点什么”。这就像微软的自动化测试转型过程一样你能看到整个趋势在不断变好慢慢变成了现在这样每次提交可以在10分钟左右完成近9万个自动化测试。
微软一直在致力于推广DevOps并且不断把自己的经验通过各种形式分享出来。仅仅从这一点上我们就能看出微软的文化转变、向开放开源的转变。我再跟你分享一些微软DevOps转型的资料你可以参考一下。
>
资料1. [https://docs.microsoft.com/en-us/azure/devops/learn/devops-at-microsoft/](https://docs.microsoft.com/en-us/azure/devops/learn/devops-at-microsoft/)
>
资料2. [https://azure.microsoft.com/en-us/solutions/devops/devops-at-microsoft/](https://azure.microsoft.com/en-us/solutions/devops/devops-at-microsoft/)
你还记得我在[第6讲](https://time.geekbang.org/column/article/154695)中提到的DevOps转型的J型曲线吗其实无论是DevOps转型还是研发效率建设都是一个长期、琐碎的过程。你要做的就是树立自己的信心做正确的事情并期待美好的事情自然发生。
## 思考题
通过案例学习DevOps是一种特别好的方法在案例中你不仅能借鉴别人的经验也能学习到系统背后的设计理念。那么你有什么好的案例学习途径吗可以分享一下吗
欢迎在留言区写下你的思考和答案,我们一起讨论,共同学习进步。如果你觉得这篇文章对你有所帮助,也欢迎你把文章分享给你的朋友。