當服務迭代更新升級時,需要使用灰度發布來保證系統的穩定性。ALB Ingress支持使用canary注解實現基于Header、Cookie、Weight的灰度發布。三種灰度策略的優先級為Header>Cookie>Weight。同時配置三種策略時,優先級高的策略將優先進行灰度。
前提條件
已創建ACK托管集群、ACK專有集群或ACK Serverless集群,Kubernetes版本為1.18及以上版本。具體操作,請參見創建Kubernetes托管版集群、創建Kubernetes專有版集群、容器服務 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