【51CTO.com原创稿件】随着互联网产业的飞速发展,IT 研发的工作方式也越发的灵活多变。从应用的角度来说,由原来的单服务应用,到现在的微服务应用,处理的数据量和类型也在不断增长。
图片来自 Pexels
从团队的角度来说,不仅包括开发,测试人员,还引入了运维,安全,系统,网络等各个专业的人员。
那么在新的时代下,我们如何利用 DevOps(开发运维)的方法论指导交付过程,就显得尤为重要了。
我们将从 DevOps 的两个要点三个原则切入,来看看组织,团队,流程的优秀实践。
DevOps 的两个要点和三原则
做任何一件事情都有其价值,做事的过程就是“把业务构想转化为客户价值的过程”,我们称之为价值流。
对于研发团队来说,也存在技术价值流。它就是通过“开发+运维”的敏捷迭代的方式为用户提供价值。技术价值流就是第一个要点。
通过开发运维的方式,帮助业务想法触达到客户需求
如果把我们创造价值流的工作分成两个阶段:
- 第一个阶段是设计和开发
- 第二个阶段是测试和运维
技术价值流创造的两个阶段
那么前置时间是客户提出需求,我们创建一个工单解决这个需求,然后处理工单,直到工作完成的时间的总和。前置时间作为第二个要点是我们值得关注的。
部署工作的前置时间和处理时间
通常情况下从设计,开发,测试,运维中间需要经历很多复杂漫长的过程。
交付的过程复杂且漫长
我们想要达到的目标是,在代码版本控制中不断提交小批量的代码,每次提交都会做自动化的编译,自动化测试,手动测试(探索测试),然后再部署到生产环境中。
为了实现这个目标,需要尽量让设计,开发,测试,发布的时间缩短,给客户提供最大程度的技术价值流。
基于上面提到的两个要点,下面三个 DevOps 原则就是最好的选择。
流动原则
为了缩短从开发到上线之间的时间,提高服务质量和可靠性,我们会加快开发(Dev)和运维(Ops)之间的流动。我们一起来看看需要注意哪些方面。
①使工作可见
和传统行业相比软件开发行业的工作可见度不高。通常只有完全做完才能看到可以使用的用户界面,有的后台服务甚至完成以后都看不到长什么样子。
但是对于不可见的东西,人们对其又难以掌控,所以我们需要对工作进行可视化。
在敏捷开发中我们会对每个阶段的任务进行切割,协助项目推荐和软件开发的完成。
开发,运维,UAT,交付全流程
同时我们要告诉团队,只有软件交付到用户手中并且给用户带来价值了,我们的工作才算完成。
②限制每人同时持有的任务数
这种场景大家是不是经常遇到,你在开发某一个功能的时候,测试同学向你报了一个急需解决的 Bug,同时产品经理又跑过来说这个需求可能需要再改改,架构师也找你谈重构的事情。
这导致一个人同时要处理很多事情,每件事情都很重要,都需要马上完成。就好像摊大饼一样,每个事情都做,每件事都做不好。你会不断地被打扰,在任务之间切换,使得效率变低。
因此,需要借助看板控制每人的任务量,让任务保持合理的数量,从而保证质量和效率。
一人持有多个任务
③减少批量大小
我们在开发过程中经常会遇到这种情况,一个事情有四个步骤组成,我们需要完成 100 件这样的事情。
于是,根据抽象和分工合作的原则,我们把这个事情分成 4 步,每个步骤分配给一个人来完成,这样每个人完成每个步骤 100 次这个事情就完成了。
这个方法没有错,但是在做这个事情的初期,最好是把这个事情的四个步骤由一个人先完成一次,看看是否存在潜在的问题,在看看在完成过程中是否有可以总结的经验和需要踩的坑。
这样往复几次,把一些问题解决以后再找其他几个人来分步骤帮忙。这种方式在快速试错的互联网企业用的非常的多。
先完成闭环流程,再复制经验
④减少交接次数
我们在完成一个事情的时候往往会和其他的团队和人员进行大量的沟通,请求,委派,通知,协调等工作。
例如:软件发布过程中就需要面临功能测试,集成测试,环境搭建,配置服务器,存储管理,网络等工作。如果任何事情都需要审核,协调势必会降低工作的效率。
这里互联网企业的扁平化管理就可以借鉴,每个小队包括技术,业务,管理和不同领域的人员,这样减少了跨部门的沟通,工作效率更高。
减少交接
⑤识别和改善约束点
在软件开发交付的过程中有很多约束,包括:人员,时间,软件,服务器,网络等等。
在 DevOps 中也一样,我们需要不断的识别这个约束,并且不断改善这些限制条件才能推进整个开发的进度。
让约束点之间能够平滑过度
环境搭建:建议使用自动的环境部署,利用现在容器技术(Docker)提高整个环境的搭建速度。
代码部署:建议让代码上传,编译,部署自动化起来。这些动作在一个软件交付团队每天都在不断的上演,开发团队的人越多这个工作更是需要做。
测试执行:这个是承接上一点的,一旦一个软件发布以后就需要跟进自动化的测试。
至少用自动化脚本针对核心 20% 的功能进行测试,然后再由测试人员对具体功能进行冒烟测试。
软件随着功能扩展,测试工作量也会随之增大。如果不用自动化测试,依靠手动测试工作量是很大的。
解耦架构:随着微服务的风行,现在基本都是组件式的设计,组件出现问题都做故障隔离和熔断机制,那么也需要针对组件进行发布。
反馈原则
如果说流动原则说的是,从开发到运维的快速流动,那么反馈原则就是从运维到开发快速的反馈。这两个原则周而复始运转,才能为客户交付最好最快的软件服务。
①及时发现问题
一个服务/产品的交付历经了很多个过程,从需求分析,原型设计,架构设计,编码,测试,发布,集成测试,验收测试,一直到上线。
每个阶段都有工作者参与其中。任何一个问题的产生都是有原因的,即使不能阻止问题的产生,但可以第一时间发现问题,让问题暴露出来。
例如:产品经理没有分析透彻,到了开发的时候就会遇到需求不清的问题,这时程序员就可以提出问题,产品经理就需要对需求进行澄清。
发现问题,反馈问题,解决问题流程图
②解决分析问题
有这样一种情况,在开发的时候发现的问题,在需求和设计上都没有提到。如果放任错误不管显然会影响系统运行。
如果采取事不关己高高挂起的态度,那么问题永远无法发现,那么出现问题我们应该如何处理。
第一,上游环节出现问题,一定不要把问题带到下游环节。在上游环节就把问题解决掉。
上游环节出现问题
第二,暂停上游环节的工作,避免新的问题继续产生。
发现问题及时处理
第三,建立 PDCA 环,计划(Plan),实施(Do),检查(Check),改进(Action)避免此类问题不再发生。
建立 PDCA 机制
③源头保证质量
什么是源头,相对下游来说上游就是源头。产品经理是开发的源头,需求质量不过关代码就受影响。
程序员是测试人员的源头,程序质量有问题测试就会受影响;测试人员是客户的源头,如果问题都被放过了,那么就不能给客户带来价值。
所以,保证源头就是保证交付的质量。对每个过程和阶段做监控是我们要关注的:
- 需求阶段:需求评审,需求确认,需求宣讲。
- 开发阶段:代码审核,结对编程,单元测试。
- 测试阶段:冒烟测试,回归测试,验收测试。
- 发布阶段:自动配置,自动部署,自动检测。
追根溯源图
④客户同理心
客户分为两种,内部客户和外部客户。外部客户是通常意义的客户,我们为客户提供软件交付,满足客户的需求,为客户创造价值。
内部客户就是我们的下游。产品经理把开发人员作为客户,开发人员把测试人员作为客户。
我们在做任何动作,发现任何问题,做任何决定的时候都要想想我们的“客户”,是否对他们有利。我们要把自己放在客户的角度来看问题,好多问题在当下就会被解决。
客户在哪里,站在客户的角度
学习原则
学习原则是对前面两个原则的支持,是基础原则。不管你在工作中踩了多少坑,不管你在编码过程中遭受多少失败都不要忘记学习,持续的学习让一个人变得更加强大,让一个团队逐渐成熟。
①建立学习型的组织结构
在服务交付的过程中,无论我们如何的小心都无法避免犯错。大家都有背锅的经历。
比如某某需求,本来产品经理就没有说清楚,程序员在实现的时候忽略了,到了交付的时候就是程序员的锅,之后项目经理就会信誓旦旦地把开发人员批评一通。
这种场景在我早期工作的时候经常遇到。后来随着带的项目越来越多,发现这样“责备”式的解决问题方式是不对的。
我们应该多从问题本身出发,找出问题的原因。总结归纳,定义好的流程和机制让兄弟们不再犯类似的错误。
如果我们把组织分为三类的话,我希望我们应该是生机型(学习型)的组织。
组织类型分类
病态型:组织中的成员感到大量的恐惧和威胁(生怕做错事情)。大家为了保全自己都不愿承担责任,甚至隐瞒真相和事实。
官僚型:规则多,流程僵化,大家自扫门前雪。
生机型(学习型):在错误中不断总结,不断学习,不断进步。大家积极探索,勇于承担,乐于共享。
生机型组织是我们的目标
②日常工作制度化
这里的制度化并不是为了官僚而给大家加入的繁文缛节,正好相反这些制度的产生都是兄弟们在工作中总结出来的经验教训,转换成制度的原因是希望不要有其他的兄弟再踩这些坑。
举个例子,早先我们做发布的时候总是忘记发布数据库的脚本,导致生产环境的程序 Run 不起来。后来,我们把更新数据库脚本作为发布前必须做的事情写入到发布制度中。
再后来,作为自动化脚本写到自动化发布中。实际上在工作中有很多好的经验,如果我们留心都可以建立这样持续改进的机制,成为心照不宣的制度。实际上我们在平时编码中有很多事情都可以好好总结。
比如:编码规范,命名规范,标准的 MVP/MVC/MVVM 写法,发布流程,测试用例,测试脚本。
制度服务于流程
③局部经验全局化
在开发/运维过程中我们经常会遇到各种各样的事件(坑),这些事件或是迎刃而解或者困扰我们许久。
但最终解决以后,我们希望把这些经验放到知识库中保存起来,这是我们共同经历的一笔财富。
实际上一个项目做完以后,问问自己你在这个项目里面学到了什么,就是这些经验的积累。
当你找下一份工作的时候,面试官问你遇到最困难的问题是什么的时候,你就可以自豪的分享这些经历了。
就算是再小的经验,在放到全局的时候对其他的技术人员甚至是跨部门的技术人员都是有启发和帮助的。
用知识库管理经验
④注入弹性模式
这里说的弹性有两个方面的意思,一个是指人员的弹性,一个是指我们维护系统的弹性。
人员的弹性,在冲刺项目的时候要有长征的韧性和抢渡大渡河的勇气。在项目不忙的时候,也需要不断总结,学习新知识,每个人的成长才能带动整个团队的成长。
项目的弹性,用压力测试的方法,对维护的系统进行正压力测试和负压力测试,探查我们系统的承受极点,从而完善他。
团队弹性和系统弹性
DevOps 组织结构
根据康威定律,软件的架构和软件团队的结构是一致的,这个是康威定律对团队和架构的解读。
我经历过团队从小到大的发展,在初期人较少时,工作流程概念不强,一个人做多个角色的事情,基本没有沟通成本,软件的架构基本是单应用。
后来随着开发,测试,运维人员的增加,总体需要处理的工作量也大了。为了方便管理和项目推进效率,会对人和事情进行切割,规定流程以及团队之间的沟通方式。
架构也从原来的单应用转变成了后来的微服务,数据库从原来的单库转化为分表分库的模式。
组织结构决定软件架构
开发,测试,运维相互融合
在开发过程中,开发,测试,运维所属不同的专业,在项目推进过程中各司其职。在 DevOps 的组织结构中,需要他们三者互相融合。
开发完成以后需要通过单元测试,结对编程的方式保证代码的质量。测试需要发现/验证 Bug,并且与运维合作完成压力测试/性能测试。
大家会发现,现在很多大厂的一线运维人员都是来自开发团队,甚至有很多公司都鼓励,开发,测试人员参与运维工作。让他们感受一下自己的工作对下游工作的影响。
开发,运维,测试相互融合
DevOps 团队搭建
团队成员互为依托
既然了解了 DevOps 的组织结构,那么团队需要哪些成员参与呢?
- 产品负责人:业务方面的代表,可以把他想象成客户。
- 开发团队:负责具体功能开发。
- QA 团队:负责质量保障。
- 运维团队:维护生产环境,配置,发布。
- 信息安全团队:负责系统和信息的安全。
当然,大家可以根据自己公司的需要在这个基础上增加一些管理和支持职责的团队。
对初创企业来说,如果没有运维和信息安全的团队,建议找开发团队的兄弟兼任。
团队价值流
多个团队合作工作,存在沟通,统一认知等方面的问题。价值流图就是为了统一大家的思想,让每个团队的成员都知道,在什么阶段需要做什么事情。实际这些图在之前的文章中也有介绍,无非是把团队和阶段对应上。
团队价值流图
工作在线
如果说要让团队站在同一个平面上面,使用高效的工具是必不可少的。例如:Confluence,石墨文档,Jira,禅道,ProcessOn,Jenkins,Bamboo,Git,JMeter,LoadRunner。
它们可以帮助我们从设计,开发,测试,发布各个阶段提升工作效率。让团队保持高度统一,让所有的工作都在线。
让工具为团队服务,让工作在线
DevOps 流水线部署
团队存在的目的是,为了客户创造价值。那么将软件交付到用户手中的过程,就好像工厂的流水线一样,流水线的上游是原料,经过加工以后,输出的是商品。作为 DevOps 的流水线部署,需要使这个过程自动化。
作为交付团队每次完成代码编写完成,都需要提交版本库。提交以后,版本库会对整体的代码进行编译(构建/Build),并且执行单元测试的代码。
如果失败,会把错误信息打回交付团队,程序员在修正错误以后再次提交代码。只有通过后,才发布到测试环境,进行自动化脚本的测试。
同样没有通过自动化测试,依旧会打回到开发团队,再次进行修改。这个过程周而复始,直到通过用户验收测试,并且发布。
DevOps 流水线
提交阶段:是从技术角度上判断系统是可以工作的。这个阶段会进行编译,运行单元测试脚本,通常这些脚本都是程序员自己编写的。
另外,会针对具体代码,由经验丰富的程序员做代码走查,或者代码互查。这里可以使用 Junit 单元测试工具。
自动化验收测试阶段:是从功能和非功能角度上断言整个系统是可以工作的,即从系统行为上看,它满足用户的需要并且符合客户的需求规范。
手工测试阶段:用于判断系统是可用的,满足了它的系统要求,试图发现那些自动化测试未能捕获的缺陷,这部分测试内容较为复杂,步骤较多,甚至存在多系统切换的情况。
这一阶段通常包括探索性测试、集成环境上的测试以及 UAT(User Acceptance Testing,用户验收测试)。测试人员会根据 UAT 的用例对系统进行测试。
发布阶段:旨在将软件交付给用户,是直接将其应用部署到生产环境,部署之后就进入运维阶段。
按照流水线部署的好处就是,控制每个阶段的交付质量,逐步建立交付者的信心,通过层层筛选将问题挡在外面。
同时对于开发,测试,运维人员也是考验。他们需要大量的协同工作,不断地让应用在流水线上流动,并且及时反馈给不同位置上的队员。
在熟悉了流水线上的几个阶段以后,再来看看每个阶段产生了哪些数据,以及这些数据是如何流动的。
①流程的起点是,开发人员向代码库提交代码。在 Checkin 代码之前,开发人员需要把代码库中相关的代码和组件下载到本地,保证修改后的代码在本地是可以编译通过的。
比较规范的公司,是需要申请 Code Review,让其他的同事走查代码。虽然在 Checkin 到代码库之后,平台会自动运行单元测试。但是建议各位,先做单元测试。
因为,一旦进入验收阶段,编译会花费大量的时间,如果出现问题,系统会生成错误报告并且发给 Team Leader 或者项目组。
如果那个时候再改代码,恐怕所有人都知道 Bug 是从你这里出来的了。因此,还是先在本地跑一下单元测试。
其范围包括你修改代码的模块,也包括其他模块。实际上,任何对代码的修改都有可能影响其他模块,即使你并没有修改其他模块。
持续集成管理系统对这次代码提交作出响应,从指定的代码库拉取代码,并且进行编译,运行单元测试,执行代码分析,组装打包。
如果单元测试都通过,并且代码符合编码标准,就可以打包成可执行文件,并放到一个成品库(artifact repository)中。
当下的持续集成服务器,都提供这些功能,并让用户和流水线的后续阶段能以简便的方式进行。
另外,还有像 Nexus 和 Artifactory 这样的工具可帮助管理过程产物。目前比较成熟的产品。例如 Bamboo,Jenkins 都可以通过配置代码库,成品库,通过脚本命令的方式完成上述操作。
②第二个阶段通常由运行时间较长的自动化验收测试。这些测试的主要内容,是针对一些 API 和模块的测试。
也有的项目组用来做页面的测试,但是个人不建议做页面的自动化,特别是在页面设计的初期,页面元素经常变动,自动化的脚本变化也很大,效果不是很好。
在此之后,部署流水线可能会有分支出现,这样就可以将该构建版本独立部署到多个不同的环境中,比如部署到用户验收测试环境、容量测试环境和生产环境。
也有串行的例子,比如 DEV(开发)环境,INT(集成测试)环境,MO(准生成)环境,Prod(生产)环境。
通常情况下,我们希望测试人员或运维人员可以做到自服务,即自己手工选择需要的某个版本。
例如:可以通过 Bamboo 或者 Jenkins 工具选择成品库中的应用版本,然后发布到指定的环境。
所谓的自动化部署脚本也就是一行能够在服务器上运行的命令,执行命令完成部署工作。
测试人员应当能够看到需要手工测试的所有构建版本,以及它们的状态,之后单击一个按钮,运行相应的部署脚本将选定的构建版本部署到选定的环境上。
提交和验收阶段
总结
DevOps 模式需要遵循三个原则,快速流动,及时反馈,坚持学习。因此,DevOps 的组织结构需要开发,测试,运维紧密合作。
按照这个标准去打造团队,让团队产生价值流,通过工作在线的方式,给用户提供价值。
DevOps 的价值体现在流水线的部署方式,这里需要合理配置提交,验收,手工测试和发布阶段。让应用快速流转,让团队收获及时反馈,从而稳步推进软件交付。
作者:崔皓
简介:十六年开发和架构经验,曾担任过惠普武汉交付中心技术专家,需求分析师,项目经理,后在创业公司担任技术/产品经理。善于学习,乐于分享。目前专注于技术架构与研发管理。
【51CTO原创稿件,合作站点转载请注明原文作者和出处为51CTO.com】