Categories
程式開發

Service Mesh 在超大規模場景下的落地挑戰


隨著微服務軟件架構在互聯網企業的廣泛實踐,新一代微服務軟件架構技術悄然興起, Service Mesh 便是其中之一。 根據Linkerd CEO Willian Morgan 對Service Mesh 的定義,Service Mesh 是一層處理服務間通信的基礎設施。 雲原生應用有著複雜的服務拓撲,Service Mesh 保證請求可以在這些拓撲中安全且可靠地穿梭,對整個服務網絡進行觀測和高效查錯,以及通過靈活的流量治理能力為新功能上線提供高效的驗證手段。 在實際應用當中,Service Mesh 通常是由一系列輕量級的網絡代理(又被稱為Sidecar)組成的,它們部署在應用進程的邊上且對應用進程完全無感。

國內Service Mesh 早期實踐基本分為先建設數據層後建設控制層和同時建設兩類,從後續發展看,隨著對服務運營能力要求的提高,控制層會越來越重要。 在實際落地方面,眾多企業都在積極探索Service Mesh 在大規模場景下的應用。

阿里巴巴高級技術專家至簡在KubeCon 2020 阿里巴巴雲原生專場分享了《Service Mesh 在超大規模場景下的落地挑戰》,基於阿里巴巴的落地實踐,分享一些經驗和思路。 以下是部分內容整理。

分佈式應用架構在阿里巴巴的現狀

阿里巴巴圍繞電商業務構建了龐大的微服務軟件架構應用生態,包括了天貓、淘寶、菜鳥、高德等。 其次,整個微服務體係是通過Dubbo RPC 連接在一起,MetaQ 用於服務之間的異步解耦。 目前阿里巴巴主要的技術棧還是Java,圍繞Java 構建了相當健全的微服務治理能力,其他技術棧的微服務治理能力相對弱很多。 在服務可見性這塊,阿里巴巴是完全沒有隔離的。 Dubbo RPC 仍是接口級服務發現,1 個應用如果提供10 個接口,那麼就會有10 個服務是可以被發現的,如果這個應用有n 台機器,那麼10 個服務就會產生10*n 個服務端點元信息,這種重複數據導致規模問題被放大。

另外一點值得跟大家分享的是,目前阿里巴巴也正經歷著應用的SDK 升級之痛,SDK 中包含了中間件和應用層的一些公共模塊,由中間件統一以Pandora 包的形式交付給業務方使用。 在應用數非常龐大的情形下,SDK 升級是一份相當繁重的工作,甚至涉及到集團層面的大協同。 為此,我們希望通過Service Mesh 先將中間件的那些能力下沉到Sidecar,將這塊升級工作從Pandora 中剝離出來,借助Service Mesh 的流量無損熱升級能力讓業務對中間件升級完全無感。

Service Mesh 面臨的挑戰

Service Mesh 面臨的第一個挑戰就是新技術如何平滑演進 。 Service Mesh 在大規模場景下的落地在業界的案例還相當少,根源在於該技術本身還沒有完全成熟。 在技​​術走向成熟的持續迭代過程中,如何平滑演進是一個很有挑戰的任務。 挑戰在於需要以終為始地規範技術架構的演進,一步一步地向終態架構演進。

第二個挑戰是發展的過程中如何協調好技術和業務的平衡。 技術團隊希望快速迭代向前發展兌現價值,而業務團隊每年有自己的業務目標,如何協調好兩者的發展關係是個不小的挑戰。 代表新技術的團隊其發展思路通常會更激進,而業務團隊會因為“穩定壓倒一切”而偏保守,短期內調和好這一矛盾或許需要自頂向下的決策力量,否則業務挑戰年年有而可能擠壓技術的發展空間,導致技術發展緩慢而無法更好地服務於業務的發展。

第三個挑戰是技術向前演進時如何處置歷史包袱。 每一次技術的演進都意味著對原有技術體系的升級,這就不可避免地需要處置過往累積下來的技術債。 新技術發展的難點往往不在於其“新”,而在於包袱太重而導致新技術演進困難,很可能因為演進太慢而嚴重影響了新技術的發展。

第四個挑戰就是克服超大規模所帶來的問題。 前面講到的Dubbo 因為是接口級服務發現,使得服務發現的數據規模非常大,給控制平面的端點數據推送能力帶去了巨大挑戰。

最後一個挑戰是Sidecar 的規模化運維。 在超大規模場景下,大量的應用機器意味著有等量的Sidecar 需要運維,如何在部署、灰度、升級以及保障安全生產是一個很大的挑戰。

