Service Mesh 初體驗

前言

計算機軟件技術發展到現在,軟件架構的演進無不朝著讓開發者能夠更加輕鬆快捷地構建大型複雜應用的方向發展。容器技術最初是為了解決運行環境的不一致問題而產生的,隨著不斷地發展,圍繞容器技術衍生出來越來越多的新方向。

最近幾年,雲計算領域不斷地出現很多新的軟件架構模式,其中有一些很熱門的概念名詞如:雲原生、函數計算、Serverless、ServiceMesh等等,而本文將初窺一下ServiceMesh的面紗。下面結合自己的理解儘量以通俗的話進行敘述。

背景和定義

微服務及服務治理

在微服務之前的軟件開發中,往往通過一個應用的方式將所有的模塊都包括進去,並一起編譯、打包、部署、運維。這種方式存在很多問題,由於單個應用包含的東西太多,其中某個模塊出現問題或者需要更新那麼整個應用就需要重新部署。這種方式給開發和運維帶來了很大的麻煩。隨著應用的逐漸複雜,單個應用涉及的東西就會越來越多,慢慢地大家發現了其中很多的缺點,開始對服務進行劃分,將一個大的應用按照不同的維度進行劃分從而產生很多個小的應用,各應用之間會形成一個調用關係,每個小的應用由不同的開發負責,大家各自部署和運維,這樣微服務就出現了。

由於微服務中各應用部署在不同的機器上,服務之間需要進行通信和協調,相比單個應用來說會麻煩很多。在同一個應用內不同方法之間的調用由於在相同的內存中,在代碼編譯打包時已經進行了鏈接,因此調用是可尋址且快速的。微服務下不同服務之間的調用涉及到不同進程或者機器之間的通信,一般需要通過第三方中間件的方式作為中介和協調,由於種種這些,面向微服務出現了很多中間件包括服務治理的框架。通過服務治理工具可以管理其接入的所有應用,使得服務之間的通信和協調更加簡單高效。

容器及容器編排

最初容器技術是為了解決應用運行環境不一致的問題而出現的,避免在本地環境或者測試環境能夠跑通,等發到生產環境卻出現問題。通過容器將程序及其依賴一起打包到鏡像中去,將程序的鏡像在任何安裝並運行了容器軟件的機器上啟動若干的容器,每個容器就是應用運行時的實例,這些實例一般擁有完全相同的運行環境和參數。使得不管在任何機器上應用都可以表現出一樣的效果。這給開發、測試、運維帶來了極大的便利,不再需要為不同機器上構建相同的運行環境而頭大。且鏡像可以Push到鏡像倉庫,這使得應用可以進行很方便的遷移和部署。Docker就是一個應用廣泛的容器技術。目前越來越多的應用以微服務的方式並通過容器進行部署,給了軟件開發極大的活力。

與微服務和服務治理的關係類似,越來越多的應用通過容器進行部署,使得集群上的容器數量急劇增加,通過人工的管理和運維這些容器已經變得很艱難且低效,為了解決諸多容器及容器之間的關係出現了很多編排工具,容器編排工具能夠管理容器的整個生命週期。如Docker官方出的docker-compose和docker swarm,這兩個工具能實現批量容器的啟動和編排,但功能較為簡單,不足以支撐大型的容器集群。Google基於內部大量的容器管理經驗,開源出了Kubernetes項目,Kubernetes(K8S)是針對Google集群上每週億級別的容器而設計的,具有很強大的容器編排能力和豐富的功能。K8S通過定義了很多資源,這些資源以聲明式的方式進行創建,可以通過JSON或者YAML文件表示一個資源,K8S支持多種容器,但主流的是Docker容器,K8S提供了容器接入的相關標準,只要容器實現了該標準就可以被K8S所編排。由於K8S的功能較多,不在此一一敘述,有興趣可以參考官方文檔或者ATA上搜索相關文章。

當某個公司的應用已經完全微服務化後,選擇以容器的方式部署應用,此時可以在集群上部署K8S,通過K8S提供的能力進行應用容器的管理,運維可以也可以面向K8S進行工作。由於K8S是目前使用最廣泛的容器編排工具,因此成為了容器編排的一個標準了,目前集團內部也有自己的容器和容器編排工具。

面向以K8S為代表的容器管理方式衍生出了一些新的技術。

雲原生

最近兩年雲原生被炒的很火,可以在各處看到很多大佬對雲原生的高談闊論,下面直接拋出CNCF對雲原生的定義:

雲原生技術有利於各組織在公有云、私有云和混合雲等新型動態環境中,構建和運行可彈性擴展的應用。雲原生的代表技術包括容器、服務網格、微服務、不可變基礎設施和聲明式API。

