天天看點

建構基于Spring Cloud向Service Mesh架構遷移的解決方案及思路

大家好!我是 xcbeyond, xcbeyond 就是我,大家也可以叫我超哥!本文首發于我的部落格:建構基于Spring Cloud向Service Mesh架構遷移的解決方案及思路

作為新一代微服務架構體系,<code>Service Mesh</code> 技術有效地解決了 <code>Spring Cloud</code> 微服務架構和服務治理過程中的痛點問題,一經推出便引起了很大的反響。近一年來,伴随着雲原生的熱火朝天,<code>Service Mesh</code> 被推向了巅峰,從陌生走向大家的視界,甚至一些初創企業都想從中獲得第一桶金。對于初創企業或全新産品,選擇 <code>Service Mesh</code> 變得相對輕松很多,畢竟不存在遷移的問題。但對于大部分企業或成熟的産品體系,這樣大的架構轉型就變得很難以實施,需要多權重衡利弊,面對 <code>Service Mesh</code> 帶來的好處,不得不迫使向它靠攏。

目前很多企業還是采用基于 <code>SDK</code> 的傳統微服務架構(例如,<code>Dubbo</code>、<code>Spring Cloud</code>)進行服務治理,而随着 <code>Service Mesh</code> 的普及,越來越多的企業開始布局自己的 <code>Service Mesh</code> 架構體系,但多數企業剛開始不會激進地将所有業務遷移至 <code>Serivice Mesh</code>,畢竟這樣風險太大、收益太慢。像 Java 技術棧應用依然保留原架構,而非 Java 技術棧應用采用 <code>Service Mesh</code> 架構,不同開發語言可以用不同的技術架構,但業務不能被架構割裂,那麼在這兩種架構體系下應用服務如何互聯互通?微服務如何統一治理?傳統微服務又如何平滑遷移至 <code>Service Mesh</code> 呢?

如何解決上述問題呢?今天我們就針對建構基于 <code>Spring Cloud</code> 向 <code>Service Mesh</code> 架構遷移過程中的諸多問題展開讨論,盡可能提供一套完善的解決方案和遷移思路,供大家參考。

微服務是近些年來軟體架構中的熱名詞,也是一個很大的概念,不同人對它的了解都各不相同,甚至在早期微服務架構中出現了一批四不像的微服務架構産品,有人把單純引入<code>Spring Boot</code>、<code>Spring Cloud</code>架構也叫做微服務架構,卻隻是将它作為服務的Web容器而已。

随着微服務的火熱,越來越多的團隊開始實踐,将微服務紛紛落地,并投入生産。但随着微服務規模的不斷壯大,每增加一個微服務,就可能會增加一些依賴的基礎設施和第三方的配置,比如 <code>Kafka</code> 執行個體等,相應 <code>CI/CD</code> 的配置也會增加或調整。 同時随着微服務數量增多、業務複雜性的提升及需求的多樣性等(如,對接第三方異構系統等),服務間通信的錯綜複雜,一步步地将微服務變得更加臃腫,服務治理也是難上加難,而這些問題在單體架構中很容易解決。為此,有人開始懷疑當初微服務化是否是明智之選,甚至考慮回歸到傳統單體應用。

正如下圖所示,PPT 中的微服務總是美好的,但現實中的微服務卻是一團糟糕,想甩甩不掉,越看越糟心。難道就沒有辦法了麼?

建構基于Spring Cloud向Service Mesh架構遷移的解決方案及思路

面對上述暴露出的問題,并在傳統微服務架構下,經過實踐的不斷沖擊,面臨了更多新的挑戰,綜上所述,産生這些問題的原因有以下這幾點:

過于綁定特定技術棧。 當面對異構系統時,需要花費大量精力來進行代碼的改造,不同異構系統可能面臨不同的改造。

代碼侵入度過高。 開發者往往需要花費大量的精力來考慮如何與架構或 <code>SDK</code> 結合,并在業務中更好的深度融合,對于大部分開發者而言都是一個高曲線的學習過程。

多語言支援受限。 微服務提倡不同元件可以使用最适合它的語言開發,但是在 <code>Spring Cloud</code> 架構下就是Java的天下,多語言的支援難度很大。這也就導緻在面對異構系統對接時的無奈,或退而求其次的方案了。

老舊系統維護難。 面對老舊系統,很難做到統一維護、治理、監控等,在過度時期往往需要多個團隊分而管之,維護難度加大。

上述這些問題都是在所難免,我們都知道技術演進來源于實踐中不斷的摸索,将功能抽象、解耦、封裝、服務化。 随着傳統微服務架構暴露出的這些問題,将迎來新的挑戰,讓大家紛紛尋找其他解決方案。

為了解決傳統微服務面臨的問題,以應對全新的挑戰,微服務架構也進一步演化,最終催生了<code>Service Mesh</code> 的出現,迎來了新一代微服務架構,也被稱為下一代微服務。為了更好地了解 <code>Service Mesh</code> 的概念和存在的意義,我們來回顧一下這一演進過程。

