灰階發布是一種常用的軟體發布策略,通過漸進式地向使用者推送新版本的服務,來保證生產環境中服務迭代升級時系統的穩定性。ALB Ingress支援使用canary註解實現基於Header、Cookie、Weight的灰階發布。本文介紹如何通過ALB Ingress的canary註解實現服務的灰階發布。
前提條件
已建立ACS叢集。具體操作,請參見建立ACS叢集。
已為ACS叢集安裝ALB Ingress Controller組件。具體操作,請參見管理ALB Ingress Controller組件。
已建立AlbConfig和IngressClass。具體操作,請參見建立AlbConfig和建立IngressClass。
串連叢集。具體操作,請參見擷取叢集KubeConfig並通過kubectl工具串連叢集或在CloudShell上通過kubectl管理Kubernetes叢集。
注意事項
通過canary註解實現的三種灰階策略的優先順序為Header>Cookie>Weight,同時配置三種策略時,優先順序高的策略將優先進行灰階發布。關於canary註解的詳細資料,請參見ALB Ingress灰階發布註解。
canary灰階發布不支援在同一條Ingress上同時配置基於Header/Cookie的灰階策略與基於權重Weight的灰階策略,這種情境下需要通過拆分為兩條Ingress或通過自訂轉寄動作實現。自訂轉寄動作可以實現基於更豐富的轉寄條件的灰階發布策略。關於自訂轉寄規則,請參見自訂ALB 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
數值調小。
步驟一:部署服務
部署服務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: ClusterIP
執行以下命令,部署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
驗證部署成功。
執行以下命令,請求訪問服務。
curl -H Host:demo.domain.ingress.top http://alb-ny3ute4r8yevni****.cn-chengdu.alb.aliyuncs.com
預期輸出:
old
步驟二:灰階發布新版本服務
部署新版本服務和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: ClusterIP
執行以下命令,部署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 ingress
預期輸出:
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 ingress canary-weight-ingress canary-header-ingress