這些技術能夠構建容錯性好、易於管理和便於觀察的松耦合系統。結合可靠的自動化手段,雲原生技術使工程師能夠輕鬆地對系統作出頻繁和可預測的重大變更。

在我看來,通過微服務的方式開發應用,以容器進行部署,使用K8S等容器編排工具進行容器集群的管理,使得開發運維都面向K8S,這就是雲原生。雲原生可以方便的構建應用,並對應用進行完整的監控,以及在應用針對不同流量時能進行快速的擴容和縮容。如下圖:

Service Mesh 初體驗

雲原生主要包括四個部分:

  • 微服務
  • 容器
  • 持續集成和交付
  • DevOps

PS:總是覺得雲原生這個叫法太抽象了,很難讓人通過名字想到這是個啥東西。

ServiceMesh的定義

前面講了微服務、容器、容器編排、雲原生等,其實就是為了得出什麼是ServiceMesh,自己總結了一下:SeviceMesh是雲原生下的微服務治理方案。

當我們通過微服務的方式將應用以容器的形式部署在K8S上後,服務之間調用和治理其實有新的方案,可以不需要依賴傳統的微服務治理框架。ServiceMesh通過對每個應用在其Pod中啟動一個Sidecar(邊車)實現對應用的透明代理,所有出入應用的流量都先經過該應用的Sidecar,服務之間的調用轉變成了Sidecar之間的調用,服務的治理轉變成了對Sidecar的治理。在ServiceMesh中Sidecar是透明的,開發無感知的,之前一直覺得奇怪,總覺得一個應用要讓別人發現它從而調用它,總得引入一些庫然後進行主動的服務註冊,不然啥都不做,別人咋知道這個應用的存在,為什麼在ServiceMesh中就可以省去這些,做到對開發者完全地透明呢?這個的實現依賴於容器編排工具,通過K8S進行應用的持續集成和交付時,在啟動應用Pod後,其實已經通過Yaml文件的形式向K8S註冊了自己的服務以及聲明瞭服務之間的關係,ServiceMesh通過和K8S進行通信獲取集群上所有的服務信息,通過K8S這個中間者實現了對開發者的透明。如下圖所示,是ServiceMesh的一個基本結構,包括數據平面和控制平面。

Service Mesh 初體驗

這種方式存在很多好處,我們可以發現在這種模式下應用的語言其實不會對整個服務治理過程有什麼影響,對於ServiceMesh來說,它只關心Pod或者說是Pod中的容器實例,並不需要在乎容器中應用的實現語言是啥,Sidecar和其負責的容器在同一個Pod中。這樣ServiceMesh就可以實現跨語言,這也是目前很多傳統的服務治理框架的一大缺點,而且採用傳統的服務治理,需要對應用引入大量的依賴,這樣就會造成依賴之間的各種衝突,集團通過Pandora對應用的各種依賴進行隔離。再者傳統的服務治理門檻較高,需要開發者對整個架構有一定的瞭解,且發現問題排查較為麻煩。這也造成了開發和運維之間的界限不清,在ServiceMesh中開發只需要交付代碼,運維可以基於K8S去維護整個容器集群。

發展現狀

通過目前查閱的資料來看,ServiceMesh一詞最早出現在2016年,最近兩年被炒的很火,螞蟻金服已經有了自己的一套完整的ServiceMesh服務框架--SofaMesh,集團很多團隊也在進行相應的跟進。

從歷史發展的路線來看,程序的開發方式經歷了很多的變化,但總的方向是變得越來越簡單了,現在我們在集團內進行開發,可以很簡單的構建一個支撐較大QPS的服務,這得益於集團的整個技術體系的完整和豐富以及強大的技術積澱。

我們下面來看看應用開發到底經歷了啥?

發展歷史

主機直接階段

Service Mesh 初體驗

如上圖,這一階段應該是最古老的階段,兩臺機器通過網線直接連接,一個應用包含了你能想到的所有的功能,包括兩臺機器的連接管理,這時還沒有網絡的概念,畢竟只能和通過網線直接連接在一起的機器進行通信。

網絡層的出現

Service Mesh 初體驗

如上圖,隨著技術的發展,網絡層出現了,機器可以和通過網絡連接的其他所有機器進行通信,不再限制於必須要網線直連兩臺機器。

集成到應用程序內部的流量控制

Service Mesh 初體驗

如上圖,由於每個應用所在環境和機器配置不一樣,接受流量的能力也不相同,當A應用發送的流量大於了B應用的接受能力時,那麼無法接收的數據包必定會被丟棄,這時就需要對流量進行控制,最開始流量的控制需要應用自己去實現,網絡層只負責接收應用下發的數據包並進行傳輸。

流量控制轉移到網絡層

