路亚技巧网

金丝雀(灰度)发布系列一:基于Kong的实现

08-24

金丝雀(灰度)发布系列一:基于Kong的实现

金丝雀发布(Canary Releases)介绍

为什么叫金丝雀发布

以前,英国的煤矿工人在下矿井之前,为防止自己中毒,会带着一只金丝雀,金丝雀对瓦斯非常敏感,如果发现金丝雀有异样,说明矿井中的瓦斯浓度过大,有中毒的危险,从而给工人起到一个预警的作用。所以后来也将灰度发布叫做金丝雀发布


金丝雀


灰度发布作用

  • 传统软件公司的新版本发布间隔一般比较长,几个月、半年甚至于一年等情况都有,每次新版本的功能点较多,发布异常谨慎,新版本发布带来的动静非常的大,我曾经面试过一个传统软件行业的同学,之所以离职就是因为所在公司每次发版都放到半夜,所有的研发都盯着系统,防止新版本发布引起生产事故,这个同学就是因为长期半夜加班,身体吃不消才离职
  • 互联网行业的公司,节奏比传统软件公司快很多,一般大的迭代版本最长一个月,绝大部分都是半个月一次新版本,作者所在公司就是半个月一个迭代,最初的时候由于软件质量、系统架构稳定等原因,导致新版本发布引起的生产事故比例非常的高,几乎到了每次发版都要出事故的节奏,让研发同学苦不堪言。
  • 对于互联网公司来说小的bugfix,或者小的迭代的频率就更高了,比如作者公司200多个线上服务,每天都会有生产环境服务更新,对于大的互联网公司,比如BAT、Google、Facebook每天都有几万个生产环境服务更新,这么高的频率带来的生产事故也会随之升高
  • 如何降低由于版本发布带来的事故呢?code review增加代码质量、提高测试的覆盖面和作用、增加仿真环境提前发现bug、灰度发布
  • 灰度发布作用就是新版本发布只会接入部分流量或者只对小部分用户开放,这样即使有影响也只会影响到小部分用户,将损失降到最低。

灰度发布策略

架构设计

灰度的设计可以从Server端和Client端来考虑,两端相辅相成,又相互隔离,独立实现,对于纯Web的公司来说就不用考虑Client端的灰度,对于有APP的公司来说,可以根据APP的重要程度来判断是否需要进行Client的灰度。

  • Client灰度Client的灰度不是本文的主要内容,只会做简要的介绍,Client的灰度依赖于对Client端的升级控制,升级接口需要有足够的控制能力,能够支持特定用户的升级策略,同时由于Client的更新升级比较慢,所以出现了Hot Patch热更新,但是由于iPhone系统的限制,很多功能也无法满足。还有一种办法就是代码冗余,客户端会同时冗余两个版本的代码,然后根据服务端的控制指令,来切换运行,这种方式导致代码比较冗余笨重,不太建议使用,很早之前滴滴使用过这种办法进行客户端灰度。

客户端灰度

  • Server灰度服务端的灰度方案一般都是基于网关来实现,比如本文将的Kong、或者Spring Cloud的zuul(下一章讲解),网关根据特定的策略将流量调度到不同的后端业务服务上,如果有异常则踢出或者回滚新的业务系统,如果正常则增大发布比例

服务端灰度

灰度实现策略

灰度发版的策略一般包含下边几种

  • 流量随机比例流量随机比例的灰度策略,就是根据用户的流量指定一个比例,随机的将流量根据比例调度到新服务,比例一般都是由低到高,比如5%-20%,比例可以根据自己的业务实际情况进行调度,此种调度方式一般适用于2C的业务,同时服务接口不存在不可兼容的升级
  • 特定用户1、添加用户列表或者白名单,指定列表的用户才会进行新版本的调度,此策略适用于发版以后本公司用户或者测试用的定向测试和验证2、用户比例,可以根据用户ID进行等比例的升级验证,比如5%、10%这样的比例,然后逐步的验证扩大比例
  • 关键字关键字过滤范围比较广,比如地域、手机型号、网络类型、自定义的关键字等都可以作为过滤的策略,此策略使用比较灵活,也比较广泛,其中特性用户的灰度策略是关键字策略的一种。

