灰度发布在生产环境中逐步推出新的版本,而不是一次性地发布给所有用户。这种发布方式可以降低新版本带来的风险,因为只有一部分用户能够访问新版本,如果出现问题,只有这部分用户受到影响,而其他用户仍然可以继续使用旧版本。
灰度发布
灰度发布可以通过多种方式实现,例如:
- 按比例分配:将流量按照一定比例分配给新版本和旧版本,比如新版本占10%,旧版本占90%。
- 随机分配:将流量随机分配给新版本和旧版本,比如每个用户有50%的机会访问新版本,50%的机会访问旧版本。
- 根据用户分配:将流量根据用户属性或行为分配给新版本和旧版本,比如只有VIP用户可以访问新版本,其他用户访问旧版本。
Istio实现灰度
Istio通过VirtualService和DestinationRule两个资源对象来实现流量管理,其中VirtualService用于定义流量路由规则,而DestinationRule用于定义服务的负载均衡策略和TLS设置
- VirtualService: 实现服务请求路由规则的动能
- DestinationRule: 实现⽬标服务的负载均衡、服务发现、故障处理和故障注⼊的功能
- Gateway: 让服务⽹格内的服务,可以被全世界看到
- ServiceEntry: 让服务⽹格内的服务,可以看到外⾯的世界
VirtualService
通过VirtualService对象,我们可以将流量路由到不同的服务版本或实例上,例如可以将10%的流量路由到新版本服务上,而90%的流量路由到旧版本服务上。同时,也可以定义一些高级的路由规则,例如基于HTTP头、查询参数、请求体等条件进行路由。
例子:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: ycloud-data-confirm
namespace: ycloud
spec:
gateways:
- ycloud-data-confirm
hosts:
- ycloud-api.mer.net
- ycloud-internal-api.mer.net
- 192.169.100.10
http:
- match:
- uri:
prefix: /testtai/
- uri:
prefix: /testtai
rewrite:
uri: /
route:
- destination:
host: ycloud-data-confirm
port:
number: 8080
DestinationRule
可以定义服务的负载均衡策略,例如可以使用轮询、随机、加权轮询等算法进行负载均衡。此外,也可以通过DestinationRule对象设置TLS,例如启用mTLS,以保证服务之间的安全通信。
例子:
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: ycloud-data-confirm
namespace: ycloud
spec:
host: ycloud-data-confirm
subsets:
- labels:
app.kubernetes.io/instance: ycloud-data-confirm
name: ycloud-data-confirm
实践案例
Helm部署案例,当我们有一个已部署上线的服务**A
**,需要做灰度,我们所需要做的流程。
- 参数定义
是否启动灰度
,如需启动,给与对应版本及比例,会自动部署 - 新增一个
Deployment
模板,为了和之前的名称区分开我们定义为.fullname-canary
- 为了
选择器区分新老服务
Deployment,我们给不同版本打上对应的标签。例:app.kubernetes.io/canary: stable - 定义好灰度发布时
镜像和分配比例
所需的渲染值 - 定义负载均衡策略,
DestinationRule
详细案例可查看 Where
启动灰度
伸腿的第一步,也算比较重要的一步。我们需要定义一个类似开关,当我们需要发生灰度时打开,不需要时则关闭。
canary:
enabled: true #or false
stable:
weight: 50
canary:
weight: 50
image:
tag: k8s-f2768b4
image:
tag: k8s-f2768b4
⚡️:可以清楚的看到这里的定义了
.canary.enabled
;还针对两个版本做了流量划分,来分配灰度比例,循序渐进更好的观测新版本的情况;.canary.canary.image.tag
是我们新版本发布所需要的镜像tag
新增模板
跟老版本的部署模板调整不是很多,直接看案例,需要调整的地方已经标出
⚡️:确认自己调整的地方无误,其实也不用担心,helm自带Debug,有问题会详细标出
负载策略
☑️:这是最重要的一步,决定灰度是否成功。能否讲对应的流量达到对应的版本上去,我们这边可以看下案例
❌:切勿忘记
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: {{ include "mobilesvr.fullname" . }}
labels:
{{- include "mobilesvr.labels" . | nindent 4 }}
spec:
host: {{ include "mobilesvr.fullname" . }}
subsets:
- labels:
app.kubernetes.io/instance: {{ include "mobilesvr.fullname" . }}
app.kubernetes.io/canary: stable
name: {{ include "mobilesvr.fullname" . }}
{{- if .Values.canary.enabled }}
- labels:
app.kubernetes.io/instance: {{ include "mobilesvr.fullname" . }}
app.kubernetes.io/canary: canary
name: {{ include "mobilesvr.fullname" . }}-canary
{{- end}}
这里我们就能看到 subsets
,指定了服务的不同版本通过我们定义的标签做区分,
可以将某些流量路由到最新版本的服务,而将其他流量路由到旧版本的服务。这样在不影响整个服务的情况下,逐步升级或测试新版本。
结束
在生产环境中,灰度,A/B测试也是不可缺少的一环,现在服务上线k8s,使用istio能解决部分问题。