Apache APISIX 是一個開源的雲原生 API 閘道器,作為 API 閘道器,它兼具動態、實時、高效能等特點,提供了負載均衡、動態上游、灰度釋出、服務熔斷、身份認證、可觀測性等豐富的流量管理功能。你可以使用 Apache APISIX 來處理傳統的南北向流量,以及服務間的東西向流量,也可以當做 K8s Ingress controller 來使用。得益於 APISIX 全動態的設計,可以隨時進行配置更改並且均不需要重啟服務。
阿里雲微服務引擎 MSE 提供了非常易用的流量泳道能力,基於 Java Agent 位元組碼增強的技術實現,無縫支援市面上近 5 年的所有 Spring Cloud 和 Dubbo 的版本,通過極簡的配置與無程式碼侵入的方式,來實現全鏈路灰度,釋放基於 APISIX 的微服務架構的新價值。
全鏈路灰度方案簡介
相關概念
- 泳道:為相同版本應用定義的一套隔離環境。只有滿足了流控路由規則的請求流量才會路由到對應泳道里的打標應用。一個應用可以屬於多個泳道,一個泳道可以包含多個應用,應用和泳道是多對多的關係。
- 基線環境:未打標的應用屬於基線穩定版本的應用,即穩定的線上環境。
- 流量回退:泳道中所部署的服務數量並非要求與基線環境完全一致,當泳道中並不存在呼叫鏈中所依賴的其他服務時,流量需要回退至基線環境,進一步在必要的時候路由回對應標籤的泳道。
- 泳道組:泳道的集合。泳道組的作用主要是為了區分不同團隊或不同場景。
業務場景
基於流量泳道的全鏈路灰度能力,適用於以下業務場景:
- 日常開發/專案/測試環境隔離;
- 全鏈路灰度釋出;
- 高可用同機房優先路由;
- 全鏈路壓測。
技術原理
如何在實際業務場景中去快速落地全鏈路灰度呢?目前主要有兩種解決方案,基於物理環境隔離和基於邏輯環境隔離。
物理環境隔離
物理環境隔離,其實就是通過增加機器的方式來搭建真正意義上的流量隔離。
該方案需要為灰度的服務搭建一套網路隔離、資源獨立的環境,並在其中部署服務的灰度版本。由於與正式環境隔離,正式環境中的其他服務無法訪問到需要灰度的服務,所以需要在灰度環境中冗餘部署 這些線上服務,以便整個呼叫鏈路正常進行流量轉發。此外,註冊中心等一些其他依賴的中介軟體元件也需要冗餘部署在灰度環境中,保證微服務之間的可見性問題,確保獲取的節點 IP 地址只屬於當前的網路環境。
該方案一般用於企業的測試、預開發環境的搭建,對於線上灰度釋出引流的場景來說其靈活性不夠。並且微服務多版本的存在在微服務架構中是非常常見的,需要為這些業務場景採用堆機器的方式來維護多套灰度環境。如果應用數目很小,該方式是可以被受的;如果您的應用數目過多的情況下,會造成運維、機器成本過大,成本和代價遠超收益。
邏輯環境隔離
另一種方案是構建邏輯上的環境隔離,我們只需部署服務的灰度版本,流量在呼叫鏈路上流轉時,由經過的閘道器、各個中介軟體以及各個微服務來識別灰度流量,並動態轉發至對應服務的灰度版本。如下圖:
上圖可以很好展示這種方案的效果,我們用不同的顏色來表示不同版本的灰度流量,可以看出無論是微服務閘道器還是微服務本身都需要識別流量,根據治理規則做出動態決策。當服務版本發生變化時,這個呼叫鏈路的轉發也會實時改變。相比於利用機器搭建的灰度環境,這種方案不僅可以節省大量的機器成 本和運維人力,而且可以幫助開發者實時快速的對線上流量進行精細化的全鏈路控制。
基於 Apache APISIX 全鏈路灰度產品實踐
全鏈路灰度是微服務最核心的功能之一,也是雲上使用者在微服務化深入過程中必須具備的功能。全鏈路灰度因為涉及到的技術和場景眾多,如果企業一一進行自我實現,需要花費大量人力成本對其進行擴充套件與運維。
MSE 服務治理提供了完整的產品化的全鏈路灰度解決方案,覆蓋 RPC、MQ、可觀測性等絕大多數場 景。只要架構是基於 Spring Cloud 或者 Dubbo 框架,應用無需升級或程式碼改動,即可實現企業級全鏈路灰度功能。
使用前提
第一步:安裝 APISIX 相關元件
- 安裝 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 應用。
使用 Helm 安裝 APISIX Dashboard。
helm repo add apisix https://charts.apiseven.com helm repo update helm install apisix-dashboard apisix/apisix-dashboard --namespace ingress-apisix
- 安裝完成後,可以繫結一個 SLB。
通過
{slb-ip}:9000
訪問 APISIX Dashboard。第二步:開啟微服務治理
這一步驟中,需要開通 MSE 微服務治理、安裝 MSE 服務治理元件(ack-onepilot)併為應用開啟微服務治理。具體操作資訊可參考阿里雲官方教程。
第三步:部署 Demo 應用程式
在阿里雲容器服務中部署 A、B、C 三個應用,每個應用分別部署⼀個
base
版本和⼀個gray
版本;並部署⼀個 Nacos Server 應用,用於實現服務發現。具體可參考此教程完成應用部署:部署Demo 應用程式。部署完成後,你可以通過 APISIX Dashboard 為應用配置Service
進行上游配置。應用場景一:按域名進行路由
在部分場景下,可以通過不同的域名來區分線上基線環境和灰度環境。灰度環境有單獨的域名可以配置,假設我們通過訪問 www.gray.com 來請求灰度環境,訪問 www.base.com 走基線環境。
呼叫鏈路Ingress-nginx -> A -> B -> C
,其中 A 可以是一個spring-boot
的應用。配置 APISIX 路由規則
在 APISIX Dashboard 選擇路由並單擊建立。匹配條件中域名、請求路徑選擇 /*,選擇對應的上游。分別配置如下路由:
- 當
host
為www.base.com
時,路由到 id 為401152455435354748
所對應的上游,即spring-cloud-a-svc
; 當
host
為www.gray.com
時,路由到 id 為401163331936715388
所對應的上游,即spring-cloud-a-gray-svc
。
然後進行base
對應的路由配置:{ "uri": "/*", "name": "spring-cloud-a", "methods": [ "GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS", "CONNECT", "TRACE" ], "host": "www.base.com", "upstream_id": "401152455435354748", "labels": { "API_VERSION": "0.0.1" }, "status": 1 }
進行
gray
對應的路由配置:{ "uri": "/*", "name": "spring-cloud-a-gray", "priority": 1, "methods": [ "GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS", "CONNECT", "TRACE" ], "host": "www.gray.com", "upstream_id": "401163331936715388", "labels": { "API_VERSION": "0.0.1" }, "status": 1 }
配置 MSE 全鏈路灰度
你需要配置完成 MSE 的全鏈路釋出,具體操作細節可參考此教程:配置全鏈路灰度。
結果驗證
訪問
www.base.com
路由到 A 應用的base
版本:curl -H"Host:www.base.com" http://47.97.253.177/a A[172.18.144.15] -> B[172.18.144.125] -> C[172.18.144.90]%
訪問
www.gray.com
路由到 A 應用的gray
版本:curl -H"Host:www.gray.com" http://47.97.253.177/a Agray[172.18.144.16] -> Bgray[172.18.144.57] -> Cgray[172.18.144.157]%
應用場景二:按指定請求引數進行路由
有些客戶端無法改寫域名,希望能訪問
www.demo.com
通過傳入不同的引數來路由到灰度環境。例如下圖中,通過env=gray
這個請求引數,來訪問灰度環境。
呼叫鏈路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
對應的路由配置,如下圖所示:{ "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。總結
基於 Apache APISIX 靈活的路由能力,配合 MSE 全鏈路灰度能力,可以快速實現企業級的全鏈路灰度的能力。
APSIX 支援按照 Header、Cookie、Params、域名等多種方式進行路由,只需要在閘道器側根據需求將流量路由至不同的“泳道”環境後,流量在對應標籤的“泳道”中自動閉環,當泳道中並不存在呼叫鏈中所依賴的其他服務時,流量需要回退至基線環境,進一步在必要的時候路由回對應標籤的泳道。