基于Ingress Nginx实现灰度发布系统
工作中,会经常对应用进行升级发版,在互联网公司尤为频繁,主要是为了满足业务的快速发展。经常用到的发布方式有滚动更新、蓝绿发布、灰度发布。
- 滚动更新:依次进行新旧替换,直到旧的全部被替换为止。
- 蓝绿发布:两套独立的系统,对外提供服务的称为绿系统,待上线的服务称为蓝系统,当蓝系统里面的应用测试完成后,用户流量接入蓝系统,蓝系统将称为绿系统,以前的绿系统就可以销毁。
- 灰度发布:在一套集群中存在稳定和灰度两个版本,灰度版本可以限制只针对部分人员可用,待灰度版本测试完成后,可以将灰度版本升级为稳定版本,旧的稳定版本就可以下线了,也称之为金丝雀发布。
本次分享如何通过ingress-nginx controller实现灰度发布。
一、通过ingress-nginx实现灰度发布原理
ingress-nginx是Kubernetes官方推荐的ingress controller,它是基于nginx实现的,增加了一组用于实现额外功能的Lua插件。
为了实现灰度发布,ingress-nginx通过定义annotation来实现不同场景的灰度发布,其支持的规则如下:
- nginx.ingress.kubernetes.io/canary-by-header:基于 Request Header 的流量切分,适用于灰度发布以及 A/B 测试。当 Request Header 设置为 always时,请求将会被一直发送到 Canary 版本;当 Request Header 设置为 never时,请求不会被发送到 Canary 入口;对于任何其他 Header 值,将忽略 Header,并通过优先级将请求与其他金丝雀规则进行优先级的比较。
- nginx.ingress.kubernetes.io/canary-by-header-value:要匹配的 Request Header 的值,用于通知 Ingress 将请求路由到 Canary Ingress 中指定的服务。当 Request Header 设置为此值时,它将被路由到 Canary 入口。该规则允许用户自定义 Request Header 的值,必须与上一个 annotation (即:canary-by-header)一起使用。
- nginx.ingress.kubernetes.io/canary-weight:基于服务权重的流量切分,适用于蓝绿部署,权重范围 0 - 100 按百分比将请求路由到 Canary Ingress 中指定的服务。权重为 0 意味着该金丝雀规则不会向 Canary 入口的服务发送任何请求。权重为 100 意味着所有请求都将被发送到 Canary 入口。
- nginx.ingress.kubernetes.io/canary-by-cookie:基于 Cookie 的流量切分,适用于灰度发布与 A/B 测试。用于通知 Ingress 将请求路由到 Canary Ingress 中指定的服务的cookie。当 cookie 值设置为 always时,它将被路由到 Canary 入口;当 cookie 值设置为 never时,请求不会被发送到 Canary 入口;对于任何其他值,将忽略 cookie 并将请求与其他金丝雀规则进行优先级的比较。
以上规则优先顺序为:
canary-by-header -> canary-by-cookie -> canary-weight
二、通过ingress-nginx实现灰度发布场景
2.1 基于服务权重的流量切分
假如在生产上已经运行了A应用对外提供服务,此时开发修复了一些Bug,需要发布A1版本将其上线,但又不希望直接的将所有流量接入到新的A1版本,而是希望将10%的流量进入到A1中,待A1稳定后,才会将所有流量接入进来,再下线原来的A版本。
实现方法:
在canary ingress中添加如下annotation
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-by-header: "Region"
nginx.ingress.kubernetes.io/canary-by-header-value: "shenzhen"
其中:
nginx.ingress.kubernetes.io/canary: “true” 开启canary
nginx.ingress.kubernetes.io/canary-by-header: “Region” 指定header关键字
nginx.ingress.kubernetes.io/canary-by-header-value: “shenzhen” 指定header关键字对应的value
三、通过ingress-nginx实现灰度发布实现思路
1、在K8S集群中运行2个应用版本,一个是stable版本,一个是canary版本
2、定义stable版本ingress,提供运行的应用正常访问;定义canary版本,在metadata中添加annotation实现类度发布,例如根据流量百分比或用户请求header
3、经过一定时间的运行,canary版本可正常提供服务后,将其切换为stable版本,并将原stable版本下线即可
四、通过ingress-nginx实现灰度发布系统
4.1 负载均衡器metallb部署
4.1.1 kube-proxy代理模式修改
[root@k8s-master01 ~]# kubectl get configmap -n kube-system
NAME DATA AGE
......
kube-proxy 2 35h
[root@k8s-master01 ~]# kubectl edit configmap kube-proxy -n kube-system
ipvs:
excludeCIDRs: null
minSyncPeriod: 0s
scheduler: ""
strictARP: true 由原来的flase修改为true
syncPeriod: 0s
tcpFinTimeout: 0s
tcpTimeout: 0s
udpTimeout: 0s
kind: KubeProxyConfiguration
logging:
flushFrequency: 0
options:
json:
infoBufferSize: "0"
verbosity: 0
metricsBindAddress: ""
mode: "ipvs" 默认为空,添加ipvs
[root@k8s-master01 ~]# kubectl rollout restart daemonset kube-proxy -n kube-system
4.1.2 metallb部署
4.1.2.1 metallb部署
[root@k8s-master01 ~]# kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.11/config/manifests/metallb-native.yaml
4.1.2.2 IP地址池准备
[root@k8s-master01 ~]# vim ippool.yaml
[root@k8s-master01 ~]# cat ippool.yaml
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: first-pool
namespace: metallb-system
spec:
addresses:
- 192.168.10.240-192.168.10.250
[root@k8s-master01 ~]# kubectl apply -f ippool.yaml
4.1.2.3 开启二层通告
[root@k8s-master01 ~]# vim l2.yaml
[root@k8s