Categories
程式開發

Service Mesh終極指南:在微服務時代管理服務與服務之間的通信


本文要點

  • 服務網格管理分佈式(一般是基於微服務的)軟件系統中所有的服務與服務間的通信。一般來講,它是通過使用名為“sidecar”代理實現的,sidecar代理會和每個服務一起部署,所有的流量都會通過它來進行透明地路由。
  • 服務網格中使用的代理通常是“應用層”可感知的(運維在OSI網絡棧中的第七層)。這意味著流量路由決策和度量指標標記可以利用HTTP頭信息或其他應用層協議元數據中的數據來實現。
  • 服務網格提供了動態服務發現和流量管理的功能,包括用於測試的流量shadowing(複製)以及用於金絲雀發布、增量發布以及A/B類型體驗的流量分割。
  • 服務網格還支持橫切性需求的實現和實施,比如安全性(提供服務標識和TLS)以及可靠性(限速、斷路器)。
  • 服務網格處於系統中每個請求處理的關鍵路徑上,所以它也可以提供額外的“可觀察性”,比如請求的分佈式跟踪、HTTP錯誤碼的頻率、全局以及服務與服務之間的延遲。
  • 使用服務網格會有明顯的收益,但是有一些權衡也需要進行分析,比如增加複雜性以及額外的運行時資源。
  • 服務網格技術正在快速成為(雲原生)應用平台“管道”的一部分。這個領域中有趣的創新是與高層次的抽象和以人為中心的控制平面息息相關的。
  • 流行的服務網格包括Linkerd、Istio、Consul、Kuma和Maesh。在這個領域中,支撐技術包括:七層感知的代理(如Envoy、HAProxy、NGINX和MOSN)以及服務網格編排、可視化以及有助於理解的工具,如SuperGloo、Kiali和Dive。

大約在2016年,“服務網格”(service mesh)這個術語突然間在微服務、雲計算和DevOps等領域冒了出來。但是,與計算機行業中的很多概念一樣,相關的模式和技術其實有著很長的歷史。

服務網格的出現在很大程度上源於IT領域的一場完美風暴。開發人員開始使用多語言(polyglot)的方式編寫分佈式系統,因此需要動態的服務發現功能。運維領域則開始使用短暫存活的基礎設施,他們希望能夠優雅地處理難以避免的通信故障並執行網絡策略。平台團隊開始使用像Kubernetes這樣的容器編排平台,他們希望能夠使用現代API驅動的網絡代理(如Envoy)來動態路由系統內和系統周邊的流量。

本文旨在回答軟件架構師和技術領導者所關切的問題,比如:服務網格是什麼?我需要服務網格嗎?我該如何評估不同的服務網格方案?

服務網格模式

服務網格模式的焦點在於管理分佈式軟件系統中所有的服務與服務間的通信。

背景(Context)

該模式有雙重背景:首先,工程師已經採用了微服務架構模式並且通過將多個服務(理想情況下,服務是單一職責的,並且是可獨立部署的)組合在一起的方式來構建應用程序。其次,組織開始採用雲原生平台技術,如容器(如Docker)、編排器(如Kubernetes)和代理/網關(如Envoy)。

意圖(Intent)

服務網格模式試圖解決的問題包括:

  • 消除將特定語言的通信庫編譯到每個服務的必要性,這些通信庫一般會用來處理服務發現、路由和應用層(第7層)的非功能性通信需求。
  • 將服務通信的配置外部化,包括外部服務的網絡位置、安全憑證和服務的質量目標。
  • 提供對其他服務的被動和主動監控。
  • 在整個分佈式系統中,實現策略實施的去中心化。
  • 提供默認的可觀察性並標準化相關數據的收集。
    • 支持請求日誌
    • 配置分佈式跟踪
    • 收集度量指標

結構(Structure)

