uuussseeennn 2020-01-11
最近听了ECUG
大会上孙敬云老师的分享感觉受益匪浅,毕竟大学课本上只讲到瀑布模型
就没有下文了,工作以后一直贯彻的都是Scrum
路线,一直也没有时间好好的去学习整理这部分的知识,直到近几天听到了孙老师的分享,所以就在这里记录下孙老师的分享也总结我自己的思路。以下内容部分摘自于孙老师的分析PPT
貌似大学的那门软件工程只给我们讲到了1980年,之后的需要我们走出校门,在社会中进行学习。
先来看下面这张图,是1980年至今的软件工程演化路线,像瀑布模型大家应该是耳熟能详。
进入1990年,Scrum这种,近几年应该也是略有耳闻,可是像极限编程
这种可能就很少听说了吧。
再向后看,进入2000年,持续集成
也就是CI/CD
中的CI和敏捷开发
近几年炒的火热,互联网公司争先恐后,kanban
(今天公司产品说,我才知道kanban是日本人发明的)也有点大势已去,不过市场上应该还有不少公司在使用kanban。
走到了2010年,我们所看到的应该就是几个随处可见的概念了,持续交付
,DevOps
,Scrumban
(我们近几年说的真正意义上的Scrum)
在这里不详细叙述,只叙述几个痛点。
敏捷软件开发(英语:Agile software development),又称敏捷开发,是一种能应对快速变化需求的软件开发能力。它们的具体名称、理念、过程、术语都不尽相同,相对于“非敏捷”,更强调程序员团队与业务专家之间的紧密协作、面对面的沟通(认为比书面的文档更有效)、频繁交付新的软件版本、紧凑而自我组织型的团队、能够很好地适应需求变化的代码编写和团队组织方法,也更注重软件开发过程中人的作用。
说人话,就是更注重沟通,快速产出新版本,并且更适应需求变更的的适合小团体开发的方法。
下图左方,是需求池的概念(比如jira中的backlog),比如7%的需求是现实中大量客户的需求,则我们将这7%的需求作为优先级最高的需求。
下图右方,是迭代和反馈的概念。
敏捷开发中有敏捷宣言,可以更好地阐述敏捷开发的概念。
下图右上方是Scrum中的角色定义。
下图左方是用户故事
(user story
),其实就是我们传统意义上的需求,只不过以一种需求方的更委婉拟人的语气来讲述该用户人群的需求。
例如:我是一个买家,我希望我的购物车能通过价格排序,这样我就能根据我卡中的钱进行合理的消费。
下图中部,则是Scrum的核心流程。有很多公司光注重了其中的流程(比如站会),却没有得到其中的精髓。Scrum中把一个迭代叫做一个冲刺
(Sprint
),这也是很多地方把计划会议叫做冲刺会的由来,一般一个Sprint为1~4周。核心流程包括4个会议,如下所示:
Sub Task
Story Point
(用以评估story的大小,有一种好玩的方式叫做Scrum Poker
)极限编程
是敏捷开发中最具成效的几种方法之一,如同其他敏捷方法,它和传统方法的本质不同在于它更强调可适应性能性以及面临的困难。
它的基础和价值观是:
它认为任何一个软件项目都可以从四个方面入手进行改善:加强交流;从简单做起;寻求反馈;勇于实事求是。
下图是极限编程的13个最佳实践。
问问自己下面的几个问题:
如果你对上述几个问题的回答时肯定的,那么恭喜你,你们的团队是关注发展的敏捷团队,如果你对上述问题有部分或全部否定,那么你可能需要调整你的团队,你们只不过是在关注敏捷的形式,而没有精髓。
DevOps
是一种开发、测试和运维之间文化沟通,通过自动化的方式来进行软件交付和架构变更的流程,使构建、测试、发布软件能更快捷、频繁、可靠。它的出现是因为软件逐渐的认识到,开发、测试和运维的紧密合作可以更好的交付软件产品和服务。
下图是DevOps的标准化流程,通过建立一个完备的团队来建立一条IT服务供应链,通过自动化实现高效率交付,不固定需求管理、工具链等,只专注于持续的稳定的价值交付
这一步工作法是关于从开发到运再到客户的自左向右
的工作流
下图展示了自循环工作流的流程,其中前4项属于Dev范畴,后4项属于Ops范畴:
下图左方是我们针对上面的工作流的一种实践,是一种工作日志的方式,这种工作方式同样适用于敏捷开发(jira中的工作日志),其实DevOps的本质就是敏捷开发。
通过上方工作日志所记录的数据,我们可以对我们的工作进行阶段性的分析,比如:
平均前置任务等待数
可以用来判断我们的任务分配是否合理手工比例
可以用来提示我们是否需要使用自动化来优化流程%C/A
可以用来判断一个人的工作质量是否需要优化xxx feature branch
xxx fix branch
这种方案是基于GitFLow
的标准来进行版本控制的。
该方案采用develop
、feature
、hotfix
、release
、prod
等分支进行实践,比较适合版本并存的团队
这种方式很灵活,代码隔离也很好,只是过于繁琐。
该方案是基于版本打tag的方式来进行版本控制的。
该方案采用master
、feature
、fix
等分支进行实践,比较适合小版本滚动升级团队
这种方式很简单,但是对多环境的支持不是很好。
我们推荐使用GitFlow+Tag的方式来进行版本控制。以触发多环境下的pipeline自动化流程。
这里主要是我们的CI/CD的流水线的结构,可已使用Jenkins
的pipeline也可以使用Gitlab
的pipeline。
这里链接下之前写的Jenkinsfile教程(Jenkins Pipeline 教程)
自动:
手动:
看过了上面的部分,你一定嗤之以鼻,因为下面的图其实就是上面的Scrum图+Pipeline的图。其实下面你的这张图才能真正意义上的指导我们如何在工作中实践Scrum+DevOps。我将下面的图分层了4块,让我们一起看看下面的图吧
第一部分的需求池的这个概念我们在上方的Scrum中已经看到了,在这里不做详细解释,如果记不太清了,可以回到上方#1.3.1 进行复习。
第二部分的Scrum流程需要我们再来回顾一下,一个迭代中的4个会议还记得吗,不记得就回去看看吧,通过小迭代来进行可持续的速度小型发布,其中要落实XP的13个实践,包括集体所有权、简单设计、重构等等。
通过代码版本控制来触发我们的的CI和CD的构建。
通过发布编码标准,测试驱动开发,代码riew等来提升我们的代码质量以进行优质的代码持续集成。
在持续集成之后,迎面而来的是构建、测试、部署,这几个步骤的才是真真正的表现我们的团队的持续交付的质量。
在3和4两个步骤,我们会看到下方有包含对号和错号的表格,这个我们会在接下来的地方讲到,这个是个CI/CD反馈表,用来表示我们某个阶段的CI/CD的缩略情况,可以通过这个反馈来进行相关的分析。
下方的图是CI/CD的持续反馈图,可能做过Jenkins的Pipeline的小伙伴已经能看出它了。
顶部的“表头”其实就是我们的Pipeline的流程,而每一行是我们的历史构建记录,通过这张图我们可以清洗的看到我们在某一阶段的pipeline的执行情况,就可以看到我们在哪一个节点发生错误的情况比较高。
在这个流程中最重要的就是测试部分,如果我们的团队对包括单元测试在内的测试环节如果不是很重视,那这个反馈将对我们的团队毫无意义。
在DevOps中,我们推崇测试驱动开发,通过先写单元测试,集成测试等用例来驱动我们的开发进行编码。
这里的制品的含义就是我们所构建的,比如java的jar,golang的native,docker的docker image等。
通过DevOps的反馈,我们可以查看制品所在的story的目前阶段
让我们再来看下面这张图,对比上面的那种图,在我们的编码、测试、部署三个阶段多了个小锤子的标志。
这里的编码、测试、部署,分别代表着开发、测试、运维,三个岗位需要不断的尝试、配合和重复学习来让这条IT服务供应链更快速更稳定更自动化,让信息反馈更精准、更全面的覆盖到整个服务生命周期。
首先画一个由x轴支持评价和y轴业务技术导向组成的四象限,我们将我们DevOps中的所有种类的测试流程放入其中,来将每一个测试落实在一个二维区间内,再在每一种测试上标识一个工作投入程度,组成下面的图。
我们之前提过,在XP极限开发中,我们推崇测试驱动开发,因为测试驱动开发可以让我们在开发之前更加深入的理解业务,并且基于接口定义程序,更好的组织我们的软件架构。
所以下图是我们的测试流程应在我们的工作中所占有的工作比例,如果所有的工作经历为100%的话,那么6颗星则为60%,每颗星占据10%。
良好的开发习惯,和标准的测试流程可以让我们的代码质量更上一层楼。
上面我们说了测试的四象限,这里我们说说运维的四象限,我们以紧急性为x轴,重要性为y轴,这个四象限其实是很多工种的人都会使用到的,会将我们每天的任务放到里面,用来确定任务的优先级,我们知道基于这种四象限,我们的优先级会有下方四种:
我们将运维的工作放在上面,如果大部分的工作都落实在紧急且重要的第一象限上的话,那么说明我们的DevOps流程是有问题的,比如我们的运维的大部分精力都在每天的线上紧急修复之类的任务,就说明我们的开发和测试的质量是有问题的。
运维的工作不应该重点在右方,而应该重心左移,偏向于重要不紧急,多做一些规划性的工作,比如从传统部署方式转向k8s容器编排等工作。
在上面我们将上面说讲述的知识合并起来,组成我们真正在工作中实践所要用到的东西。Scrum+XP+DevOps
小团队内部要做到:
公司级别:
定义每种语言的标准的目录结构,比如下方的目录结构就是Node.js的标准目录结构,我将一些语言级通用的结构用红框画了出来。
下图使用的是基于Tag的版本控制,我这里看推荐使用GitFLow+Tag的方式来进行基于Tag多多环境的版本控制的方式进行构建使用。
下图中的快速失败的概念是指当pipeline中某一节点未达到通过的要求,则不再运行之后得节点,以当前节点的失败为整个pipeline的失败。
像jenkins原生就兼容快速失败。下图是jenkins最新的Blue Ocean界面,很友好的。
在第二工作法中,我们学习到了反馈工作流,如果使用jenkins构建pipeline的时候,我们就可以通过jenkins原生支持的可视化结果来了解到我们近期的CI/CD情况。
在我们的产品设计中,有一个MVP
的概念,它的意思是最小可行产品
,这个概念来自于《精益创业:新创企业的成长思维》这本书中,书中提倡首先定义一个面向市场的最小可用的极简原型产品,然后再不断的试验和学习中,以最小的成本和最有效的方式来验证产品是否符合用户需求,灵活调整方向,以达到“快速失败,廉价失败”的方式来验证产品是否符合市场需求。这是一种不断学习,挖掘用户需求,迭代优化产品的方式。
我们对待我们的团队,其实也要像对待我们的产品一样,不停地学习,不停地尝试,不停地优化,这样让我们的团队快速成长,要允许我们的团队犯错(但是不能重复掉进相同或相似的坑中)。
通过良好的测试+自动化流水线来提高我们的代码的质量
在部署前:
部署后测试:
通过配置中心来区别应用在各个环境中的配置,以防止出现踩到带着开发测试的配置上线的这种老旧坑。
制品库推荐也同样隔离开,预发和生产使用同一个制品库,开发和测试使用同一个制品库,在两个制品库之间,需要人为来审核和同步。
这里的流程控制主要指的是CI/CD的流程控制。因为我们都知道jenkins单节点在同一时间自由一个pipeline能构建,也就是说单节点jenkins不能多条pipeline并发构建。所以我们需要搭建分布式的jenkins集群,来对pipeline的构建进行调度。
另一种更好的方式就是通过gitlab或其他支持并发pipeline构建的工具进行构建。
下方的pipeline中在测试环节分成了三个分支,这个特性我们再使用jenkins的pipeline时是有完美支持的,名字叫并行流,是根据条件来判断三个分支是否进行的。
我们的服务上线后,我们需要使用两种方式来确保我们线上使用的服务能够健康的提供服务。
通过采集我们的线上的服务的日志,来对线上日志进行分析,达到实时监控服务健康情况的需求。这里推荐使用市场较为开放通用的开源方案ELK
我们同时还要对我们的中间件,流量,物理硬件等进行相关监控,以确定基础环境的实时监控情况,这里我推荐使用Prometheus+Granfa进行监控。
当我们的应用日益复杂且用户量逐渐提高后,我们需要对我们的服务进行容灾配置以及周期醒的混沌工程演练。我们的服务应该像下图一样逐渐进阶为可用性更高的部署方式。
我们永远都不能问心无愧的拍着胸口说我们的服务非常的问题,可用性能达到100%。因为100%是我们的服务的可用性极限,就算我们的服务可用性做到6个9,8个9,但是永远也达不到100%,永远只能无限的趋近于100%。因为我们永远都没办法避免黑天鹅事件。但是我们能做的是出现黑天鹅事件后,我们要快速响应,将我们的损失降到最低。下面就说说当出现线上故障的时候,我们应该怎么做才能更好的减少我们的损失。
事故发生前(凡事有预案):
事故发生时(先通报,后处理):
事故处理中(先止损,后查因):
事故处理后(反思,定级):