新技術在架構上平滑演進是關鍵

Service Mesh 在超大規模場景下的落地挑戰 1

新技術的不成熟很可能在相當長的一段時間內是常態,演進的關鍵在於如何實現新技術架構的平滑演進,避免出現推倒重來這種勞命傷財之事。 為此,基於這一考量,我們一共經歷了“起步”、“三位一體”和“規模化落地”三大階段,而每一個階段採用了不同的軟件架構或部署方案。

在起步階段,Istio 控制平面的Pilot 組件放在一個單獨的容器中,同時當作一個獨立的進程和Sidecar 部署在一個Pod 裡。 採用這樣的方式,使得對開源的Envoy 和Pilot 可以做最小的改動而加速落地,也方便我們基於開源的版本做能力增強和反哺。 這一方案的缺點在於,每個Pod 中都包含了一個Pilot 進程,增大了應用所在機器上的資源消耗,因在服務規模並不大的情形下資源消耗相對小而可以忽視這一缺點。

在三位一體階段,Pilot 進程從業務Pod 中抽離了出來變成了一個獨立的集群,在Sidecar 和Pilot 之間仍是xDS 協議。 這一架構雖節省了應用所在機器的資源消耗,但必須正視規模化落地的問題。 xDS 中有一個叫EDS(Endpoint Discovery Service)的協議,Pilot 通過EDS 向Sidecar 推送服務發現所需使用到的機器IP(又被稱之為Endpoint)信息,在阿里的大規模場景下因為有大量的端點需要通過Pilot 推送給Sidecar,導致Sidecar 的CPU 消耗相當大,讓人擔心業務進程因為Sidecar 對資源的爭搶而受影響。 這一規模化問題並非在起步階段的技術方案中不存在,只不過因為那時落地應用的服務規模小而沒有成為瓶頸。

為了解決規模化落地的問題,我們設計出了規模化落地的技術架構。 在這一架構中,雖然還是Sidecar 對接Pilot 集群,但是Pilot 集群只提供xDS 中的LDS/CDS/RDS 這些標準的服務,而EDS 採用Sidecar 直接對接服務註冊中心解決。 值得強調,雖然Sidecar直接對服務接註冊中心,但是它仍然沿用了Envoy 裡面對EDS 所抽象的數據結構和服務模型,只是在數據的獲取上對接註冊中心來實現。 之所以Sidecar 直接對接服務註冊中心能解決走EDS 所存在的規模化問題,根源在於阿里巴巴的服務註冊中心具備了增量推送的能力。

在這三種架構中,未來的終態一定是採用三位一體的架構,且數據平面和控制平面也一定是並重發展。 由於阿里巴巴今天的服務規模非常龐大而沒辦法一步到位做到三位一體。 通過規模化落地這一過渡方案,仍然有助於我們更好地反哺開源社區,通過儘早大規模落地會讓我們清楚地知道開源方案仍存在的問題,從而讓我們能為開源方案的完善做出更大的貢獻。

業務與技術協同發展—— 飛行中更換引擎

業務與技術的協同發展首先要回答好一個問題,即新技術帶給業務的價值是什麼。 從業務的角度,採納新技術最開始考慮的一定是短期價值,然後才是放眼看長遠價值。

Service Mesh 對於業務所帶去的短期價值是:

  • 中間件能力下沉,下沉的過程中去除歷史包袱輕裝上陣。
  • 業務對中間件升級無感,中間件資源消耗可量化、優化可度量。

從長遠來看,完全解決阿里巴巴面臨的Pandora/SDK 升級之痛是需要相當長的一段時間,而Service Mesh 在流量治理這塊的新價值也需要規模化落地達到一定水平後才能兌現,基礎技術對業務的價值需要具備長遠的眼光。 Service Mesh 的長遠價值有:

  • 業務與基礎技術全面解耦,業務更聚集於自身而加速創新,基礎技術獨立演進而加速迭代。
  • 對微服務生態完成標準化、體系化的收口與治理,收斂故障和促進安全生產,加速應用功能正確性的驗證效率。
  • 為多種編程語言的應用提供微服務治理能力,完善並豐富雲原生多編程語言的應用生態。
  • 共建全球事實標準,通過阿里雲的產品落實客戶IT 設施的多雲和混合雲戰略,加速中國社會乃至全球的數字化轉型。