服務網格模式主要關注傳統上的“東-西(east-west)流量”,也就是基於遠程過程調用(remote procedure call,RPC)的流量:起源於數據中心內部並且會跨服務的請求/響應類型的通信。這與API網關或邊緣代理是不同的,後者旨在處理“南-北(north-south)流量”:起源於外部的通信並且要進入(ingress)數據中心中的一個端點或服務。

服務網格的特性

服務網格的實現一般會提供如下特性中的一項或多項:

  • 規範化命名並添加邏輯路由(如將代碼級別的名字“user-service”映射至平台中的特定地址“user-service”)。
  • 提供路由重塑(traffic shaping)和路由轉移(traffic shifting)功能。
  • 維護負載均衡,通常會通過可配置的算法實現。
  • 提供服務發布控制(如金絲雀發布和流量切分)
  • 提供針對每個請求的路由(如流量shadowing、故障注入和調試重路由)。
  • 添加基線可靠性,比如健康檢查、超時/截止期限、斷路器和重試。
  • 增加安全性,這是通過透明的雙向傳輸層安全(Transport Level Security,TLS)和像訪問控制列表(Access Control List,ACL)這樣的策略實現的。
  • 提供額外的可觀察性和監控,比如最重要的指標(請求量、成功率和延遲),支持分佈式跟踪,以及“捕獲”和實時檢查服務與服務之間通信的能力。
  • 支持平台團隊配置“sane defaults(一組能夠讓程序運行地更好、更快的Linux/Unix配置,參見該地址——譯者註)”,保護系統免受不良通信的影響。

服務網格的架構:直探本質

服務網格有兩個高層級的組件所組成:數據平面和控制平面。Envoy Proxy的創建者Matt Klein曾經就服務網格的數據平面和控制平面這一話題寫過一篇非常精彩的深入介紹文章。

一般來講,數據平面​​“完成真正的工作”,負責“有條件地翻譯、轉發和觀察流入和流出某個[网络端点]的網絡包”。在現代系統中,數據平面​​一般會以代理的方式來實現(比如Envoy、HAProxyMOSN),代理會作為“sidecar”在每個服務的進程之外運行。

Klein指出,在服務網格中,數據平面​​“會接觸系統中的每個包/請求,它要負責服務發現、健康檢查、路由、負載均衡、認證/授權和可觀察性。”CNCF正在根據Klein之前題為The Universal Data Plane API的博客文章創建一個統一的Data Plane API。這個提議擴展了由Envoy定義和實現的xDS API,並且在其他的代理中得到了支持,比如MOSN。

控制平面則“監督工作的執行”,它會獲取所有的數據平面實例(即一組隔離的無狀態sidecar代理)並將它們轉換成一個分佈式系統。控制平面不會接觸系統中的包/請求,它允許運維人員為網格中所有運行的數據平面提供策略和配置。控制平面還能夠收集和集中數據平面的遙測數據,供運維人員使用。 Red Hat為這個場景專門研發了Kiali

下圖出自Istio的架構文檔,儘管所標記的技術是Istio特有的,但是組件是對所有的服務網格實現通用的。

Service Mesh終極指南:在微服務時代管理服務與服務之間的通信 1

Istio架構,闡述了控制平面和代理數據平面是如何交互的(圖片來源於Istio文檔)

使用場景

服務網格能夠適用於或支持各種使用場景。

動態服務發現和路由

服務網格提供了動態服務發現和流量管理的功能,包括針對測試的流量shadowing(duplicating),以及針對金絲雀發布和A/B類型體驗的流量切分。

服務網格中所使用的代理一般是“應用層”可感知的(運維在OSI網絡棧中的第七層)。這意味著流量路由的決策和度量指標的標記可以利用HTTP頭信息或其他應用層協議元數據中的數據。

服務與服務之間通信的可靠性

服務網格支持橫切的可靠性需求的實現和實施,比如請求重試、超時、限速和斷路器。服務網格通常用於補償(或封裝)分佈式計算八大謬誤的處理。應該注意的是,服務網格只能提供線路級別的可靠性支持(如重試HTTP請求),最終應該由服務來處理相關的業務影響,比如多次(非冪等)的HTTP POST請求。

