通過 MSE 實現基於Apache APISIX的全鏈路灰度

語言: CN / TW / HK

作者:十眠

什麼是全鏈路灰度?

微服務體系架構中,服務之間的依賴關係錯綜複雜,有時某個功能發版依賴多個服務同時升級上線。我們希望可以對這些服務的新版本同時進行小流量灰度驗證,這就是微服務架構中特有的全鏈路灰度場景,通過構建從閘道器到整個後端服務的環境隔離來對多個不同版本的服務進行灰度驗證。

在釋出過程中,我們只需部署服務的灰度版本,流量在呼叫鏈路上流轉時,由流經的閘道器、各個中介軟體以及各個微服務來識別灰度流量,並動態轉發至對應服務的灰度版本。如下圖:

1.png

上圖可以很好展示這種方案的效果,我們用不同的顏色來表示不同版本的灰度流量,可以看出無論是微服務閘道器還是微服務本身都需要識別流量,根據治理規則做出動態決策。當服務版本發生變化時,這個呼叫鏈路的轉發也會實時改變。相比於利用機器搭建的灰度環境,這種方案不僅可以節省大量的機器成本和運維人力,而且可以幫助開發者實時快速的對線上流量進行精細化的全鏈路控制。

那麼全鏈路灰度具體是如何實現呢?通過上面的討論,我們需要解決以下問題:

1.鏈路上各個元件和服務能夠根據請求流量特徵進行動態路由

2.需要對服務下的所有節點進行分組,能夠區分版本

3.需要對流量進行灰度標識、版本標識

4.需要識別出不同版本的灰度流量

下面將藉著介紹 OpenSergo 對於流量路由所定義的 v1alpha1 標準,來告訴大家實現全鏈路灰度所需的技術細節。

Q:OpenSergo 是什麼?

A:OpenSergo 是一套開放、通用的、面向分散式服務架構、覆蓋全鏈路異構化生態的服務治理標準,基於業界服務治理場景與實踐形成服務治理通用標準。OpenSergo 的最大特點就是以統一的一套配置/DSL/協議定義服務治理規則,面向多語言異構化架構,做到全鏈路生態覆蓋。無論微服務的語言是 Java, Go, Node.js 還是其它語言,無論是標準微服務或 Mesh 接入,從閘道器到微服務,從資料庫到快取,從服務註冊發現到配置,開發者都可以通過同一套 OpenSergo CRD 標準配置針對每一層進行統一的治理管控,而無需關注各框架、語言的差異點,降低異構化、全鏈路服務治理管控的複雜度

Q:為什麼瞭解全鏈路灰度之前先給我介紹 OpenSergo?

A:OpenSergo 定義了一套統一的 YAML 配置方式來針對分散式架構進行全鏈路的服務治理的規範,介紹規範與標準的同時,我們可以瞭解其中的技術細節的實現,同時我們還可以將新的元件與 OpenSergo 的標準進行實現。

OpenSergo 流量路由 v1alpha1 標準

流量路由,顧名思義就是將具有某些屬性特徵的流量,路由到指定的目標。流量路由是流量治理中重要的一環,開發者可以基於流量路由標準來實現各種場景,如灰度釋出、金絲雀釋出、容災路由、標籤路由等。

全鏈路灰度示例:

2.png

流量路由規則(v1alpha1) 主要分為三部分:

  • Workload 標籤規則 (WorkloadLabelRule):將某一組 workload 打上對應的標籤,這一塊可以理解為是為 APISIX 的各個上游打上對應的標籤
  • 流量標籤規則 (TrafficLabelRule):將具有某些屬性特徵的流量,打上對應的標籤
  • 按照 Workload 標籤和流量標籤來做匹配路由,將帶有指定標籤的流量路由到匹配的 workload 中

我們可以賦予標籤不同的語義,從而實現各個場景下的路由能力。

3.png

給流量打標:

需要將具有某些屬性特徵的流量,打上對應的標籤。

假設現在需要將內部測試使用者灰度到新版主頁,測試使用者 uid=12345,UID 位於 X-User-Id header 中:

apiVersion: traffic.opensergo.io/v1alpha1 kind: TrafficLabelRule metadata: name: my-traffic-label-rule labels: app: my-app spec: selector: app: my-app trafficLabel: gray match: - condition: "==" # 匹配表示式 type: header # 匹配屬性型別 key: 'X-User-Id' # 引數名 value: 12345 # 引數值 - condition: "==" value: "/index" type: path

通過上述配置,我們可以將 path 為 /index,且 uid header 為 12345 的 HTTP 流量,打上 gray 標,代表這個流量為灰度流量。

給 Workload 打標籤:

那麼如何給服務節點新增不同的標籤呢?在如今火熱的雲原生技術推動下,大多數業務都在積極進行容器化改造之旅。這裡,我就以容器化的應用為例,介紹在使用 Kubernetes Service 作為服務發現和使用比較流行的 Nacos 註冊中心這兩種場景下如何對服務 Workload 進行節點打標。

在使用 Kubernetes Service 作為服務發現的業務系統中,服務提供者通過向 ApiServer 提交 Service 資源完成服務暴露,服務消費端監聽與該 Service 資源下關聯的 Endpoint 資源,從 Endpoint 資源中獲取關聯的業務 Pod 資源,讀取上面的 Labels 資料並作為該節點的元資料資訊。所以,我們只要在業務應用描述資源 Deployment 中的 Pod 模板中為節點新增標籤即可。

在使用 Nacos 作為服務發現的業務系統中,一般是需要業務根據其使用的微服務框架來決定打標方式。如果 Java 應用使用的 Spring Cloud 微服務開發框架,我們可以為業務容器新增對應的環境變數來完成標籤的新增操作。比如我們希望為節點新增版本灰度標,那麼為業務容器新增  traffic.opensergo.io/label: gray ,這樣框架向 Nacos 註冊該節點時會為其新增一個 gray 標籤。

對於一些複雜的 workload 打標場景(如資料庫例項、快取例項標籤),我們可以利用 WorkloadLabelRule CRD 進行打標。示例:

apiVersion: traffic.opensergo.io/v1alpha1 kind: WorkloadLabelRule metadata: name: gray-sts-label-rule spec: workloadLabels: ['gray'] selector: app: my-app-gray

流量染色:

請求鏈路上各個元件如何識別出不同的灰度流量?答案就是流量染色,為請求流量新增不同灰度標識來方便區分。我們可以在請求的源頭上對流量進行染色,前端在發起請求時根據使用者資訊或者平臺資訊的不同對流量進行打標。如果前端無法做到,我們也可以在微服務閘道器上對匹配特定路由規則的請求動態新增流量標識。此外,流量在鏈路中流經灰度節點時,如果請求資訊中不含有灰度標識,需要自動為其染色,接下來流量就可以在後續的流轉過程中優先訪問服務的灰度版本。

目前在 OpenSergo v1alphal1 並未詳細定義流量染色這一塊的標準,可以後續社群一起討論來設計流量染色標準。Apache APISIX 也會適配實現 OpenSergo 的標準,開發者可以通過同一套 OpenSergo CRD 標準配置針對流量閘道器層進行統一的治理管控,可以釋放基於 Apache APSIX 的微服務架構的新價值。

全鏈路灰度是微服務最核心的功能之一,也是雲上使用者在微服務化深入過程中必須具備的功能。全鏈路灰度因為涉及到的技術和場景眾多,如果企業一一進行自我實現,需要花費大量人力成本對其進行擴充套件與運維。

基於 Apache APISIX 全鏈路灰度方案產品實踐

介紹完技術,下面來介紹一下阿里雲上基於 Apache APISIX 的全鏈路灰度的產品實踐。

前提條件

第一步:安裝 Ingress-APISIX 元件

APISIX 架構如下圖所示,我們需要安裝 APISIX。

4.png

  1. 安裝 apisix、apisix-ingress-controller、etcd 等元件

helm repo add apisix https://charts.apiseven.com helm repo add bitnami https://charts.bitnami.com/bitnami helm repo update kubectl create ns ingress-apisix helm install apisix apisix/apisix \ --set gateway.type=LoadBalancer \ --set ingress-controller.enabled=true \ --set etcd.persistence.storageClass="alicloud-disk-ssd" \ --set etcd.persistence.size="20Gi" \ --namespace ingress-apisix \ --set ingress-controller.config.apisix.serviceNamespace=ingress-apisix kubectl get service --namespace ingress-apisix

看到在 ingress-apisix名稱空間下看到無狀態 apisix、apisix-ingress-controller 應用、以及有狀態的 etcd 應用。

  1. 安裝 APISIX Admin

helm repo add apisix https://charts.apiseven.com helm repo update helm install apisix-dashboard apisix/apisix-dashboard --namespace ingress-apisix

安裝完成後,可以繫結一個 SLB

5.png

通過{slb-ip}:9000 訪問 APISIX 控制檯(預設密碼admin/admin)

6.png

第二步:開啟微服務治理

這一步驟中,需要開通 MSE 微服務治理、安裝 MSE 服務治理元件(ack-onepilot)併為應用開啟微服務治理。具體操作資訊可參考阿里雲官方教程:

https://help.aliyun.com/product/123350.html

第三步:部署 Demo 應用程式

在阿里雲容器服務中部署 A、B、C 三個應用,每個應用分別部署⼀個base 版本和⼀個gray 版本;並部署⼀個 Nacos Server 應用,用於實現服務發現。具體可參考此教程完成應用部署:部署Demo 應用程式。部署完成後,你可以通過 APISIX Dashboard 為應用配置 Service 進行上游配置。

應用場景:按照指定請求引數進行路由,實現全鏈路灰度

有些客戶端沒法改寫域名,希望能訪問 www.demo.com 通過傳入不同的引數來路由到灰度環境。例如下圖中,通過 env=gray 這個請求引數,來訪問灰度環境。

7.png

呼叫鏈路 Ingress-APISIX -> A -> B -> C ,其中 A 可以是一個 spring-boot 的應用。

配置 APISIX 路由規則

在 APISIX Dashboard 選擇路由並單擊建立。匹配條件中新建高階匹配規則、請求路徑選擇 /*,選擇對應的上游。分別配置如下路由:

  • 當 host 為 www.demo.com,請求引數 env=gray 時,路由優先匹配 id 為 401163331936715388 所對應的上游,即 spring-cloud-a-gray-svc;
  • 當 host 為 www.demo.com 時,路由經會匹配 id 為 401152455435354748 所對應的上游,即 spring-cloud-a-svc。

然後進行 base 對應的路由配置:

{ "uri": "/*", "name": "spring-cloud-a", "methods": [ "GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS", "CONNECT", "TRACE" ], "host": "www.demo.com", "upstream_id": "401152455435354748", "labels": { "API_VERSION": "0.0.1" }, "status": 1 }

進行 gray 對應的路由配置,如下圖所示:

8.png

{ "uri": "/*", "name": "spring-cloud-a-gray", "priority": 1, "methods": [ "GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS", "CONNECT", "TRACE" ], "host": "www.demo.com", "vars": [ [ "arg_env", "==", "gray" ] ], "upstream_id": "401163331936715388", "labels": { "API_VERSION": "0.0.1" }, "status": 1 }

配置 MSE 全鏈路灰度

你需要配置完成 MSE 的全鏈路釋出,具體操作細節可參考此教程:配置全鏈路灰度。

結果驗證

此時,訪問 www.demo.com 路由到 基線環境

curl -H"Host:www.demo.com" http://47.97.253.177/a A[172.18.144.15] -> B[172.18.144.125] -> C[172.18.144.90]%

此時,訪問 www.demo.com 同時env=gray時路由到灰度環境

curl -H"Host:www.demo.com" http://47.97.253.177/a?env=gray Agray[172.18.144.16] -> Bgray[172.18.144.57] -> Cgray[172.18.144.157]%

注意:其中 47.97.253.177 為 APISIX 的公網 IP

總結

目前 MSE 服務治理全鏈路灰度能力已經支援了雲原生閘道器、ALB、APISIX、Apache Dubbo、Spring Cloud、RocketMQ 以及資料庫。

基於 Apache APISIX 靈活的路由能力,配合 MSE 全鏈路灰度能力,可以快速實現企業級的全鏈路灰度的能力。APSIX 支援按照 Header、Cookie、Params、域名等多種方式進行路由,只需要在閘道器側根據需求將流量路由至不同的“泳道”環境後,流量在對應標籤的“泳道”中自動閉環,當泳道中並不存在呼叫鏈中所依賴的其他服務時,流量需要回退至基線環境,進一步在必要的時候路由回對應標籤的泳道。

服務治理是微服務改造深入到一定階段之後的必經之路,在這個過程中我們不斷有新的問題出現。

  • 除了全鏈路灰度,服務治理還有沒其他能力?
  • 服務治理能力有沒一個標準的定義,服務治理能力包含哪些?
  • 多語言場景下,有無全鏈路的最佳實踐或者標準?
  • 異構微服務如何可以統一治理? 

當我們在探索服務治理的過程中,我們在對接其他微服務的時候,我們發現治理體系不同造成的困擾是巨大的,打通兩套甚者是多套治理體系的成本也是巨大的。為此我們提出了 OpenSergo 專案。OpenSergo 要解決的是不同框架、不同語言在微服務治理上的概念碎片化、無法互通的問題。

OpenSergo 社群也在聯合 Apache APISIX 社群進行進一步的合作,社群來一起討論與定義統一的服務治理標準。當前社群也在聯合 bilibili、位元組跳動等企業一起共建標準,也歡迎感興趣的開發者、社群與企業一起加入到 OpenSergo 服務治理標準共建中。歡迎大家加入 OpenSergo 社群交流群(釘釘群)進行討論:34826335

相關連結

MSE 註冊配置中心專業版首購享 9 折優惠,MSE 雲原生閘道器預付費全規格享 9 折優惠。點選此處,即享優惠~