在微服務架構中,服務發現、熔斷、治理等能力是微服務架構重要的組成部分。微服務化之後,服務更加的分散,複雜度變得更高,起初開發者将諸如熔斷、逾時等功能和業務代碼封裝在一起,使服務具備了網絡控制能力,如下圖所示。

建構基于Spring Cloud向Service Mesh架構遷移的解決方案及思路

這種方案雖然易于實作,但從設計角度來講卻存在一定的缺陷。

基礎設施功能(如,服務發現,負載均衡、熔斷等)和業務邏輯高度耦合。

每個微服務都重複實作了相同功能的代碼。

管理困難。如果某個服務的負載均衡發生變化,則調用它的相關服務都需要更新變化。

開發者不能集中精力隻關注于業務邏輯開發。

基于上面存在的問題,很容易會想到将基礎設施功能設計為一個公共庫SDK,讓服務的業務邏輯與這些功能降低耦合度,提高重複使用率,更重要的是開發者隻需要關注公共庫SDK的依賴及使用,而不必關注實作這些公共功能,進而更加專注于業務邏輯的開發,比如 <code>Spring Cloud</code> 架構是類似的方式。如下圖所示:

建構基于Spring Cloud向Service Mesh架構遷移的解決方案及思路

實際上即便如此,它仍然有一些不足之處。

這些公共庫SDK存在較為陡峭的學習成本,需要耗費開發人員一定的時間和人力與現有系統內建,甚至需要考慮修改現有代碼進行整合。

這些公共庫SDK一般都是通過特定語言實作,缺乏多語言的支援,在對現有系統整合時有一定的局限性。

公共庫SDK的管理和維護依然需要耗費開發者的大量精力,并需專門人員來進行管理維護。

有了上面公共庫SDK的啟發,加上跨語言問題、更新後的釋出和維護等問題,人們發現更好的解決方案是把它作為一個代理,服務通過這個透明的代理完成所有流量的控制。

這就是典型的 <code>Sidecar</code> 代理模式,也被翻譯為邊車代理,它作為與其他服務通信的橋梁,為服務提供額外的網絡特性,并與服務獨立部署,對服務零侵入,更不會受限于服務的開發語言和技術棧,如下圖所示。

建構基于Spring Cloud向Service Mesh架構遷移的解決方案及思路

以 <code>Sidecar</code> 模式進行通信代理,實作了基礎實施層與業務邏輯的完全隔離,在部署、更新時帶來了便利,做到了真正的基礎設施層與業務邏輯層的徹底解耦。另一方面,<code>Sidecar</code> 可以更加快速地為應用服務提供更靈活的擴充,而不需要應用服務的大量改造。<code>Sidecar</code> 可以實作以下主要功能:

服務注冊。 幫助服務注冊到相應的服務注冊中心,并對服務做相關的健康檢查。

服務路由。 當應用服務調用其它服務時,<code>Sidecar</code> 可以幫助從服務發現中找到相應的服務位址,完成服務路由功能。

服務治理。 <code>Sidecar</code> 可以完全攔截服務進出的流量,并對其進行相應的調用鍊跟蹤、熔斷、降級、日志監控等操作,将服務治理功能集中在 <code>Sidecar</code> 中實作。

集中管控。 整個微服務架構體系下的所有服務完全可以通過 <code>Sidecar</code> 來進行集中管控,完成對服務的流控、下線等。

于是,應用服務終于可以做到跨語言開發、并更專注于業務邏輯的開發。

把 <code>Sidecar</code> 模式充分應用于一個龐大的微服務架構系統,為每個應用服務配套部署一個 <code>Sidecar</code> 代理,完成服務間複雜的通信,最終就會得到一個如下所示的網絡拓撲結構,這就是 <code>Service Mesh</code>,又稱之為“服務網格“。

建構基于Spring Cloud向Service Mesh架構遷移的解決方案及思路

至此,迎來了新一代微服務架構——<code>Service Mesh</code>,它徹底解決了傳統微服務架構所面臨的問題。

在開始進入主題之前,我認為有必要再對 <code>Service Mesh</code> 進行統一的闡述,這樣将有助于了解它,更加便于閱讀接下來的内容。

<code>Service Mesh</code>翻譯為“服務網格”,作為服務間通信的基礎設施層。輕量級高性能網絡代理,提供安全的、快速的、可靠地服務間通訊,與實際應用部署一起,但對應用透明。應用作為服務的發起方,隻需要用最簡單的方式将請求發送給本地的服務網格代理,然後網格代理會進行後續的操作,如服務發現,負載均衡,最後将請求轉發給目标服務。

<code>Service Mesh</code>目的是解決系統架構微服務化後的服務間通信和治理問題。 服務網格由<code>Sidecar</code>節點組成,這個模式的精髓在于實作了資料面(業務邏輯)和控制面的解耦。具體到微服務架構中,即給每一個微服務執行個體同步部署一個<code>Sidecar</code>。