流量的可觀察性

由於服務網格位於系統中每個請求處理的關鍵路徑上,所以它能夠提供額外的“可觀察性”,比如分佈式跟踪請求、HTTP錯誤碼的頻率、全局以及服務與服務之間的延遲。儘管“單面板(single pane of glass)”視圖這個術語在企業級領域已經被濫用了,但是服務網格被認為是一種能夠捕獲所有必要數據,從而實現整個系統中“單面板”流量視圖的方法。

通信的安全性

服務網格還支持橫切安全性需求的實現和實施,比如提供服務識別(通過x509證書)、啟用應用層的服務/網絡分段(segmentation)(例如,“服務A”可以與“服務B”通信,但是不能與“服務C”通信)、確保所有的通信都是加密的(通過TLS)並確保存在有效的用戶級身份token或“passports”

反模式

當使用某項技術的反模式出現時,這通常是該技術成熟的標誌。服務網格也不能例外。

過多的流量管理層(就像海龜一樣,一層駝一層)

當開發人員無法與平台或運維團隊協作時,就會出現這種反模式,並且會在代碼中復制服務網格已經實現的通信處理邏輯。例如,除了服務網格配置所提供的線路級別的重試策略之外,應用程序還在代碼中實現了重試策略。這種反模式還可能會導致重複事務的問題。

服務網格銀彈

在IT行業,並不存在所謂的“銀彈”,但是供應商有時候會忍不住給某項新技術打上這樣的標籤。服務網格不能解決微服務、容器編排器(如Kubernetes)或云網絡中所有的通信問題。服務網格只致力於解決服務與服務(東-西)通信的問題,部署和運行服務網格有很明顯的運維成本。

企業級服務總線2.0

在微服務面向服務架構(service-oriented architecture,SOA)時代之前,企業服務總線(Enterprise Service Bus,ESB)實現了軟件組件之間的通信系統。有些人擔心,ESB時代的很多錯誤會在服務網格的使用過程中重複出現。

ESB所提供的通信中心化控制顯然是很有價值的。但是,這些技術的開發是由供應商驅動的,這會帶來很多問題,比如:ESB之間缺少互操作性、行業標準的定制擴展(如向WS-*兼容模式添加供應商特定的配置)以及高昂的成本。 ESB供應商也無法阻止將業務邏輯集成和緊耦合到通信總線中。

大爆炸式的部署

IT界普遍存在這樣一種誤解,即認為大爆炸式的部署方法最易於管理,但根據來自Accelerate的研究和DevOps的狀態報告,情況並非如此。隨著服務網格的全面推出,這意味著該技術正處於處理所有終端用戶請求的關鍵路徑上,因此大爆炸式的部署具有很高的風險。

服務網格實現和產品

以下是當前服務網格實現的非詳盡列表:

服務網格的對比:該採用哪個服務網格?

服務網格領域發展非常快,因此對它們進行對比很快就會過時。但是,依然還是有很多對比可供參考。請注意,這裡面可能會有一些來源相關的偏見,並且要注意對比的日期。

InfoQ始終建議服務網格採用者對每個產品都要進行詳盡調查和試驗。

服務網格教程

想要嘗試各種服務網格的工程師或架構師可以參考如下的教程、實驗和工具:

服務網格的歷史

自從2013年Airbnb發布SmartStack以來,InfoQ就一直在跟踪我們稱為服務網格的話題,SmartStack為新興的“微服務”風格架構提供了進程外的服務發現機制(借助HAProxy)。在此之前,很多之前被稱為“獨角獸”的組織都在研究類似的技術。從2000年代初開始,谷歌就在開​​發其Stubby RPC框架,後來該框架演化成了gRPC,另外,Google Frontend (GFE)和Global Software Load Balancer(GSLB)的特徵在Istio中都可以看到。在2010年代早期,Twitter開始開發基於Scala的Finagle,而Linkerd服務網格就是基於它出現的。

