DevOps From Agile To DevOps - 微软开发部门 DevOps 经验谈

laofo · 2017年10月16日 · 4 次阅读

微软 MSDN 开发社区 DevOps 2017-10-13

在2013年11月13日,我们正式发行了 Visual Studio 2013,以及全新的 Visual Studio Online 服务。但在服务发表之后,Visual Studio Online 却发⽣了异常,造成七个小时服务中断,这是因为在服务上线时,我们没有预想到它会⾯临如此大的流量冲击,所以仅使⽤⼀个扩展单元(Scale Unit)来运行我们的服务,但在欧洲和美国的服务上线时,我们的系统遭遇了流量的顶峰,必须要同时提供服务给上百万的使⽤者,系统不足以乘载这么大量的使用者导致服务中断。在技术上来说,这次的上线过程可说是⼀个⾎淋淋的惨痛经验,就算我们拥有许多已经开发完成,但暂时透过功能开关(Feature flag)隐藏,等待着推出给使⽤者的新功能,却无法监控服务与服务的网络层级问题,才会造成在线服务中断,这些监控机制其实对我们来说才是最重要的,也因为这次的教训,这些机制马上被我们列入接下来的主要开发项目中。

图一, Visual Studio 2013 发表时, Visual Studio Online 因为过⼤流量造成的服务中断,但在市场层⾯来说,这次的服务发表其实是非常成功的,因为 Visual Studio Online 的使⽤者每个月以成倍速度成⻑。(而且在接下来的一年中,使⽤服务的⼈数持续成⻑,已拥有超过两百万名使⽤者)

在新功能开发与在线维运中取得平衡

⼀开始,Visual Studio Online 只有使⽤芝加哥数据中心的⼀个扩展单元(Scale Unit)提供服务。我们当然知道服务如果要能够稳定运行,必须具备横向扩展(Scale out)到多个地区的能力,也要让每个地区的部署可以独⽴进⾏不互相干扰,但总是有更多重要的新功能等着我们开发,让我们不得不将这些事情往后排。⽽在经过了 Visual Studio Online 上线时惨痛的教训之后,我们决定推迟新功能开发,优先专注在提供稳定的服务上,我们调整了 Visual Studio Online 部署更新流程,改为使⽤循序渐进部署(Canary Release)⽅式。不变部署到芝加哥数据中心的动作,⽽是在部署到芝加哥数据中心之前,增加⼀个部署阶段,称之为 SU0 (Scale Unit 0)。 在新的流程中,每⼀个 Sprint 开发完成之后,都会先部署到圣安东尼奥(SU0),也是我们工作所在地。然后我们会在内部进⾏⼀⼩段时间的新功能试⽤,当功能都没有问题时,才会进行下一阶段部署到芝加哥(SU1)。而如果我们在 SU0 遇到问题时,我们就可以实时停⽌部署过程并回头修正问题,不会影响到其他部署单位的服务。在这之后,我们也陆陆续续把其他 Azure 数据中心加⼊我们的部署流程,在 2014 年秋天时,我们加入阿姆斯特丹部署阶段(SU5),很快地我们将要增加澳洲作为下⼀个部署阶段。我们主要是透过 Visual Studio Release Management 来处理整个部署流程,也透过 Release Management 来将产品部署到全世界。

图⼆,在 2013 年 11 月, Visual Studio Online 由单一数据中⼼扩展为多个,这让我们可以进⾏循序渐进部署( Canary Release )及提供服务到全球。

在下图中可以清楚看到我们一直强调维持在线服务质量的结果。在 2013 年 11 ⽉时是 43 LSIs,⽽在六个⽉后,我们已经减低到了 7 LSIs,并且只有两个是公开的服务,我们也持续在 DevOps 上学习成长,让我们提供的服务更加稳定。

图三,相较于 6 个⽉之前 (2013 年 11 月 ) 发⽣了 43 次 LSIs,Visual Studio Online 在 2014 年 4 ⽉只发⽣了 7 次 LSIs ,只有 2 个是发⽣在公开的功能中。

从 Agile 到 DevOps 的过程

微软拥抱 Agile 超过七年,并汲取了 XP(eXtreme Programming)的精华,使⽤更为 SOLID 的⽅式改善了超过 15x 个技术债。我们透过 Scrum,搭配跨部门或是不同的产品线协同合作,来训练每⼀个团队成员,并专注在创造对于客户更有价值的产品,这也让我们在推出 Visual Studio 2010 时,在客⼾中获得了空前好评。 在发表 VS2010 之后,我们知道是时候开始将 Team Foundation Server 转换为 SaaS 服务了。我们决定使用 Azure 作为 SaaS 版本的 TFS(也就是现在的 Visual Studio Online)的服务运⾏平台,这也代表着我们必须开始把资源投注在 DevOps 上,也必须将我们过去使用 Agile 的经验,延伸到 DevOps 之中,但这两者⼜有什么差别呢?在使用 Agile 时,⼤家往往习惯遵循经验丰富的 Product Owner 规划,有经验的 Product Owner 也会准备好 backlog 让⼤家进⾏开发。相较之下,DevOps 的精神可以说是从使用中学习。