建構基于Spring Cloud向Service Mesh架構遷移的解決方案及思路

在<code>Service Mesh</code>部署網絡結構圖中,綠色方塊為應用服務,藍色方塊為 <code>SideCar</code>,應用服務之間通過<code>Sidecar</code>進行通信,整個服務通信形成圖中的藍色網絡連線,圖中所有藍色部分就形成了<code>Service Mesh</code>。其具備如下主要特點:

應用程式間通訊的中間層。

輕量級網絡代理。

應用程式無感覺。

解耦應用程式的重試/逾時、監控、追蹤和服務發現。

<code>Service Mesh</code> 的出現解決了傳統微服務架構中的痛點,使得開發人員專注于業務本身,同時,将服務通信及相關管控功能從業務中分離到基礎設施層。

那麼 <code>Service Mesh</code> 到底能夠做什麼呢?

<code>Service Mesh</code> 作為微服務架構中負責網絡通信的基礎設施層,具備網絡處理的大部分功能。下面列舉了一些主要的功能:

動态路由。 可通過路由規則來動态路由到所請求的服務,便于不同環境、不同版本等的動态路由調整。

故障注入。 通過引入故障來模拟網絡傳輸中的問題(如延遲)來驗證系統的健壯性,友善完成系統的各類故障測試。

熔斷。 通過服務降級來終止潛在的關聯性錯誤。

安全。 在<code>Service Mesh</code>上實作安全機制(如<code>TLS</code>),并且很容易在基礎設施層完成安全機制更新。

多語言支援。 作為獨立運作且對業務透明的 <code>Sidecar</code> 代理,<code>Service Mesh</code> 很輕松地支援多語言的異構系統。

多協定支援。 同多語言一樣,也支援多協定。

名額和分布式鍊路追蹤。

概括起來,<code>Service Mesh</code> 主要展現在以下4個方面:

可見性: 運作時名額遙測、分布式跟蹤。

可管理性: 服務發現、負載均衡、運作時動态路由等。

健壯性: 逾時、重試、熔斷等彈性能力。

安全性: 服務間通路控制、<code>TLS</code> 加密通信。

從上述<code>Service Mesh</code>的介紹和功能來看:

基礎設施層是<code>Service Mesh</code>的定位,緻力于解決微服務基礎設施标準化、配置化、服務化和産品化的問題。

服務間通信是<code>Service Mesh</code>技術層面對的問題,對微服務屏蔽通信的複雜度,解決微服務的通信治理問題。

請求的可靠傳遞是<code>Service Mesh</code>的目标。

輕量級網絡代理是<code>Service Mesh</code>的部署方式。

對應用程式透明是<code>Service Mesh</code>的亮點和特色,實作對業務無侵入。

綜合上述,<code>Service Mesh</code>主要解決使用者如下3個次元的痛點需求:

完善的微服務基礎設施

通過将微服務通信下沉到基礎設施層,屏蔽了微服務處理各種通信問題的複雜度,形成微服務之間的抽象協定層。開發者無需關心通信層的具體實作,也無需關注<code>RPC</code>通信(包含服務發現、負載均衡、流量排程、流量降級、監控統計等)的一切細節,真正像本地調用一樣使用微服務,通信相關的一起工作直接交給<code>Service Mesh</code>。

語言無關的通信和鍊路治理

功能上,<code>Service Mesh</code>并沒有提供任何新的特性和能力,<code>Service Mesh</code>提供的所有通信和服務治理能力在<code>Service Mesh</code>之前的技術中均能找到,比如<code>Spring Cloud</code>就實作了完善的微服務<code>RPC</code>通信和服務治理支援。

<code>Service Mesh</code>改變的是通信和服務治理能力提供的方式,通過将這些能力實作從各語言業務實作中解耦,下沉到基礎設施層面,以一種更加通用和标準化的方式提供,屏蔽不同語言、不同平台的差異性,有利于通信和服務治理能力的疊代和創新,使得業務實作更加友善。

<code>Service Mesh</code>避免了多語言服務治理上的重複建設,通過<code>Service Mesh</code>語言無關的通信和服務治理能力,助力于多語言技術棧的效率提升。

通信和服務治理的标準化

微服務治理層面,<code>Service Mesh</code>是标準化、體系化、無侵入的分布式治理平台。

标準化方面,<code>Sidecar</code>成為所有微服務流量通信的限制标準,同時<code>Service Mesh</code>的資料平台和控制平面也通過标準協定進行互動。

體系化方面,從全局考慮,提供多元度立體的微服務可觀測能力(<code>Metric</code>、<code>Trace</code>、<code>Logging</code>),并提供體系化的服務治理能力,如限流、熔斷、安全、灰階等。

