Istio服務網格與微服務平臺整合實踐
前言
Istio釋出1.0版本後,其服務發現和路由規則功能已基本具備production能力,我們也開始了Istio和公司內部微服務平臺的整合工作,打算以Istio為基礎打造一個微服務管控中心,在這裡把目前的進展和遇到的坑和大家分享一下。
現有系統架構
目前公司的微服務架構如圖所示,系統中主要包含三類服務:
-
業務服務,大部分的業務服務都已經實現了微服務化和無狀態,採用docker容器部署在K8s叢集中,利用K8s的容器管理能力進行服務部署,彈縮。但也有部分服務只做了容器化,但並未進行微服務改造,此類服務屬於SOA架構,一個服務可能對外暴露多個業務API,這和敖小劍老師在ofollow,noindex" target="_blank">《SOFAMesh中的多協議通用解決方案》 系列文章中提到的情況是類似的。
-
一些有狀態的公共服務,例如資料庫,FTP伺服器,共享快取等,目前未放入到K8s叢集中,但業務服務對這些公共服務存在大量的依賴。
-
其他未納入K8S叢集的服務,如遺留系統和第三方系統提供的服務。某些業務服務和這些服務之間存在互相訪問的需求。
服務註冊
電信領域與IT領域相比有一些特殊性,其中一點就是多網路平面的需求。多網路平面是電信領域的一個術語,通俗來講就是系統中存在多個網路。採用多個網路的目的一般是為了管理原因,例如管理系統採用一個網路進行通訊,而應用之間的通訊在另一個網路上,這多個網路之間是相互隔離的。
採用多網路平面後,和標準的K8S網路模型有所不同,標準的K8S叢集中的一個Pod上只會有一個網路介面。我們的PaaS對K8S的網路進行了擴充套件,使其支援多個網路,即一個Pod上可以有多個網路介面(該解決方案已開源,參見https://github.com/ZTE/Knitter)。
由於需要支援多網路平面,我們開發了自己的服務註冊系統,該服務註冊系統中同時包含了K8s租戶中的微服務,公共服務和外部服務的所有服務相關資訊。服務註冊系統通過REST介面對外提供服務註冊介面,也提供管理介面。K8S叢集中的服務啟動後通過代理檢測並自動註冊,外部服務可以通過管理介面註冊,也可以開發第三方代理進行註冊。
採用了定製的服務註冊系統後的另一個優勢是K8S中部署的執行例項和註冊的服務關係是很靈活的,一個執行例項可以註冊多個服務,以支援尚未進行微服務改造的SOA型別的應用。
服務發現
系統內部服務之間採用客戶端發現機制,先通過服務發現介面從Service Registry中查詢到對端服務地址再發起請求。平臺提供了封裝好的SDK提供給應用微服務使用,SDK中封裝了服務發現以及LB,重試,斷路等服務底層通訊機制。
API Gateway
系統外部對內的呼叫通過API Gateway進入,採用服務端服務發現機制。服務名編碼在請求URL中,API Gateway解析URL得到服務名後,再根據Service Registry的服務註冊資訊進行分發。
根據PaaS的部署場景,系統可以採用1級或者2級API Gateway進行請求分發。單租戶場景下采用1級API Gateway;多租戶場景下可採用2級API Gateway。第一級的Gateway在K8S叢集外,是整個系統的總入口,負責分流K8s不同租戶以及外部服務的流量。第二級Gateway在K8S租戶中,是租戶內服務的請求入口。兩級API Gateway都從Service Registry獲取服務資訊,考慮到安全和效率因素,每個Gateway只能拉取和自己負責部分的服務資訊。
API Gateway支援虛擬主機,提供4層和7層的LB。除此以外,API Gateway被設計為一個可插拔的平臺,可以採用外掛方式進行擴充套件,目前實現了下述外掛功能:
- 對外部請求進行效能資料收集和統計分析。
- 呼叫認證服務對外部請求進行登入驗證。
- 實現了限流、熔斷、黑白名單等功能。
- 可以通過分流規則實現應用的灰度釋出。
痛點
-
在系統的初始階段,大部分的微服務都是基於JAVA編寫的,我們通過SDK封裝了服務發現,重試,限流,熔斷等用於服務間點對點通訊的邏輯提供給各個業務微服務使用。但隨著系統的發展,越來越多微服務開始採用Golang編寫,還有相當一部分基於Python的微服務,而且作為一個平臺,可以預見到將來還可能會有更多其他語言。為每一種語言編寫一套SDK的方案漸漸變得難以維護。將微服務的通訊層下沉到Mesh層是一個趨勢。
-
在API Gateway處可以對外部請求的效能資料進行統計分析,但無法對系統內部各個微服務之間呼叫的效能資料進行收集處理。如果採用侵入式的方案,則需要在各個語言和框架中採用一套標準的介面,並且要針對不同語言編寫對應的SDK,維護工作量很大,而且對於業務微服務的編碼有較大的限制,因此採用sidecar方式對微服務之間呼叫效能資料進行收集是一個更為合理的方式。
-
通過在API Gateway處使用分流規則來實現灰度釋出的方案有較大限制,只能對應用整體進行分流,而無法對應用中的單個微服務的不同版本進行分流配置。因此基本上無法通過灰度釋出來實現微服務粒度的快速升級迭代。
Istio整合方案
引入Istio後,系統架構如下圖所示:
控制面
引入Istio Pilot提供服務發現和流量規則。Service Registry是基於Consul自研的,由於Pilot已經支援Consul的介面卡,因此可以很容易地將我們的Service Registry作為服務資訊提供者整合到Pilot中。
提供使用者介面對Mesh中的traffic rule進行配置,規則可以在設計應用藍圖時進行配置,也可以在執行期進行動態修改、新增和刪除。
資料面
在各個業務微服務的Pod中加入Envoy proxy,提供服務發現,可靠通訊,並根據Pilot下發的路由規則對服務通訊進行路由。
雖然Istio提供了Ingress Gateway,但Ingress Gateway只是提供了一個虛擬主機和Https終結的功能,並不能滿足我們的業務需求。因此我們決定繼續採用自研的API Gateway。但API Gateway的服務發現,LB功能交給Envoy接管,並將API Gateway上已實現的限流、熔斷、重試等規則切換為Pilot的Traffic rule,改為由Envoy處理。處理方式是在Internal API Gateway處也部署一個Envoy代理。
目前的進展
- 目前我們已經完成了Pilot和Mixer的整合,由於系統內部採用了是自己的安全方案,暫未考慮Citadel的整合。
- 驗證了服務發現,路由規則,Metrics收集和Distributed Tracing
- 開發使用者友好的介面對Istio的路由規則進行配置和管理。
- 基於Istio的路由規則,結合K8S開發了微服務的線上灰度升級。
遇到的坑和待解決問題
- Istio不支援多網路平面,導致Envoy在進行服務轉發時出現了死迴圈,環境中Envoy由於File Descriptor被耗光不停重啟。這個問題隱藏較深,花了差不多兩週時間定位和排除。我們正在基於Istio進行擴充套件以支援多網路平面,並準備向社群貢獻這部分程式碼。
- 社群沒有給出Mixer如何在K8S外進行部署的詳細文件,在部署Mixer時遇到了較多的坑。
- Mixer沒有Consul environment的 Adapter,因此上報的Metrics中缺失部分attribute,我們正在評估編寫該介面卡,並準備向社群貢獻這部分程式碼。
- Istio目前主要支援的是HTTP和GRPC,對於非同步訊息如Kafaka並未支援。而要完成一個業務級的端到端路由控制,非同步訊息是必不可少的一環,可喜的是Envoy社群已經有計劃要對Kafaka進行支援。 (https://github.com/envoyproxy/envoy/issues/2852 )
- 對於IT應用來說,Service Mesh面對的主要是使用者(北向)流量和服務間(東西向)流量,但對於CT應用來說,還有很大一部分屬於網元到管理系統(南向)的流量,這部分流量基本上都是採用的自定義協議,目前尚不能被Istio理解。敖小劍老師在《SOFAMesh中的多協議通用解決方案x-protocol介紹系列(3)——TCP協議擴充套件》 介紹的阿里SOFAMesh的擴充套件方案已經提出了一個很好的思路。