
无论从开发运维还是产品运营的角度来看,任何一次上线都是有风险的。从最基本的应用停止导致流量丢失、服务不可用、服务QPS水位下降,到步骤的遗漏、流程的不规范、开发过程中引入的bug,以及新产品/新功能上线导致用户体验的变化,都会导致线上风险。在日常和用户交流过程中,我们也经常会被用户问到关于发布的问题,比如不同职能团队之间应该如何配合、发布的最佳实践应该是什么样子的等等。今天我们就来聊聊常见应用发布方式的选择,以及每种发布模式适合什么样的场景。
分批发布通常指取出一例或多例应用实例,将其停止服务、升级到新版本;周而复始地重复这一过程,直到所有实例都升级到新版本。使用滚动发布,可以最大程度地避免因发布导致的流量丢失和服务不可用问题;这一模式也是Kubernetes应用部署使用的缺省模式。
针对部署规模较小、领域边界较清晰,同时面临业务快速发展变化的微服务应用,滚动发布流程简易且可靠性较高。不过由于通常情况下缺乏强干预手段,发布的可逆程度较差;一旦在发布过程中觉察到问题,往往需要进行全量回滚。
一般来说,滚动发布适用于符合如下条件的场景:
下面我们分别以ECS和Kubernetes为例,展示如何在云效平台上进行滚动发布。
在云效中,我们可以使用主机部署任务进行滚动发布。如图所示,假设需要对以下由2台ECS构成的主机组进行滚动发布,每次滚动更新1台主机:

在流水线中,配置主机部署任务:

设置“暂停方式”为“不暂停”、“分批数量”为2,即可实现滚动发布。

在进行ECS滚动发布时需要注意一点:通常情况下,滚动发布中的主机无法对外提供服务,这意味着集群整体服务水位(如可承接的QPS)会降低——例如在上面2台主机分2批发布的过程中,集群始终只有1台主机可以响应请求,整体QPS水位下降了50%。发布人员需要仔细评估“由于发布而导致服务主机不可用”对服务水位的影响,并选择合适的时间(如业务低峰期)进行发布。
YAML发布是我们在使用Kubernetes时最直接的应用部署方式。在持续交付流水线中,我们一般将这些用于描述Kubernetes资源的YAML文件通过Git进行统一版本管理,通过云效CI/CD平台监听代码库的变更事件,并通过流水线将这些YAML变更同步到集群当中。
例如下面的app.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: ${IMAGE}
ports:
- containerPort: 80
由于没有声明发布策略,Kubernetes会缺省指定RollingUpdate策略,也即滚动发布。
YAML文件中的占位符${IMAGE}是为云效流水线专门留出的替换变量,发布时会被替换成具体的镜像。
如下图所示,我们可以通过“Kubernetes发布”任务实现上述Deployment的滚动发布:

具体的发布进度,可以参考发布单中的展示:

在一些开发团队与运维团队分工较为明确的场景中,开发团队可能希望够尽可能少地理解Kubernetes相关概念,由专职的运维团队负责完成应用环境的部署和初始化;开发团队只负责完成代码开发,并通过流水线自动化完成应用镜像构建,并使用该镜像对集群中已有的应用进行升级。
如下图所示,在云效流水线中,我们监听应用代码库的变化,并构建出相应的Docker镜像;发布阶段只需要指定对集群中实例并关联前序任务产生的镜像,即可完成应用的升级发布。与YAML发布相同,缺省情况下,镜像升级也使用了滚动发布模式:

如上所述,该场景适用于:
分批发布通常指取出一批应用实例,将其停止服务、升级到新版本;人工观察实际效果符合期望后,再取出下一批;周而复始地重复这一过程,直到所有实例都升级到新版本。在滚动过程中,新旧版本共存且同等地接受流量、提供服务;发布人员基于对服务质量(如请求成功率、响应时间等基础指标,或特定的业务成功率等业务指标)进行观察,决定是否进一步扩大新版本部署比例,或是放弃发布进行回滚。
分批发布的基本模式与滚动发布相似,主要差异则在于允许人工控制新版本上线、老版本下线的过程。由于新版本的部署比例可控,发布人员可以预先制定批次部署计划,在少量部署的新版本上,基于生产环境流量进行小规模线上验证;若应用自身规模较大或逻辑较复杂,维持一段时间的小规模验证也能起到线上回归测试的作用。另一方面,人工控制部署批次使得发布整体具有较好的可逆性:一旦在小规模验证中发现问题,可以快速回滚已经发布的新版本。
分批发布通常适合:
在云效中,主机部署任务也可以被配置为分批发布模式,如下图所示:


我们可以通过指定“第一批暂停”或“每批暂停”,实现分批控制:
发布人员可根据应用的部署规模、重要程度及逻辑的复杂程度,选用不同的分批暂停模式。
云效的分批发布中,我们以Service为最小发布单元,在发布开始阶段我们将基于新版镜像创建出应用的版本V2,并根据当前应用的副本总数以及分批数量,对新旧两个版本的应用实例分别进行缩容和扩容,来控制实际进入到新版应用的流量比例,从而可以实现小规模的发布验证,在对发布进行充分验证后,再逐步完全下线老版应用。
与ECS部署类似,批次之间支持暂停和手动恢复,用以对发布过程进行控制。

该模式适用于:采用Kubernetes原生的服务发现机制,并希望获得相比于原生Kubernetes发布更好过程控制性以及安全性的用户。
较之滚动/分批发布,灰度发布加强了对线上验证影响范围的控制:通常需要以同样的实例数,部署新/老版本两套服务;再通过流量分发控制手段,将特定的线上流量导入新版本、其余流量仍然流入老版本;线上验证通过后,所有流量都将导入新版本实例,而老版本实例则可用作下一次发布的模板。
常见的流量分发控制手段如:
使用相对明确的规则进行流量分发控制,从技术团队的角度来看意味着进一步的变更风险控制:发布人员可以选定具有某种特征的请求,用于在验证新发布的功能同时,使得影响范围尽量容易识别。而从产品运营团队的角度来看,灰度发布除了可以更精确地控制技术风险的影响面之外,更重要的一点是可以辅助他们进行客户数据对比:举例来说,运营团队可以事先和某些有意向体验新功能的客户达成合作,使用灰度方式为他们开通新功能进行试用;另一类典型的例子则是A/B test, 通过灰度发布提供的流量控制能力,收集新/老版本的用户数据,用以评估新的设计是否更为合理。
灰度发布一般适用于:
由于Kubernetes生态提供了很多方便的流量管控手段,我们以kubernetes发布为例,展示如何在云效上进行灰度发布。
一种典型的对外接收流量的场景,是使用Ingress暴露服务。在云效流水线的Ingress灰度发布中,我们以Ingress作为发布单元,当触发部署后,将会根据当前Ingress以及其关联的Service/Deployment资源,基于新版镜像创建出V2版本的Service/Deployment,并通过Nginx Ingress的Annoation完成对流量规则声明,从而确保只有满足特定特征的流量才能进入到V2版本中。
例如在下图的流水线中,我们根据cookie匹配流量,进行灰度发布:

当处于灰度状态时,流水线将会等待人工验证,以触发发布或者或者回滚操作。

当采用微服务架构时,大部分的后端服务只在集群内部开放,微服务之间通过Kubernetes Service进行相互访问。在这种情况下,如果希望采用灰度发布模式,则需要在Service级别进行流量控制,以确保指定的流量进入到灰度的链路,而不对正常用户产生影响。
不过由于Kubernetes原生Service级别并不支持任何的流量控制规则,因此我们需要在集群中部署Istio或者采用阿里云ServiceMesh来对服务之间的流量进行细粒度的控制。
如下图所示,当使用Kubernetes蓝绿发布模式时,可以设置灰度流量规则,从而只有当请求中包含指定的Cookie配置的请求转发到灰度版本当中:

该模式适用于:采用Istio或者阿里云ServiceMesh的Kubernetes用户,并且希望能够通过灰度的方式对发布进行验证。
点击下方链接即可前往云效帮助中心查看详细操作文档。
https://help.aliyun.com/document_detail/224586.html
了解更多关于云效DevOps的最新动态,可微信搜索关注【云效】公众号;
彩蛋:公众号后台回复【指南】,可获得《阿里巴巴DevOps实践指南》&《10倍研发效能提升案例集》;
看完觉得对您有所帮助别忘记点赞、收藏和关注呦;
所以我开始关注ruby,很多东西看起来不错,但我对隐式return语句很反感。我理解默认情况下让所有内容返回self或nil但不是语句的最后一个值。对我来说,它看起来非常脆弱(尤其是)如果你正在使用一个不打算返回某些东西的方法(尤其是一个改变状态/破坏性方法的函数!),其他人可能最终依赖于一个返回对方法的目的并不重要,并且有很大的改变机会。隐式返回有什么意义?有没有办法让事情变得更简单?总是有返回以防止隐含返回被认为是好的做法吗?我是不是太担心这个了?附言当人们想要从方法中返回特定的东西时,他们是否经常使用隐式返回,这不是让你组中的其他人更容易破坏彼此的代码吗?当然,记录一切并给出
给定以下方法:defsome_method:valueend以下语句按我的预期工作:some_method||:other#=>:valuex=some_method||:other#=>:value但是下面语句的行为让我感到困惑:some_method=some_method||:other#=>:other它按预期创建了一个名为some_method的局部变量,随后对some_method的调用返回该局部变量的值。但为什么它分配:other而不是:value呢?我知道这可能不是一件明智的事情,并且可以看出它可能有多么模棱两可,但我认为应该在考虑作业之前评估作业的右侧...我已经在R
我在我的Rails3示例应用程序上使用CarrierWave。我想验证远程位置上传,因此当用户提交无效URL(空白或非图像)时,我不会收到标准错误异常:CarrierWave::DownloadErrorinImageController#createtryingtodownloadafilewhichisnotservedoverHTTP这是我的模型:classPaintingtrue,:length=>{:minimum=>5,:maximum=>100}validates:image,:presence=>trueend这是我的Controller:classPaintingsC
无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD
有人知道在发布新版本的Ruby和Rails时收到电子邮件的方法吗?他们有邮件列表,RubyonRails有一个推特,但我不想听到那些随之而来的喧嚣,我只想知道什么时候发布新版本,尤其是那些有安全修复的版本。 最佳答案 从therailsblog获取提要.http://weblog.rubyonrails.org/feed/atom.xml 关于ruby-on-rails-如何在发布新的Ruby或Rails版本时收到通知?,我们在StackOverflow上找到一个类似的问题:
电脑0x0000001A蓝屏错误怎么U盘重装系统教学分享。有用户电脑开机之后遇到了系统蓝屏的情况。系统蓝屏问题很多时候都是系统bug,只有通过重装系统来进行解决。那么蓝屏问题如何通过U盘重装新系统来解决呢?来看看以下的详细操作方法教学吧。 准备工作: 1、U盘一个(尽量使用8G以上的U盘)。 2、一台正常联网可使用的电脑。 3、ghost或ISO系统镜像文件(Win10系统下载_Win10专业版_windows10正式版下载-系统之家)。 4、在本页面下载U盘启动盘制作工具:系统之家U盘启动工具。 U盘启动盘制作步骤: 注意:制作期间,U盘会被格式化,因此U盘中的重要文件请注
我正在研究使用EventMachine支持的twitter-streamrubygem来跟踪和捕获推文。我对整个事件编程有点陌生。我如何判断我在事件循环中所做的任何处理是否导致我落后?有没有简单的检查方法? 最佳答案 您可以通过使用周期性计时器并打印出耗时来确定延迟。如果您使用的是1秒的计时器,您应该已经过了大约1秒,如果它更长,您就知道您正在减慢react器的速度。@last=Time.now.to_fEM.add_periodic_timer(1)doputs"LATENCY:#{Time.now.to_f-@last}"@
啊,正则表达式有点困惑。我正在尝试删除字符串末尾所有可能的标点符号:ifstr[str.length-1]=='?'||str[str.length-1]=='.'||str[str.length-1]=='!'orstr[str.length-1]==','||str[str.length-1]==';'str.chomp!end我相信有更好的方法来做到这一点。有什么指点吗? 最佳答案 str.sub!(/[?.!,;]?$/,'')[?.!,;]-字符类。匹配这5个字符中的任何一个(注意,。在字符类中并不特殊)?-前一个字符或组
在Ruby中有运算符(operator)。在API中,他们没有命名它的名字,只是:Theclassmustdefinetheoperator...Comparableusestoimplementtheconventionalcomparison......theobjectsinthecollectionmustalsoimplementameaningfuloperator...它叫什么名字? 最佳答案 参见上面的@Tony。然而,它也被称为(俚语)“宇宙飞船运算符(operator)”。
我安装了ruby、yeoman,当我运行我的项目时,出现了这个错误:Warning:Running"compass:dist"(compass)taskWarning:YouneedtohaveRubyandCompassinstalledthistasktowork.Moreinfo:https://github.com/gruUse--forcetocontinue.Use--forcetocontinue.我有进入可变session目标的路径,但它不起作用。谁能帮帮我? 最佳答案 我必须运行这个:geminstallcom