通過标準化,帶來一緻的服務治理體驗,減少多業務之間由于服務治理标準不一緻帶來的溝通和轉換成本,提升全局服務治理的效率。

下面對針對目前市面上常見的 <code>Service Mesh</code> 架構進行的比較彙總,見下表所示:

功能

Linkerd 2

Envoy

Istio

Conduit

代理

<code>Finagle</code> + <code>Jetty</code>

<code>Envoy</code>

<code>Conduit</code>

熔斷

支援。基于連接配接的熔斷器<code>Fast Fail</code>和基于請求的熔斷器<code>Failure Accrual</code>。

支援。通過特定準則,如最大連接配接數、 最大請求數、最大挂起請求數或者最大重試數的設定。

支援。通過特定準則,如最大連接配接數和最大請求數等的設定。

暫不支援。

動态路由

支援。通過設定<code>Linkerd</code>的<code>dtab</code>規則實作不同版本服務請求的動态路由。

支援。通過服務的版本或環境資訊實作。

流量分流

支援。以增量和受控的方式實作分流。

服務發現

支援。支援多種服務發現機制,如基于檔案的服務發現、<code>Consul</code>、<code>Zookeeper</code>、<code>Kubernetes</code>等。

支援。通過提供平台無關的服務發現接口實作與不同服務發現工具內建。

隻支援<code>Kubernetes</code>。

負載均衡

支援。提供多種負載均衡算法。

支援。提供多種負載均衡算法,如<code>Round Robin</code>、權重最小請求、哈希環、<code>Maglev</code>等。

支援。目前隻有HTTP請求支援基于<code>P2C</code> + <code>least-loaded</code>的負載均衡算法。

安全通信

支援<code>TLS</code>。

通路控制

不支援。

支援。基于<code>RBAC</code>的通路控制。

可見性

分布式追蹤(<code>Zipkin</code>)、運作時名額(<code>InfluxDB</code>、<code>Prometheus</code>、<code>statsd</code>)

分布式追蹤(<code>Zipkin</code>)、運作時名額(<code>statsd</code>)

分布式追蹤(<code>Zipkin</code>)、運作時名額(<code>Prometheus</code>、<code>statsd</code>)、監控(<code>NewRepic</code>、<code>Stackdriver</code>)

運作時名額(<code>Prometheus</code>)

部署模式

<code>sidecar</code>或者<code>per-host</code>模式

<code>sidecar</code>模式

控制平面

<code>Namerd</code>

沒有,但可通過API實作。

<code>Pilot</code>、<code>Mixer</code>、<code>Citadel</code>

協定支援

<code>HTTP/1.x</code>、<code>HTTP/2</code>、<code>gRPC</code>

<code>HTTP/1.x</code>、<code>HTTP/2</code>、<code>gRPC</code>、<code>TCP</code>

運作平台

平台無關

目前支援<code>Kubernetes</code>,平台無關是最終實作目标。

上述任何一個 <code>Service Mesh</code> 架構都能夠滿足您的基本需求。到⽬前為⽌,<code>Istio</code> 具有這幾個服務⽹格架構中最多的功能和靈活性,靈活性意味着複雜性,是以需要團隊更為充⾜的準備。如果隻想使⽤基本的 <code>Service Mesh</code> 治理功能,<code>Linkerd</code> 可能是最佳選擇。如果您想⽀持同時包含 <code>Kubernetes</code> 和 <code>VM</code> 的異構環境,并且不需要 <code>Istio</code> 的複雜性,那麼 <code>Consul</code> 可能是您的最佳選擇,⽬前 <code>Istio</code> 也提供了同時包含 <code>Kubernetes</code> 和 <code>VM</code> 的異構環境的⽀持。

從另一個角度來看,目前 <code>Istio</code> 社群正在快速疊代以應對各種場景,并力争作為 <code>Service Mesh</code> 的标杆,本文以選取 <code>Istio</code> 架構作為最終遷移架構。

為了更好的占領市場,滿足更多業務場景的需求,傳統微服務架構(如,基于 <code>Spring Cloud</code> 架構的微服務架構)面臨了衆多新的挑戰,而 <code>Service Mesh</code> 的出現正好解決了這些問題。面對新的架構體系,對于傳統微服務架構該如何應對?

對于 <code>Spring Cloud</code> 架構的微服務向 <code>Service Mesh</code> 架構遷移必将迫在眉睫,是推翻重來,還是循序遷移?如果遷移,又該如何?

對于還未涉足 <code>Service Mesh</code> 的企業或産品,其傳統微服務架構如若已采用 <code>Spring Cloud</code> 架構建構,此時向<code>Service Mesh</code> 架構遷移該如何做呢?需要綜合考慮哪些因素?是否有依可據呢?

接下來,我們就建構基于<code>Spring Cloud</code> 向 <code>Service Mesh</code> 架構遷移提供一些建議方案和思路,供大家參考。

