
作者 | 至簡,阿裡雲進階技術專家
随着微服務軟體架構在網際網路企業的廣泛實踐,新一代微服務軟體架構技術悄然興起, 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 需要運維,如何在部署、灰階、更新以及保障安全生産是一個很大的挑戰。
新技術在架構上平滑演進是關鍵
新技術的不成熟很可能在相當長的一段時間内是常态,演進的關鍵在于如何實作新技術架構的平滑演進,避免出現推倒重來這種勞命傷财之事。為此,基于這一考量,我們一共經曆了“起步”、“三位一體”和“規模化落地”三大階段,而每一個階段采用了不同的軟體架構或部署方案。
在起步階段,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 對于業務所帶去的短期價值是:
(1)中間件能力下沉,下沉的過程中去除曆史包袱輕裝上陣。
(2)業務對中間件更新無感,中間件資源消耗可量化、優化可度量。
從長遠來看,完全解決阿裡巴巴面臨的 Pandora/SDK 更新之痛是需要相當長的一段時間,而 Service Mesh 在流量治理這塊的新價值也需要規模化落地達到一定水準後才能兌現,基礎技術對業務的價值需要具備長遠的眼光。Service Mesh 的長遠價值有:
- 業務與基礎技術全面解耦,業務更聚集于自身而加速創新,基礎技術獨立演進而加速疊代。
- 對微服務生态完成标準化、體系化的收口與治理,收斂故障和促進安全生産,加速應用功能正确性的驗證效率。
- 為多種程式設計語言的應用提供微服務治理能力,完善并豐富雲原生多程式設計語言的應用生态。
- 共建全球事實标準,通過阿裡雲的産品落實客戶 IT 設施的多雲和混合雲戰略,加速中國社會乃至全球的數字化轉型。
明确了技術的價值之後,業務與技術協同發展接下來的挑戰在于,需要技術演進的過程中完全不影響業務,這好比給一架高速運作的飛機換引擎。為此,新技術的落地方案需要考慮對業務無侵入,換句話說規避業務應用新技術的改造成本。
為了應用 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 中應用流量的操作。
為了保證打開和關閉透明攔截功能時無業務流量的調用損失,請注意圖中紅色辨別出的二大塊流程。開啟流量攔截時: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)發起熱更新流程。
熱更新大緻包含如下幾個流程:老版本程序中所有的偵聽 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 兩種角色。
上圖有一個點值得特别指出,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 化并非一刀切的一次性完成,存在一個應用的部分機器先 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 開銷資料比較。
圖中深藍色代表的是規模化落地方案,橙色代表的是三位一體的方案,測試資料表明三位一體方案在設定的越大規模壓測場景下因服務中繼資料推送給 Envoy 所帶去的 CPU 開銷是規模化落地方案的三倍。
進一步地,我們比對了非 mesh 方案和規模化落地 mesh 方案因服務中繼資料推送所導緻的 CPU 開銷(如下圖所示)。資料表明,非 mesh 方案(圖中橙色表示)因 Java 程序在資料推送場景下存在 GC 而使得 CPU 開銷要顯著地高于規模化落地 mesh 方案(圖中深藍色表示),這是因 Envoy 采用 C++ 程式設計語言而獲得的優勢。
後續我們會考慮參與共建 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 是面向未來五年、甚至十年的技術。
期待更多對分布式應用相關技術挑戰有熱情的志同道合之士加入共建與共創,在創變的道路上我們共同成長、共同收獲。如果您有意向,請将履歷發送至[email protected],我們在深圳、上海和杭州都有 Service Mesh 的職位長期開放。
雲栖大會預告:
9月18日13:00-14:00 分論壇:Serverless,引領雲的下一個十年
簡介:Serverless 是雲的下一個十年的主要形态,通過大量端到端的整合和雲服務的內建,Serverless 能極大地提高研發效率,讓使用者隻需要專注于業務邏輯,聚焦于業務創新。本論壇将解讀阿裡雲的 Serverless 理念,釋出 Serverless 産品新特性。同時介紹阿裡巴巴以及其他先鋒企業如何通過 Serverless 實作 IT 架構更新的實踐。
(點選
訂閱論壇,當天會提醒您觀看呦~)