2014年底,Netflix發布了基於JVM的完整工具套件,其中包括Prana,這是一個“sidecar”進程,任何語言編寫的應用服務都能通過HTTP與獨立的庫實例進行通信。在2016年,NGINX團隊開始討論所謂的“Fabric模型”,它非常類似於服務網格,但是需要使用商業的NGINX Plus產品來實現。

在服務網格歷史上,其他值得關注的還有2017年5月發布的Istio、2018年7月發布的Linkerd 2.0、2018年11月發布的Consul ConnectSuperGloo、2019年5月發布的服務網格接口(service mesh interface,SMI)以及2019年9月發布的Maesh和Kuma。

甚至還有在獨角獸組織之外出現的服務網格,比如HashiCorp的Consul,其靈感來源於上述的技術,通常致力於實現CoreOS創造的“GIFEE”理念,即:適用於所有人的谷歌基礎設施。

關於現代服務網格理念如何演化的深入歷史,Phil Calçado曾經寫過一篇綜合性的文章“模式:服務網格”

探索服務網格的未來

因為服務網格依然處於早期採用階段,還有許多工作需要未來完成。廣泛地來講,有四個特別有趣的領域:在RPC之外,添加對其他使用場景的支持、標準化接口和運維、將服務網格進一步推送至平台fabric中以及為服務網格技術構建有效的人工控制平面。

Kasun Indrasiri探索了“將服務網格用於事件驅動消息的潛力”,在他的探索中,討論了在服務網格中實現消息支持的兩種新興架構模式:協議代理sidecar以及HTTP橋接sidecar。在服務網格社區,這是一個很活躍的開發領域,在Envoy中支持Apache Kafka得到了很多的關注。

Christian Posta曾經寫過一篇文章“以統一、標準的API來整合服務網格”,試圖將服務網格的使用標準化。這篇文章也討論了最近微軟和KubeCon EU的合作夥伴所發布的服務網格接口(Service Mesh Interface,SMI)。 SMI定義了一組通用且可移植的API,旨在提供一種方式允許在不同的服務網格技術(包括Istio、Linkerd和Consul Connect)之間實現互操作性。

關於如何將服務網格集成至平台fabric又可以分為兩個子話題。

首先,需要有些工作來減少服務網格數據平面所帶來的網絡開銷。這包括數據平面開發工具包(data plane development kit,DPDK),這是一個用戶空間應用,它“繞過了Linux內核網絡棧厚重的分層,直接與網絡硬件對話”,
Cilium團隊的工作利用了Linux內核中擴展的Berkley包過濾(extended Berkley Packet Filter,eBPF)功能 ,它適用於“非常高效的網絡、策略執行和負載均衡功能”。另外一個團隊正在藉助網絡服務網格(Network Service Mesh)將服務網格的理念映射到L2/L3載荷中,致力於“以雲原生的方式重新想像網絡功能虛擬化(network function virtualization,NFV)”。

其次,有很多舉措正在試圖將服務網格與公有云平台更緊密地集成在一起,比如AWS App MeshGCP Traffic DirectorAzure Service Fabric Mesh

Buoyant團隊正在開發針對服務網格技術的以人為中心的控制平面。他們最近發布了Dive,這是一個基於SaaS的“團隊控制平面”,適用於運維Kubernetes的平台團隊。 Dive在Linkerd服務網格之上添加了更高層級的、以人為中心的功能,並提供了服務目錄、應用程序發布的審計日誌、全局服務拓撲等功能。

FAQ

什麼是服務網格?

服務網格技術管理分佈式(可能是基於微服務的)軟件系統中所有的服務與服務(即“東-西”方向)之間的流量。它提供了以業務為中心的功能性操作,比如路由,也提供了非功能性支持,比如實施安全策略、服務質量以及速度限制。它通常會以sidecar代理的形式來實現(儘管不是唯一方案),所有的服務都會通過sidecar代理通信。

