概述
您可以基于微服務治理在不修改任何業務代碼的情況下,實現全鏈路灰度的流量控制。本文介紹用戶如何通過自建網關實現全鏈路灰度功能。
前提條件
1、用戶已開通微服務治理中心企業版。
2、用戶已開通云容器引擎。
背景信息
在微服務架構下,一次需求可能會同時修改多個微服務應用。在發布應用時,通常將這些應用劃分為同一個分組,使灰度流量始終在灰度應用中流轉。當上游有灰度流量時,會通過引流的方式將灰度流量引導至灰度分組,在此次鏈路調用過程中,如果存在一些微服務沒有灰度環境,那這些請求在下游時依然能回到灰度環境中,以此實現全鏈路灰度。
通過使用微服務治理中心,可以在不修改業務代碼的情況下,輕松實現全鏈路灰度。本文介紹如何通過自建網關實現全鏈路灰度。
部署Demo應用
準備自建入口網關msgc-zuul,準備應用msgc-app-a,msgc-app-b和msgc-app-c。調用過程是msgc-app-a –> msgc-app-b -> msgc-app-c。
步驟1:在云容器引擎集群中安裝微服務治理插件:
- 登錄云容器引擎控制臺。
- 在左側菜單欄選擇集群,點擊目標集群。
- 在集群管理頁面點擊插件-插件市場,選擇cubems插件安裝。

步驟2:為應用開啟微服務治理能力:
- 登錄云容器引擎控制臺。
- 左側菜單欄選擇集群,點擊目標集群。
- 在集群管理頁面點擊工作負載-無狀態,選擇目標命名空間。

-
在Deployment列表頁選擇指定Deployment,并點擊全量替換,進入Deployment編輯頁。
-
在Deployment編輯頁點擊顯示高級設置,新增Pod標簽: mseCubeMsAutoEnable:on。
-
在發布應用時,配置指定環境變量,可指定注入微服務治理中心的應用名、命名空間和標簽等信息。
環境變量配置如下:
| 環境變量名 | 環境變量值 |
|---|---|
| MSE_APP_NAME | 接入到微服務治理中心的應用名。 |
| MSE_SERVICE_TAG | 應用標簽信息,如灰度應用可配置gray。 |
| MSE_NAMESPACE(選填) | 接入到微服務治理中心的命名空間,默認為:default。 |
- 完成編輯后點擊提交,重新發布容器即可接入。
app-a應用的配置:
基線:
apiVersion: "apps/v1"
kind: "Deployment"
metadata:
name: "app-a"
namespace: "default"
spec:
progressDeadlineSeconds: 600
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
name: "app-a"
template:
metadata:
labels:
mseCubeMsAutoEnable: "on"
name: "app-a"
spec:
containers:
- env:
- name: "MSE_APP_NAME"
value: "app-a"
image: "鏡像倉庫域名/xxx/app-a:latest"
imagePullPolicy: "Always"
name: "app-a"
ports:
- containerPort: 26160
livenessProbe:
tcpSocket:
port: 26160
initialDelaySeconds: 10
periodSeconds: 30
resources:
limits:
cpu: "1"
memory: "1Gi"
requests:
cpu: "1"
memory: "1Gi"
灰度:
apiVersion: "apps/v1"
kind: "Deployment"
metadata:
name: "app-a"
namespace: "default"
spec:
progressDeadlineSeconds: 600
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
name: "app-a"
template:
metadata:
labels:
mseCubeMsAutoEnable: "on"
name: "app-a"
spec:
containers:
- env:
- name: "MSE_APP_NAME"
value: "app-a"
- name: "MSE_SERVICE_TAG"
value: "gray"
image: "鏡像倉庫域名/xxx/app-a:latest"
imagePullPolicy: "Always"
name: "app-a"
ports:
- containerPort: 26160
livenessProbe:
tcpSocket:
port: 26160
initialDelaySeconds: 10
periodSeconds: 30
resources:
limits:
cpu: "1"
memory: "1Gi"
requests:
cpu: "1"
memory: "1Gi"
app-b應用的配置:
基線:
apiVersion: "apps/v1"
kind: "Deployment"
metadata:
name: "app-b"
namespace: "default"
spec:
progressDeadlineSeconds: 600
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
name: "app-b"
template:
metadata:
labels:
mseCubeMsAutoEnable: "on"
name: "app-b"
spec:
containers:
- env:
- name: "MSE_APP_NAME"
value: "app-b"
image: "鏡像倉庫域名/xxx/app-b:latest"
imagePullPolicy: "Always"
name: "app-b"
ports:
- containerPort: 26160
livenessProbe:
tcpSocket:
port: 26160
initialDelaySeconds: 10
periodSeconds: 30
resources:
limits:
cpu: "1"
memory: "1Gi"
requests:
cpu: "1"
memory: "1Gi"
灰度:
apiVersion: "apps/v1"
kind: "Deployment"
metadata:
name: "app-b"
namespace: "default"
spec:
progressDeadlineSeconds: 600
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
name: "app-b"
template:
metadata:
labels:
mseCubeMsAutoEnable: "on"
name: "app-b"
spec:
containers:
- env:
- name: "MSE_APP_NAME"
value: "app-b"
- name: "MSE_SERVICE_TAG"
value: "gray"
image: "鏡像倉庫域名/xxx/app-b:latest"
imagePullPolicy: "Always"
name: "app-b"
ports:
- containerPort: 26160
livenessProbe:
tcpSocket:
port: 26160
initialDelaySeconds: 10
periodSeconds: 30
resources:
limits:
cpu: "1"
memory: "1Gi"
requests:
cpu: "1"
memory: "1Gi"
app-c應用的配置:
基線:
apiVersion: "apps/v1"
kind: "Deployment"
metadata:
name: "app-c"
namespace: "default"
spec:
progressDeadlineSeconds: 600
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
name: "app-c"
template:
metadata:
labels:
mseCubeMsAutoEnable: "on"
name: "app-c"
spec:
containers:
- env:
- name: "MSE_APP_NAME"
value: "app-c"
image: "鏡像倉庫域名/xxx/app-c:latest"
imagePullPolicy: "Always"
name: "app-c"
ports:
- containerPort: 26160
livenessProbe:
tcpSocket:
port: 26160
initialDelaySeconds: 10
periodSeconds: 30
resources:
limits:
cpu: "1"
memory: "1Gi"
requests:
cpu: "1"
memory: "1Gi"
灰度:
apiVersion: "apps/v1"
kind: "Deployment"
metadata:
name: "app-c"
namespace: "default"
spec:
progressDeadlineSeconds: 600
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
name: "app-c"
template:
metadata:
labels:
mseCubeMsAutoEnable: "on"
name: "app-c"
spec:
containers:
- env:
- name: "MSE_APP_NAME"
value: "app-c"
- name: "MSE_SERVICE_TAG"
value: "gray"
image: "鏡像倉庫域名/xxx/app-c:latest"
imagePullPolicy: "Always"
name: "app-c"
ports:
- containerPort: 26160
livenessProbe:
tcpSocket:
port: 26160
initialDelaySeconds: 10
periodSeconds: 30
resources:
limits:
cpu: "1"
memory: "1Gi"
requests:
cpu: "1"
memory: "1Gi"
zuul應用的配置:
apiVersion: "apps/v1"
kind: "Deployment"
metadata:
name: "zuul"
namespace: "default"
spec:
progressDeadlineSeconds: 600
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
name: "zuul"
template:
metadata:
labels:
mseCubeMsAutoEnable: "on"
name: "zuul"
spec:
containers:
- env:
- name: "MSE_APP_NAME"
value: "zuul"
image: "鏡像倉庫域名/xxx/zuul:latest"
imagePullPolicy: "Always"
name: "zuul"
ports:
- containerPort: 26160
livenessProbe:
tcpSocket:
port: 26160
initialDelaySeconds: 10
periodSeconds: 30
resources:
limits:
cpu: "1"
memory: "1Gi"
requests:
cpu: "1"
memory: "1Gi"
創建泳道組及灰度泳道
step1:創建泳道組
- 登錄微服務治理控制臺。
- 在左側導航欄選擇全鏈路灰度,點擊創建泳道組。
- 在創建泳道組頁面,設置泳道組相關參數,然后單擊確定。