Service Mesh 初體驗

如上圖,慢慢地大家發應用中的網絡流量控制是可以轉移到網絡層的,所以網絡層中的流量控制出現了,我想大概就是指TCP的流量控制吧,這樣還能保證可靠的網絡通信。

應用程序的中集成服務發現和斷路器

Service Mesh 初體驗

如上圖,開發者通過在自己的代碼模塊中實現服務發現和斷路器。

專門用於服務發現和斷路器的軟件包/庫

Service Mesh 初體驗

如上圖,開發者通過引用第三方依賴去實現服務發現和斷路器。

出現了專門用於服務發現和斷路器的開源軟件

Service Mesh 初體驗

如上圖,基於各種中間件去實現服務發現和斷路器。

ServiceMesh出現

Service Mesh 初體驗

最終到了現在,ServiceMesh大法誕生,進一步解放了生產力,提高了軟件整個生命週期的效率。

ServiceMesh市場競爭

雖然直到2017年底,ServiceMesh才開始較大規模被世人瞭解,這場微服務市場之爭也才顯現,但是其實ServiceMesh這股微服務的新勢力,早在 2016年初就開始萌芽:

2016年1月,離開Twitter的基礎設施工程師William Morgan和Oliver Gould,在github上發佈了Linkerd 0.0.7版本,業界第一個ServiceMesh項目就此誕生。Linkerd基於Twitter的Finagle開源項目,大量重用了Finagle的類庫,但是實現了通用性,成為了業界第一個ServiceMesh項目。而Envoy是第二個ServiceMesh項目,兩者的開發時間差不多,在2017年都相繼成為CNCF項目。2017年5月24日,Istio 0.1 release版本發佈,Google和IBM高調宣講,社區反響熱烈,很多公司在這時就紛紛站隊表示支持Istio。Linkerd的風光瞬間被蓋過,從意氣風發的少年一夜之間變成過氣網紅。當然,從產品成熟度上來說,linkerd作為業界僅有的兩個生產級ServiceMesh實現之一,暫時還可以在Istio成熟前繼續保持市場。但是,隨著Istio的穩步推進和日益成熟,外加第二代ServiceMesh的天然優勢,Istio取代第一代的Linkerd只是個時間問題。自從在2016年決定委身於Istio之後,Envoy就開始了一條波瀾不驚的平穩發展之路,和Linkerd的跌宕起伏完全不同。在功能方面,由於定位在數據平面,因此Envoy無需考慮太多,很多工作在Istio的控制平面完成就好,Envoy從此專心於將數據平面做好,完善各種細節。在市場方面,Envoy和Linkerd性質不同,不存在生存和發展的戰略選擇,也沒有正面對抗生死大敵的巨大壓力。

從Google和IBM聯手決定推出Istio開始,Istio就註定永遠處於風頭浪尖,無論成敗,Istio面世之後,讚譽不斷,尤其是ServiceMesh技術的愛好者,可以說是為之一振:以新一代ServiceMesh之名橫空出世的Istio,對比Linkerd,優勢明顯。同時產品路線圖上有一大堆令人眼花繚亂的功能。假以時日,如果Istio能順利地完成開發,穩定可靠,那麼這會是一個非常美好、值得憧憬的大事件,

Service Mesh 初體驗

Istio介紹

Istio是目前最熱的ServiceMesh開源項目,Istio主要分為兩個部分:數據平面和控制平面。Istio實現了雲原生下的微服務治理,能實現服務發現,流量控制,監控安全等。Istio通過在一個Pod裡啟動一個應用和Sidecar方式實現透明代理。Istio是一個拓展性較高的框架,其不僅可以支持K8S,還可以支持其他如Mesos等資源調度器。如下圖所示,為Istio的整體架構:

Service Mesh 初體驗

  • 邏輯上分為數據平面(上圖中的上半部分)和控制平面(上圖中的下半部分)。
  • 數據平面由一組以 Sidecar 方式部署的智能代理(Envoy)組成。這些代理可以調節和控制微服務及 Mixer 之間所有的網絡通信。
  • 控制平面負責管理和配置代理來路由流量。此外控制平面配置 Mixer 以實施策略和收集遙測數據。
  • Pilot是整個架構中的抽象層,將對接K8S等資源調度器的步驟進行抽象並以適配器的形式展現,並和用戶以及Sidecar交互。
  • Galley負責資源配置為驗證。
  • Citadel用於生成身份,及密鑰和證書管理
  • 核心功能包括流量控制、安全控制、可觀測性、多平臺支持、可定製化。

Mixer