服務網格與API網關的區別是什麼?

服務網格技術管理分佈式(可能是基於微服務的)軟件系統中所有的服務與服務(即“東-西”方向)之間的流量。它提供了以業務為中心的功能性操作,比如路由,也提供了非功能性支持,比如實施安全策略、服務質量以及速度限制。

API網關管理所有進入(ingress)集群的“南-北”流量,並對跨功能性的通信需求提供額外的支持。它作為系統的唯一入口,使多個API或服務具有內聚性,為用戶提供一致的體驗。

如果我正在部署微服務的話,那麼我需要服務網格嗎?

不一定。服務網格會給技術棧帶來運維複雜性,因此只有當組織在擴展服務與服務之間的通信時遇到問題或者有特定的使用場景需要解決時,才應該考慮部署。

我需要服務網格來實現微服務的服務發現功能嗎?

並非如此。服務網格確實提供了一種實現服務發現的方式。但是,還有其他方案,包括特定語言的庫(如Ribbon和Eureka,或者Finagle)。

服務網格會增加服務與服務間通信的開銷/延遲嗎?

是的,當一個服務與另一個服務通信時,服務網格至少會增加兩次額外的網絡躍點(第一個來自處理源的出站連接的代理,第二個來自處理目標的入站連接的代理)。然而,這種額外的網絡跳躍通常發生在本地主機或環回網絡接口上,並且只會增加很少量的延遲(以毫秒為單位)。對目標使用場景進行試驗並確定是否是一個問題,這應該是服務網格分析和評估工作的一部分。

服務網格不應該是應用程序部署到Kubernetes或“雲原生平台”的一部分嗎?

有這種可能。在雲原生平台組件中,在維持關注點分離方面還有爭論(例如,Kubernetes負責提供容器編排,服務網格負責服務與服務之間的通信)。但是,將類似服務網格這樣的功能引入到現代平台即服務(PaaS)的工作也在進行中。

我該如何實現、部署和採用服務網格?

最佳方式就是分析各種服務網格產品(參見上文),並遵循所選服務網格的實現指南。總體而言,最好與所有的利益相關者一起工作,並逐步將新技術部署到生產環境中。

我可以構建自己的服務網格嗎?

可以,但是更該問的問題是你應該這樣做嗎?構建服務網格是組織的核心競爭力嗎?你能以更有效的方式為客戶提供價值嗎?你是否承諾要維護自己的服務網格,修補它的安全問題,並不斷更新它,難道只有這樣才能利用新技術?隨著開源和商業服務網格產品的出現,使用現有的解決方案可能更有效。

在軟件交付組織中,哪個團隊要負責服務網格?

一般來講,平台或運維團隊負責服務網格,以及Kubernetes和持續交付管道基礎設施。但是,開發人員會配置服務網格的屬性,因此兩個團隊要緊密合作。很多組織在跟隨雲先驅(如Netflix、Spotify和谷歌)的腳步,創建內部的平台團隊,該團隊負責為 全週期以產品為核心的開發團隊提供工具和服務。

Envoy是服務網格嗎?

不是,Envoy是一個雲原生代理,它最初是由Lyft團隊設計和構建的。在服務網格中,Envoy通常被用作數據平面。但是,要成為服務網格,Envoy必須與控制平面聯合使用,這樣技術組合起來才能成為服務網格。控制平面可以是簡單的中心化配置文件倉庫和指標收集器,也可以是綜合、複雜的方案,如Istio。

“Istio”和“服務網格”這兩個詞是一回事兒嗎?

不是。 Istio是一種服務網格。鑑於服務網格剛出現時,Istio的流行程度,有些地方將Istio與服務網格混為一談。這種問題並不是服務網格特有的,相同的挑戰也出現在Docker和容器技術中。

我該使用哪個服務網格?

