文章导读
一、相关概念
(1) 蓝绿部署:不停止老版本,额外搞一套新版本,等测试发现新版本OK后,删除老版本。
(2) 滚动发布:按批次停止老版本实例,启动新版本实例。
(3) 灰度发布/金丝雀部署:不停止老版本,额外搞一套新版本,常常按照用户设置路由权重,例如90%的用户维持使用老版本,10%的用户尝鲜新版本。不同版本应用共存,经常与A/B测试一起使用,用于测试选择多种方案。
在本文中:蓝应用通过cats/pets模拟,绿应用通过cities模拟。
在这个实验中,我们将定义为V1,cities定义为V2,将cats定义为V1.1,pets定义为V1.2。
其中V1和V2的切换,是通过修改router指向的svc来实现的;而V1.1和V1.2,是通过修改pod dc的selector来实现的,这会触发pod的重新部署。
V1.1 Blue:蓝应用
oc new-app --name='blue' --labels=name="blue" php~https://github.com/wkulhanek/cotd.git --env=SELECTOR=cats
启动应用程序的curl循环以验证它是否正常工作并提供猫图片(我们将看到图像的URL类似于data / images / cats / wellington.jpg。它是 猫部分你需要验证,看看图像确实是猫的图像):
V2:Green:绿应用:
设置另一个服务城市的cotd应用程序(绿色应用程序)。
oc new-app --name='green' --labels=name=green php~https://github.com/wkulhanek/cotd.git --env=SELECTOR=cities
应用程序运行后,通过更新bluegreen路径将流量移动到新的应用程序实例(观察curl终端窗口以查看其更改)。
三、实验展现:通过修改router的service指向实现蓝绿发布
使用oc patch命令更新bluegreen路由以指向绿色服务。
在第二个终端窗口中观察应用程序现在提供城市图片。 将再次看到图像的URL类似于data / images / cities / wellington.jpg。 需要验证城市部分才能看到图像确实是城市的图像。
四、实验展现:修改pods dc的selector
V1.2 Blue:蓝应用
通过修改蓝色应用程序来显示宠物,执行另一个蓝绿色部署。需要更新蓝色应用程序的SELECTOR环境变量。这是配置更改,因此请等待应用程序重新部署。
这时候,curl的结果还没变:
过一会,发生了变化(目录从cats换成了pets):
这时候,狗也出现了:
这次,将两个服务添加到路由并相应地设置服务的权重(如在A / B部署中)。
四、实验展现:实现灰度发布
最初,将当前活动的绿色应用程序设置为权重100,将当前不活动的蓝色应用程序设置为权重0。
保持curl运行并观察先前的更改未改变应用程序所服务的数据 - 它仍然提供城市图像。现在通过简单地调整bluegreen路径的权重来执行蓝绿色开关,将绿色应用程序设置为0,将蓝色应用程序设置为100。
查看路由:
最后放一篇旧的文章,2017年2月份写的:
版权说明:
本文引用了周立的文章《微服务部署:蓝绿部署、滚动部署、灰度发布等部署方案对比与总结》(文章最后有原作者的二维码,欢迎读者关注)。在此基础上,大卫增加了实验展现。
在项目迭代的过程中,不可避免需要”上线“。上线对应着部署,或者重新部署;部署对应着修改;修改则意味着风险。
目前有很多用于部署的技术,有的简单,有的复杂;有的得停机,有的不需要停机即可完成部署。本文笔者简单讨论一下目前比较流行的几种部署方案,或者说策略。如有不足之处请指出,如有谬误,请指正^_^。
Blue/Green Deployment(蓝绿部署)
蓝绿部署无需停机,并且风险较小。
(1) 部署版本1的应用(一开始的状态)
所有外部请求的流量都打到这个版本上。
(2) 部署版本2的应用
版本2的代码与版本1不同(新功能、Bug修复等)。
(3) 将流量从版本1切换到版本2。
(4) 如版本2测试正常,就删除版本1正在使用的资源(例如实例),从此正式用版本2。
从过程不难发现,在部署的过程中,我们的应用始终在线。并且,新版本上线的过程中,并没有修改老版本的任何内容,在部署期间,老版本的状态不受影响。这样风险很小,并且,只要老版本的资源不被删除,理论上,我们可以在任何时间回滚到老版本。
Openshift蓝绿部署的实现
Openshift实现蓝绿部署,都需要一个应用的两个版本同时存在:
在测试环境中,首先有个php代码库。当前版本的代码版本为V1(index.php)。通过该版本代码,部署一个V1版本的应用(网页访问输出结果为:I am VERSION 1 My Pod IP is : 172.17.0.7)。然后,将代码修改为V2,再部署一个V2版本的应用(网页访问输出结果为:I am VERSION 2 My Pod IP is : 172.17.0.6)
如下图:V1、V2两个版本的php应用:
Openshift实现灰度发布有两种方式:
(1) 给不同版本的应用容器(pod)设置label,版本切换的时候,修改应用指向pod的label。
(2)在router上设置流量访问比重。初始情况,100%的流量都在V1版本;V2测试正常以后,修改router,将全部流量切换到V2(修改是动态实现的)。
两种方法中,第二种操作更为简便和直观,因此我们展示第二种方式。
在实验环境中,有两个pods,分别是承载两个版本应用的容器:
查看两个版本应用的serviceip:
我们查看应用对外的路由:
可以看到,所有流量都会发到V1版本的应用。通过curl或者浏览器,可以确认,此时访问域名grey.apps.example.com,会指向到V1版本的应用(V1版本应用显示I am VERSION 2,V2版本应用显示I am VERSION 3),并显示容器的IP。
接下来,V2版本应用测试成功,我们进行版本切换,修改router,将V2的权重调整为100%:
通过命令行也可以确认:
这时候,在访问域名,得到的结果将是V2应用的内容:
而如果V2版本的应用如果出现问题,需要回退,可以再次修改router,将流量调回到V1版本的应用。
rolling update(滚动发布)
滚动发布,一般是取出一个或者多个服务器停止服务,执行更新,并重新将其投入使用。周而复始,直到集群中所有的实例都更新成新版本。
这种部署方式相对于蓝绿部署,更加节约资源——它不需要运行两个集群、两倍的实例数。我们可以部分部署,例如每次只取出集群的20%进行升级。
这种方式也有很多缺点,例如:
(1) 没有一个确定OK的环境。使用蓝绿部署,我们能够清晰地知道老版本是OK的,而使用滚动发布,我们无法确定。
(2) 修改了现有的环境。
(3) 如果需要回滚,很困难。举个例子,在某一次发布中,我们需要更新100个实例,每次更新10个实例,每次部署需要5分钟。当滚动发布到第80个实例时,发现了问题,需要回滚。此时,脾气不好的程序猿很可能想掀桌子,因为回滚是一个痛苦,并且漫长的过程。
(4) 有的时候,我们还可能对系统进行动态伸缩,如果部署期间,系统自动扩容/缩容了,我们还需判断到底哪个节点使用的是哪个代码。尽管有一些自动化的运维工具,但是依然令人心惊胆战。
并不是说滚动发布不好,滚动发布也有它非常合适的场景。
Openshift滚动发布的实现
Openshift可以通过修改一个应用的dc,实现滚动发布。
在openshift中,一个应用的部署方式,有三种,分别为recreate、Rolling、Custom。
默认会被设置为rolling,也就是滚动升级。
而和滚动升级相关的参数,有四个(英文描述写的很清楚,笔者不再翻译):
Timeout:How long to wait for a pod to scale up before giving up
Interval:Time to wait between polling deployment status after running a pod.
Maximum Number of Unavailable Pods:The maximum number of pods that can be unavailable during the rolling deployment. This can be either a percentage (10%) or a whole number (1).
Maximum Number of Surge Pods:The maximum number of pods that can be scheduled above the original number of pods while the rolling deployment is in progress. This can be either a percentage (10%) or a whole number (1).
接下来,我们看一下滚动升级的效果:
应用被修改以后,触发重新部署:
从下面三种图我们可以看到,当重新部署应用时,升级是平滑的。
灰度发布/金丝雀部署
先贴个百度百科:
灰度发布是指在黑与白之间,能够平滑过渡的一种发布方式。AB test就是一种灰度发布方式,让一部分用户继续用A,一部分用户开始用B,如果用户对B没有什么反对意见,那么逐步扩大范围,把所有用户都迁移到B上面来。灰度发布可以保证整体系统的稳定,在初始灰度的时候就可以发现、调整问题,以保证其影响度。
很多人把灰度发布与蓝绿部署混为一谈,笔者认为,与灰度发布最类似的应该是金丝雀部署。
“金丝雀部署”是增量发布的一种类型,它的执行方式是在原有软件生产版本可用的情况下,同时部署一个新的版本。同时运行同一个软件产品的多个版本需要软件针对配置和完美自动化部署进行特别设计。
我们来看一下金丝雀部署的步骤:
(1) 准备好部署各个阶段的工件,包括:构建工件,测试脚本,配置文件和部署清单文件。
(2) 从负载均衡列表中移除掉“金丝雀”服务器。
(3) 升级“金丝雀”应用(排掉原有流量并进行部署)。
(4) 对应用进行自动化测试。
(5) 将“金丝雀”服务器重新添加到负载均衡列表中(连通性和健康检查)。
(6) 如果“金丝雀”在线使用测试成功,升级剩余的其他服务器。(否则就回滚)
灰度发布中,常常按照用户设置路由权重,例如90%的用户维持使用老版本,10%的用户尝鲜新版本。不同版本应用共存,经常与A/B测试一起使用,用于测试选择多种方案。灰度发布比较典型的例子,是阿里云那个“新版本”,点击“进入新版本”,我们就成了金丝雀。
Openshift灰度发布的实现
Openshift灰度发布的实现,可以借助于修改router的权重(蓝绿部署设置权重只有0和100,而灰度发布会有中间值)
初始情况,所有流量访问V1版本应用。随后,将两个版本的应用访问权重设置为6:4。也就是60%的终端访问V2,40%的用户访问V1。
设置完毕后,通过浏览器和命令行都可以看到设置的结果(权重的设置是动态调整、即时生效的)
然后通过写一个循环,查看返回结果,与我的预设值是相同的,我们看到,持续10次对URL的访问中,6次指向了V2,4次指向了V1。达到了我们想要的效果。
当V2版本应用完全测试成功后,将V2版本应用的访问权重设置为100%。
总结
(1) 蓝绿部署:不停止老版本,额外搞一套新版本,等测试发现新版本OK后,删除老版本。
(2) 滚动发布:按批次停止老版本实例,启动新版本实例。
(3) 灰度发布/金丝雀部署:不停止老版本,额外搞一套新版本,常常按照用户设置路由权重,例如90%的用户维持使用老版本,10%的用户尝鲜新版本。不同版本应用共存,经常与A/B测试一起使用,用于测试选择多种方案。