明確了技術的價值之後,業務與技術協同發展接下來的挑戰在於,需要技術演進的過程中完全不影響業務,這好比給一架高速運行的飛機換引擎。 為此,新技術的落地方案需要考慮對業務無侵入,換句話說規避業務應用新技術的改造成本。

Service Mesh 在超大規模場景下的落地挑戰 2

為了應用mesh 化時對業務無感,在以RPC 流量做mesh 化為切入點的背景下,我們設計了動態流量無損透明攔截的技術方案。 上圖示例說明了應用mesh 化前後的三種狀態。 在“過去”,流量是直接通過RPC SDK 在Provider 和Consumer 之間互通的,SDK 直接跟中間件的服務註冊中心、配置中心對接。

到了“現在”,Service Mesh 直接被插入到了應用和中間件之間,SDK 不做任何的變化,但通過iptables 將SDK 的流量攔截到Sidecar 中。 由於iptables 是否開啟和關閉流量攔截是可以通過運維控制台從應用或機器維度進行控制的,這就使得在mesh 技術自身出現問題的情形下可以方便禁用,讓應用回退到通過SDK 直連的方式互通。

面向“未來”,當Service Mesh 技術完全成熟時,SDK 需要從“胖”變“瘦”,那時並不需要SDK 中存在下沉到Sidecar 的那些能力,從而節約重複功能所導致的資源開銷。

下圖示例說明了打開和關閉流量透明攔截功能的關鍵流程。 其中應用進程中包含了RPC SDK 而沒有區分錶達,Traffic Interceptor、Pilot Agent 和Envoy 三個組件在同一個容器中,所有組件共享同一個Pod。 OneOps Core 是基於K8s 所構建的中心化mesh 運維Operator,收到控制台(圖中標識為小人的Operator 指代)調用開啟或關閉流量透明攔截的接口後,通過調用Pilot Agent 所提供的接口完成對Pod 中應用流量的操作。

Service Mesh 在超大規模場景下的落地挑戰 3

為了保證打開和關閉透明攔截功能時無業務流量的調用損失,請注意圖中紅色標識出的二大塊流程。 開啟流量攔截時:Pilot Agent 將調用RPC SDK 的offline 接口(消息2.1.1),間接完成從服務註冊中心對本機做去註冊摘除流量;然後調用Traffic Interceptor 組件所提供的接口開啟流量攔截功能(消息2.1.2);最後再調用RPC SDK 的online 接口將本機註冊到服務註冊中心(消息2.1.3)。

關閉流量攔截時:Pilot Agent 將調用Envoy 的優雅關閉接口(消息4.1.1),Envoy 會在RPC SDK 與Envoy 建立的連接上透傳這一消息(即Envoy 會調用RPC SDK 的優雅關閉接口,上圖並沒有表達出),告訴RPC SDK 不要再向已建立的這一長連接上發送任何RPC 請求;隨後Pilot Agent 調用Traffic Interceptor 接口關閉流量攔截功能(消息4.1.2);最後,Envoy 的優雅關閉接口被調用時會啟動一個延時15秒的定時器,確保RPC SDK 與Envoy 間已建立的長連接上還沒有完成處理的請求有足夠的時間處理完以免出現流量有損,當定時器到期後Envoy 會主動關閉與RPC SDK 所建立的連接(消息6)。

為了讓mesh 技術自身的迭代對業務無感,我們設計了流量無損熱升級方案,確保Sidecar 可以隨時對業務無感升級。 設計流量無損熱升級方案的核心考量是投入產出比,以最小的工程成本構建一個容易做到穩定的技術方案,下圖示例了站在Consumer 視角(既Consumer 側的Envoy 進行升級,Consumer 代表流量調用的發起方)所觀測到的熱升級流程。

當Envoy 有一個新版本需要升級時(圖中標識為v2),通過運維控制台可以設置這個新版本的鏡像信息,通過OpenKruise 的SidecarSet 可以拉到這一鏡像並將鏡像中的新版本Envoy 二進制程序拉起。 隨後,新版本Envoy 會向老版本Envoy(路中標識為v1)發起熱升級流程。

Service Mesh 在超大規模場景下的落地挑戰 4

熱升級大致包含如下幾個流程:老版本進程中所有的偵聽fd 通過進程間通訊的方式交給新版本進程(消息5.1),由新版本進程繼續在之上進行偵聽(消息5.1.1 ),換句話說,之後所有在這些被偵聽端口上新建的連接都會發生在新版本進程中;老版本進程調用RPC SDK 的優雅關閉接口(消息5.3),告訴RPC SDK 不要再已建立的連接上發起新的調用,如果要發起新調用則必須重新建立連接,顯然新連接將與新版本進程建立,隨後的調用流量將全部進到新版本進程;老版本進程向RPC SDK 發起優雅關閉接口調用的同時會建立一個時延15秒的定時器,確保與RPC SDK 所建立的連接在這15秒中都處理完,定時器到期後關閉這一連接並退出老版本進程(消息5.4),從而結束整個熱升級流程。

