前端灰度發布與可監控、可回滾策略相結合,形成了一個強大的系統穩定性保障機制。通過這三個策略的協同工作,可以確保前端應用在不斷迭代和更新的同時,保持高性能和高穩定性,本文介紹如何通過配置MSE云原生網關實現前端灰度。
端到端全鏈路灰度實現
在微服務場景中,應用間的調用是隨機的。當您部署的Spring Cloud應用或Dubbo應用存在升級版本時,可能會導致無法將具有一定特征的流量路由到應用的目標版本。通過MSE提供的云原生網關實現全鏈路灰度,配合前端灰度方案,即可實現端到端的全鏈路灰度。
前端用戶每一次的請求都經過云原生網關,經過權限系統驗證后,所有請求的Cookie中都帶上了用戶的唯一標識,比如 userid: 001
。
網關掛載了一個 frontend-gray
插件,通過配置插件規則,將灰度流量進行映射并傳遞。
前提條件
已下載frontend-gray,源代碼請參見GitHub。
Ingress類型服務實現前端灰度
通過MSE Ingress訪問容器服務,請參見MSE Ingress訪問容器服務。
步驟1:使用容器服務部署應用
應用部署的具體操作,請參見創建無狀態工作負載Deployment。
frontend-base.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: frontend
template:
metadata:
labels:
app: frontend
spec:
containers:
- image: 'registry.cn-hangzhou.aliyuncs.com/mse-demo-hz/user-gray:base'
imagePullPolicy: Always
name: frontend
resources: {}
---
apiVersion: v1
kind: Service
metadata:
name: frontend-base-svc
namespace: default
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: frontend
type: ClusterIP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
labels:
ingress-controller: mse
namespace: default
name: frontend-base-ingress
spec:
ingressClassName: mse
rules:
- http:
paths:
- backend:
service:
name: frontend-base-svc
port:
number: 80
path: /
pathType: Prefix
frontend-gray.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend-gray
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: frontend-gray
template:
metadata:
labels:
app: frontend-gray
spec:
containers:
- image: 'registry.cn-hangzhou.aliyuncs.com/mse-demo-hz/user-gray:gray'
imagePullPolicy: Always
name: frontend-gray
resources: {}
---
apiVersion: v1
kind: Service
metadata:
name: frontend-gray-svc
namespace: default
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: frontend-gray
type: ClusterIP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
labels:
ingress-controller: mse
annotations:
nginx.ingress.kubernetes.io/canary: 'true'
nginx.ingress.kubernetes.io/canary-by-header: x-higress-tag
nginx.ingress.kubernetes.io/canary-by-header-value: gray
name: frontend-gray-ingress
namespace: default
spec:
ingressClassName: mse
rules:
- http:
paths:
- backend:
service:
name: frontend-gray-svc
port:
number: 80
path: /
pathType: Prefix
步驟2:MSE控制臺配置灰度插件
登錄MSE網關管理控制臺,并在頂部菜單欄選擇地域。
在左側導航欄,選擇云原生網關 > 網關列表,單擊目標網關名稱。
在左側導航欄,單擊插件市場。
在插件市場頁面,選擇自定義,然后單擊創建插件。
在創建插件面板,填寫插件參數信息,單擊確定,等待插件發布成功。
參數
值
插件名稱
frontend-gray
插件描述
frontend-gray
wasm實現語言
TinyGo
wasm文件
上傳下載的 frontend-gray(
main.wasm
)文件插件執行階段
默認階段
插件執行優先級
100
插件發布成功之后,單擊創建的插件
frontend-gray
選項卡,選擇插件配置 > 實例級插件規則。在實例級插件規則頁面配置如下規則,詳細配置可參見配置規則。
grayKey: userid rules: - name: beta-user grayKeyValue: - "00000002" - "00000003" baseDeployment: version: base grayDeployments: - name: beta-user version: gray enabled: true
步驟3:結果驗證
登錄容器服務控制臺,在左側導航欄選擇集群,在集群列表頁面單擊所創建的容器服務集群,進入集群詳情頁,在左側導航欄選擇網絡 > 路由,查看公網訪問端點。
訪問公網端點
8.136.xxx.xxx
,登錄admin/ice
賬號,訪問主版本,用戶ID為 00000001。訪問公網端點
8.136.xxx.xxx
,登錄普通用戶user/ice
,訪問灰度版本,用戶ID為 00000002。
ACK容器服務實現前端灰度
步驟1:使用容器服務部署應用
應用部署的具體操作,請參見創建無狀態工作負載Deployment。
frontend-base.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: frontend
template:
metadata:
labels:
app: frontend
spec:
containers:
- image: 'registry.cn-hangzhou.aliyuncs.com/mse-demo-hz/user-gray:base'
imagePullPolicy: Always
name: frontend
resources: {}
---
apiVersion: v1
kind: Service
metadata:
name: frontend-base-svc
namespace: default
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: frontend
type: ClusterIP
frontend-gray.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend-gray
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: frontend-gray
template:
metadata:
labels:
app: frontend-gray
spec:
containers:
- image: 'registry.cn-hangzhou.aliyuncs.com/mse-demo-hz/user-gray:gray'
imagePullPolicy: Always
name: frontend-gray
resources: {}
---
apiVersion: v1
kind: Service
metadata:
name: frontend-gray-svc
namespace: default
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: frontend-gray
type: ClusterIP
為ACK命名空間中的應用開啟MSE微服務治理
登錄MSE治理中心控制臺,并在頂部菜單欄選擇地域。
在左側導航欄,選擇治理中心 > 應用治理。
在應用列表頁面,單擊ACK應用接入。
在ACK應用接入對話框中,進行配置,配置完成后,單擊確定。
配置項
說明
集群類型
選擇ACK集群、ACK Serverless集群或ACS集群。
說明如果您尚未授權容器服務調用微服務引擎,則需要單擊請授權進行授權。
集群名稱/ID
選擇接入MSE微服務治理的集群名稱/ID,可通過關鍵詞搜索。
ack-onepilot
顯示ack-onepilot接入狀態。
如果您未安裝ack-onepilot,單擊ack-onepilot右側的點擊安裝,安裝完成后狀態會顯示為已安裝。
如果您使用子賬號接入,提示沒有權限使用時,您可以登錄容器服務管理控制臺進入目標集群,然后單擊運維管理>組件管理,找到ack-onepilot,點擊安裝。
說明該步驟接入的組件為ack-onepilot,您可以登錄容器服務管理控制臺進入目標集群,然后單擊運維管理>組件管理查看詳情。
ack-onepilot安裝后會自動注入探針,可能會導致應用啟動耗時增加(10s內)。
接入類型
選擇命名空間接入。
容器集群命名空間
選擇容器集群命名空間。
治理命名空間
選擇治理命名空間。在對應命名空間下重新部署現有應用或新創建的應用,均會接入到MSE微服務治理中。關于命名空間的相關信息,請參見微服務命名空間管理。
為單個應用開啟MSE微服務治理
登錄MSE治理中心控制臺,并在頂部菜單欄選擇地域。
在左側導航欄,選擇治理中心 > 應用治理。
在應用列表頁面,單擊ACK應用接入。
在ACK應用接入對話框中,進行配置,配置完成后,單擊確定。
配置項
說明
集群類型
選擇ACK集群、ACK Serverless集群或ACS集群。
說明如果您尚未授權容器服務調用微服務引擎,則需要單擊請授權進行授權。
集群名稱/ID
選擇接入MSE微服務治理的集群名稱/ID,可通過關鍵詞搜索。
ack-onepilot
顯示ack-onepilot接入狀態。
如果您未安裝ack-onepilot,單擊ack-onepilot右側的點擊安裝,安裝完成后狀態會顯示為已安裝。
如果您使用子賬號接入,提示沒有權限使用時,您可以登錄容器服務管理控制臺進入目標集群,然后單擊運維管理>組件管理,找到ack-onepilot,點擊安裝。
說明該步驟接入的組件為ack-onepilot,您可以登錄容器服務管理控制臺進入目標集群,然后單擊運維管理>組件管理查看詳情。
ack-onepilot安裝后會自動注入探針,可能會導致應用啟動耗時增加(10s內)。
接入類型
選擇單個應用接入。
接入步驟
按照接入步驟進行操作。
Step 1:進入集群工作負載-無狀態應用頁面,切換到應用的命名空間下。
Step 2:找到所接入的應用,點擊「查看Yaml」。
Step 3:按以下格式編輯Labels,完成后點擊「更新」。
spec: template: metadata: labels: # 填寫“on”表示開啟接入,需加上雙引號 msePilotAutoEnable: "on" # 填寫接入到的治理命名空間,值不存在可自動新建 mseNamespace: 202401 # 填寫接入MSE的實際應用名稱,需加上雙引號 msePilotCreateAppName: "your-deployment-name"
步驟2:MSE控制臺配置灰度插件
登錄MSE網關管理控制臺,并在頂部菜單欄選擇地域。
在左側導航欄,選擇云原生網關 > 網關列表,單擊目標網關名稱。
在左側導航欄,單擊插件市場。
在插件市場頁面,選擇自定義,然后單擊創建插件。
在創建插件面板,填寫插件參數信息,單擊確定,等待插件發布成功。
參數
值
插件名稱
frontend-gray
插件描述
frontend-gray
wasm實現語言
TinyGo
wasm文件
上傳下載的 frontend-gray(
main.wasm
)文件插件執行階段
默認階段
插件執行優先級
100
插件發布成功之后,單擊創建的插件
frontend-gray
選項卡,選擇插件配置 > 實例級插件規則。在實例級插件規則頁面配置如下規則,詳細配置可參見配置規則。
grayKey: userid rules: - name: beta-user grayKeyValue: - "00000002" - "00000003" baseDeployment: version: base grayDeployments: - name: beta-user version: gray enabled: true
步驟3:添加網關服務來源
登錄MSE網關管理控制臺,并在頂部菜單欄選擇地域。
在左側導航欄,選擇云原生網關 > 網關列表,單擊目標網關名稱。
在左側導航欄,選擇路由管理,然后選擇來源頁簽。
單擊創建來源。在創建來源面板,配置來源類型為容器服務,ACK/ACK Serverless集群選擇所創建的容器服務集群, 然后單擊確定。
步驟4:創建服務
登錄MSE網關管理控制臺,并在頂部菜單欄選擇地域。
在左側導航欄選擇云原生網關 > 網關列表。
在網關列表頁面,單擊目標網關名稱。
在左側導航欄,選擇路由管理,然后選擇服務頁簽。
單擊創建服務。在創建服務面板,配置服務相關參數,然后單擊確定。
步驟5:創建base路由
登錄MSE網關管理控制臺,并在頂部菜單欄選擇地域。
在左側導航欄,選擇云原生網關 > 網關列表,單擊目標網關名稱。
在左側導航欄,單擊路由管理,然后在路由頁簽單擊創建路由。
在創建路由頁面,配置相關項,然后單擊保存。
步驟6:創建gray路由
登錄MSE網關管理控制臺,并在頂部菜單欄選擇地域。
在左側導航欄,選擇云原生網關 > 網關列表,單擊目標網關名稱。
在左側導航欄,單擊路由管理,然后在路由頁簽單擊創建路由。
在創建路由頁面,配置相關配置項,然后單擊保存。
說明gray
代表灰度版本,和frontend-gray
配置中deploy.gray.version
對應
步驟7:結果驗證
登錄MSE網關管理控制臺,并在頂部菜單欄選擇地域。
在左側導航欄,選擇云原生網關 > 網關列表,單擊目標網關名稱。
在網關詳情頁面找到網關入口,查看公網訪問端點。
訪問公網端點
8.136.xxx.xxx
,登錄admin/ice
賬號,訪問主版本,用戶ID為 00000001。訪問公網端點
8.136.xxx.xxx
,登錄普通用戶user/ice
,訪問灰度版本,用戶ID為 00000002。
ECS類型服務實現前端灰度
步驟1:ECS分別部署兩個前端應用
基線應用地址為:120.79.137.243:80
灰度應用地址為:120.79.137.243:8081
步驟2:創建服務
登錄MSE網關管理控制臺,并在頂部菜單欄選擇地域。
在左側導航欄選擇云原生網關 > 網關列表。
在網關列表頁面,單擊目標網關名稱。
在左側導航欄,選擇路由管理,然后選擇服務頁簽。
單擊創建服務。在創建服務面板,服務來源為固定地址,配置服務相關參數,然后單擊確定。
步驟3:創建base路由
登錄MSE網關管理控制臺,并在頂部菜單欄選擇地域。
在左側導航欄,選擇云原生網關 > 網關列表,單擊目標網關名稱。
在左側導航欄,單擊路由管理,然后在路由頁簽單擊創建路由。
在創建路由頁面,配置相關配置項,然后單擊保存。
步驟4:創建gray路由
登錄MSE網關管理控制臺,并在頂部菜單欄選擇地域。
在左側導航欄,選擇云原生網關 > 網關列表,單擊目標網關名稱。
在左側導航欄,單擊路由管理,然后在路由頁簽單擊創建路由。
在創建路由頁面,配置相關項,然后單擊保存。
說明gray
代表灰度版本,和frontend-gray
配置中deploy.gray.version
對應
步驟5:MSE控制臺配置灰度插件
登錄MSE網關管理控制臺,并在頂部菜單欄選擇地域。
在左側導航欄,選擇云原生網關 > 網關列表,單擊目標網關名稱。
在左側導航欄,單擊插件市場。
在插件市場頁面,選擇自定義,然后單擊創建插件。
在創建插件面板,填寫插件參數信息,單擊確定,等待插件發布成功。
參數
值
插件名稱
frontend-gray
插件描述
frontend-gray
wasm實現語言
TinyGo
wasm文件
上傳下載的 frontend-gray(
main.wasm
)文件插件執行階段
默認階段
插件執行優先級
100
插件發布成功之后,單擊創建的插件
frontend-gray
選項卡,選擇插件配置 > 實例級插件規則。在實例級插件規則頁面配置如下規則,詳細配置可參見配置規則。
grayKey: userid rules: - name: beta-user grayKeyValue: - "00000002" - "00000003" baseDeployment: version: base grayDeployments: - name: beta-user version: gray enabled: true
步驟6:結果驗證
登錄MSE網關管理控制臺,并在頂部菜單欄選擇地域。
在左側導航欄,選擇云原生網關 > 網關列表,單擊目標網關名稱。
在網關詳情頁面找到網關入口,查看公網訪問端點。
訪問公網端點
8.136.xxx.xxx
,登錄admin/ice
賬號,訪問主版本,用戶ID為 00000001。訪問公網端點
8.136.xxx.xxx
,登錄普通用戶user/ice
,訪問灰度版本,用戶ID為 00000002。
CDN/OSS類型服務實現前端灰度
步驟1:OSS文件規劃
- app1 # 應用
- dev # dev版本
- index.html
- js
...
- css
...
- images
...
- 0.0.1 # 001版本
- index.html
- js
...
- css
...
- images
...
- 0.0.2 # 002版本
- index.html
- js
...
- css
...
- images
...
- app2
- dev
- index.html
- js
...
- css
...
- images
...
- 0.0.1
- index.html
- js
...
- css
...
- images
...
- 0.0.2
- index.html
- js
...
- css
...
- images
...
步驟2:創建服務
登錄MSE網關管理控制臺,并在頂部菜單欄選擇地域。
在左側導航欄選擇云原生網關 > 網關列表。
在網關列表頁面,單擊目標網關名稱。
在左側導航欄,選擇路由管理,然后選擇服務頁簽。
單擊創建服務。在創建服務面板,服務來源為DNS域名,域名列表填寫OSS地址,然后單擊確定。
重要如果OSS的和網關在同一個Region,建議填寫OSS的內網地址,如果不在一個Region,請填寫公網地址。
步驟3:創建路由
登錄MSE網關管理控制臺,并在頂部菜單欄選擇地域。
在左側導航欄,選擇云原生網關 > 網關列表,單擊目標網關名稱。
在左側導航欄,單擊路由管理,然后在路由頁簽單擊創建路由。
在創建路由頁面,配置相關項,然后單擊保存。
步驟4:MSE控制臺配置灰度插件
登錄MSE網關管理控制臺,并在頂部菜單欄選擇地域。
在左側導航欄,選擇云原生網關 > 網關列表,單擊目標網關名稱。
在左側導航欄,單擊插件市場。
在插件市場頁面,選擇自定義,然后單擊創建插件。
在創建插件面板,填寫插件參數信息,單擊確定,等待插件發布成功。
參數
值
插件名稱
frontend-gray
插件描述
frontend-gray
wasm實現語言
TinyGo
wasm文件
上傳下載的 frontend-gray(
main.wasm
)文件插件執行階段
默認階段
插件執行優先級
100
插件發布成功之后,單擊創建的插件
frontend-gray
選項卡,選擇插件配置 > 實例級插件規則。在實例級插件規則頁面配置如下規則,詳細配置可參見配置規則。
grayKey: userid rules: - name: beta-user grayKeyValue: - "00000002" - "00000003" rewrite: host: xx.oss-cn-shanghai.aliyuncs.com ##OSS 地址 indexRouting: "/app1": "/project-a/app1/{version}/index.html" #首頁(html)路徑重寫 fileRouting: "/app1": "/project-a/app1/{version}" #資源(css/js/images)路徑重寫 baseDeployment: version: dev grayDeployments: - name: beta-user version: 0.0.1 enabled: true
步驟5:結果驗證
登錄MSE網關管理控制臺,并在頂部菜單欄選擇地域。
在左側導航欄,選擇云原生網關 > 網關列表,單擊目標網關名稱。
在網關詳情頁面找到網關入口,查看公網訪問端點。
訪問公網端點
8.136.xxx.xxx
,登錄admin/ice
賬號,訪問主版本,用戶ID為 00000001。訪問公網端點
8.136.xxx.xxx
,登錄普通用戶user/ice
,訪問灰度版本,用戶ID為 00000002。
FAQ
前端灰度是否還可以配置重寫策略
如果服務來源是非CDN/OSS ,可以搭配重寫策略生效。
如果服務來源是CDN/OSS的前端灰度是不可以搭配重寫策略,因為相關的重寫策略在frontend-gray灰度插件中實現了,如果配置重寫策略,會發生沖突,返回403等一些異常情況。
是否可以往HTML首頁注入一些全局變量
可以在html的<head> 標簽中(一般是CSS樣式等屬性),或者<body>標簽的頭部和尾部注入一些全局JavaScript腳本。
通過injection往HTML首頁注入代碼,可以在head標簽注入代碼,也可以在body標簽的first和last位置注入代碼。
grayKey: userid
rules:
- name: inner-user
grayKeyValue:
- '00000001'
- '00000005'
baseDeployment:
version: base
grayDeployments:
- name: beta-user
version: gray
enabled: true
weight: 80
injection:
head:
- <script>console.log('Header')</script>
body:
first:
- <script>console.log('hello world before')</script>
- <script>console.log('hello world before1')</script>
last:
- <script>console.log('hello world after')</script>
- <script>console.log('hello world after2')</script>
灰度版本生效時機?
假設A用戶現在的前端版本是0.0.1
, 這時候發布前端版本 0.0.2
, 并且A客戶命中了灰度規則,是否能立即生效?
是不會立即生效,出于下面幾點原因考慮:
如果發布版本需要實時生效,這時候就需要由后端來動態控制版本。首先無法實現前后端發布解耦,其次頁面的穩定性強依賴這個接口,無法做CDN加速。
假設版本能夠實時生效,客戶在使用某個功能的時候,可能出現上一秒還在使用某個按鈕,下一秒這個按鈕就不見了的情況。體驗非常糟糕。
什么時機刷新頁面?
一般網站是有設置Session超時重新登錄,一段時間沒有訪問后,需重新登錄頁面。
用戶通過登錄頁面登錄到應用中。
所以,在登錄頁面的時候,需要刷新頁面,以獲取最新的灰度信息。前端登錄示例代碼如下:
async function handleLogin(values: LoginParams) {
try {
const result = await login(values);
if (result.success) {
message.success('登錄成功!');
await updateUserInfo();
const urlParams = new URL(window.location.href).searchParams;
window.location.href = `${urlParams.get('redirect') || '/'}`;
return;
}
console.log(result);
// 如果失敗去設置用戶錯誤信息,顯示提示信息
setLoginResult(result);
} catch (error) {
message.error('登錄失敗,請重試!');
console.log(error);
}
}