为什么需要实现金丝雀发布?
在当前项目的工程实践中, 已经有了充分的单元测试, 预发布环境测试, 但是还是会在线上环境出现非预期的情况, 导致线上事故, 因此, 为了提升服务质量, 需要线上能够有一个预验证的机制.
如何实现金丝雀发布?
使用AWS code deploy方案
AWS code deploy 原生支持蓝绿部署, 用户只需要在配置中,配置好服务相关的检查策略,切换策略就可以轻松地使用, 公司内部也有团队已经使用了code deploy的方案.
但是由于当前公司内部有自己封装的EC2 服务的发布组件, 如果使用code deploy的方案, 当前微服务相关的组件都需要手动重新定义, 修改的工作量比较大.
于是舍弃了code deploy的方案, 尝试寻找其他方案.
使用Envoy proxy方案
Envoy 是一个类似Nginx的反向代理的中间件, 包含了对镜像请求等高级网络功能的原生支持.
Step 0: 部署之前的架构
外部的请求通过ELB, 转发到EC2内的nginx上, nginx反向代理到真正的服务, 这里的service使用的是旧版本代码打包的docker镜像.
Step 1: 使用新代码创建新的临时的stack
旧的stack依旧使用旧的image, 新创建的临时stack使用新版本的代码打包的docker image, 两套服务都会使用相同的RDS资源, 保证验证的一致性, 这里需要注意的是, 我们的这个服务只是提供数据暴露的接口, 也就是只读, 需要保证服务的幂等性才能使用该方案.
Step 2: 更新当前的stack使用Envoy proxy
将nginx替换为envoy proxy, envoy proxy有几个关键的配置:
- 配置镜像请求的host地址
- 配置镜像请求的比例
- request timeout的时间需要与之前nginx配置的一致
如果请求量比较高,可以适当减少镜像请求比例,因为过高的比例会导致流量到达RDS,增加RDS的负载. 如果服务本来请求量较低,配置了较低的比例,会导致没有足够的请求来对新的服务进行验证.
Step 2-1: 等待验证窗口结束
设置一个合理的验证窗口, 太长导致新代码上线太慢, 太短无法进行有效验证.
Step 3: 对新的服务执行结果进行验证
这里对临时stack的ELB的alart状态进行验证, alart触发对应的条件是: 如果有任何的请求出现5XX错误,会触发alart.
如果触发alart, 则停止部署.
如果检查正常,继续执行将部署,将现有的stack中的envoy proxy再切换回nginx, 将服务替换为已经在线上环境验证过的新的docker image.
至此, 新的代码已经成功上线,并且在线上做了金丝雀验证.
Step 4: 删除临时的stack
清理之前创建的临时stack
Additional step: 部署失败回滚策略
在step 3的验证过程中, 可能会出现验证失败的情况, 由于当前线上的服务已经被更新成了envoy作为proxy, 并且会将流量持续转发到临时temp的服务上, 在实际的性能测试中, envoy proxy的性能是低于nginx的, 所以, 需要手动部署之前版本的代码, 将当前使用的stack中的代理切换回nginx.
同时, 部署失败之后, 临时的stack已经没有再使用了, 也需要手动进行删除.
总结
AWS 提供了code deploy 支持蓝绿部署, 但受限于已经集成了现有组件, 我们使用了Envoy proxy的流量镜像功能, 实现了金丝雀部署. 本文主要介绍了详细的部署,验证,回滚步骤.