1. 场景描述
为了达成线上发布可灰度的目的,一种做法是控制不同版本的实例数量,从而达到基于流量比例灰度的目的,例如典型的分批发布场景。如下图所示,我们将发布过程暂停在新、旧实例比为1:4的状态,此时将有20%的流量进入到新版本,从而达到灰度验证的目的。
然而,通过流量比例实现灰度发布,会存在2个关键的不足:
(1)无法精准控制灰度范围。如:无法满足“指定用户请求新版本”的场景;
(2)无法灵活的控制流量比例。如:线上服务有5个Pod,此时最小灰度比例即20%;如果想要达到1%的灰度流量比例,线上至少需要100个Pod,这对大部分应用来说是不现实的。
当能够控制不同请求参数进入不同版本服务,并且覆盖全链路场景,即实现了全链路的灰度发布。例如:基于阿里云MSE,可支持基于http/https、RocketMq流量的灰度发布,可参考实践:MSE+云效AppStack实现应用服务全链路灰度 。
本篇将会介绍另一种基于开源工具Istio实现全链路灰度发布的原理以及在云效应用交付平台AppStack上配置的方法,满足基于http、gRPC、WebSocket的流量灰度发布场景。
2. 原理介绍
在Istio中,为了实现基于特定header的流量路由,需要完成如下操作:
安装Istio,参考:https://istio.io/latest/zh/docs/setup/getting-started/;
给命名空间添加标签,在部署应用的时候自动注入Envoy sidecar代理
kubectl label namespace default istio-injection=enabled
根据规则配置DestinationRule和VirtualService,如:
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: service-a
spec:
host: service-a
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: service-a
spec:
hosts:
- service-a
http:
- match:
- headers:
end-user:
exact: jason
route:
- destination:
host: service-a
subset: v2
- route:
- destination:
host: service-a
subset: v1
配置完上述规则后,header 中包含 end-user=jason 的请求将全部路由到service-a的v2版本,其余请求将继续访问service-a的v1版本。
3. 操作实践
在云效AppStack中,我们提倡将发布规范固化在研发流程中,业务研发团队可自助式地完成发布。我们以官方的Bookinfo微服务为例,演示在云效AppStack中的配置过程:
前提条件:预先在k8s集群中完成Istio的安装,并为相关namespace打上 istio-injection=enabled 的标签。做法可参考上文“原理介绍”部分。
3.1 应用配置
依次创建 details、ratings、reviews、productpage 4个应用(在云效AppStack中,我们推荐一个微服务对应一个应用)。
配置应用编排(应用编排定义了应用的部署架构,在k8s中,即 k8s manifest),完整的示例编排已上传至 https://atomgit.com/aliyun_appstack/bookinfo_k8s_manifest。配置编排示例(部署顺序上,我们推荐将非工作负载放在一个阶段,工作负载独立放在一个阶段)。
在4个应用下创建生产环境(环境名称:prod),reviews应用额外创建一个灰度环境(环境名称:gray),创建环境时需要关联k8s资源。
分别进入4个应用的生产环境中完成首次部署,部署后可在环境详情页看到部署后的资源清单。
针对需要灰度发布验证的reviews应用,编辑研发流程流水线添加灰度环境部署任务,经过人工卡点验证后再发布生产环境。
3.2 运行验证
在运行验证前,需要参考官方示例创建网关,确保后续能够从集群外部访问应用。
运行研发流程并部署灰度环境后,访问BookInfo服务:
以 jason 用户登录,访问的是灰度环境:
匿名或以其他用户身份登录,访问的是生产环境:
3.3 灰度环境资源清理
生产环境发布完成后,可以通过配置自动清理灰度环境,删除灰度环境相关资源并将流量全部导入生产环境。
在研发流程最后,添加 AppStack清理环境组件;
清理环境组件配置示例,清理类型选择“仅清理资源保留环境元数据”:
重新运行研发流程,执行完成 AppStack清理环境步骤后
前往k8s集群查看资源,灰度环境资源已经被删除;访问 BookInfo 服务,所有用户都访问到生产环境新的版本