簡介:目前,業界已經總結出了幾種常見的服務釋出政策來解決版本更新過程中帶來的流量有損問題。本文首先會對這些普遍的釋出政策進行簡單的原了解析,最後結合阿裡雲的雲原生網關對這些釋出政策進行實踐。
作者 | 揚少
背景
目前,業界已經總結出了幾種常見的服務釋出政策來解決版本更新過程中帶來的流量有損問題。本文首先會對這些普遍的釋出政策進行簡單的原了解析,最後結合阿裡雲的雲原生網關對這些釋出政策進行實踐。
釋出政策
被業界廣泛采用的服務釋出政策包括藍綠釋出、A/B 測試以及金絲雀釋出。
1、藍綠釋出
藍綠釋出需要對服務的新版本進行備援部署,一般新版本的機器規格和數量與舊版本保持一緻,相當于該服務有兩套完全相同的部署環境,隻不過此時隻有舊版本在對外提供服務,新版本作為熱備。當服務進行版本更新時,我們隻需将流量全部切換到新版本即可,舊版本作為熱備。由于備援部署的緣故,是以不必擔心新版本的資源不夠。如果新版本上線後出現嚴重的程式 BUG,那麼我們隻需将流量全部切回至舊版本,大大縮短故障恢複的時間。待新版本完成 BUG 修複并重新部署之後,再将舊版本的流量切換到新版本。
藍綠釋出通過使用額外的機器資源來解決服務釋出期間的不可用問題,當服務新版本出現故障時,也可以快速将流量切回舊版本。
如圖,某服務舊版本為 v1,對新版本 v2 進行備援部署。版本更新時,将現有流量全部切換為新版本 v2。