傳統微服務架構,我們以最為典型的 <code>Spring Cloud</code> 架構為例進行遷移說明。首先,我們先看一下這樣的一個遷移場景,目前的微服務架構是這樣的,如下圖左邊部分:

應用是部署在虛拟機或實體機上。(服務還未容器化)

架構是基于 <code>Spring Cloud</code> 架構開發。(服務中包含的業務邏輯和 <code>Spring Cloud</code> 元件相依賴,業務和架構耦合度過高)

開發語言是以Java為主。(存在跨語言的問題)

注冊中心采用的是 <code>Consul</code> 或 <code>Eureka</code>。(服務需引入注冊中心依賴包,存在一定的耦合)

目前開源 <code>Istio</code> 已經成為 <code>Service Mesh</code> 事實上的标準,更是新一代微服務架構發展的趨勢,是以公司希望嘗試遷移到 <code>Istio</code> 架構,希望最終形成類似下圖右邊部分。

建構基于Spring Cloud向Service Mesh架構遷移的解決方案及思路

面對上述遷移場景,确定要引入 <code>Service Mesh</code> 時,就要徹底搞清楚 <code>Service Mesh</code> 遷移的具體路徑。

首先,要對自己項目做以下評估:

是否真的有必要引入遷移到 <code>Service Mesh</code> 上?

目前微服務架構下,是否面臨傳統微服務架構面臨的挑戰?

目前微服務架構,是否已經阻礙或影響未來業務的發展?

公司或技術團隊,是否有能力、人力、精力來投入到 <code>Service Mesh</code> 的遷移?

其次,完成 <code>Service Mesh</code> 微服務平台的搭建。目前所處階段是否已經支援容器化和 <code>Kubernetes</code>。如果目前業務已經運作在 <code>Kubernetes</code> 之上,則 <code>Service Mesh</code> 的遷移将會比較順暢;如果目前業務沒有運作在<code>Kubernetes</code>上,因 <code>Service Mesh</code> 目前典型的 <code>Istio</code> 架構對 <code>Kubernetes</code> 有着過度依賴,是以可能就無法直接從 <code>Spring Cloud</code> 遷移到 <code>Istio</code> 架構,即使定制修改 <code>Istio</code> 以接觸對 <code>Kubernetes</code> 的依賴,将會付出很大的代價。這時通常有兩條遷移路徑可以選擇。

路徑一:非 <code>Kubernetes</code> 環境下,先接入 <code>Sidecar</code>

如果目前業務沒法快速容器化,同時又有引入 <code>Service Mesh</code> 的迫切需求,可采取先接入 <code>Sidecar</code>,來滿足目前業務的痛點需求。在引入 <code>Sidecar</code> 時,要注意其未來的演進方向,考慮後續可能繼續向 <code>Service Mesh</code> 遷移,一旦時機成熟并引入 <code>Kubernetes</code> 容器化後,則能夠順利由 <code>Sidecar</code> 的方式直接演進到 <code>Service Mesh</code>。

<code>Service Mesh</code> 目前典型的 <code>Istio</code> 架構在非 <code>Kubernetes</code> 下沒有很好的支援(據說未來會完全脫離對<code>Kubernetes</code> 的依賴),對 <code>Istio</code> 進行定制化修改以支援非 <code>Kubernetes</code> 環境将會付出很大的代價,非特别強烈的需求和強大的技術儲備,一般不建議這麼做,特别是對于一些中小公司而言。

如果一定要在非 <code>Kubernetes</code> 環境下引入 <code>Service Mesh</code>,資料平面可使用 <code>Envoy</code>,控制平面可根據 <code>XDS</code> 協定進行自研。

路徑二:先進行 <code>Kubernetes</code> 容器化改造,再接入 <code>Service Mesh</code>

倘若公司有雲平台或容器化團隊,可采用公司資源共享的方式,先借助其他團隊來完成 <code>Kubernetes</code> 容器化改造,再接入 <code>Service Mesh</code>。

最後,基于建構的 <code>Service Mesh</code> 架構,将業務應用逐漸遷移到 <code>Service Mesh</code> 上來。

在實施遷移時,必須要時刻遵守以下遷移原則。

漸進式遷移: 為了避免 <code>Service Mesh</code> 遷移過程中的風險,必須采用漸進式遷移原則,每次隻遷移少量服務,待遷移後觀察足夠長的時間,沒有問題後再繼續遷移。

業務透明: 為減少 <code>Service Mesh</code> 遷移對業務的影響,減少業務的遷移阻力,遷移初期必須確定業務完全透明且不需要過多的變更和修改。

方案上,為保證遷移對業務的完全透明,在資料平面通信上可采用支援透明攔截的方式,對業務請求流量透明攔截。

相容性: 在遷移階段,必然會存在兩種模式( <code>Spring Cloud</code> 和 <code>Service Mesh</code> 架構)并存,在遷移過程中需要充分考慮兩者的相容性,使得遷移前後網絡打通,至少能夠滿足未遷移和已遷移部分能夠通信。