实现细节

Kong介绍

  • Kong诞生于2014年11月,最早是基于OpenResty(nginx+lua)实现的一个API网关,基于plugin的思想开发,可以根据自己的需求定制特定的plugin
  • 随着Kong的发展已经升级到了2.1.x的release版本,已经有41K GitHub Stars、53K+ Community Members、下载数200M+,而且紧跟技术前沿,可以实现无缝集成到kubernetes中,除了http协议,还支持了很多其他的协议,同时也实现了Kong Mesh,能够在Mesh Service领域占有一席之地,从下图可以看的更确切
    灰度.png

落地实现

  • 本公司是从Kong 1.0的版本开始使用,当时就是想通过Kong来作为我们的接入网关层,能够实现我们的灰度发布的落地,通过调研可以通过实现一个plugin来实现,所以就开始通过lua来实现这个plugin。

kong灰度plugin

1、灰度调度通过Redis存储,通过管理平台进行调度测量的修改

2、Kong-plugin,定时拉取Redis来更新灰度策略,Kong会存储一份灰度策略在table中,同时增加过期时间。

3、灰度的策略粒度不只是到Domain层,可以到URI层

4、内部Nginx是因为Kong1.x版本不支持动态upstream,只能通过内部域名的方式来进行调度

5、由于是SaaS公司,本身有客户标识,可以通过客户标识来进行灰度的策略调度

6、由于是通过Redis来进行统一策略存储,这样就让Kong作为一个无状态的方式部署,可以横向扩容,通过定时拉取同步保证灰度策略数据的最终一致

7、随着Kong的版本升级,对于上述架构也做出来一些调整,完全能够满足当前业务需求,同时增加了kubernetes的ingress,所以去掉了内部Nginx层,架构更加的清晰

使用升级

多环境

  • 由于系统SaaS系统,主要是针对2B的一些大客户,不免有些客户会尝试进行云端的系统隔离,考虑到APP、WEB、内部依赖、基础服务的软件隔离,所以我们做了架构的设计,通过Kong来进行服务之间调度的多环境隔离,那么Kong作为流量中转层,来进行环境的调度,同样的调度策略,通过用户标识来进行控制

多环境

双活

  • 当前业内分享比较多的就是饿了么的双活架构设计,对于用户划区,然后通过接入网关进行分区之间的系统隔离,那么我们的双活设计也是参考了饿了么的设计,在接入层做分区的调度
  • 同样的原因,SaaS系统有做分区天然的优势,首先对客户打标签,客户的所在城市就是其中的一个标签,那么这个城市决定了用户的调度地址应该是在哪里,对于WEB端我们通过DNSPod做了一些隔离控制(准确率低相对高),对于APP端我们通过自研的HttpDNS来控制访问的入口。但是不可避免上述两种方式都有可能有部分流量进入到不属于自己的分区,造成流量污染。所以我们就需要在流量接入层同时也需要做一些流量的调度控制,来确保不会有流量污染。
  • 双活最难的就是数据层的双写和隔离,但是当前的开源系统、设置于阿里云的DTS都很难保证数据双写双向同步的高保证,我们就是用的阿里云的DTS,经常会遇到同步延时、主键冲突的事情发生,从而造成脏数据,然后需要DBA来手动的修复数据,所以只能靠接入层来保证流量的精准调度

双活

总结

  • 灰度是保证服务可用性非常重要的一个设计,所以需要吃透,结合自己的业务需求能够落地到自己的系统中去
  • 本文是根据自己的实际使用情况针对Kong接入层来落地的灰度发布
  • 下一篇文章会介绍基于Spring Cloud的zuul网关如何来实现灰度发布

比利时兔

宠物医疗器械