在ACK集群中通過(guò)ALB Ingress實(shí)現(xiàn)灰度發(fā)布
當(dāng)服務(wù)迭代更新升級(jí)時(shí),需要使用灰度發(fā)布來(lái)保證系統(tǒng)的穩(wěn)定性。ALB Ingress支持使用canary注解實(shí)現(xiàn)基于Header、Cookie、Weight的灰度發(fā)布。三種灰度策略的優(yōu)先級(jí)為Header>Cookie>Weight。同時(shí)配置三種策略時(shí),優(yōu)先級(jí)高的策略將優(yōu)先進(jìn)行灰度。
前提條件
已創(chuàng)建ACK托管集群、ACK專有集群或ACK Serverless集群,Kubernetes版本為1.18及以上版本。具體操作,請(qǐng)參見創(chuàng)建Kubernetes托管版集群、創(chuàng)建Kubernetes專有版集群、容器服務(wù) Serverless 版使用快速入門。
已創(chuàng)建兩個(gè)不同可用區(qū)的交換機(jī),且與集群處于同一VPC。具體操作,請(qǐng)參見創(chuàng)建和管理交換機(jī)。
已為集群安裝ALB Ingress Controller組件。具體操作,請(qǐng)參見管理ALB Ingress Controller組件。
說(shuō)明若需要在ACK專有集群中通過(guò)ALB Ingress訪問(wèn)服務(wù),在部署服務(wù)前需要為ALB Ingress Controller授權(quán)。具體操作,請(qǐng)參見為ACK專有集群授予ALB Ingress Controller訪問(wèn)權(quán)限。
已創(chuàng)建ALBConfig和IngressClass。具體操作,請(qǐng)參見創(chuàng)建ALBConfig。
注意事項(xiàng)
canary灰度發(fā)布不支持在同一條Ingress上基于Header/Cookie灰度策略與基于權(quán)重Weight灰度策略同時(shí)配置,需要拆分為兩條Ingress或通過(guò)自定義轉(zhuǎn)發(fā)動(dòng)作實(shí)現(xiàn)。
通過(guò)canary注解項(xiàng)實(shí)現(xiàn)灰度發(fā)布時(shí),ALB Ingress轉(zhuǎn)發(fā)規(guī)則生效順序依賴
Ingress namespace/name
字典序,為保證灰度規(guī)則生效順序,可以使用alb.ingress.kubernetes.io/order
標(biāo)識(shí)Ingress之間的生效順序。alb.ingress.kubernetes.io/order
的取值范圍為1~1000,默認(rèn)標(biāo)識(shí)為數(shù)字10,值越小表示優(yōu)先級(jí)越高。例如,如果您想提高Ingress的優(yōu)先級(jí),可以將目標(biāo)Ingress的alb.ingress.kubernetes.io/order
數(shù)值調(diào)小。您可以通過(guò)自定義轉(zhuǎn)發(fā)動(dòng)作實(shí)現(xiàn)基于更豐富的轉(zhuǎn)發(fā)條件的灰度發(fā)布策略。關(guān)于自定義轉(zhuǎn)發(fā)規(guī)則,請(qǐng)參見自定義ALB Ingress的轉(zhuǎn)發(fā)規(guī)則。
步驟一:部署服務(wù)
部署服務(wù)tea。
使用以下內(nèi)容,創(chuàng)建tea-deploy.yaml。
apiVersion: apps/v1 kind: Deployment metadata: name: tea spec: replicas: 1 selector: matchLabels: app: tea template: metadata: labels: app: tea spec: containers: - name: tea image: registry.cn-hangzhou.aliyuncs.com/acs-sample/old-nginx:latest ports: - containerPort: 80
執(zhí)行以下命令,部署服務(wù)tea。
kubectl apply -f tea-deploy.yaml
部署名為tea-svc的Service。
使用以下內(nèi)容,創(chuàng)建tea-svc.yaml。
apiVersion: v1 kind: Service metadata: name: tea-svc spec: ports: - port: 80 targetPort: 80 protocol: TCP selector: app: tea type: NodePort
執(zhí)行以下命令,部署Service。
kubectl apply -f tea-svc.yaml
部署名為tea-ingress的Ingress。
使用以下內(nèi)容,創(chuàng)建tea-ingress.yaml。
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: tea-ingress spec: ingressClassName: alb rules: - host: demo.domain.ingress.top # 請(qǐng)?zhí)鎿Q成您自己的域名,并確保它已正確解析到Ingress控制器所在的負(fù)載均衡器的IP地址。 http: paths: - path: / pathType: Prefix backend: service: name: tea-svc port: number: 80
執(zhí)行以下命令,部署Ingress。
kubectl apply -f tea-ingress.yaml
步驟二:灰度發(fā)布新版本服務(wù)
部署新版本服務(wù)和Ingress,使得當(dāng)請(qǐng)求Header為location: hz
時(shí)將路由到新版本服務(wù)canary,其他請(qǐng)求Header以及不攜帶請(qǐng)求Header將以50%的權(quán)重路由到新版本服務(wù)canary。
部署新版本服務(wù)canary。
使用以下內(nèi)容,創(chuàng)建canary-deploy.yaml。
apiVersion: apps/v1 kind: Deployment metadata: name: canary spec: replicas: 1 selector: matchLabels: app: canary template: metadata: labels: app: canary spec: containers: - name: canary image: registry.cn-hangzhou.aliyuncs.com/acs-sample/new-nginx:latest ports: - containerPort: 80
執(zhí)行以下命令,部署canary。
kubectl apply -f canary-deploy.yaml
部署名為canary-svc的Service。
使用以下內(nèi)容,創(chuàng)建canary-svc.yaml。
apiVersion: v1 kind: Service metadata: name: canary-svc spec: ports: - port: 80 targetPort: 80 protocol: TCP selector: app: canary type: NodePort
執(zhí)行以下命令,部署Service。
kubectl apply -f canary-svc.yaml
部署基于Header分配流量的Ingress。
使用以下內(nèi)容,創(chuàng)建canary-header-ingress.yaml。
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: alb.ingress.kubernetes.io/canary: "true" alb.ingress.kubernetes.io/canary-by-header: "location" alb.ingress.kubernetes.io/canary-by-header-value: "hz" name: canary-header-ingress namespace: default spec: ingressClassName: alb rules: - host: demo.domain.ingress.top # 請(qǐng)?zhí)鎿Q成您自己的域名,并確保它已正確解析到Ingress控制器所在的負(fù)載均衡器的IP地址。 http: paths: - backend: service: name: canary-svc port: number: 80 path: / pathType: Prefix
alb.ingress.kubernetes.io/canary:設(shè)置為true,表示啟用canary注解功能。
alb.ingress.kubernetes.io/canary-by-header與alb.ingress.kubernetes.io/canary-by-header-value:設(shè)置請(qǐng)求Header的鍵值對(duì)。本文設(shè)置為
location: hz
,表示請(qǐng)求Header為location: hz
,請(qǐng)求流量會(huì)被分配到新版本服務(wù);對(duì)于其他Header,將會(huì)忽略,并通過(guò)灰度優(yōu)先級(jí)將請(qǐng)求流量分配到其他規(guī)則設(shè)置的新版本服務(wù)。
執(zhí)行以下命令,部署基于Header分配流量的Ingress。
kubectl apply -f canary-header-ingress.yaml
部署基于權(quán)重分配流量的Ingress。
使用以下內(nèi)容,創(chuàng)建canary-weight-ingress.yaml。
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: alb.ingress.kubernetes.io/canary: "true" alb.ingress.kubernetes.io/canary-weight: "50" name: canary-weight-ingress namespace: default spec: ingressClassName: alb rules: - host: demo.domain.ingress.top # 請(qǐng)?zhí)鎿Q成您自己的域名,并確保它已正確解析到Ingress控制器所在的負(fù)載均衡器的IP地址。 http: paths: - backend: service: name: canary-svc port: number: 80 path: / pathType: Prefix
alb.ingress.kubernetes.io/canary-weight:設(shè)置路由到新版本服務(wù)的流量百分比。本文設(shè)置為50,表示50%的流量將路由到新版本服務(wù)。
執(zhí)行以下命令,部署基于權(quán)重分配流量的Ingress。
kubectl apply -f canary-weight-ingress.yaml
驗(yàn)證灰度發(fā)布新版本服務(wù)是否成功。
執(zhí)行以下命令,獲取ALB實(shí)例的訪問(wèn)地址。
kubectl get ing
預(yù)期輸出:
NAME CLASS HOSTS ADDRESS PORTS AGE canary-header-ingress alb demo.domain.ingress.top alb-ny3ute4r8yevni****.cn-chengdu.alb.aliyuncs.com 80 8m23s canary-weight-ingress alb demo.domain.ingress.top alb-ny3ute4r8yevni****.cn-chengdu.alb.aliyuncs.com 80 8m16s tea-ingress alb demo.domain.ingress.top alb-ny3ute4r8yevni****.cn-chengdu.alb.aliyuncs.com 80 7m5s
執(zhí)行以下命令,多次使用攜帶
location: hz
請(qǐng)求頭的請(qǐng)求訪問(wèn)服務(wù)。curl -H Host:demo.domain.ingress.top -H "location:hz" http://alb-ny3ute4r8yevni****.cn-chengdu.alb.aliyuncs.com
預(yù)期輸出:
new
多次使用攜帶
location: hz
請(qǐng)求頭的請(qǐng)求訪問(wèn)服務(wù),都返回new
的結(jié)果,說(shuō)明使用攜帶location: hz
請(qǐng)求頭的請(qǐng)求訪問(wèn)服務(wù)時(shí),請(qǐng)求都路由到新版本服務(wù)。多次執(zhí)行以下命令,發(fā)送不攜帶請(qǐng)求頭的請(qǐng)求訪問(wèn)服務(wù)。
curl -H Host:demo.domain.ingress.top http://alb-ny3ute4r8yevni****.cn-chengdu.alb.aliyuncs.com
多次不攜帶請(qǐng)求頭的請(qǐng)求訪問(wèn)服務(wù),50%概率返回
new
的結(jié)果,50%概率返回old
的結(jié)果,說(shuō)明不攜帶請(qǐng)求頭的請(qǐng)求訪問(wèn)服務(wù)時(shí),請(qǐng)求按照50%權(quán)重路由到新版本服務(wù)。多次執(zhí)行以下命令,使攜帶
location: bj
請(qǐng)求頭的請(qǐng)求訪問(wèn)服務(wù)。curl -H Host:demo.domain.ingress.top -H "location:bj" http://alb-ny3ute4r8yevni****.cn-chengdu.alb.aliyuncs.com
多次攜帶
location: bj
請(qǐng)求頭的請(qǐng)求訪問(wèn)服務(wù),50%的概率返回new
的結(jié)果,50%的概率返回old
的結(jié)果,說(shuō)明攜帶location: bj
請(qǐng)求頭的請(qǐng)求訪問(wèn)服務(wù)時(shí),請(qǐng)求按照50%的權(quán)重路由到新版本服務(wù)。
根據(jù)以上結(jié)果,可以看到當(dāng)請(qǐng)求Header為
location: hz
時(shí)將路由到新版本服務(wù)canary,不攜帶請(qǐng)求Header以及其他請(qǐng)求Header以50%的權(quán)重路由到新版本服務(wù)canary,說(shuō)明灰度發(fā)布canary服務(wù)成功。
步驟三:下線老版本服務(wù)
系統(tǒng)運(yùn)行一段時(shí)間后,當(dāng)新版本服務(wù)已經(jīng)穩(wěn)定并且符合預(yù)期后,需要下線舊版本的服務(wù),僅保留新版本服務(wù)在線上運(yùn)行。為了達(dá)到該目標(biāo),需要將原服務(wù)的Ingress中的Service修改為新版本服務(wù)的Service,使得流量都路由到新版本服務(wù),然后刪除灰度Ingress。
執(zhí)行以下命令,修改tea-ingress.yaml文件。
vim tea-ingress.yaml
將tea-ingress.yaml文件中的Service由tea-svc修改為canary-svc。
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: tea-ingress spec: ingressClassName: alb rules: - host: demo.domain.ingress.top # 請(qǐng)?zhí)鎿Q成您自己的域名,并確保它已正確解析到Ingress控制器所在的負(fù)載均衡器的IP地址。 http: paths: - path: / pathType: Prefix backend: service: name: canary-svc # 將tea-svc替換為canary-svc。 port: number: 80
執(zhí)行以下命令,使修改后的Ingress生效。
kubectl apply -f tea-ingress.yaml
驗(yàn)證下線老版本服務(wù)是否成功。
執(zhí)行以下命令,多次使用攜帶
location: hz
請(qǐng)求頭的請(qǐng)求訪問(wèn)服務(wù)。curl -H Host:demo.domain.ingress.top -H "location:hz" http://alb-ny3ute4r8yevni****.cn-chengdu.alb.aliyuncs.com
預(yù)期輸出:
new
多次使用攜帶
location: hz
請(qǐng)求頭的請(qǐng)求訪問(wèn)服務(wù),都返回new
的結(jié)果,說(shuō)明使用攜帶location: hz
請(qǐng)求頭的請(qǐng)求訪問(wèn)服務(wù)時(shí),請(qǐng)求都路由到新版本服務(wù)。執(zhí)行以下命令,多次使用不攜帶請(qǐng)求頭的請(qǐng)求訪問(wèn)服務(wù)。
curl -H Host:demo.domain.ingress.top http://alb-ny3ute4r8yevni****.cn-chengdu.alb.aliyuncs.com
預(yù)期輸出:
new
多次使用不攜帶請(qǐng)求頭的請(qǐng)求訪問(wèn)服務(wù),都返回
new
的結(jié)果,說(shuō)明使用不攜帶請(qǐng)求頭的請(qǐng)求訪問(wèn)服務(wù)時(shí),請(qǐng)求都路由到新版本服務(wù)。執(zhí)行以下命令,使多次攜帶
location: bj
請(qǐng)求頭的請(qǐng)求訪問(wèn)服務(wù)。curl -H Host:demo.domain.ingress.top -H "location:bj" http://alb-ny3ute4r8yevni****.cn-chengdu.alb.aliyuncs.com
預(yù)期輸出:
new
多次使用攜帶
location: bj
請(qǐng)求頭的請(qǐng)求訪問(wèn)服務(wù),都返回new
的結(jié)果,說(shuō)明使用攜帶location: bj
請(qǐng)求頭的請(qǐng)求訪問(wèn)服務(wù)時(shí),請(qǐng)求都路由到新版本服務(wù)。
根據(jù)以上結(jié)果,可以看到攜帶
location: hz
請(qǐng)求頭,攜帶其他請(qǐng)求頭,或者不攜帶請(qǐng)求頭的請(qǐng)求都路由到新版本服務(wù),說(shuō)明下線老版本服務(wù)成功。執(zhí)行以下命令,刪除名為canary-weight-ingress和canary-header-ingress的灰度Ingress。
kubectl delete ing canary-weight-ingress canary-header-ingress