下圖是從Provider 視角(既Provider 側的Envoy 進行升級,Provider 代表提供相應服務能力的被調用方)所觀察到的升級流程。 不難看出,紅色標識出的部分與前一張圖是完全一樣的,熱升級流程完全無需基於Envoy 的Consumer 或Provider 身份做特殊的處理。 畢竟,現實中每個應用大多會同時承擔Consumer 和Provider 兩種角色。

Service Mesh 在超大規模場景下的落地挑戰 5

上圖有一個點值得特別指出,Envoy 需要實現序號為5.3的優雅關閉消息,並將這一消息透傳給RPC SDK(圖中並沒有表達)。

發展新技術是償還技術債的重要契機

不少新技術的出現多少會引發我們的糾結,在新技術所創造的短期價值不那麼有吸引力的情形下,似乎舊技術不改變就不會帶來風險。 但經驗表明,不改變的後果是包袱會越積越重,由此所帶來的技術債的潛在風險最終都不可忽視。 技術債是軟件的本質屬性,因為無法做到已有架構能一直百分百優雅實現新需求。 換句話說,技術債對於一個長期提供服務的軟件來說是一直存在的,只不過存在大小之別和何時償還的問題。

阿里巴巴對分佈式系統的探索有超過十年的積累,為了做應用的服務化改造提出了HSF RPC 開發框架並將之開源為Dubbo。 基於框架思維所構建的RPC 協議為了更好地滿足不同業務對服務路由的定制化訴求,提供了通過Groovy 腳本進行定制的能力。 然而,這種靈活的手段在向Service Mesh 這一平台技術演進時將帶來流量治理隱患。

我們認為,平台思維下構建的Service Mesh 得限製過於靈活的定制能力,避免平台出現“窟窿”而無法有效、有力地完成全局最優的治理。 為此,我們將去除Groovy 腳本當作是一項技術債加以償還。 Groovy 腳本帶來的問題主要有兩個:

  • 過於靈活且導致了開發框架與應用代碼的耦合。
  • 給流量治理能力下沉留下了潛在隱患。

為了去除Groovy 腳本,我們擴展了Istio 的VirtualService 和DestinationRule,抽像出按應用名、方法和參數路由的能力。 下圖示例說明了某應用基於應用名做路由在Groovy 腳本和Service Mesh 下的具體實現。

Service Mesh 在超大規模場景下的落地挑戰 6

由於單個應用的Service Mesh 化並非一刀切的一次性完成,存在一個應用的部分機器先mesh 化做灰度的場景。 為此,需要在去Groovy 腳本這件事上,讓新舊技術方案能同時無縫工作,背後是兩種形式的路由表達如何做好同步,背後就涉及控制台收口和格式轉化等問題需要妥善解決。

系統性解決超大規模問題

為了最終解決阿里巴巴在Service Mesh 落地過程中所面臨的大規模問題,我們從三個方面著手:

  • Service Mesh 技術自身的持續優化。 需要從CPU 開銷、內存佔用和時延三大維度進行持續優化,通過軟硬件結合等技術手段做到應用Service Mesh 化前後零新增成本甚至下降。
  • Dubbo 實現應用級服務發現而非接口級。 通過應用級服務發現將使得控制平面向數據平面推送的服務元數據有數量級下降,讓Service Mesh 的控制平面向數據平面推送的數據急劇下降。
  • 服務註冊數據進行單元封閉並分級治理。 動機依然是降低Service Mesh 控制平面向數據平面推送的數據量,通過單元封閉讓全局服務元數據通過局部化而減少。

這三方面在阿里巴巴分別有相應的團隊在探索解決,這裡主要分享Service Mesh 技術本身。 阿里巴巴對Service Mesh 技術的探索策略是“借力開源,反哺開源”。 “借力”體現於整體技術方案採納的是開源的Istio(控制平面) + Envoy(數據平面),在工程實踐中特別注意自有代碼與開源代碼做充分的解耦,以及頻繁跟進開源社區發布的新版本;“反哺”表在我們積極將性能優化、bugfix 等代碼提交給開源社區。