從 <code>Spring Cloud</code> 向 <code>Service Mesh</code> 架構遷移,大體上分為四個步驟:<code>Spring Cloud</code> 架構分析、容器化改造、<code>Service Mesh</code> 微服務平台搭建和應用遷移。

<code>Spring Cloud</code> 架構分析的目的在于重新了解我們目前微服務架構下的所有功能,便于在向 <code>Service Mesh</code> 遷移時做準備,考慮哪些功能需要遷移,哪些不需要遷移,哪些需要改造等。我們先看一下基于 <code>Spring Cloud</code> 完整建構的微服務架構解決方案,如下圖所示。

建構基于Spring Cloud向Service Mesh架構遷移的解決方案及思路

從上圖經過分析,我們可以彙總得知它主要由以下幾部分組成:

代理&amp;網關: 提供統一對外或對内的通路入口,包括路由、鑒權、限流、熔斷、降級等統一處理。

注冊中心: 提供服務的注冊與發現功能。

應用服務: 覆寫整個業務服務,包括業務邏輯實作、架構SDK及外部元件依賴互動等。

中間件&amp;資料存儲: 為應用服務提供額外的支援能力。

CI&amp;CD: 持續內建、持續部署。

上述這幾部分中哪些内容是我們可以去掉或者說基于 <code>Service Mesh</code> (以 <code>Istio</code> 為例)能夠去做的?經過分析得知,可以替換的元件包括網關(<code>Gateway</code> 或者 <code>Zuul</code>,由 <code>Ingress gateway</code> 或者 <code>egress</code> 替換),熔斷器(<code>hystrix</code>,由 <code>Sidecar</code> 替換),注冊中心(<code>Eureka</code> 及 <code>Eureka client</code>,由 <code>Polit</code>,<code>Sidecar</code> 替換),負責均衡( <code>Ribbon</code>,由 <code>Sidecar</code> 替換)等。

此階段,我們能夠大緻知道 <code>Spring Cloud</code> 中的哪些内容可以由 <code>Istio</code> 處理,哪些内容可以繼續沿用。

容器化改造,主要針對目前還未引入 <code>Kubernetes</code> 容器化的場景。

在容器化改造之前,我們有必要知道改造的優勢及要求。

容器化改造優勢:

更省: 極大的資源利用效率, 最大限度榨取和共享實體資源,多項目更能展現出容器化多優勢,節約部署 IT 成本。

更快: 秒級啟動,實作業務系統更快的開發疊代 和 傳遞部署。

彈性: 可根據業務負載進行彈性容器伸縮,彈性擴充。

友善: 容器化業務部署支援藍綠/灰階/金絲雀等釋出,復原,更加靈活友善。

靈活: 監控底層 node 節點健康狀态,靈活排程至最優節點部署。

強一緻性: 容器将環境和代碼打包在鏡像内,保證了測試與生産環境的強一緻性。

容器化改造要求:

掌握 <code>Docker</code> 技術: 開發人員需熟悉 <code>Docker</code> 容器化技術,熟練編寫 <code>Dockerfile</code> 檔案。

掌握 <code>Kubernetes</code> 編排系統: 熟悉 <code>Kubernetes</code> 容器化編排系統, 熟悉各元件資源清單編寫、高可用、 <code>RBAC</code> 安全政策等。

容器化改造,主要分為以下兩個階段:

容器化建構: 将基于 <code>Spring Cloud</code> 搭建的所有服務實作容器化建構,實作 <code>Docker</code> 鏡像打包。

容器化管理: 基于 <code>Kubernetes</code> 進行服務容器的管理。

容器化建構需借助編寫的 <code>Dockerfile</code> 檔案,并通過 <code>Jenkins</code> 自動化完成對 <code>Docker</code> 鏡像的制作。這裡以一個簡單的serviceProvider服務(基于 <code>Spring Cloud</code> 架構開發)為例說明建構過程:

(1)建立 <code>Dockerfile</code> 檔案。

在服務<code>serviceProvider/src/main/docker</code>目錄下建立一個 <code>Dockerfile</code> 檔案,内容如下:

(2)配置pom <code>docker-maven-plugin</code>插件。

在服務<code>serviceProvider</code> 的 <code>pom.xml</code> 中配置 <code>build</code> 部分,内容如下:

(3)打包。

在執行 <code>mvn package</code> 的時候,會根據 <code>pom.xml</code> 中 <code>build</code> 配置自動打包 <code>Docker</code> 鏡像,并推送到Docker伺服器上。

至此,就順利地完成了容器化建構,這一步對于原有服務基本沒有影響,打包成功後隻需進行驗證測試即可,以確定鏡像打包存在問題。

容器化管理實際上就是将服務容器通過 <code>Kubernetes</code>編排系統,完成對服務部署、管理等,需要對 <code>Kubernetes</code> 有一定的了解,會熟練使用它,看參考之前寫的”Kubernetes從入門到精通“系列文章。

