近幾年,微服務架構逐漸發展成熟,從最初的星星之火到現在大規模的落地和實踐,幾乎已經成爲分布式環境下的首選架構。然而軟件開發沒有銀彈,基于微服務構建的應用系統在享受其優勢的同時,痛點也越加明顯。Service Mesh 技術也因此而生,受到越來越多的開發者關注,並擁有了大批擁趸。本文會從概念介紹開始,讓大家理解 Service Mesh 技術出現的原因以及願景;接著會對目前最主流的兩個産品 Istio 和 AWS App Mesh 進行詳細的比較;最後簡要介紹一下我們目前在該領域的一些探索與實踐。
Service Mesh – 服務通信的濟世良方
Service Mesh 是什麽?
Service Mesh(中文譯做服務網格)這一概念由 Buoyant 公司的 CEO,William Morg」n 首先提出。2017 年 4 月該公司發布了第一個 Service Mesh 産品 Linkerd,這篇同一時間發表的文章 What’s a service mesh? And why do I need one? 也被業界公認是 Service Mesh 的權威定義。
“A service mesh is a dedicated infrastructure layer for handling service-to-service communication. It’s responsible for the reliable delivery of requests through the complex topology of services that comprise a modern, cloud native application. In practice, the service mesh is typically implemented as an array of lightweight network proxies that are deployed alongside application code, without the application needing to be aware.”
其定義翻譯爲:Service Mesh 是一個處理服務通訊的專門的基礎設施層。它的職責是在由雲原生應用組成服務的複雜拓撲結構下進行可靠的請求傳送。在實踐中,它是一組和應用服務部署在一起的輕量級的網絡代理,對應用服務透明。這段話有點晦澀難懂,但只要抓住下面 4 個關鍵點就能輕松理解:
- 本質:基礎設施層
- 功能:請求分發
- 部署形式:網絡代理
- 特點:透明
如果用一句話來總結,我個人對它的定義是:Service Mesh 是一組用來處理服務間通訊的網絡代理。
爲什麽需要 Service Mesh?
上面晦澀抽象的定義很難讓你真正理解 Service Mesh 存在的意義。你可能會想,服務間通信(service-to-service communication)無非就是通過 RPC、HTTP 這些方式進行,有什麽可處理的?沒錯,服務間只需要遵循這些標准協議進行交互就可以了,但是在微服務這樣的分布式環境下,分散的服務勢必帶來交互的複雜性,而規模越大的系統其通信越加錯綜複雜。分布式計算下的 8 個謬論很好的歸納了分布式環境下存在的網絡問題。而爲了解決這些問題,提高系統的容錯能力和可用性,出現了服務注冊與發現、負載均衡、熔斷、降級、限流等等和通信相關的功能,而這些才是 Service Mesh 要真正處理的問題。
Pattern:Service Mesh 這篇文章詳細的講述了微服務架構下通訊處理的演進,由此引出 Service Mesh 出現的意義和核心價值。下圖爲服務通信演變的過程:
上面的圖展示了這幾個概念的關系:當用戶請求一個虛擬服務時,服務配置的路由器根據路由策略將請求指向對應的虛擬節點,這些節點最終會與集群中某個對外提供服務的 DNS 或者服務名一一對應。
那麽這些 App Mesh 自創的術語是否能在 Istio 中找到相似甚至相同的對象呢?我歸納了下面的表格來做一個對比:
App MeshIstio服務網格(Service mesh)Istio 並未顯示的定義這一概念,我們可以認爲在一個集群中,由 Istio 管理的服務集合,它們組成的網絡拓撲即是服務網格。虛擬服務(Virtual services)Istio 中也存在虛擬服務的概念。它的主要功能是定義路由規則,使請求可以根據這些規則被分發到對應的服務。從這一點來說,它和 App Mesh 的虛擬服務的概念基本上是一致的。虛擬節點(Virtual nodes)Istio 沒有虛擬節點的概念,可以認爲類似 Kubernetes 裏的 Deployment。虛擬路由器(Virtual routers)Istio 也沒有虛擬路由器的概念。路由(Routes)Istio 中的目標規則(DestinationRule)和路由的概念類似,爲路由設置一些策略。從配置層面講,其中的子集(subset)和 App Mesh 路由裏選擇的目標即虛擬節點對應。但 Istio 的目標規則更加靈活,也支持更多的路由策略。
從上面的對比看出,App Mesh 目前基本上實現了最主要的流量控制(路由)的功能,但像超時重試、熔斷、流量複制等高級一些的功能還沒有提供,有待進一步完善。
架構
AWS App Mesh 是一個商業産品,目前還沒有找到架構上的技術細節,不過我們依然可以從現有的、公開的文檔或介紹中發現一些有用的信息。
熟悉 Istio 架構的朋友有沒有覺得似曾相識?沒錯,這個控制平面的職責和 Pilot 基本一致。由此可見,不管什麽産品的控制平面,也必須具備這些核心的功能。
那麽在平台的支持方面呢?下面這張圖展示了 App Mesh 可以被運行在如下的基礎設施中,包括 EKS、ECS、EC2 等等。當然,這些都必須存在于 AWS 這個閉環生態中。
Istio 的架構大家都比較熟悉,數據平面由 Envoy sidecar 代理組成,控制平面包括了 Pilot、Mixer、Citadel、Galley 等控件。它們的具體功能這裏就不再贅述了,感興趣的同學可以直接去官網查看詳細信息。
功能與實現方式
部署
無論是 Istio 還是 App Mesh 都使用了控制平面 + 數據平面的模式,且 Sidecar 都使用了 Envoy 代理。Istio 的控制平面組件較多,功能也更複雜,1.0.x 版本完整安裝後的 CRD 有 50 個左右。架構修改後 Mixer 的一些 adapter 被獨立出去,crd 有所降低。下面是最新的 1.4 版本,安裝後仍然有 24 個 crd。
複制代碼
$ kubectl get crd -nistio-systemNAME CREATED ATadapters.config.istio.io 2019-12-24T03:46:41Zattributemanifests.config.istio.io 2019-12-24T03:46:41Zauthorizationpolicies.security.istio.io 2019-12-24T03:46:41Zclusterrbacconfigs.rbac.istio.io 2019-12-24T03:46:41Zdestinationrules.networking.istio.io 2019-12-24T03:46:41Zenvoyfilters.networking.istio.io 2019-12-24T03:46:42Zgateways.networking.istio.io 2019-12-24T03:46:42Zhandlers.config.istio.io 2019-12-24T03:46:42Zhttpapispecbindings.config.istio.io 2019-12-24T03:46:42Zhttpapispecs.config.istio.io 2019-12-24T03:46:42Zinstances.config.istio.io 2019-12-24T03:46:42Zmeshpolicies.authentication.istio.io 2019-12-24T03:46:42Zpolicies.authentication.istio.io 2019-12-24T03:46:42Zquotaspecbindings.config.istio.io 2019-12-24T03:46:42Zquotaspecs.config.istio.io 2019-12-24T03:46:42Zrbacconfigs.rbac.istio.io 2019-12-24T03:46:42Zrules.config.istio.io 2019-12-24T03:46:42Zserviceentries.networking.istio.io 2019-12-24T03:46:42Zservicerolebindings.rbac.istio.io 2019-12-24T03:46:42Zserviceroles.rbac.istio.io 2019-12-24T03:46:42Zsidecars.networking.istio.io 2019-12-24T03:46:42Ztemplates.config.istio.io 2019-12-24T03:46:42Zvirtualservices.networking.istio.io 2019-12-24T03:46:42Z
而 App Mesh 就簡單得多,只針對核心概念添加了如下 3 個 crd,用一個 controller 進行管理。
複制代碼
$ kubectl get crd -nappmesh-systemNAME CREATED ATmeshes.appmesh.k8s.aws 2019-12-13T05:35:00Zvirtualnodes.appmesh.k8s.aws 2019-12-13T05:35:00Zvirtualservices.appmesh.k8s.aws 2019-12-13T05:35:00Z
盡管 Istio 更多的 crd 在一定程度上代表了更加豐富的功能,但同時也爲維護和 troubleshooting 增加了困難。
流量控制
盡管兩者的數據平面都基于 Envoy,但它們提供的流量控制能力目前還是有比較大的差距的。在路由的設置方面,App Mesh 提供了相對比較豐富的匹配策略,基本能滿足大部分使用場景。下面是 App Mesh 控制台裏的路由配置截圖,可以看出,除了基本的 URI 前綴、HTTP Method 和 Scheme 外,也支持請求頭的匹配。
下圖是網格內部的邏輯視圖,展示了如何利用 App Mesh 進行智能路由。Forecast service 作爲調用者被定義爲虛擬節點,Data service 作爲虛擬服務,挂載著虛擬路由,內部根據需要可以設定若幹路由規則。用 App Mesh 實現一個金絲雀發布的過程非常簡單:假設在 Data service 的新版本(V2)發布前,流量都被指向 V1 版本;此時我們在 App Mesh 裏配置好一個新的路由規則,將 10% 的流量指向新的 V2 版本;只需要將新的規則通過 kubectl apply -f new-rule.yaml 應用到集群中,金絲雀發布就可以完成,且無縫切換,對用戶透明。