至今,在Istio 開源社區我們提交了9 個PR,解決性能問題和bugfix;在Envoy 開源社區我們提交了14個PR,包含內存開銷下降50%的優化、新增對Dubbo和RocketMQ協議的支持等內容。 此外,我們曾與Istio 社區共同探索實現了EGDS (Endpoint Group Discovery Service),作為EDS 的增強,但由於Envoy 社區擔心該feature 通用性不足而最終沒能接受而完成這次反哺。 這一“失敗”不只體現了我們反哺社區的意願和熱情,也是更好融入開源社區的一次很好的學習機會。

在EGDS 並不能很好解決在“三位一體”方案下的大規模落地問題的情形下,我們重新調整了落地方案,形成了本文前面所講到的讓Envoy 直接對接服務註冊中心的“規模化落地”方案。 下圖展示了兩個方案的CPU 開銷數據比較。

Service Mesh 在超大規模場景下的落地挑戰 7

圖中深藍色代表的是規模化落地方案,橙色代表的是三位一體的方案,測試數據表明三位一體方案在設定的越大規模壓測場景下因服務元數據推送給Envoy 所帶去的CPU 開銷是規模化落地方案的三倍。

进一步地,我们比对了非 mesh 方案和规模化落地 mesh 方案因服务元数据推送所导致的 CPU 开销(如下图所示)。数据表明,非 mesh 方案(图中橙色表示)因 Java 进程在数据推送场景下存在 GC 而使得 CPU 开销要显著地高于规模化落地 mesh 方案(图中深蓝色表示),这是因 Envoy 采用 C++ 编程语言而获得的优势。

Service Mesh 在超大規模場景下的落地挑戰 8

後續我們會考慮參與共建Envoy 社區所提出的LEDS 協議,讓Istio + Envoy 的三位一體方案天然地能運用於阿里巴巴的大規模場景。

除了CPU 開銷的優化,我們在內存優化方面也取得了巨大的進展。 同樣服務規模的情形下,Envoy 的內存開銷從之前超過3G 優化至500M 左右。 此外,壓測數據表明應用mesh 化完成後整體內存開銷比mesh 化前更低。

Sidecar 的規模化運維

Sidecar 的規模化運維也是很具挑戰的一件事,內容包含Sidecar 的部署、灰度、升級,以及需要構建相應的監控和報警設施。

Sidecar 的部署、灰度、升級我們全面基於由阿里巴巴開源的OpenKruise 中的SidecarSet 實現。 SidecarSet 提供了對Sidecar 進行部署、灰度和升級的通用能力,能很好地運用於Service Mesh 而省去了重複建設。 當然,流量無損熱升級這樣的能力並非SidecarSet 原生提供的,需要從Service Mesh 層面去增強。 在Sidecar 的運維和流量治理這塊,監控和報警全面採用了阿里雲上的Prometheus 和ARMS 兩大雲產品,一旦當下服務於阿里巴巴內部的Service Mesh 技術將來要通過產品化輸送給阿里雲上的客戶時會更加方便。

在運維管控上,我們全新構建了雲原生OneOps 運維繫統。 OneOps 包含控制台和OneOps Core 兩大子系統。 後者是基於K8s 構建的運維Operator,通過CRD 的形式暴露給控制台調用接口。 OneOps Core 可以多區域部署,而控制台是全局集中部署的,這樣方便運維人員在同一個控制台上能無縫地管理多個區域的Service Mesh。 目前OneOps 已具備管理包含了Sidecar 和Ingress Gateway在內的東西南北向流量的能力。

總結

本文總結了阿里巴巴大規模落地Service Mesh 所面臨並克服的技術挑戰,希望這些內容對行業同仁在這一技術的探索和學習有所幫助。 現階段,阿里巴巴對於Service Mesh 的探索更多停留於解決歷史包袱和完成應用與中間件的解耦,仍沒有在服務流量治理方面做出新價值和新體驗,期待未來能儘早給大家分享這方面的內容。

Service Mesh 是雲原生的關鍵技術,對於阿里巴巴來說,我們篤定這是分佈式應用微服務軟件架構的未來。 正因如此,CTO 魯肅也站台Service Mesh 技術,並做出了未來整個經濟體全面走Istio + Envoy 方案的技術決策。 在構建阿里巴巴全球商業操作系統的道路上,Service Mesh 是面向未來五年、甚至十年的技術。

本文轉載自公眾號阿里巴巴中間件(ID:Aliware_2018)。

原文鏈接

Service Mesh 在超大規模場景下的落地挑戰