<code>Service Mesh</code> 我們選取 <code>Istio</code> 架構,關于選型方案可參考之前文章:Service Mesh 架構選型對比分析:Linkerd、Envoy、Istio、Conduit。

基于 <code>Istio</code> 架構搭建 <code>Istio</code> 基礎架構,在控制平面和資料平台提供分别提供以下能力:

控制平面: 提供服務⽹格控制指令下發、服務配置、 權限控制等功能。

資料平台: 提供服務治理、服務監控及運維、流量管控等功能。

上述功能在 <code>Istio</code> 架構上都能找到對應的功能,并通過适當的資源清單配置即可完成。

<code>Istio</code> 架構圖如下:

建構基于Spring Cloud向Service Mesh架構遷移的解決方案及思路

至此,一個 <code>Istio</code> 基礎架構搭建完成,能夠提供 <code>Service Mesh</code> 的所有能力。

在遷移路徑中已經提及過,對于非 <code>Kubernetes</code> 環境,建議先引入 <code>Sidecar</code>,并采取 <code>istio</code> 對虛拟機的支援方案,在虛拟機環境下運作。但如果有多平台支援的場景,比如既有 <code>Kubernetes</code> 環境,又有虛拟機環境,需對 <code>istio</code> 進行定制化改造,去掉對 <code>Kubernetes</code> 的強依賴和耦合,增加對其他平台的支援。(對于多平台的支援,目前<code>istio</code> 還未支援,但從 <code>istio</code> 官方相關文檔可以看出,多平台的支援最終肯定支援,我們隻需拭目以待。)

<code>Istio</code> 對 <code>Kubernetes</code> 的耦合主要有以下幾個方面,是以需要針對性的适配修改。

(1)API資源管理層對 Kubernetes API Server 的依賴

資源管理層是 <code>Istio</code> 對 <code>Kubernetes</code> 依賴最大的地方。<code>Istio</code> 對核心資源的管理,是以 <code>Kubernetes CRD</code> 為基礎,并使用 <code>kubectl</code> 作為指令行操作入口,<code>kubectl</code> 調用 <code>API Server</code>,将資源存放在 <code>etcd</code> 中,并通過 <code>Kubernetes CRD</code> 機制觸發資源變更事件通知,通知關心 <code>Istio</code> 資源變更事件的子產品進行相關處理。

如需解除<code>Istio</code> 對 <code>Kubernetes</code> 的綁定,則需要自行實作這一套API管理方式,并且做到平台無關。

(2)通信通路層面對 kube DNS 的依賴

通信層面,在用戶端發送請求前,先通過 <code>DNS</code> 擷取服務的虛拟IP位址,<code>Istio</code> 的 <code>DNS</code> 實作沿用<code>Kubernetes DNS</code> 方案,基于 <code>DNS</code> 通過服務名實作直接通路。是以需要在 <code>DNS</code> 方案層面接觸和<code>Kubernetes</code> 的耦合,并使用平台無關的 <code>DNS</code> 解決方案。

對于體量較大的業務,不可能一次性遷移完成,需遵守“漸進式遷移”原則,逐漸遷移,是以實際遷移過程中可能面臨這樣的訴求:

一些存量老業務運作在虛拟機或者實體機上,暫時沒有容器化改造計劃,但希望通過 <code>Service Mesh</code> 來做服務治理。

新上的業務或者存量的非關鍵業務可以做為試點,先容器化、<code>Service Mesh</code> 化,其它業務依然采用原有的運作方式和微服務架構。

對于未遷移的存量應用和遷移完成的 <code>Service Mesh</code> 應用依然能保持業務上的互通。

面對上述這些真實而又合理的訴求,在進行 <code>Service Mesh</code> 微服務平台搭建時,必然會存在兩種架構并存的場景,如下圖所示,左邊是未遷移的存量服務,右邊是容器化并 <code>Service Mesh</code> 化的試點服務,但這種模式服務間卻是互不相同,且無法統一治理。

建構基于Spring Cloud向Service Mesh架構遷移的解決方案及思路

那麼兩種架構并存時,如何服務間互通,統一治理呢?

在業内流行這樣一句話:計算機科學領域的任何問題都可以通過增加一個間接的中間層來解決。

同樣,我們可以針對 <code>Service Mesh</code> 的控制平面做些文章,通過自定義控制插件(<code>WASM</code>)将 <code>Spring Cloud</code> 架構中原有注冊中心的功能納入進來,由控制平面提供原有服務注冊與發現的能力,并結合 <code>Istio</code> 中入口網關 <code>Ingress</code> 和 <code>ServiceEntry</code> 資源配置,以實作服務間互通,統一治理,整個實作邏輯架構如下圖所示。

建構基于Spring Cloud向Service Mesh架構遷移的解決方案及思路

至此,實作了基于<code>Spring Cloud</code> 和 <code>Istio</code> 兩種架構的并存。

