本文作者:敏捷DevOps首席布道师赵卫,他将于10月15-16日,在首届EE卓越工程生产力大会上为我们分享《京东精益创新的底层逻辑》的话题,文末扫码即可获得开幕式观看资格。
1、前言
2、什么是部署与发布
3、什么是持续部署
4、持续部署实践
蓝绿部署滚动部署黑启动5、按需发布实践
金丝雀发布灰度发布A/B测试6、支持不同发布方式的技术实现
特性开关特性分支抽象分支7、非死不可Facebook的案例
8、总结
9、参考
前言
敏捷DevOps的一个主要目的是要达成持续的最短的周期进行价值交付,这就离不开快速的部署和发布。那么问题就来了,部署和发布到底是一个概念还是不同的概念?有哪些常见的部署和发布策略?本文将会剖析不同的概念,以及介绍不同的部署和发布的策略,在文章的最后,会对所有的策略和技术进行总结。
什么是部署与发布
在谈持续部署之前,让我们澄清一下什么是部署,什么是发布。
01
在互联网和SaaS之前的时代,通常是,先有发布(Release),再有部署(Deployment)1、发布研发团队发布一个版本,代表着开发完成并且测试完成是一个可以销售的软件,也代表着这个软件的上市将软件售卖之前,需要把版本复制到软盘、U盘或者刻录到光盘上,通常叫做发布到工厂(RTM,Releasetomanufacturing)软件正式上市售卖代表着软件已经GoneLive,上线2、部署如果是面向个人的桌面系统软件,那么由个人担当部署的人员,将软件(来源于软盘、光盘、U盘)进行安装,安装后自行进行配置如果是面向企业的软件,那么由甲方的IT工程师负责安装和配置,或者是由乙方的服务人员负责安装和配置还有另外一种情况,在甲方真正安装和配置软件之前,有一个用户验收测试(UAT,UserAcceptanceTest),在甲方的机房,先安装和配置一套,然后由甲方进行测试,如果测试通过,代表验收成功,就可以正式的去安装和配置02
在互联网、移动互联网和SaaS时代,通常是,部署就代表着发布1、发布用户能看见软件或者直接使用软件,概念上和互联网之前的年代是一样的,目的都是上市通常是将一个版本发布到网上(RTW,Releasetotheweb)或者叫做网上发布(Webrelease)在中国互联网行业,通常称之为上线(Releasetoproduction)2、部署部署变成了将软件包发布到生产环境的一个动作,或者是一个步骤即通过部署的动作,达成了发布的结果03
敏捷DevOps时代,部署和发布解耦,变成了持续部署,按业务需要发布1、持续部署持续的,自动化的,将软件包发布到生产环境SaaS和网站类型的,就是直接部署到网站上移动应用App类型的会通过各种APP分发渠道,发到应用市场,例如苹果的AppStore,安卓的各种应用市场2、按需发布根据业务需要,发布功能发布,代表用户看见软件或者可以直接使用软件的功能,即releasethefunctionalitytoendusers3、补充说明对于一些ToB的企业级软件,例如电信行业,通常是软件+硬件整体销售给运营商(例如中国移动),仍然会涉及到发送硬件(例如交换件、路由器)到运营商,然后设备商(例如华为)的服务人员在客户现场进行机房、硬件等的安装和配置,之后才会割接上线而年建立的开放网络基金会开始在业界大力提倡软件定义网络(SDN,Software-definednetworking)和OpenFlow协议,在一定程度上解耦了软件和硬件,那么DevOps的理念就有可能被达成,例如在华为生产的软件通过网络直接在中国移动的网络上升级软件如下图所示,是规模化敏捷框架SAFe(ScaledAgileFramework)的持续交付流水线,部署和发布是解耦开的,部署不意味着用户可见,发布才是功能对用户可见,部署仅仅是将软件部署在生产环境,新的代码变更对于用户来说还是“黑/暗”(dark)的。
让我们正式的定义一下部署和发布,《DevOps实践指南》的定义如下:
1、部署
是指在特定的环境中安装指定版本的软件(例如,将代码部署到集成测试环境中,或者部署到生产环境中)。具体的说,部署可能与某个特性的发布无关如果部署与某个特性发布有关,部署后即时生效,即代表着发布,部署=发布
2、发布
是指把一个特性(或者一组特性)提供给所有客户或者一部分客户(例如,向5%的客户群开放特性)。代码和环境架构要能够满足这种要求:特性发布不需要变更应用的代码。
部署和发布是解耦开的,也就是:让部署可以独立于发布单独进行;而特性部署后,业务可以灵活决定什么时候发布,向哪些目标客群发布。如果部署周期过程,就会限制向市场频繁地发布新特性的能力。如果能做到按需部署,或者持续部署,那么什么时候发布新特性,就成了业务和市场决策,而不再是技术决策,所以部署是技术范畴,而发布时业务范畴。
什么是持续部署
持续部署(CD,ContinuousDeployment)是将在预发、类生产环境中经过验证确认的特性部署到生产环境的过程,部署后这些特性就已经就绪,需要发布的时候随时发布。
按需发布(ReleaseonDemand)是团队和企业的关键能力。按需发布使得业务具备持续的在最短的前置时间(LeadTime)内,以高频率的方式,让客户使用新功能,从而通过高价值方案响应市场机会。
为了支持业务具备按需发布的能力,特性在业务需要它们之前,必须在生产环境得到验证和等待发布。所以需要将部署过程优化并从发布过程中分离出来,这样将代码变更部署到生产环境,并不会影响整个系统的行为。持续部署的能力使团队可以进行更小的增量的代码变更,并持续地部署到生产环境,但是并不发布,直到业务需要的时间才正式发布给客户。
而对于持续部署的“持续”,每个公司的程度是不一样的,例如,亚马逊年5月的部署数据,在工作日平均每11.6秒部署一次,一个小时部署最多的一次是部署了次部署,一次部署平均部署到一万台云主机,最多的时候一次部署是部署到三万台云主机。
如下图所示,《凤凰项目》提到国外的一些大厂年的部署频率和每次部署花费的时间(DeployLeadTime)。
笔者于年在苹果的AppStore查看了国内各大主流IOSAPP的版本发布情况,大多数的APP是在2周以内发布一次。
拿京东来说,在APP市场,大多数情况下,京东商城APP是两周一个版本,京东金融APP也是两周一个版本。对于京东的服务端的发布,基本上是每周有两次上线窗口进行小批量的上线,当然对于紧急的线上问题的修复根据情况随时上线。
如下图所示,《发布!设计与部署稳定的分布式系统第2版》提到:部署间隔时间有更长的延迟,将会导致每次的部署包含更多的代码变更,结果就是出现更多缺陷和宕机的风险,因此会增加更多的评审环节,那么又大大增加了部署之间的间隔时间。这是一个越来越差的增强回路。正如《发布》这本书所说的“如果每次部署都很痛苦,那么就频繁多次做”,所以高频的持续部署可以颠覆这个恶性循环,并且从以上国外大厂和国内大厂发布的频率来看,充分说明持续的部署是业务按需发布的必要条件。
持续部署实践
01
蓝绿部署(Blue-GreenDeployments)蓝绿部署是指有两个完全相同的、互相独立的生产环境,一个叫做“蓝环境”,一个叫做”绿环境“。绿环境是用户正在使用的生产环境。当要部署一个新版本的时候,先把这个新版本部署到蓝环境中,然后在蓝环境中运行冒烟测试,来检查是否正常工作,当一切准备就绪以后,向新版本迁移就非常简单了,只要修改一下路由配置,将用户流量从绿环境导向蓝环境就可以,这个时候蓝环境就变成了生产环境,这种切换通常在一秒钟之内就能搞定。如果出了问题,把路由器切回到绿环境上即可,然后在蓝环境中调试,找到问题的原因。所以蓝绿部署,是在部署之后,仅仅一次切换,立刻就向所有用户推出新版本,新功能对所有用户立刻生效可见。
如果由于成本和投资回报的考虑,不能建设两套完全一样的生产环境,那么可以将蓝环境作为预发或预生产环境,将软件的新版本部署在预发环境,并进行验收测试,之后将访问流量引流到这个预发环境,那么蓝环境就是正式的生产环境,同时保持旧版本所在的绿环境不变,直至新版本没有问题后,再将旧版本所运行的环境作为下一个新版本的预发环境。
蓝绿部署中,如果是保持两份一样的数据库,需要处理的问题是数据库的问题,一个是如何快速复制数据库,一个是涉及数据库的事务时如何处理数据的一致性问题。
在电信行业中,通常需要保证99.%的时间是服务可用的,所以通常会投入冗余的设计和实现,例如一个设备的双CPU、双存储、多个板卡等,双机主备等,网络建设的时候进行冗余设备的设计,通信链路有保护协议时刻进行心跳式的检测,如果某个链路数据不通,就自动切换到另外的链路等等。例如交换机或路由器有两个CPU,一个是主,一个是备,主备之间内存使用内存数据库进行同步,备机如果内存数据库被更新了,就立刻同步到备机的持久化存储中。这样可以保证设备如果有问题的时候主备之间进行切换,同时可以被用来零停机部署、不中断业务升级(ISSU,In-ServiceSoftwareUpgrade)在standby备机CPU中升级到新版本,再将其切换成主服务CPU,而原来的主活CPU变成了备机待机状态,再将其升级,这样既不影响实时业务,又升级了新版本。
那么在非电信行业,可以考虑两套环境使用同一个数据库,降低技术复杂度和节约成本。
02
滚动部署(RollingDeployment)滚动部署是指从服务集群中选择一个或多个服务单元,停止服务后执行版本更新,再重新将其投入使用,循环往复,直至集群中所有的服务实例都更新到新版本,而不是将所有的服务实例一次性的同时更新。
滚动部署分批进行部署,每次同时更新的服务实例数称之为窗口大小(Windowsize),根据需要配置每个批次服务实例的窗口大小,例如首先部署2%的服务实例,第二批为10%,第三批为50%,第四批为%。
03
黑启动(DarkLaunching)黑启动原意是指将新版本部署到生产环境后,对用户无感。所以黑启动意味着暗部署。
当然,黑启动终极目的还是为了发布,对原有黑启动含义扩展之后,就会先让小部分用户感知新功能,再逐渐扩大感知到新功能的用户范围,那么黑启动就代表发布。
如下图黑启动的本意所示,马丁·福勒(MartinFowler)在黑启动文章提到,黑启动针对的是后端行为,后端系统部署在生产环境之后,现有用户使用前端界面的时候,新部署的后端功能被调用,但是用户并没有感知,可以对新功能的性能进行监控。也就是说用户和系统的交互逻辑保持不变,用户在界面上没有地方选择新部署的功能,也就是对用户不可见。
《持续交付2.0》的例子如下图所示,用户对新算法的使用是无感知的:
对黑启动本意的扩展,是正式发布给所有用户之前发布给部分用户的过程。黑启动将部署和发布解耦,部署之后,发布给部分用户,这样可以获得部分真实用户的反馈,测试缺陷,评估基础设施性能等。黑启动的黑(Dark)代表用户无感知,也就是新版本的功能已经被部署到生产环境,但是用户无感知:
1、企业并没有广而告之声明有新版本发布,用户不知道软件已经升级,并且只有发布给选定的小部分用户,他们才能感知到新功能
2、用户不知道被选定在测试新功能,例如用户界面没有变化,仅仅是后端算法逻辑等发生变化
3、黑启动的另外一种做法,就是选定的部分用户实际上是公司内部员工,这样内部员工可以先吃自己的狗粮,对新功能进行测试,而真实用户并未真正使用新功能
贾斯汀·贝克(JustinBaker)描述了黑启动有如下几种场景:
场景A——我想发布一个实验性质的功能,验证下是否能增加总成交额GMV
要黑启动这个功能,先发布给1%用户给他们启动这个功能,然后再分别发布给5%,30%用户在这个过程中评估结果。如果结果是增加了成交额,就可以逐渐增加推出的百分比,否则可以简单地回滚该功能,以便进一步评估和优化这个功能
场景B——我想测试应用的新基础设施,而不必切换所有流量
在将所有流量切换到新的系统架构之前,可以通过专门用于配置管理的开关/标志(toggle/flag)切换路由流量,以黑启动新的基础架构。例如,假设要停止维护自己的队列系统并切换到托管服务。可能会创建一个标志,将一些作业发送到新的托管服务,同时仍将大多数作业发送到旧的队列系统(并且设置了守护程序来监听这两个作业)。然后,可以在监视性能和其他指标时逐渐过渡到全托管服务。这个发布策略和笔者年在敏捷中国大会参加会前KentBeck的响应式设计培训是一致的,KentBeck提到响应式软件设计的四个策略:飞跃Leap,并行Parallel,踏脚石Steppingstone,简化Simplification。针对风险比较大的重构或者新的基础设施,可以采用新老两套架构并行的方式,逐步迁移,并且两个架构同时向前发展,直到最终新架构代替老架构。
场景C——我想发布一个新功能给特定的人群进行β测试
新功能对原有用户与系统的交互逻辑进行了修改通过ID(例如邮件或者用户名等)来圈出特定的要进行测试的β用户群,黑启动新功能给这些特定人群,企业随时可以添加或者删除β用户。这种场景,被选定的用户群是可以感知新的功能的,这也被称作金丝雀发布,金丝雀发布时黑启动的一种类型
场景D——我想首先给我的VIP用户发布一个新功能
在全面发布给所有用户之前,黑启动允许向VIP用户推出新功能可以允许用户自己选择加入或者退出黑启动功能
黑启动按用户百分比分批发布,就是在国内互联网常用的灰度发布;黑启动仅仅针对部分机器、服务实例或者客群发布,就是金丝雀发布。
按需发布实践
01
金丝雀发布(Canaryrelease)软件行业的金丝雀发布这个术语来自20世纪初期英国煤矿工人在下井采矿之前会把笼养的金丝雀携带到矿井中,如果矿井中一氧化碳等有毒气体的浓度过高,在影响矿工之前,金丝雀相比人类表现的更加敏感快速,金丝雀中毒之后,煤矿工人就知道该立刻撤离。金丝雀发布,在将整个软件的新版本发布给所有用户之前,通过将新版本发布给部分用户,用真实的客户流量来测试,以保证软件不会出现严重问题,降低发布风险。
金丝雀发布也被称之为按阶段发布或者增量发布。
第一批金丝雀用户:先将新版本部署部分机器或者服务实例,并对部分选定用户开放第二批所有用户:之后再将所有其他机器或者服务实例进行部署,并对所有用户开放
如下图所示,《DevOps实践指南》的Facebook的金丝雀发布模式,采用了不同的环境组A1组,A2组合A3组。
A1组:仅向内部员工提供服务的生产环境服务器。A2组:仅向一小部分客户提供服务的生产环境服务器,在软件达到某些验收标准后部署(自动化部署或手动部署均可)。A3组:其余的生产环境服务器,软件在A2组中达到某些验收标准后再部署。
金丝雀发布通常包括以下步骤:
1、暂存用于部署的工件,包括:构建工件,测试脚本,配置文件和部署清单。
2、从负载均衡(LoadBalancer)中删除“金丝雀”服务器。
3、在“金丝雀”服务器上升级新版本应用程序。
4、自动化测试应用程序。
5、恢复“金丝雀”服务器连接到负载均衡(连接性和完整性检查)。
6、如果用户实时使用情况下的“金丝雀”测试成功,则升级其余服务器。(否则回滚)
金丝雀发布,可以结合滚动部署一起使用,例如上图的A3组,如果服务实例或者机器非常多,可以滚动的部署。
02
灰度发布(GrayRelease)灰度发布是在金丝雀发布基础上进行延伸,不是将发布分成两批,而是将发布分成不同的阶段/批次发布,每个阶段/批次的用户数量逐级增加。如果新版本在当前阶段没有发现问题,就再扩展用户数量进入下一个阶段,直至扩展到全部用户。
如下图所示,《持续交付2.0》提到的金丝雀发布与灰度发布示意图。
灰度发布,可以结合滚动部署一起使用,通过分批部署,部署即发布,来让部分客群可见;灰度发布,需要结合特性开关等技术,做更复杂灵活的灰度。
03
A/B测试(A/BTesting)简单来说,A/B测试是针对用户的需要,提供两个版本的功能,一部分用户能看到版本A,一部分用户能看到版本B,经过对比实验,得出哪个版本更优的测试过程。
A/B测试基于科学方法,对假设进行对照实验,即其他条件相同,只有一个条件不同的实验。
1、实验目标:为同一个目标(例如优化转化率或改进某些业务指标等)
2、实验变量:针对单一变量(例如页面的按钮颜色发生了变化)
3、实验方案:制定两个版本(即A和B两个变体),在总体用户中取出一小部分,将这部分用户完全随机地分在两个组中,使两组用户在统计角度无差别,将两个版本分别展示给不同的用户组
4、试验分析:有可能版本A是老版本称之为对照组,B是新版本称之为实验组,收集对照组和实验组组对应的用户体验数据和业务数据,最后分析、评估出最好版本,正式采用。
虽然A/B测试名字中只包含A、B,但并不是说它只能用于比较两个版本的好坏,事实上,完全可以设计两个以上版本进行测试,比如A,B,C测试,即A/B/n测试,“A/B测试”这个名字只是一个习惯的叫法。
A/B测试对单一变量,例如一个页面、功能等测试两个不同版本,而多变量测试会使用更多变量进行测试,可以提供更多的洞察。
5、A/B测试的场景包括:页面交互变化对比、文案变化对比、页面布局变化对比、产品功能对比、算法调优对比等等。
A/B测试目的在于通过科学的实验设计、采样样本代表性、流量分割与小流量测试等方式来获得具有代表性的实验结论,并确信该结论在推广到全部流量可信。所以说,A/B测试和金丝雀发布、灰度发布的讨论维度是不一样的,A/B测试是发布之后,倾向于产品功能的受欢迎程度、可用性以及可见性等,而金丝雀发布、灰度发布等目的是安全稳定地发布新版本应用,并在必要时回滚。
支持不同发布方式的技术实现
01
特性开关(FeatureToggle/FeatureFlag)利用代码中的特性开关(FeatureToggle/Flag/Switch)来控制发布逻辑,在生产环境中不用编写代码,不用发布新版本,在线上运行时,通过开关,打开或关闭特性。
一般不需要复杂的发布工具和智能负载均衡(LoadBalancer)的配合,是一种相对比较低成本和简单的发布方式。
特性开关的原理如下图所示:
特性开关本质上就是一个“if…else…”的代码。而开关本身的配置可以是一个配置文件,或者是一个集中化的开关管理中心。
当开关关闭的时候,实际上体现的就是部署,将新版本部署到生产环境的时候,用户不可见,当打开开关的时候,功能对用户可见。所以特性开关很好的支持了将部署和发布解耦。同时特性开关的各种应用方式可以很好的支持黑启动发布,金丝雀发布,灰度发布,A/B测试等。
如下图所示,特性开关对所有人有效。这是最简单的一种方式,与20年前的License许可证方式类似,例如:
ToC的例子,所有的用户使用同样的单体软件部署到PC上之后,根据用户的购买的License,打开和关闭某些特性ToB的例子,电信行业,例如华为和中兴卖给中国移动的设备,在部署到客户网路之中后,不用升级软件,只要购买了新的License,相应的特性就会被打开
同时这种方式也可以支持持续集成的主干开发,所有开发人员在一个主干上开发代码,针对比较大的、周期长的、风险大的功能使用特性开关,可以保证主干出版本的时候,带上了部分未完成的代码,这些半成品代码通过开关关闭掉,发布给用户之后,半成品功能对用户不可见,也不会破坏已经完成的代码功能。
如下图所示,特性开关对选定的用户群有效。
如下图所示,特性开关可以增量的进行灰度发布,逐步扩大开关匹配的人员百分比。
与特性开关所配对的不同范围的客群,需要结合其他手段识别和分流,例如不同的设备id、user_id、pin、用户画像、地域、渠道(PC,