什么是灰度更新
为了让大家更好的理解,我通过一个简单的例子和大家说一下什么是灰度更新。
假设你有⼀个关于酒店预定的项⽬,需要对外提供⼀个 Web 网站,供用户预定房间。为了保证业务的⾼可⽤,该项⽬研发的服务端是⽀持分布式的。因此,你在⽣产环境,组了⼀个酒店预定 Web 集群,⼀共起了 3 个服务端,通过 Nginx 反向代理的方式对外提供服务。
左图是传统意义上的灰度更新,即先将部分流量导到新版本上进行测试,如果可以就全面推广,如果不行就退回上一个版本。具体举例来说的话,有三台机器分别部署了服务端,IP 地址分别为 0.2、0.3、0.4。日常更新的话,选择先在 0.4 服务端更新并看一下是否有问题出现,在确定没有问题后才进行 0.3 和 0.2 的更新。郑州哪家医院看心理咨询好http://www.hyde8871.com/
右图则是使用容器技术,它会比物理机部署的方式更加灵活。它用到的概念是 instance,也就是实例,同一台机器上可以起多个实例。访问流量会如图从左往右的方向,先经过网关,通过在网关上添加一些策略,让 95% 的流量走上面的原服务,5% 的流量走下面的灰度服务。通过观察灰度服务是否有异常,如果没有异常,则可以把原服务的容器镜像版本更新到最新,并删掉下面的灰度服务。这和左图是不一样的,它不是滚动式一台接一台的更新,而是借助一个弹性资源平台直接把原服务全部更新掉。
灰度更新现状
上图是灰度更新在 Luffy2 上面的现状,主要问题出现在 API 处理这一块,因为之前的状态是靠数据库来维护的,容易出现状态不统一的问题。
左图是一个简略的处理流程。当一个 API 请求服务过来要求进行服务灰度更新时,第一步会先生成一个带灰度名称的 App。
第二步这里给大家细说,首先要将生成的 App 放入数据库,同时在 Kubernetes 创建无状态服务,这通常需要 10 分钟左右的时间。这期间会通过一个 Go 语言程序对 App 表进行不间断扫描以确认服务是否完成创建。同时还需要使用 Kubernetes 创建转发规则等,等待所有需求都创建完成后就返回原版 ok 给调用方。
这里涉及到性能问题,因为数据库内有很多条要处理的东西,这些要等待挨个处理,而这其中有很多都是无用数据,在扫到 App 前的这 10 分钟里,就算去 Kubernetes 那边调用,也是在做无用操作。
另外还有一个调用链很长的问题,在 Kubernetes 里创建的很多东西都会包含在同一次 API 请求里,这就导致随时可能出现在一步完成后,下一步崩溃的情况。这种时候可能要考虑是否回滚的问题,而如果回滚就要删掉相关服务和数据库。这种情况在调用外部组件越多时,越容易出现。比较直观的解决方法是简化 API 流程,针对这个方法 Kubernetes 提供了 CRD。