本文主要介绍了在k8s中利用 Ingress-nginx 的 Canary 功能实现蓝绿、灰度发布
更新于 2021-03-20
Canary功能介绍
Ingress-Nginx在0.21版本引入了Canary功能,可以为网关入口配置多个版本的应用程序,使用annotation来控制多个后端服务的流量分配。
canary通过下面的一些注释来实现流量分配:
nginx.ingress.kubernetes.io/canary: "true"
:启用Canary功能;
nginx.ingress.kubernetes.io/canary-weight
:指定一个0-100的整数,根据设置的值来决定大概有百分之多少的流量会分配Canary Ingress中指定的后端服务;
nginx.ingress.kubernetes.io/canary-by-header
:基于request header 的流量切分,适用于灰度发布或者A/B测试,当设定的hearder值为always是,请求流量会被一直分配到Canary入口,当hearder值被设置为never时,请求流量不会分配到Canary入口,对于其他hearder值,将忽略,并通过优先级将请求流量分配到其他规则;
nginx.ingress.kubernetes.io/canary-by-header-value
: 要和nginx.ingress.kubernetes.io/canary-by-header
一起使用,当请求中的hearder key和value 与nginx.ingress.kubernetes.io/canary-by-header
nginx.ingress.kubernetes.io/canary-by-header-value
匹配时,请求流量会被分配到Canary Ingress入口,对于其他任何hearder值,将忽略,并通过优先级将请求流量分配到其他规则;
nginx.ingress.kubernetes.io/canary-by-cookie
:基于cookie的流量切分,也适用于灰度发布或者A/B测试,当cookie值设置为always时,请求流量将被路由到Canary Ingress入口,当cookie值设置为never时,请求流量将不会路由到Canary入口,对于其他值,将忽略,并通过优先级将请求流量分配到其他规则;
以上几种注释的优先级为:canary-by-header - > canary-by-cookie - > canary-weight
基于权重分配流量
创建v1版本服务
检查创建情况
1
| kubectl get pod,service,ingress -n echoserver
|
访问服务
1
| for i in `seq 10`;do curl -s echo.example.com|grep Hostname;done
|
可以看到,所有的请求都正常返回且版本为v1
发布v2版本服务
检查v2版本服务
1
| kubectl get pod,service,ingress -n echoserver
|
访问服务
1
| for i in `seq 10`;do curl -s echo.example.com|grep Hostname;done
|
可以看到,v1和v2两个版本的请求比几乎是50%
更新v2版本服务
访问服务
因为设置了nginx.ingress.kubernetes.io/canary-by-header: v2
,将会出现以下的集中情况:
只需要在v2版本的ingress中指定nginx.ingress.kubernetes.io/canary-by-header-value
即可:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| apiVersion: extensions/v1beta1 kind: Ingress metadata: annotations: kubernetes.io/ingress.class: nginx nginx.ingress.kubernetes.io/canary: "true" nginx.ingress.kubernetes.io/canary-weight: "50" nginx.ingress.kubernetes.io/canary-by-header: "v2" nginx.ingress.kubernetes.io/canary-by-header-value: "true" labels: app: echoserverv2 name: echoserverv2 namespace: echoserver spec: rules: - host: echo.example.com http: paths: - backend: serviceName: echoserverv2 servicePort: 8080 path: /
|
此时因为指定了header key和value,则请求的header必须包含:v2:true
才能进入v2版本,否则会按照比例进行v1,v2版本分配。
基于cookie进行流量分配
更新v2版本服务
基于cookie进行分配的时候,不能定义cookie的value
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| apiVersion: extensions/v1beta1 kind: Ingress metadata: annotations: kubernetes.io/ingress.class: nginx nginx.ingress.kubernetes.io/canary: "true" nginx.ingress.kubernetes.io/canary-weight: "50" nginx.ingress.kubernetes.io/canary-by-cookie: "user_from_shanghai" labels: app: echoserverv2 name: echoserverv2 namespace: echoserver spec: rules: - host: echo.example.com http: paths: - backend: serviceName: echoserverv2 servicePort: 8080 path: /
|
访问服务