當服務迭代更新升級時,需要使用灰階發布來保證系統的穩定性。ALB Ingress支援使用canary註解實現基於Header、Cookie、Weight的灰階發布。三種灰階策略的優先順序為Header>Cookie>Weight。同時配置三種策略時,優先順序高的策略將優先進行灰階。
前提條件
已建立ACK託管叢集、ACK專有叢集或ACK Serverless叢集,Kubernetes版本為1.18及以上版本。具體操作,請參見建立Kubernetes託管版叢集、建立Kubernetes專有版叢集、Container Service Serverless 版使用快速入門。
已建立兩個不同可用性區域的交換器,並且與叢集處於同一VPC。具體操作,請參見建立和管理交換器。
已為叢集安裝ALB Ingress Controller組件。具體操作,請參見管理ALB Ingress Controller組件。
說明若需要在ACK專有叢集中通過ALB Ingress訪問服務,在部署服務前需要為ALB Ingress Controller授權。具體操作,請參見為ACK專有叢集授予ALB Ingress Controller存取權限。
已建立ALBConfig和IngressClass。具體操作,請參見建立ALBConfig。
注意事項
canary灰階發布不支援在同一條Ingress上基於Header/Cookie灰階策略與基於權重Weight灰階策略同時配置,需要拆分為兩條Ingress或通過自訂轉寄動作實現。
通過canary註解項實現灰階發布時,ALB Ingress轉寄規則生效順序依賴
Ingress namespace/name
字典序,為保證灰階規則生效順序,可以使用alb.ingress.kubernetes.io/order
標識Ingress之間的生效順序。alb.ingress.kubernetes.io/order
的取值範圍為1~1000,預設標識為數字10,值越小表示優先順序越高。例如,如果您想提高Ingress的優先順序,可以將目標Ingress的alb.ingress.kubernetes.io/order
數值調小。您可以通過自訂轉寄動作實現基於更豐富的轉寄條件的灰階發布策略。關於自訂轉寄規則,請參見自訂ALB Ingress的轉寄規則。
步驟一:部署服務
部署服務tea。
使用以下內容,建立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
執行以下命令,部署服務tea。
kubectl apply -f tea-deploy.yaml
部署名為tea-svc的Service。
使用以下內容,建立tea-svc.yaml。
apiVersion: v1 kind: Service metadata: name: tea-svc spec: ports: - port: 80 targetPort: 80 protocol: TCP selector: app: tea type: NodePort
執行以下命令,部署Service。
kubectl apply -f tea-svc.yaml
部署名為tea-ingress的Ingress。
使用以下內容,建立tea-ingress.yaml。
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: tea-ingress spec: ingressClassName: alb rules: - host: demo.domain.ingress.top # 請替換成您自己的網域名稱,並確保它已正確解析到Ingress控制器所在的負載平衡器的IP地址。 http: paths: - path: / pathType: Prefix backend: service: name: tea-svc port: number: 80
執行以下命令,部署Ingress。
kubectl apply -f tea-ingress.yaml
步驟二:灰階發布新版本服務
部署新版本服務和Ingress,使得當請求Header為location: hz
時將路由到新版本服務canary,其他請求Header以及不攜帶請求Header將以50%的權重路由到新版本服務canary。
部署新版本服務canary。
使用以下內容,建立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
執行以下命令,部署canary。
kubectl apply -f canary-deploy.yaml
部署名為canary-svc的Service。
使用以下內容,建立canary-svc.yaml。
apiVersion: v1 kind: Service metadata: name: canary-svc spec: ports: - port: 80 targetPort: 80 protocol: TCP selector: app: canary type: NodePort
執行以下命令,部署Service。
kubectl apply -f canary-svc.yaml
部署基於Header分配流量的Ingress。
使用以下內容,建立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 # 請替換成您自己的網域名稱,並確保它已正確解析到Ingress控制器所在的負載平衡器的IP地址。 http: paths: - backend: service: name: canary-svc port: number: 80 path: / pathType: Prefix
alb.ingress.kubernetes.io/canary:設定為true,表示啟用canary註解功能。
alb.ingress.kubernetes.io/canary-by-header與alb.ingress.kubernetes.io/canary-by-header-value:佈建要求Header的索引值對。本文設定為
location: hz
,表示請求Header為location: hz
,請求流量會被分配到新版本服務;對於其他Header,將會忽略,並通過灰階優先順序將請求流量分配到其他規則設定的新版本服務。
執行以下命令,部署基於Header分配流量的Ingress。
kubectl apply -f canary-header-ingress.yaml
部署基於權重分配流量的Ingress。
使用以下內容,建立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 # 請替換成您自己的網域名稱,並確保它已正確解析到Ingress控制器所在的負載平衡器的IP地址。 http: paths: - backend: service: name: canary-svc port: number: 80 path: / pathType: Prefix
alb.ingress.kubernetes.io/canary-weight:設定路由到新版本服務的流量百分比。本文設定為50,表示50%的流量將路由到新版本服務。
執行以下命令,部署基於權重分配流量的Ingress。
kubectl apply -f canary-weight-ingress.yaml
驗證灰階發布新版本服務是否成功。
執行以下命令,擷取ALB執行個體的訪問地址。
kubectl get ing
預期輸出:
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
執行以下命令,多次使用攜帶
location: hz
要求標頭的請求訪問服務。curl -H Host:demo.domain.ingress.top -H "location:hz" http://alb-ny3ute4r8yevni****.cn-chengdu.alb.aliyuncs.com
預期輸出:
new
多次使用攜帶
location: hz
要求標頭的請求訪問服務,都返回new
的結果,說明使用攜帶location: hz
要求標頭的請求訪問服務時,請求都路由到新版本服務。多次執行以下命令,發送不攜帶要求標頭的請求訪問服務。
curl -H Host:demo.domain.ingress.top http://alb-ny3ute4r8yevni****.cn-chengdu.alb.aliyuncs.com
多次不攜帶要求標頭的請求訪問服務,50%機率返回
new
的結果,50%機率返回old
的結果,說明不攜帶要求標頭的請求訪問服務時,請求按照50%權重路由到新版本服務。多次執行以下命令,使攜帶
location: bj
要求標頭的請求訪問服務。curl -H Host:demo.domain.ingress.top -H "location:bj" http://alb-ny3ute4r8yevni****.cn-chengdu.alb.aliyuncs.com
多次攜帶
location: bj
要求標頭的請求訪問服務,50%的機率返回new
的結果,50%的機率返回old
的結果,說明攜帶location: bj
要求標頭的請求訪問服務時,請求按照50%的權重路由到新版本服務。
根據以上結果,可以看到當請求Header為
location: hz
時將路由到新版本服務canary,不攜帶請求Header以及其他請求Header以50%的權重路由到新版本服務canary,說明灰階發布canary服務成功。
步驟三:下線老版本服務
系統運行一段時間後,當新版本服務已經穩定並且符合預期後,需要下線舊版本的服務,僅保留新版本服務線上上運行。為了達到該目標,需要將原服務的Ingress中的Service修改為新版本服務的Service,使得流量都路由到新版本服務,然後刪除灰階Ingress。
執行以下命令,修改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 # 請替換成您自己的網域名稱,並確保它已正確解析到Ingress控制器所在的負載平衡器的IP地址。 http: paths: - path: / pathType: Prefix backend: service: name: canary-svc # 將tea-svc替換為canary-svc。 port: number: 80
執行以下命令,使修改後的Ingress生效。
kubectl apply -f tea-ingress.yaml
驗證下線老版本服務是否成功。
執行以下命令,多次使用攜帶
location: hz
要求標頭的請求訪問服務。curl -H Host:demo.domain.ingress.top -H "location:hz" http://alb-ny3ute4r8yevni****.cn-chengdu.alb.aliyuncs.com
預期輸出:
new
多次使用攜帶
location: hz
要求標頭的請求訪問服務,都返回new
的結果,說明使用攜帶location: hz
要求標頭的請求訪問服務時,請求都路由到新版本服務。執行以下命令,多次使用不攜帶要求標頭的請求訪問服務。
curl -H Host:demo.domain.ingress.top http://alb-ny3ute4r8yevni****.cn-chengdu.alb.aliyuncs.com
預期輸出:
new
多次使用不攜帶要求標頭的請求訪問服務,都返回
new
的結果,說明使用不攜帶要求標頭的請求訪問服務時,請求都路由到新版本服務。執行以下命令,使多次攜帶
location: bj
要求標頭的請求訪問服務。curl -H Host:demo.domain.ingress.top -H "location:bj" http://alb-ny3ute4r8yevni****.cn-chengdu.alb.aliyuncs.com
預期輸出:
new
多次使用攜帶
location: bj
要求標頭的請求訪問服務,都返回new
的結果,說明使用攜帶location: bj
要求標頭的請求訪問服務時,請求都路由到新版本服務。
根據以上結果,可以看到攜帶
location: hz
要求標頭,攜帶其他要求標頭,或者不攜帶要求標頭的請求都路由到新版本服務,說明下線老版本服務成功。執行以下命令,刪除名為canary-weight-ingress和canary-header-ingress的灰階Ingress。
kubectl delete ing canary-weight-ingress canary-header-ingress