環(huán)境
kubernetes v1.15
nginx-ingress-controller v0.32.0
介紹
金絲雀發(fā)布:又叫灰度發(fā)布,控制產(chǎn)品從A版本平滑的過度到B版本
ingress-nginx:k8s ingress工具,支持金絲雀發(fā)布,可以實現(xiàn)基于權(quán)重、請求頭、請求頭的值、cookie轉(zhuǎn)發(fā)流量。
rancher:k8s集群管理工具,使用UI簡化k8s相關(guān)操作
ingress-nginx canary官方說明://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/nginx-configuration/annotations.md#canary
首先創(chuàng)建兩個nginx應(yīng)用
#deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: appv1
labels:
app: v1
spec:
replicas: 1
selector:
matchLabels:
app: v1
template:
metadata:
labels:
app: v1
spec:
containers:
- name: nginx
image: zerchin/canary:v1
ports:
- containerPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: appv2
labels:
app: v2
spec:
replicas: 1
selector:
matchLabels:
app: v2
template:
metadata:
labels:
app: v2
spec:
containers:
- name: nginx
image: zerchin/canary:v2
ports:
- containerPort: 80
kubectl查看pod
kubectl get pod -o wide |grep app
appv1-69bf545f96-lkqfm 1/1 Running 0 89m 172.17.0.12 minikube <none> <none>
appv2-787866684-b9hhh 1/1 Running 0 89m 172.17.0.11 minikube <none> <none>
這兩個應(yīng)用輸出以下內(nèi)容
$ curl 172.17.0.12
v1
$
$ curl 172.17.0.11
canary-v2
分別為應(yīng)用創(chuàng)建對應(yīng)的service
假設(shè)你已經(jīng)了解了svc 和deployment概念,這步操作你應(yīng)該了解。
#service.yaml
apiVersion: v1
kind: Service
metadata:
name: appv1
spec:
selector:
app: v1
ports:
- protocol: TCP
port: 80
targetPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: appv2
spec:
selector:
app: v2
ports:
- protocol: TCP
port: 80
targetPort: 80
驗證svc是否成功運行了
kubectl get svc |grep app
appv1 ClusterIP 10.109.87.198 <none> 80/TCP 7m
appv2 ClusterIP 10.106.40.192 <none> 80/TCP 7m
部署一個正常的ingress
路由到appv1上
#ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: app
namespace: default
spec:
rules:
- host: nginx2.192.168.99.101.xip.io
http:
paths:
- backend:
serviceName: appv1
servicePort: 80
path: /
kubectl查看ingress
kubectl get ingress
NAME HOSTS ADDRESS PORTS AGE
app nginx2.192.168.99.101.xip.io 192.168.99.101 80 9m43s
訪問nginx2.192.168.99.101.xip.io
curl nginx2.192.168.99.101.xip.io
###v1
金絲雀發(fā)布
有三種方法
金絲雀發(fā)布規(guī)則優(yōu)先級:canary-by-header -> canary-by-cookie -> canary-weight
目前,每個ingress規(guī)則最多可以應(yīng)用一個canary ingress
我把yaml文件貼出來,注釋掉分別就可以用了。
#canary.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/canary: "true"
# 基于cookie轉(zhuǎn)發(fā)流量 nginx.ingress.kubernetes.io/canary-by-cookie: "test"
# 基于請求頭轉(zhuǎn)發(fā)流量 nginx.ingress.kubernetes.io/canary-by-header: "canary"
# 基于請求頭和請求頭的值轉(zhuǎn)發(fā)流量 nginx.ingress.kubernetes.io/canary-by-header-value: "haha"
基于權(quán)重轉(zhuǎn)發(fā)流量 nginx.ingress.kubernetes.io/canary-weight: "30"
name: app-canary
namespace: default
spec:
rules:
- host: nginx2.192.168.99.101.xip.io
http:
paths:
- backend:
serviceName: appv2
servicePort: 80
path: /
1.基于權(quán)重轉(zhuǎn)發(fā)流量
nginx.ingress.kubernetes.io/canary-by-header:用于通知Ingress將請求路由到Canary Ingress中指定的服務(wù)的標(biāo)頭。當(dāng)請求標(biāo)頭設(shè)置always為時,它將被路由到Canary。當(dāng)標(biāo)頭設(shè)置never為時,它將永遠(yuǎn)不會路由到金絲雀。對于任何其他值,標(biāo)頭將被忽略,并且按優(yōu)先級將請求與其他金絲雀規(guī)則進行比較。
修改app-canary的ingress配置,修改annotation,如下:
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-by-header: "canary"
結(jié)果
for i in `seq 1 10`;do curl http://nginx2.192.168.99.101.xip.io/;done
canary-v2
canary-v2
canary-v2
v1
v1
v1
v1
v1
v1
v1
2.基于請求頭轉(zhuǎn)發(fā)流量
nginx.ingress.kubernetes.io/canary-by-header:用于通知Ingress將請求路由到Canary Ingress中指定的服務(wù)的標(biāo)頭。當(dāng)請求標(biāo)頭設(shè)置always為時,它將被路由到Canary。當(dāng)標(biāo)頭設(shè)置never為時,它將永遠(yuǎn)不會路由到金絲雀。對于任何其他值,標(biāo)頭將被忽略,并且按優(yōu)先級將請求與其他金絲雀規(guī)則進行比較。
修改app-canary的ingress配置,修改annotation,如下:
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-by-header: "canary"
測試結(jié)果
# curl http://nginx2.192.168.99.101.xip.io/
v1
# curl -H "canary:always" http://nginx2.192.168.99.101.xip.io/
canary-v2
3.基于請求頭和請求頭的值轉(zhuǎn)發(fā)流量
nginx.ingress.kubernetes.io/canary-by-header-value:匹配的報頭值,用于通知Ingress將請求路由到Canary Ingress中指定的服務(wù)。當(dāng)請求標(biāo)頭設(shè)置為此值時,它將被路由到Canary。對于任何其他標(biāo)頭值,標(biāo)頭將被忽略,并按優(yōu)先級將請求與其他金絲雀規(guī)則進行比較。此注釋必須與nginx.ingress.kubernetes.io/canary-by-header一起使用。
修改app-canary的ingress配置,修改annotation,如下:
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-by-header: "canary"
nginx.ingress.kubernetes.io/canary-by-header-value: "haha"
測試
# curl http://nginx2.192.168.99.101.xip.io/
v1
# curl -H "canary:haha" http://nginx2.192.168.99.101.xip.io/
canary-v2
# curl -H "canary:always" http://nginx2.192.168.99.101.xip.io/
v1
4.基于cookie轉(zhuǎn)發(fā)流量
nginx.ingress.kubernetes.io/canary-by-cookie:用于通知Ingress將請求路由到Canary Ingress中指定的服務(wù)的cookie。當(dāng)cookie值設(shè)置always為時,它將被路由到canary。當(dāng)cookie設(shè)置never為時,它將永遠(yuǎn)不會路由到Canary。對于任何其他值,將忽略cookie,并按優(yōu)先級將請求與其他canary規(guī)則進行比較。
修改app-canary的ingress配置,修改annotation,如下:
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-by-cookie: "test"
測試結(jié)果
# curl http://nginx2.192.168.99.101.xip.io/
v1
# curl -b "test=never" http://nginx2.192.168.99.101.xip.io/
v1
# curl -b "test=always" http://nginx2.192.168.99.101.xip.io/
canary-v2
# curl -b "test=1" http://nginx2.192.168.99.101.xip.io/
v1
高級的可以參考:
Kubernetes Ingress-nginx使用