在 DevOps 的开发流程中,我们会直接开发具有实验性质的新功能,发行到正式环境并收集用户对于这些功能的使⽤状况及反馈,以此为基础来决定下⼀轮 backlog 的内容,同时也由于在 DevOps 中,发⾏新功能是没有负担⽽且可靠的,所以我们可以经常的进行新功能的部署,快速的开发新产品或是测试市场反应的新功能,并且很迅速的从第一线使用者的使⽤体验中得到回馈,再将所获得的资料作为规划下一轮 backlog 的基础。相较于在传统的软件开发流程,我们总是会假设性的进行产品⼤范围的规划与使⽤情境想象,再经过漫⻑的开发过程,最后才能投入到市场一次定生死, DevOps 讲求的是直接根据市场反应来修正产品的功能,与其不断假设用户可能的需求以及行为,DevOps 会直接开发新功能,投⼊市场取得产品营运的状况以及使⽤者的回馈,马上根据这些回馈修改⾃己产品来更贴近用户。这也让产品开发的⾵险⼤大降低,缩短从开发到获得市场反应的时程,并且可以实时修正产品方向,让产品永远是针对使⽤者的需求提供服务。

在图四之中,DevOps 延伸了 Agile 的四个准则进⾏开发。

图四,从 Agile 延伸到 DevOps 。

和大部分一开始就提供云端服务的公司不同,我们并不是一开始就有提供 SaaS 版本的服务,大部分的客⼾原本都是购买软件在⾃己公司内部使用(像是 Team Foundation Server,从最早的 2005 版本到目前最新的 2015 版本)。⽽在我们决定开发 Visual Studio Online 时,我们决定让云端和地端版本的 Visual Studio Online 使⽤同⼀份程序代码基础进行开发,并优先进⾏云端部分的功能开发。当⼯程师签入程序代码时,会⾺上触发持续整合的流程进行软件建置、自动化测试及检查。每三周 Sprint 结束之后,我们就会更新云端版本的产品,在 Visual Studio Online 中提供新功能给使⽤者抢先使⽤,累积了 4~5 个 Sprint 后,我们就会发⾏地端版本 Team Foundation Server 季度的更新 Patch 檔。(参考图五)不论在 Agile 或 DevOps 之中,持续整合(Continuous Integration)的机制都是十分重要的,我们可以设定持续整合服务器在程序代码被签入时第⼀时间被执 ⾏,并同时进⾏程序代码建置、⾃动化测试及产⽣程序代码质量报告,让我们在第一时间确认被签入的程序代码是否有潜在风险,也让问题可以在第⼀时间被解决,这么一来可以避免掉许多以往系统上线时可能发生的环境问题,甚⾄是产品部署问题,随时确保版本控制系统(Version Control)中的程序代码是可靠的。并透过自动化让程序代码维持水平时,也不会增加⼤家开发的负担。

图五、我们使用同一份程序代码来同时满足 Visual Studio Online 和 Team Foundation Server ,每三周会将最新版本的 Release 发行到 Visual Studio Online ,每⼀季发⾏一次 TFS 的更新。当我们发行 TFS 的主要更新时,其实也是由⽬前 Visual Studio Online 功能⽽来的。

控制功能曝光对象

当你开始使用 DevOps 的流程经营一个服务时,你会开始习惯频繁的发⾏新版本,就像我们在开发 Visual Studio Online 时,每隔三周(⼀个 Sprint)会发行⼀次最新的版本到在线服务。这也同时让我们有很多将新功能曝光的机会,因此我们必须对于要能够让哪些⼈看到这些新功能进⾏管理,以下是⼀些⽐比较常⾒的问题: 1.如何开发跨 Sprint 的需求? 2.如果有功能必须调整时,我们如何透过实验来获得使用者的操作体验以及反馈(例如 A/B Testing)? 3.如何在你准备好将产品推出到市场之前,隐藏在线的新功能不被使⽤者发现?

基于以上这些原因,我们开始使⽤用了⼀个叫做功能开关模式( Feature flag pattern )的方法来控制新功能要让谁可以使用。功能开关其实是⼀种算法,用来控制所有正式环境中的功能可以被谁看到。当团队开始开发一个新功能时,你可以在功能开关服务( feature flag service )注册这个功能,它默认是关闭不会被任何⼈人看到的,而当你的功能开发完成,准备好给某些⼈试用时,你可以在正式环境中针对特定使用者或群组开放你的功能。当你想要修改某个功能时,你只要关闭它的开关,不需要经过任何在线版本的发⾏或更动,就可以让这个功能不会被任何⼈人看到或使用。 透过控制各种功能的开放与关闭,使用功能开关(feature flags)也提供了一个在正式环境进行测试的⽅法,我们通常会先对⾃⼰⼈开放新功能进⾏开发或测试,再来开放给先⾏使⽤者们试用,最后都没有问题才会开放给其他⼤部分的使用者。透过功能开关,并搭配观察新功能在在线运行的效能和使⽤者的使用状况,可以让我们确保新服务不会有意料之外的问题发⽣。 ⽽在某些⾓度来说,其实这也是循序渐进部署(Canary Release)另⼀⽅面的延伸,不会让系统存在潜在风险时(例如在在线环境时某些被期待的功能无法顺利使用),就一次⾯对大量的使用者,⽽造成⼤部分使用者不好的使用体验,而是透过逐步开放的⽅式,让⼤多数人的使用者体验都是好的,若有问题也能实时停止开放,修正后再提供给使用者。

暂无回复。
需要 登录 后方可回复。