當新版本 v2 存在程式 BUG 或者發生故障時,可以快速切回舊版本 v1。
藍綠部署的優點:
1、部署結構簡單,運維友善;
2、服務更新過程操作簡單,周期短。
藍綠部署的缺點:
1、資源備援,需要部署兩套生産環境;
2、新版本故障影響範圍大。
2、A/B 測試
相比于藍綠釋出的流量切換方式,A/B 測試基于使用者請求的元資訊将流量路由到新版本,這是一種基于請求内容比對的灰階釋出政策。隻有比對特定規則的請求才會被引流到新版本,常見的做法包括基于 Http Header 和 Cookie。基于 Http Header 方式的例子,例如 User-Agent 的值為 Android 的請求 (來自安卓系統的請求)可以通路新版本,其他系統仍然通路舊版本。基于 Cookie 方式的例子,Cookie 中通常包含具有業務語義的使用者資訊,例如普通使用者可以通路新版本,VIP 使用者仍然通路舊版本。
如圖,某服務目前版本為 v1,現在新版本 v2 要上線。希望安卓使用者可以嘗鮮新功能,其他系統使用者保持不變。
通過在監控平台觀察舊版本與新版本的成功率、RT 對比,當新版本整體服務預期後,即可将所有請求切換到新版本 v2,最後為了節省資源,可以逐漸下線到舊版本 v1。
A/B 測試的優點:
1、可以對特定的請求或者使用者提供服務新版本,新版本故障影響範圍小;
2、需要建構完備的監控平台,用于對比不同版本之間請求狀态的差異。
A/B 測試的缺點:
1、仍然存在資源備援,因為無法準确評估請求容量;
2、釋出周期長。
3、金絲雀釋出
在藍綠釋出中,由于存在流量整體切換,是以需要按照原服務占用的機器規模為新版本克隆一套環境,相當于要求原來1倍的機器資源。在 A/B 測試中,隻要能夠預估中比對特定規則的請求規模,我們可以按需為新版本配置設定額外的機器資源。相比于前兩種釋出政策,金絲雀釋出的思想則是将少量的請求引流到新版本上,是以部署新版本服務隻需極小數的機器。驗證新版本符合預期後,逐漸調整流量權重比例,使得流量慢慢從老版本遷移至新版本,期間可以根據設定的流量比例,對新版本服務進行擴容,同時對老版本服務進行縮容,使得底層資源得到最大化利用。
如圖,某服務目前版本為 v1,現在新版本 v2 要上線。為確定流量在服務更新過程中平穩無損,采用金絲雀釋出方案,逐漸将流量從老版本遷移至新版本。
金絲雀釋出的優點:
1、按比例将流量無差别地導向新版本,新版本故障影響範圍小;
2、釋出期間逐漸對新版本擴容,同時對老版本縮容,資源使用率高。
金絲雀釋出的缺點:
1、流量無差别地導向新版本,可能會影響重要使用者的體驗;
實踐
接下來,我們會基于阿裡雲的容器運維平台 ACK 以及 MSE 雲原生網關對以上介紹的三種釋出政策進行實踐。這裡我們采用最簡單的業務架構來展示,即一個雲原生網關、一個後端服務(響應中傳回目前版本資訊)和注冊中心。注冊中心決定了業務架構中服務發現方式,我們會分别以 K8s 容器服務和 Nacos 兩種服務發現機制來實踐不同的釋出政策。
1、前提條件
- 建立了阿裡雲容器運維平台 ACK
- 建立了 MSE 雲原生網關
- 建立了 MSE 注冊中心 Nacos(服務發現方式為 Nacos 時需要)
2、服務發現方式:K8s 容器服務
在這個例子中,我們使用 K8s 原生的服務發現方式,即通過聲明式 Service API 資源将後端服務注冊到 CoreDNS。例子中的後端服務提供一個查詢目前版本的接口/version,并且目前版本為 v1。雲原生網關深度內建 ACK,可以實時動态地從 ACK 叢集中擷取服務資訊,友善通過雲原生網關将該後端服務暴露給外部使用者。
業務架構如下圖:
1、部署
将以下資源(Service和Deployment)應用到 ACK 叢集,完成後端服務的部署和釋出,目前應用版本為 v1。
apiVersion: v1
kind: Service
metadata:
name: httpbin
spec:
ports:
- port: 8080
protocol: TCP
selector:
app: httpbin
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: httpbin-v1
spec:
replicas: 3
selector:
matchLabels:
app: httpbin
version: v1
template:
metadata:
labels:
app: httpbin
version: v1
spec:
containers:
- image: specialyang/spring-cloud-httpbin-k8s:v1
imagePullPolicy: Always
name: spring-cloud-httpbin-k8s
ports:
- containerPort: 8080
在雲原生網關的服務管理->來源管理中,添加目标 ACK 叢集。
在服務管理中導入要暴露給雲原生網關的服務 httpbin。
在 httpbin 服務的政策配置中添加服務版本 v1,注意需要選擇對應的标簽來篩選出 v1 版本的節點,因為目前我們隻部署了 v1 版本,是以 v1 版本的節點數占總執行個體數 100%。
在路由管理中為該服務建立一條路由規則,進而将服務暴露給外部使用者。httpbin 服務暴露的 api 的 path 為/version,請求轉發至服務 httpbin 的 v1 版本。
執行以下腳本測試請求的響應結果。
for i in {1..10}; do curl "${GATEWAY_EXTERNAL_IP}/version"; echo ""; done
version: v1
version: v1
version: v1
version: v1
version: v1
version: v1
version: v1
version: v1
version: v1
version: v1
2、藍綠部署
藍綠部署需要按照服務目前版本所占用的資源狀況為服務新版本申請同樣的資源規格,部署完畢之後将流量整體切換到服務新版本。
利用 K8s 的聲明式 API 資源部署 httpbin 服務的新版本 v2,副本數同樣是 3。
apiVersion: apps/v1
kind: Deployment
metadata:
name: httpbin-v2
spec:
replicas: 3
selector:
matchLabels:
app: httpbin
version: v2
template:
metadata:
labels:
app: httpbin
version: v2
spec:
containers:
- image: specialyang/spring-cloud-httpbin-k8s:v2
imagePullPolicy: Always
name: spring-cloud-httpbin-k8s
ports:
- containerPort: 8080
在 httpbin 服務的政策配置中添加服務版本 v2,注意需要選擇對應的标簽來篩選出 v2 版本的節點,叢集中現在 v1 和 v2 版本的節點數一緻,是以各占 50%。
現在,我們開始利用藍綠釋出的思想将流量從 v1 整體切換至 v2,僅需要之前修改上面建立的路由規則中目标服務即可。
for i in {1..10}; do curl "${GATEWAY_EXTERNAL_IP}/version"; echo ""; done
version: v2
version: v2
version: v2
version: v2
version: v2
version: v2
version: v2
version: v2
version: v2
version: v2
現在我們發現通路 api 資源/version 的請求的流量已經全部從 v1 切換至 v2。
3、A/B測試
A/B 測試基于使用者請求的元資訊将流量路由到新版本,換句話說,就是可以根據請求内容來動态路由。舉個例子,我們希望 User-Agent 的值為 Android 的請求 (來自安卓系統的請求)可以通路新版本,其他系統仍然通路舊版本。
我們仍然利用上面實踐中部署的 httpbin 的 v1,v2 的 deployment。此外,需要建立兩條路由規則:
- 比對 path 為/version 的請求通路服務版本 v1
- 比對 path 為/version,且 User-Agent 頭部含有 Android 的請求通路服務版本 v2
注意相比 version 路由規則,version-v2 的路由規則中需要增加請求頭比對規則。
通過以下腳本測試 A/B test 的效果。
// user agent中不含有 android
curl ${GATEWAY_EXTERNAL_IP}/version
version: v1
// user agent中含有 android
curl -H "User-Agent: Mozilla/5.0 (Linux; Android 4.0.3)" ${GATEWAY_EXTERNAL_IP}/version
version: v2
可以看出,目前請求會按照來源的作業系統對流量進行分流。
4、金絲雀釋出
金絲雀釋出允許引流一小部分流量到服務新版本,待驗證通過後,逐漸調大流量,直至切流完畢,期間可伴随着新版本的擴容,舊版本的縮容操作,達到資源使用率最大化。
在金絲雀釋出政策中,服務新版本的副本初始部署數無需與原始保持一緻。僅需保持資源始終滿足灰階流量,是以我們将新版本的副本數調為 1,可以在服務政策中服務版本子產品看到目前各版本節點數的占比情況。
清除掉其他釋出政策遺留的路由規則,我們新建立一條路由規則,在目标服務中按照權重将流量轉發至新舊版本。
其中,目标服務需要配置兩個目的地,httpbin 的 v1 和 v2 版本,并設定對應的流量比。
通過以下腳本測試金絲雀釋出的效果。
for i in {1..10}; do curl "${GATEWAY_EXTERNAL_IP}/version"; echo ""; done
version: v1
version: v1
version: v1
version: v1
version: v1
version: v2
version: v1
version: v2
version: v1
version: v1
在以上測試結果中,可以發現 10 個請求中,有 2 個是通路的新版本 v2,其流量比确實符合期望的 8:2。
在真實業務場景中,新版本驗證完畢後,就可以繼續調大通路新版本的流量權重,期間注意對新版本擴容,按需對舊版本縮容。
3、服務發現方式:Nacos 注冊中心
Kubernetes 平台為容器化應用帶來了動态彈性,加快了應用傳遞程序,提高了底層資源的使用率,但在服務發現能力上,相比其他主流注冊中心 Nacos、Consul 等,其功能完整性、可用性上略顯不足。是以,即使大部分業務應用已經遷移至 Kubernetes 運維平台,但仍然選擇為業務保留了原始的注冊中心。
針對這種業務場景,我們額外舉例當使用 Nacos 注冊中心時,如何為服務進行藍綠釋出、A/B 測試和金絲雀釋出。例子中的後端服務提供一個查詢目前版本的接口/version,并且目前版本為 v1。雲原生網關深度內建 MSE Nacos 注冊中心,可以實時動态地從 Nacos 執行個體中擷取服務資訊,友善通過雲原生網關将該後端服務暴露給外部使用者。
将以下資源(Deployment)應用到 ACK 叢集,完成後端服務的部署,并将服務釋出到 Nacos 注冊中心,目前應用版本為 v1。需要注意以下幾點:
1、該 yaml 資源中變量${NACOS_SERVER_ADDRESS}需要替換為你的 MSE Nacos 位址,如果和網關在一個 VPC,那麼内網域名即可;否則,你需要配置公網域名。
2、在 K8s Service 服務發現中,Pod 中 Labels 資訊可看做是節點的中繼資料資訊。而在 Nacos 注冊中心中,節點的中繼資料資訊取決于服務注冊時攜帶的資訊。在 Spring Cloud 架構中,通過環境變量 spring.cloud.nacos.discovery.metadata.xxx 無侵入式為節點添加中繼資料資訊,在該例子中,我們以 version 作為版本标用來區分不同版本的節點。是以,需要為業務容器添加環境變量 spring.cloud.nacos.discovery.metadata.version=v1。
apiVersion: apps/v1
kind: Deployment
metadata:
name: httpbin-v1
spec:
replicas: 3
selector:
matchLabels:
app: httpbin
template:
metadata:
labels:
app: httpbin
spec:
containers:
- image: specialyang/spring-cloud-httpbin-nacos:v1
imagePullPolicy: Always
name: spring-cloud-httpbin-nacos
ports:
- containerPort: 8080
env:
- name: spring.cloud.nacos.discovery.server-addr
value: ${NACOS_SERVER_ADDRESS}
- name: spring.cloud.nacos.discovery.metadata.version
value: v1
在雲原生網關的服務管理->來源管理中,添加目标 MSE Nacos 注冊中心叢集。
在服務管理中導入要暴露給雲原生網關的服務 httpbin,注意服務來源選擇 MSE Nacos 注冊中心。
與 K8s Service 服務發現的例子一樣,在政策配置中添加服務版本 v1,标簽名和标簽值可以選擇為我們在 httpbin 服務注冊時添加的中繼資料資訊 version=v1。之後配置路由比對 path為/version 的請求轉發至 httpbin 服務的 v1 版本。
for i in {1..10}; do curl "${GATEWAY_EXTERNAL_IP}/version"; echo ""; done
version: v1
version: v1
version: v1
version: v1
version: v1
version: v1
version: v1
version: v1
version: v1
version: v1
其釋出政策如下圖所示:
部署 httpbin 服務的新版本 v2,注意注冊中心與上面保持一緻,同時為業務容器增加環境變量 spring.cloud.nacos.discovery.metadata.version=v2,業務應用啟動時會向指定 Nacos 注冊服務,同時攜帶上使用者自定義的中繼資料資訊。雲原生網關可以利用這些中繼資料資訊來對節點區分不同的版本。
apiVersion: apps/v1
kind: Deployment
metadata:
name: httpbin-v2
spec:
replicas: 3
selector:
matchLabels:
app: httpbin
template:
metadata:
labels:
app: httpbin
spec:
containers:
- image: specialyang/spring-cloud-httpbin-nacos:v2
imagePullPolicy: Always
name: spring-cloud-httpbin-nacos
ports:
- containerPort: 8080
env:
- name: spring.cloud.nacos.discovery.server-addr
value: ${NACOS_SERVER_ADDRESS}
- name: spring.cloud.nacos.discovery.metadata.version
value: v2
與 K8s Service 的例子中藍綠釋出操作一樣,在 httpbin 服務的政策配置中添加服務版本 v2,然後将路由規則中的目标服務 httpbin 的 v1 版本修改為 v2 版本,釋出成功之後,檢視請求結果全部為 version: v2。
3、A/B 測試
我們同樣用之前的例子,User-Agent 的值為 Android 的請求 (來自安卓系統的請求)可以通路新版本,其他系統仍然通路舊版本。涉及的路由規則的操作、與驗證方式與 K8s Service 的例子一緻。
同樣,涉及的路由規則的操作、與驗證方式與 K8s Service 的例子一緻。
總結
本文對常見的釋出政策進行了簡單介紹和原了解析,并以圖文并茂的方式對每個釋出政策進行了詳細探讨,總結如下:
- 藍綠釋出:簡單了解就是流量切換,依據熱備的思想,備援部署服務新版本。
- A/B 測試:簡單了解就是根據請求内容(header、cookie)将請求流量路由到服務的不同版本。
- 金絲雀釋出:是一種基于流量比例的釋出政策,部署一個或者一小批新版本的服務,将少量(比如 1%)的請求引流到新版本,逐漸調大流量比重,直到所有使用者流量都被切換新版本為止。
雲原生網關以托管的方式來作為您的流量入口,提供了豐富的流量治理能力,支援多種服務發現方式,如 K8s Service、Nacos、Eurake、ECS 和域名,并以統一的模型支援了服務版本以及灰階釋出能力。在上面的實踐中,可以發現兩種服務發現方式僅僅是中繼資料資訊所處的位置不同,但服務版本管理以及路由規則中的灰階釋出模型都是一緻的,您可以輕松學會為不同服務發現方式的服務進行灰階釋出,確定版本更新過程中平滑無損。
原文連結:301 Moved Permanently
本文為阿裡雲原創内容,未經允許不得轉載。