Mixer同樣是一個可拓展的模塊,其負責遙感數據的採集以及集成了一些後端服務(BAAS),Sidecar會不斷向Mixer報告自己的流量情況,Mixer對流量情況進行彙總,以可視化的形式展現,此外Sidecar可以調用Mixer提供的一些後端服務能力,例如鑑權、登錄、日誌等等,Mixer通過適配器的方式對接各種後端服務。

Service Mesh 初體驗

In-process Adapter形式

之前版本的Isito採用這種將後端服務適配器集成在Mixer內部的形式,這種方式會有一個問題,就是某個後端服務適配器出現問題即會影響整個Mixer模塊,但由於適配器和Mixer集成在一起,在同一個進程內,方法的調用會很快。

Service Mesh 初體驗

Out-of-process Adapter形式

目前版本的Istio將Adapter移到Mixer外部,這樣可以實現Mixer與Adapter的解耦,當Adapter出現問題並不會影響Mixer,但這種方式同樣也存在問題,即Adapter在Mixer外,是兩個不同的進程,二者之間的調用是通過RPC的方式,這種方式比同進程內部的方法調用會慢很多,因此性能會受到影響。

Pilot

Service Mesh 初體驗

  • Envoy API負責和Envoy的通訊, 主要是發送服務發現信息和流量控制規則給Envoy。
  • Abstract Model 是 Pilot 定義的服務的抽象模型, 以從特定平臺細節中解耦, 為跨平臺提供基礎。
  • Platform Adapter則是這個抽象模型的實現版本, 用於對接外部的不同平臺如k8s/mesos等。
  • Rules API提供接口給外部調用以管理 Pilot, 包括命令行工具Istioctl以及未來可能出現的第三方管理界面。

Galley

Galley 原來僅負責進行配置驗證, 1.1 後升級為整個控制面的配置管理中心, 除了繼續提供配置驗證功能外, Galley還負責配置的管理和分發, Galley 使用 網格配置協議(Mesh Configuration Protocol) 和其他組件進行配置的交互.

Istio 創造了50多個CRD, 其複雜度可見一斑, 所以有人說面向k8s編程近似於面向yaml編程.早期的Galley 僅僅負責對配置進行運行時驗證, Istio 控制面各個組件各自去list/watch 各自關注的配置。越來越多且複雜的配置給Istio用戶帶來了諸多不便, 主要體現在:

  • 配置的缺乏統一管理, 組件各自訂閱, 缺乏統一回滾機制, 配置問題難以定位。
  • 配置可複用度低, 比如在1.1之前, 每個Mixer adpater 就需要定義個新的CRD。
  • 配置的隔離, ACL 控制, 一致性, 抽象程度, 序列化等等問題都還不太令人滿意

隨著Istio功能的演進, 可預見的Istio CRD數量還會繼續增加, 社區計劃將Galley 強化為Istio配置控制層, Galley 除了繼續提供配置驗證功能外, 還將提供配置管理流水線, 包括輸入, 轉換, 分發, 以及適合Istio控制面的配置分發協議(MCP)。

Citadel

將服務拆分為微服務之後,在帶來各種好處的同時,在安全方面也帶來了比單體時代更多的需求,畢竟不同功能模塊之間的調用方式從原來單體架構中的方法調用變成了微服務之間的遠程調用:

  • 加密:為了不洩露信息,為了抵禦中間人攻擊,需要對服務間通訊進行加密。
  • 訪問控制:不是每個服務都容許被任意訪問,因此需要提供靈活的訪問控制,如雙向 TLS 和細粒度的訪問策略。
  • 審計:如果需要審核系統中哪些用戶做了什麼,則需要提供審計功能。

Citadel 是 Istio 中負責安全性的組件,但是 Citadel 需要和其他多個組件配合才能完成工作:

  • Citadel:用於密鑰管理和證書管理,下發到Envoy等負責通訊轉發的組件。
  • Envoy:使用從Citadel下發而來的密鑰和證書,實現服務間通訊的安全,注意在應用和Envoy之間是走Localhost,通常不用加密。
  • Pilot:將授權策略和安全命名信息分發給Envoy。
  • Mixer:負責管理授權,完成審計等。

Istio支持的安全類功能有:

  • 流量加密:加密服務間的通訊流量。
  • 身份認證:通過內置身份和憑證管理可以提供強大的服務間和最終用戶身份驗證,包括傳輸身份認證和來源身份認證,支持雙向TLS。
  • 授權和鑑權:提供基於角色的訪問控制(RBAC),提供命名空間級別,服務級別和方法級別的訪問控制。

阿里雲雙11億元補貼提前領,進入抽取iPhone 11 Pro:https://www.aliyun.com/1111/2019/home?utm_content=g_1000083110

作者:彭家浩,花名毅忻,阿里巴巴淘系技術部開發工程師,熱愛雲計算。


分享到:


相關文章: