1. 程式人生 > >阿里巴巴 Service Mesh 落地的架構與挑戰

阿里巴巴 Service Mesh 落地的架構與挑戰

點選下載《不一樣的 雙11 技術:阿里巴巴經濟體雲原生實踐》

本文節選自《不一樣的 雙11 技術:阿里巴巴經濟體雲原生實踐》一書,點選上方圖片即可下載!

作者 | 方克明(溪翁)阿里雲中間件技術部技術專家

導讀:雲原生已成為整個阿里巴巴經濟體構建面向未來的技術基礎設施,Service Mesh 作為雲原生的關鍵技術之一,順利完成在 雙11 核心應用嚴苛而複雜場景下的落地驗證。本文作者將與大家分享在完成這一目標過程中我們所面臨和克服的挑戰。

部署架構

切入主題前,需要交代一下在 雙11 核心應用上落地的部署架構,如下圖所示。在這篇文章中,我們主要聚焦於 Service A 和 Service B 之間 RPC 協議的 Mesh 化。

圖中示例說明了 Service Mesh 所包含的三大平面:即資料平面(Data Plane)、控制平面(Control Plane)和運維平面(Operation Plane)。資料平面我們採用的是開源的 Envoy(上圖中的 Sidecar,請讀者注意這兩個詞在本文中可以互換使用),控制平面採用的是開源的 Istio(目前只使用了其中的 Pilot 元件),運維平面則完全自研。

與半年前落地時不同,這次 雙11 核心應用上落地我們採用了 Pilot 叢集化部署的模式,即 Pilot 不再與 Envoy 一起部署到業務容器中,而是搭建了一個獨立的叢集。這一變化使得控制平面的部署方式演進到了 Service Mesh 應有的終態。

挑戰

落地所選擇的 雙11 核心應用都是採用 Java 程式語言實現的,在落地的過程中我們面臨了以下挑戰。

1. 在 SDK 無法升級的情形下如何實現應用的 Mesh 化

在決定要在 雙11 的核心應用上落地 Mesh 時,Java 應用依賴的 RPC SDK 版本已經定稿,為了 Mesh 化完全沒有時間去開發一個適用於 Mesh 的 RPC SDK 並做升級。那時,擺在團隊面前的技術問題是:如何在不升級 SDK 的情形下,實現 RPC 協議的 Mesh 化?

熟悉 Istio 的讀者想必清楚,Istio 是通過 iptables 的 NAT 表去做流量透明攔截的,通過流量透明攔截可在應用無感的情形下將流量劫持到 Envoy 中從而實現 Mesh 化。但很不幸,NAT 表所使用到的 nf_contrack 核心模組因為效率很低,在阿里巴巴的線上生產機器中被去除了,因此無法直接使用社群的方案。好在年初開始不久我們與阿里巴巴 OS 團隊達成了合作共建,由他們負責承擔 Service Mesh 所需的流量透明攔截和網路加速這兩塊基礎能力的建設。經過兩個團隊的緊密合作,OS 團隊探索了通過基於 userid 和 mark 標識流量的透明攔截方案,基於 iptables 的 mangle 表實現了一個全新的透明攔截元件。

下圖示例說明了存在透明攔截元件的情形下,RPC 服務呼叫的流量走向。其中,Inbound 流量是指調進來的流量(流量的接受者是 Provider 角色),而 Outbound 是指調出去的流量(流量的發出者是 Consumer 角色)。通常一個應用會同時承擔兩個角色,所以有 Inbound 和 Outbound 兩股流量並存。

有了透明攔截元件之後,應用的 Mesh 化完全能做到無感,這將極大地改善 Mesh 落地的便利性。當然,由於 RPC 的 SDK 仍存在以前的服務發現和路由邏輯,而該流量被劫持到 Envoy 之後又會再做一次,這將導致 Outbound 的流量會因為存在兩次服務發現和路由而增加 RT,這在後面的資料部分也將有所體現。顯然,以終態落地 Service Mesh 時,需要去除 RPC SDK 中的服務發現與路由邏輯,將相應的 CPU 和記憶體開銷給節約下來。

2.短時間內支援電商業務複雜的服務治理功能

路由

在阿里巴巴電商業務場景下的路由特性豐富多樣,除了要支援單元化、環境隔離等路由策略,還得根據 RPC 請求的方法名、呼叫引數、應用名等完成服務路由。阿里巴巴內部的 Java RPC 框架是通過嵌入 Groovy 指令碼來支援這些路由策略的,業務方在運維控制檯上配置 Groovy 路由模板,SDK 發起呼叫時會執行該指令碼完成路由策略的運用。

未來的 Service Mesh 並不打算提供 Groovy 指令碼那麼靈活的路由策略定製方案,避免因為過於靈活而給 Service Mesh 自身的演進帶去掣肘。因此,我們決定借 Mesh 化的機會去除 Groovy 指令碼。通過落地應用所使用 Groovy 指令碼的場景分析,我們抽象出了一套符合雲原生的解決方案:擴充套件 Istio 原生的 CRD 中的 VirtualService 和 DestinationRule,增加 RPC 協議所需的路由配置段去表達路由策略。

目前阿里巴巴環境下的單元化、環境隔離等策略都是在 Istio/Envoy 的標準路由模組內做了定製開發,不可避免地存在一些 hack 邏輯。未來計劃在 Istio/Envoy 的標準路由策略之外,設計一套基於 Wasm 的路由外掛方案,讓那些簡單的路由策略以外掛的形式存在。如此一來,既減少了對標準路由模組的侵入,也在一定程度上滿足了業務方對服務路由定製的需要。設想的架構如下圖所示:

限流

出於效能考慮,阿里巴巴內部落地的 Service Mesh 方案並沒有採用 Istio 中的 Mixer 元件,限流這塊功能借助阿里巴巴內部廣泛使用的 Sentinel 元件來實現,不僅可以與已經開源的 Sentinel 形成合力,還可以減少阿里巴巴內部使用者的遷移成本(直接相容業務的現有配置來限流)。為了方便 Mesh 整合,內部多個團隊合作開發了 Sentinel 的 C++版本,整個限流的功能是通過 Envoy 的 Filter 機制來實現的,我們在 Dubbo 協議之上構建了相應的 Filter(Envoy 中的術語,代表處理請求的一個獨立功能模組),每個請求都會經過 Sentinel Filter 做處理。限流所需的配置資訊則是通過 Pilot 從 Nacos 中獲取,並通過 xDS 協議下發到 Envoy 中。

3. Envoy 的資源開銷過大

Envoy 誕生之初要解決的一個核心問題就是服務的可觀測性,因此 Envoy 一開始就內建了大量的 stats(即統計資訊),以便更好地對服務進行觀測。

Envoy 的 stats 粒度很細,甚至細到整個叢集的 IP 級別,在阿里巴巴環境下,某些電商應用的 Consumer 和 Provider 服務加起來達到了幾十萬之多的 IP(每個 IP 在不同的服務下攜帶的元資訊不同,所以不同的服務下的相同 IP 是各自獨立的)。如此一來,Envoy 在這塊的記憶體開銷甚是巨大。為此,我們給 Envoy 增加了 stats 開關,用於關閉或開啟 IP 級別的 stats,關閉 IP 級別的 stats 直接帶來了記憶體節約 30% 成果。下一步我們將跟進社群的 stats symbol table 的方案來解決 stats 指標字串重複的問題,那時的記憶體開銷將進一步減少。

4. 解耦業務與基礎設施,實現基礎設施升級對業務無感

Service Mesh 落地的一項核心價值就是讓基礎設施與業務邏輯完全解耦,兩者可以獨立演進。為了實現這個核心價值,Sidecar 需要具備熱升級能力,以便升級時不會造成業務流量中斷,這對方案設計和技術實現的挑戰還是蠻大的。

我們的熱升級採用雙程序方案,先拉起新的 Sidecar 容器,由它與舊的 Sidecar 進行執行時資料交接,在新的 Sidecar 準備發接管流量後,讓舊的 Sidecar 等待一定時間後退出,最終實現業務流量無損。核心技術主要是運用了 Unix Domain Socket 和 RPC 的節點優雅下線功能。下圖大致示例了關鍵過程。

資料表現

公佈效能資料一不小心就會引發爭議和誤解,因為效能資料的場景存在很多變數。比如,併發度、QPS、payload 大小等對最終的資料表現將產生關鍵影響。也正因如此,Envoy 官方從來沒有提供過本文所列出的這些資料,背後的原因正是其作者 Matt Klein 擔心引發誤解。值得強調的是,在時間非常緊迫的情形下,我們所落地的 Service Mesh 並非處於最優狀態,甚至不是最終方案(比如 Consumer 側存在兩次路由的問題)。我們之所以選擇分享出來,是希望讓更多的同行瞭解我們的進展和狀態。

本文只列出了 雙11 所上線核心應用中某一個的資料。從單機 RT 抽樣的角度,部署了 Service Mesh 的某臺機器,其 Provider 側的 RT 均值是 5.6ms,Consumer 側的是 10.36ms。該機器在 雙11 零點附近的 RT 表現如下圖所示:

沒有部署 Service Mesh 的某臺機器,Provider 側的均值為 5.34ms,Consumer 側的則是 9.31ms。下圖示例了該機器在 雙11 零點附件的 RT 表現。

相比之下,Provider 側的 RT 在 Mesh 化前後增加了 0.26ms,Consumer 側則增加了 1.05ms。注意,這個 RT 差是包含了業務應用到 Sidecar,以及 Sidecar 處理的所有時間在內的,下圖示例說明了帶來時延增加的鏈路。

整體上,該核心應用所有上線了 Service Mesh 的機器和沒有上線 Service Mesh 的機器在某個時間段的整體均值資料做了對比。Provider 側 Mesh 化後的 RT 增加了 0.52ms,而 Consumer 側增加了 1.63ms。

在 CPU 和記憶體開銷方面,Mesh 化之後,Envoy 所消耗的 CPU 在所有核心應用上都維持在 0.1 核左右,會隨著 Pilot 推送資料而產生毛刺。未來需要藉助 Pilot 和 Envoy 之間的增量推送去對毛刺做優化。記憶體的開銷隨著應用的服務和叢集規模不同而存在巨大差異,目前看來 Envoy 在記憶體的使用上仍存在很大的優化空間。

從所有雙11 上線的核心應用的資料表現來看,Service Mesh 的引入對於 RT 的影響和帶來的 CPU 開銷是基本一樣的,而記憶體開銷則因為依賴服務和叢集規模的不同而有相當大的差異。

展望

在雲原生的浪潮下,阿里巴巴借這波技術浪潮致力於打造面向未來的技術基礎設施。在發展的道路上將貫徹“借力開源,反哺開源”的發展思路,通過開源實現技術普惠,為未來的雲原生技術在更大範圍的普及做出自己的貢獻。

接下來,我們的整體技術著力點在於:

  • 與 Istio 開源社群共同增強 Pilot 的資料推送能力。在阿里巴巴具備 雙11 這種超大規模的應用場景下,我們對於Pilot 的資料推送能力有著極致的要求,相信在追求極致的過程中,能與開源社群一道加速全球事實標準的共建。從阿里巴巴內部來看,我們目前拉通了與 Nacos 團隊的共建,將通過社群的 MCP 協議與 Nacos 對接,讓阿里巴巴所開源的各種技術元件能體系化地協同工作;

  • 以 Istio 和 Envoy 為一體,進一步優化兩者的協議以及各自的管理資料結構,通過更加精煉、更加合理的資料結構去減少各自的記憶體開銷;

  • 著力解決大規模 Sidecar 的運維能力建設。讓 Sidecar 的升級做到可灰度、可監控和可回滾;

  • 兌現 Service Mesh 的價值,讓業務與技術設施能以更高的效率彼此獨立演進。

本書亮點

  • 雙11 超大規模 K8s 叢集實踐中,遇到的問題及解決方法詳述
  • 雲原生化最佳組合:Kubernetes+容器+神龍,實現核心系統 100% 上雲的技術細節
  • 雙 11 Service Mesh 超大規模落地解決方案

“阿里巴巴雲原生微信公眾號(ID:Alicloudnative)關注微服務、Serverless、容器、Service Mesh等技術領域、聚焦雲原生流行技術趨勢、雲原生大規模的落地實踐,做最懂雲原生開發者的技術公眾號。”