step2:創建泳道
- 找到目標泳道組頁面,點擊創建第一個分流泳道。
- 設置泳道名稱,選擇目標應用所屬標簽,創建泳道。

場景應用及驗證:通過設置泳道組路由規則,實現全鏈路灰度
step1:設置Header路由規則
設置路由規則,通過前端訪問傳過來不同的Header,在自建網關通過header判斷將流量路由到指定的泳道。


step2:通過Header驗證灰度流量
通過自建網關訪問app-a->app-b->app-c。
- 訪問基線環境,不帶上參數名為tag的header,流量路由到基線環境。
curl //localhost/a/callA


- 訪問灰度環境,帶上tag=gray的header,流量會自動路由到灰度泳道。
curl –H“tag:gray”//localhost/a/callA


基于上述實踐,可以看到,當前端請求帶上tag=gray的header時,會路由到灰度環境。
step3:通過設置Parameter實現標簽路由
路由規則除了設置Header以外,還可以通過設置Cookie、Parameter和Body Content實現流量路由。
設置路由規則,通過前端訪問傳過來不同的Parameter,在自建網關通過Parameter判斷將流量路由到指定的泳道。


step4:通過Parameter驗證灰度流量
通過自建網關訪問app-a->app-b->app-c。
- 訪問基線環境,當member不等于12345時,流量路由到基線環境。
curl //localhost/a/callA?memberId=123


- 訪問灰度環境,帶上memberId=12345的參數,流量會自動路由到灰度泳道。
curl //localhost/a/callA?memberId=12345


基于上述實踐,可以看到,當前端請求帶上memberId=12345的參數,會路由到灰度環境。