一些历史
John Scott Haldane 于 1895 年提出,因为小型恒温动物的呼吸交换比人类更快,矿井中的一氧化碳等有毒气体或甲烷等窒息性气体会先影响它们。
比如,同样的一氧化碳浓度,老鼠会在几分钟内受到一氧化碳的影响,人类需要 20 倍的时间才会受到影响,于是 1896 年左右开始,老鼠被用作井下有毒气体预警的物种。
一段时间后,人们发现金丝雀这种生物对于有毒气体更加敏感。在 1900 年开始有记录显示,一些矿井开始把金丝雀作为井下有毒气体的预警物种。
后来,人们为了能重复使用金丝雀,发明了一个用于金丝雀毒气探测的专用笼子。笼子可以主动充氧,前方设有一个通气孔,通气孔可以通过密闭窗进行开启和关闭。在需要金丝雀进行预警的时候,把通气孔打开。如果笼子中的金丝雀被毒气毒晕,关上通气孔的窗口并让笼子充满氧气。如果金丝雀如果没有被毒死,就有可能活过来。
因为科技的不断发展,有毒气体探测器被发明了出来。这种用生命来探测的方式开始逐步退出历史舞台。直到1986 年英国和美国完全停止使用金丝雀来作为预警生物使用。
金丝雀部署,这种部署方式的目标与逻辑和使用金丝雀来预警非常类似(通过开关通气孔/流量的方式来控制危害与恢复能力),我猜想可能大家也希望能纪念一下在 20 世纪为矿工献出生命的金色小鸟们,所以这种方式被冠上了金丝雀的名称。
了解了名字的来历,我们开始来了解一下金丝雀部署到底是什么样的。
基本定义
金丝雀部署是在将更改推广到整个服务集群并使其对所有人可用之前,将更改推广到一小部分用户进行测试。并在测试过程中持续观测被测试的服务各个维度的状态,验证新版本的健壮性、可用性、稳定性等。
当验证结果达到期望目标后,可以逐步将新的版本部署到更多服务器,使更多用户使用到它。
优势
- 零下线时间与快速回滚:
- 在一系列的相关验证和测试之后,如果新版本的软件被认为不合适,则很容易回滚和控制影响范围。
- 真实场景下的测试:
- 由于是直接将新版本部署到生产环境进行测试,所以能够通过真实流量对新版本进行针对性的验证。当然,需要对流量和用户进行限制,来控制验证的范围和影响面。
- 较低的基础设施成本:
- 因为金丝雀部署策略是通过一定规则,按规则对的请求进行要求的分流或路由(例如:用户名、地区、年龄、随机等),所以只需要少量额外的基础设施,就可以达到验证的效果。对比蓝绿部署策略,需要准备与生产环境同样的一套基础设施,部署成本显然会高很多。
- 灵活的按需进行验证相关版本、功能的正确性。
- 可以根据不同的特征和标识,对请求的流量进行多个维度分流和路由,以达到不同粒度不同特征的灵活验证。
不是银弹
虽然金丝雀部署能够为大家的部署提供强力的支持和帮助。但是,软件工程中是没有银弹的。金丝雀部署在很多场景也需要谨慎使用:
- 严格不允许出错的系统,例如:医疗系统、消防系统等
- 需要部署的数据结构无法向下兼容已经当前版本数据结构
- 虽然阿里云的 MDS 能够提供分流影子数据库的能力。但是,正式用户使用的话,依然会影响到实际的数据和行为体验。所以,仅限于测试人员或内部用户体验使用才能发挥他的能力。
- 非自动化的金丝雀部署,既耗时又容易出现错误。所以,我们应该尽可能使用自动化的方式去使用它,而不是手动去维护分流策略和逻辑。
- 以及很多其他对于生产环境要求严格的场景,均不建议使用
接下来换个思维,让我们来看看一些与细节无关的讨论。
金丝雀发布 or 金丝雀部署?
在交流和口语中,大家习惯于将发布和部署混用。常常会看到类似于将蓝绿部署、灰度发布(比起金丝雀大家更愿意用灰度)、滚动发布等名词被列举到一起,以表示他们都是发布版本的一些不同的方法。
下面我们开始来咬文嚼字。
发布:
[issue;release;deliver;distribute] 宣布,发表例句:向全国发布新闻
部署:
(1) [disposition;deployment]∶处理;料理
例句:炮兵的部署已标明在这张地图上
(2) [arrange;lay out]∶安排
例句:部署计划
根据上面的两个词典释义,我是这样理解发布和部署的:
发布广义上是指思想、观点、文章和意见等通过报纸、书刊、网络或者公众演讲等文字和演讲的形式公之于众,向外界传输消息的一种过程。放在计算机这个范畴中时,它是一种将某个特定的软件放到大家能接触到的一些地方,被动的让大家去更新或者同步。比如:我把软件的某个版本打包发布了。
部署广义上是指安排或执行人力、计划、任务等。放到计算机这个范畴,它是一种将特定软件安装或更新到对应的环境中,使其可以为用户提供服务。比如:我把新版本部署到测试环境了,你测试一下。
根据上面的解释,我认为用更准确的是金丝雀部署(Canary Deployment)。
与 A/B 测试的关系
刚开始对金丝雀部署了解时,发现许多地方将 A/B 测试与金丝雀部署混为一谈,甚至有直接将这它们两个当成一个东西来对待。实际上,在深入了解后,会发现它们之前确实是有联系,不过还没达到可以画上等号的程度。
相同之处
他们之间的网络流量处理逻辑非常相似,都是通过流量不同特征来决定,对流量进行服务的版本。
金丝雀部署可用作实现A/B 测试的技术基础的一部分;但是不要将它们避免混为一谈。
不同之处
他们两者的目的是完全不同的,金丝雀部署被用来检测问题和回归功能,A/B 测试是一种来用来测试业务设计假设的方法。从二者的目标出发,他们测试的和观测的方法是不一样的。
金丝雀部署的通常是使用偏技术侧观测工具(APM、日志监控等)。技术/开发人员会对需要部署的新版本服务进行观测。当观测结果与预期相符,则技术人员可以进一步操作。否则,需要先解决问题,再部署和观测,直到能够达到预期,再进行进一步下一步操作。
如果我们用同样的方式和工具来希望对业务观测,是无法得到准确结果的。甚至观测的人员职能都不同。一般情况下,A/B 测试对观测部分需要预先的观测数据收集埋点。接着,对收集到的业务数据进行整理和统计,最终得出相关的数据分析结果和统计结果,以提供给业务人员对新业务进行分析和判断。
最后,从更时间的角度来说,业务人员在收集足够的数据以证明A/B 测试的显着性可能需要数天时间,而技术人员希望金丝雀部署在几分钟或几小时内完成。
聊了这么多实现无关的话题,接下来让我们来一起看看,实现金丝雀部署有哪些办法吧。
实现
实现结构
金丝雀部署的关键点有如下几点:
- 网络流量分流
- 分流策略管理
- 多应用间分流传递策略
- 数据兼容性处理
由上图关键点我们可以通过下图了解的更加明确:
下面我们从流程入手,看看金丝雀部署具体的执行过程是什么样的。
具体流程
从流程入手,这样很容易就能了解到金丝雀部署在不同阶段,呈现出什么样的特征,提供了什么样的能力等。
-
正常阶段: 当前环境中只有 1-n 个版本已验证版本, 为所有的用户提供服务
-
验证阶段:当前环境存在 2 到 n 个版本, 其中有一个已验证版本, 为大部分用户提供相对稳定服务, 剩下的 1 到 n-1 版本为需验证版本, 为特定用户(某些场景下随机挑选)提供相对不稳定服务。同时,持续观需验证版本运行情况,以判断该版本是需要进行部署,还是进行其他处理。
-
部署阶段: 某个需验证版本通过验证后,此需验证版本将被部署至计划的服务集群占比。如果,还需进一步测试,则又回到验证期进行验证.直至,需验证版本部署占比达到最终需要。往往会使用滚动部署的方式进行部署。
-
状态流转总览
实现方式
这里提到的主要都是服务器端的实现方式。
我根据不同的实现方式将他们分为下列几种类型:
- 基础设施实现(IaaS):比如通过阿里云 MDS 工具实现
- 平台实现(PaaS):通过 K8S 的 Ingress 组件或 Istio 来实现
- 通过 Nginx 等中间件实现:直接在 Nginx 中通过脚本控制流量转发规则
- ...
由于,金丝雀部署本身的实现细节与应用场景具有紧耦合特性。具体的实现方法就不在这里展开了。在使用过程中关注文中提到它的特性与注意事项(不是银弹)以及具体的执行流程和结构来进行部署。我在这里做的更多的抛砖引玉,希望大家能有更多金丝雀部署的精彩内容和思考能一起来讨论。
最后
20 世纪的某一天,昏暗的狭窄的矿井中。头戴矿灯的矿工一手提着一个笼子,另一手并着脚努力的往前爬行,汗水裹着黑色的粉末在脸上往下流淌。 美丽的鸟儿在摇摇晃晃的笼子中努力的保持着平衡,不知道迎接他侥幸逃脱后的阳光还是窒息的毒气。
文/Thoughtworks黄逸偲
原文链接:https://insights.thoughtworks.cn/canary-deployment/
更多精彩洞见,请关注微信公众号Thoughtworks洞见。