到這裡,我們已經完成了 <code>Service Mesh</code> 微服務平台的搭建,那在這樣的平台上我們如何将應用 <code>Spring Cloud</code> 應用逐漸向 <code>Service Mesh</code> 遷移呢?

我們先來看一下 <code>Spring Cloud</code> 架構與 <code>Istio</code> 架構的功能重疊情況:

功能清單

Spring Cloud

Isito

服務注冊與發現

支援,基于Eureka,consul等元件。

支援,基于<code>XDS</code>接口擷取服務資訊,并依賴“虛拟服務路由表”實作服務發現,可靈活擴充任何注冊中心。

鍊路監控

支援,基于<code>Zikpin</code> 、 <code>Pinpoint</code>或者<code>Skywalking</code> 實作。

支援,基于<code>Sidecar</code> 代理模型,記錄網絡請求資訊。

服務網關

支援,基于 <code>zuul</code> 或者 <code>Spring-Cloud-gateway</code> 實作。

支援,基于<code>Ingress gateway</code> 以及 <code>egress</code>實作。

熔斷器

支援,基于<code>Hystrix</code> 實作。

支援,基于聲明配置檔案,最終轉化成路由規則實作。

服務路由

支援,基于網關層實作路由轉發。

支援,基于iptables規則實作,通過 <code>VirtualService</code> 和<code>DestinationRule</code>靈活配置。

安全政策

支援,基于 <code>spring-security</code>元件實作,包括認證,鑒權等,支援通信加密。

支援,基于 <code>RBAC</code> 的權限模型,依賴 <code>Kubernetes</code>實作,同時支援通信加密。

配置中心

支援,<code>Spring Cloud Config</code>元件實作。

性能監控

支援,基于 <code>Spring cloud</code> 提供的監控元件收集資料,對接第三方的監控資料存儲。

支援,基于<code>Sidecar</code>代理,記錄服務調用性能資料,并通過metrics adapter,導入第三方資料監控工具。

日志收集

支援,對接第三方日志系統,例如 <code>ELK</code>。

支援,基于 <code>Sidecar</code> 代理,記錄日志資訊,并通過<code>log adapter</code>,導入第三方日志系統。

從上表功能情況,存在大量重疊功能,需将<code>Spring Cloud</code> 與 <code>Istio</code> 中重疊功能去除,缺失功能保留,理論上可輕松去重。對于 <code>Spring Cloud</code> 而言,這些重疊功能大部分隻需去除 <code>pom.xml</code> 中依賴包、相關配置及代碼中注解即可輕松完成,剩餘一個相對幹淨的應用。

應用注入是指在将應用服務部署到網格時,将 <code>Sidecar</code> 注入到應用服務中去,以實作網格的代理。

<code>Sidecar</code> 注入,分為手動注入和自動注入:

手動注入: 通過手動執行 <code>istioctl kube-inject</code> 來重新構造應用的 <code>CRD yaml</code>。

自動注入: 通過 <code>Kubernetes</code> 的 <code>mutable webhook</code> 回調 <code>istio-sidecar-injector</code> 服務來重新構造應用的 <code>CRD yaml</code>。

如下圖所示:

建構基于Spring Cloud向Service Mesh架構遷移的解決方案及思路

無論是手動注入還是自動注入,<code>Sidecar</code> 注入的本質是将運作 <code>Sidecar</code> 所需要的鏡像位址、啟動參數、所連接配接的 <code>Istio</code> 叢集(<code>Pilot</code>、<code>Citadel</code>、<code>Galley</code>)及配置資訊填充到注入模版,并添加到應用的 <code>CRD yaml</code> 中,最終通過 <code>Kubernetes</code> 持久化資源并拉起應用和 <code>Sidecar</code> 的 <code>POD</code>。

此時,應用已成功遷移部署到 <code>Service Mesh</code> 中了。

這篇文章從傳統微服務架構開始一步步介紹到 <code>Service Mesh</code>,并提出了傳統微服務架構面臨的挑戰,針對現狀,如何能夠更好的滿足市場需求,而不被市場淘汰,介紹了傳統微服務如何平滑遷移至 <code>Service Mesh</code> 的過程,并給出了一些解決方案、步驟及思路,供大家參考。

希望能夠幫您解決實際遷移過程中遇到的問題,能夠幫助大家在做架構演進或遷移時帶來一些思考和啟發。

參考資料:

https://istio.io/latest/docs/concepts/what-is-istio/

劉俊海 著《Service Mesh微服務架構設計》

https://mp.weixin.qq.com/s/y9PZLgHhVcdsMuTzAyIMsQ

https://www.servicemesher.com/blog/service-mesh-rebuild-microservice-market/

https://mp.weixin.qq.com/s/-MszFJORuDJKf3V5ndyimw

https://www.servicemesher.com/blog/netease-yeation-service-mesh/

繼續閱讀