這個問題沒有唯一的答案。工程師必須了解他們當前的需求,以及實現團隊的技能、資源和時間。上文中關於服務網格對比的鏈接是一個很好的探索起點,但是我們強烈建議組織至少嘗試兩個服務網格,以便了解哪些產品、技術和工作流最適合它們。

我可以在Kubernetes之外使用服務網格嗎?

是的。很多服務網格允許在各種基礎設施上安裝和管理數據平面代理和相關的控制平面。HashiCorp的Consul是這方面最著名的例子,Istio也被實驗性地用在Cloud Foundry中

補充材料

術語表

API網關:管理集群中所有的進入(ingress)流量,即南-北流量,並提供額外的功能。它作為系統的唯一入口點,使多個API或服務具有內聚性,為用戶提供統一的體驗。

Consul:來自HashiCorp的基於Go的服務網格。

控制平面:獲取數據平面(代理)的所有實例並將它們轉換成運維人員可以進行可視化和控制的分佈式系統。

數據平面:一個代理,負責有條件地翻譯、轉發和觀察流入和流出服務網絡端點的每個網絡包。

東-西流量:數據中心、網絡或Kubernetes集群內部的網絡流量。傳統的網絡圖在繪製服務到服務(數據中心間)的流量時是從左到右(從東到西)繪製的。

Envoy代理:開源的邊緣和服務代理,為雲原生應用而設計。 Envoy通常用作服務網格實現中的數據平面。

進入(Ingress)流量:來自數據中心、網絡或Kubernetes集群外部的網絡流量。

Istio:基於C++(數據平面)和Go(控制平面)的服務網格,最初由谷歌和IBM與來自Lyft的Envoy團隊合作創建。

Kubernetes:CNCF託管的容器編排和調度框架,起源於谷歌。

Kuma:來自Kong的基於Go的服務網格。

Linkerd:一個基於Rust(數據平面)和Go(控制平面)的服務網格,源自Twitter早期基於JVM的通信框架。

Maesh:來自Containous的基於Go的服務網格,Containous是Traefik API網關的維護者。

MOSN:來自Ant Financial團隊的基於Go的代理,實現了(Envoy)xDS API。

南-北流量:進入(ingress)數據中心、網絡或Kubernetes集群的流量。在傳統的網絡圖中,進入數據中心的流量會繪製在頁面頂部並(從北向南)流經網絡。

代理:充當端點組件之間中介的軟件系統。

分區(Segmentation):將網絡或集群切分為多個子網絡。

服務網格:管理分佈式(可能是基於微服務的)軟件系統中所有的服務與服務(即“東-西”方向)之間的流量。它提供了功能性操作,比如路由,也提供了非功能性支持,比如實施安全策略、服務質量以及速度限制。

服務網格接口(Service Mesh Interface,SMI):一個正在製定中的標準接口,用於將服務網格部署到Kubernetes。

服務網格策略:服務/端點集合之間以及和其他網絡端點之間如何通信的規範。

Sidecar:一種部署模式,在這種模式中,附加的進程、服務或容器會與現有的服務(參考摩托車的挎鬥)一起部署。

單面板(Single pane of glass):在一個UI或管理控制台中統一展示多個源的數據。

流量重塑(Traffic shaping):修改網絡中的流量,例如,速率限製或負載削減。

流量轉移(Traffic shifting):將流量從一個位置遷移到另一個位置。

作者簡介:

Daniel Bryant一直在組織內和技術方面引領變化。 Daniel現在的技術專長是“DevOps”工具、雲/容器平台和微服務實現。他還是倫敦 Java 社區(LJC)的領導者,參與多個開源項目,為 InfoQ、DZone 和 Voxxed 技術網站撰寫文章,並且經常在 QCon、JavaOne 和 Devoxx 這樣的國際會議上發表演講。

原文鏈接:

Service Mesh Ultimate Guide: Managing Service-to-Service Communications in the Era of Microservices