腾讯云Service Mesh生产实践及架构演进
背景介紹
Service Mesh(服務網(wǎng)格)是一個基礎設施層,讓服務之間的通信更安全、快速和可靠,是云原生技術棧的關鍵組建之一。2018年是Service Mesh 高歌猛進的一年,Service Mesh數(shù)據(jù)面板百花齊放,遍地開花,業(yè)界幾乎所有大廠都在推出自己的Service Mesh 產品。2018年Service Mesh大事件如下:
- 2018年7月31日,Istio 1.0版本發(fā)布,標志著Istio可用于生產環(huán)境。
- 2018年9月19日,Conduit,這個史上唯一一個主打rust語言的Mesh,宣布合入到Linkerd,后續(xù)作為linkerd2.x版本繼續(xù)演進。
- 2018年11月28日,Istio的官配sidecar,高性能邊緣代理Envoy,成為了繼k8s以及prometheus之后,第三個從CNCF畢業(yè)的項目。
- 2018年12月5日,AWS推出服務網(wǎng)狀網(wǎng)絡App Mesh公開預覽版,供用戶輕松的監(jiān)視與控制AWS上,構成應用程序微服務之間的通信。
早在2017年騰訊云中間件團隊就選定Istio為技術路線,開始Service Mesh的相關研發(fā)工作,作為騰訊云TSF(微服務平臺)的無侵入式服務框架的核心實現(xiàn),并在18年初在騰訊廣告平臺投入,打磨穩(wěn)定后陸續(xù)開始對外輸出,目前在銀行、電商、零售、汽車等行業(yè)都有落地案例。
落地過程并非一帆風順,本文將對騰訊云Service Mesh 在生產實踐過程中遇到的典型問題以及解決方案進行總結分享,同時對騰訊云Service Mesh后續(xù)重點探索的技術方案進行簡要闡述。
騰訊云 Service Mesh 核心技術實現(xiàn)
騰訊云Service Mesh,遵循Service Mesh的理念進行設計,為應用提供服務自動注冊發(fā)現(xiàn)、灰度路由、限流、熔斷等服務治理能力,且應用無需對源碼進行侵入式變更即可與該服務框架進行集成。
在實現(xiàn)上,基于業(yè)界達到商用標準的開源軟件Istio、envoy進行構建。整體架構上,從功能邏輯上分為數(shù)據(jù)面和控制面:
控制面主要提供配置及控制指令支撐sidecar的正常運行,以及對服務運行過程中的相關數(shù)據(jù)進行采集。
數(shù)據(jù)面主要是提供通信代理(sidecar)來進行透明的服務調用,支撐正常的業(yè)務流程。
接下來,讓我們對騰訊云Service Mesh各關鍵優(yōu)化點做詳細的描述。
解耦k8s,擁抱其他計算平臺
眾所周知,Istio強依賴于Kubernetes ,大部分功能都依托于Kubernetes 平臺進行構建。下面列舉幾個核心的功能:
但實際落地過程中,TSF的用戶并非全部是Kubernetes用戶,例如公司內部的一個業(yè)務因歷史遺留問題,不能完全容器化部署,同時存在VM和容器環(huán)境,架構如下:
從業(yè)務架構圖可以看出,業(yè)務要求TSF可以支持其部署在自研PAAS以及Kubernetes 的容器、虛擬機以及裸金屬的服務都可以通過Service Mesh進行相互訪問。
因此,為了實現(xiàn)多平臺的部署,必須與Kubernetes 進行解耦。經(jīng)過分析發(fā)現(xiàn),脫離Kubernetes 后,Istio存在以下三個問題:
針對這3個問題,TSF團隊對Istio的能力進行了擴展和增強,增強后的架構如下:
下表更詳細的描述了存在的問題、解決方案以及所得到的目的,同時TSF 團隊實現(xiàn)了Istio 對Consul的完整適配。
經(jīng)過改造后,Service Mesh成功與Kubernetes 平臺解耦,組網(wǎng)變得更加簡潔,通過REST API可以對數(shù)據(jù)面進行全方位的控制,可從容適配任何的底層部署環(huán)境,對于私有云客戶可以提供更好的體驗。
服務尋址模式的演進
解決了跨平臺部署問題后,第二個面臨的問題就是服務的尋址互通問題。
Istio下的應用使用FQDN(fully qualified domain?name)進行相互調用,基于FQDN的尋址依賴DNS服務器,Istio官方對DNS服務器的說明如下:
Istio的官方demo中,Reviews與Ratings之間的完整的服務調用會經(jīng)過以下過程:
從圖上可以看出,Reviews和Ratings的互通,kube-dns主要實現(xiàn)2個功能:
在私有云的實際交付中,客戶的生產環(huán)境不一定包含Kubernetes 或者kube-dns,我們需要另外尋找一種機制來實現(xiàn)上面的兩個功能。
在DNS選型中,有集中式和分布式兩種方案,分別如下:
- 集中式DNS:代表有ConsulDNS, CoreDNS等,通過內置機制或者插件的方式,實現(xiàn)與服務注冊中心進行數(shù)據(jù)同步。其架構組網(wǎng)如下:
kube-dns也屬于集中式DNS的一種,集中式DNS存在以下問題:組網(wǎng)中額外增加一套DNS集群,并且一旦DNS Server集群不可服務,所有數(shù)據(jù)面節(jié)點在DNS緩存失效后都無法工作,因此需要為DNS Server考慮高可用甚至容災等一系列后續(xù)需求,會導致后期運維成本增加。
- 分布式DNS:就是將服務DNS的能力下沉到數(shù)據(jù)平面中,其架構組網(wǎng)如下:
分布式DNS運行在數(shù)據(jù)面節(jié)點上,DNS無單點故障,無需考慮集群容災等要素,只需要有機制可以在其down掉后重新拉起即可。但是,由于其與業(yè)務進程運行在同一節(jié)點,因此其資源占用率必須控制得足夠低,才不會對業(yè)務進程產生影響。
綜合考慮,最終選用了分布式DNS的方案,最開始團隊采用獨立進程作為DNS Server的方案,如下圖:
該方案新增監(jiān)聽在127.0.0.1:53 上的mesh-dns進程,該進程實時從Pilot同步服務列表。Mesh-dns在節(jié)點啟動時將127.0.0.1寫入到/etc/resolv.conf首行中,同時接管/etc/resolv.conf的其他nameserver。這樣,當app發(fā)起DNS查詢時,DNS請求首先會到達mesh-dns,遇到匹配服務名的查詢則直接返回,而當遇到不是針對服務名的DNS查詢時,就把DNS請求轉發(fā)給其他nameserver進行處理。
該方案看起來簡單可行,但是經(jīng)測試驗證后發(fā)現(xiàn)存在以下問題:
針對上述問題,對方案進行了進一步的優(yōu)化,優(yōu)化后的方案如下圖:
mesh-dns不再監(jiān)聽53端口,而是監(jiān)聽在5353端口(可配置),啟動時無需修改resolv.conf。通過增加iptables規(guī)則,將所有發(fā)往nameserver的流量導入到mesh-dns,從而解決了上文中的“端口監(jiān)聽沖突”以及“nameserver選擇策略”的問題。
mesh-dns通過inotify監(jiān)聽/etc/resolv.conf,可以隨時獲取環(huán)境中dns配置的更改,從而解決了上文中的“resolv.conf修改時間差”的問題。
與非Service Mesh服務的互通
現(xiàn)實總是復雜的,前面解決mesh服務之間相互訪問的問題,如何解決用戶Service Mesh應用和其他非Mesh 應用的相互訪問呢? 用戶內部有不同技術棧,一部分服務基于service mesh進行實現(xiàn)服務,另外一部分服務基于spring cloud框架進行實現(xiàn)。同時,客戶的微服務組網(wǎng)中,存在大量第三方服務如支付網(wǎng)關、分布式存儲、設備等,微服務需要與這些第三方服務也存在交互。用戶期望支持的架構如下圖所示:
這個架構中,最大的挑戰(zhàn)在于涉及了兩個不同的微服務框架之間的互通。但是,這兩個微服務框架從架構模式、概念模型、功能邏輯上,都存在較大的差異。唯一相通的點,就是他們都是微服務框架,可以將應用的能力通過服務的形式提供出來,給消費者調用,消費者實際上并不感知服務的具體實現(xiàn)。
基于這個共通點,為了使得不同框架開發(fā)的服務能夠正常工作,TSF團隊做了大量的開發(fā)工作,將兩個微服務框架,從部署模式、服務及功能模型上進行了拉通,主要包括如下幾點:
代理單節(jié)點多服務
用戶的需求是多種多樣的,在交付過程中存在如下多服務場景:
為了支持多服務場景,簡化用戶的使用流程,TSF提供了服務描述文件,可支持多服務場景,服務配置文件與Kubernetes 標準格式一致:
pilot-agent會根據(jù)服務配置,按照--的格式將配置中services注冊成多個獨立的服務實例。
在OutBound服務路由時,可以通過LDS-\u0026gt;RDS-\u0026gt;CDS-\u0026gt;EDS的方式進行路由,和獨立部署的服務沒有區(qū)別:
然而,在InBound服務路由過程中,通過開源Istio生成的listener會遇到一些坑。
對于多服務監(jiān)聽同一端口的場景,開源Istio在生成inbound的時候,會將同IP+Port的其中一個服務給reject掉。
因此,生成的LDS中,只有其中一個服務的相關路由信息:
這樣一來,普通消息投遞,不會有什么問題(目標端點信息是一致的),但是假如需要與mixer結合,做api鑒權或者限流等操作,則會出現(xiàn)兩個服務的mixer_attribute互相混淆的情況,導致功能不可用。
為了解決這個問題,團隊分析了envoy的filter_chain_match能力,對pilot進行改造,擴展了listener能力,通過server_name來分流數(shù)據(jù)包到不同的filter中。
最終生成的LDS如下:
經(jīng)過這樣的改造,同一端口上,不同的服務的filter配置不再沖突,兩個服務的mixer_attribute也能相互隔離,順利支持同端口多服務的場景。
二進制協(xié)議的支持
在當前業(yè)界的開源Service Mesh產品中,主打的協(xié)議都是標準協(xié)議(HTTP1/2, GRPC),標準協(xié)議都有一個特點,那就是協(xié)議頭中包含了目的端相關的所有信息,Service Mesh會根據(jù)這些信息進行路由。如下表所示:
對于其他二進制協(xié)議,則分為2大類:
第一種是協(xié)議中帶有目標端信息的二進制協(xié)議,如thrift,dubbo等;
第二種是協(xié)議中不帶有目標端信息的二進制協(xié)議,這種就比較多了,一般常見于私有云中的各種私有通信協(xié)議。
開源Istio中,對于二進制協(xié)議的支持,僅僅局限于四層的端口轉發(fā),一般用于集成外部服務(mysql, mongodb等),典型場景是對不同入口的流量做轉發(fā),如下圖所示:
單純的四層轉發(fā),無法滿足復雜的微服務路由的需求。當前TSF交付的客戶中,多個客戶都提出了需要支持私有協(xié)議路由的需求,因此,針對這個問題,TSF團隊提供了兩種解決方案。
由于GRPC的Data Frame本身傳輸?shù)木涂梢允荰CP協(xié)議,因此用戶可以直接把自己的二進制協(xié)議通過GRPC的bytes類型編碼,然后通過Data Frame傳輸過來.
該方案適用于本身有一定的技術積累,愿意去做GRPC改造的用戶。
該方案適用于自身帶有目標端信息的二進制協(xié)議,可以讓私有協(xié)議的用戶無需任何的改造,即可接入Service Mesh。
總結
騰訊云Service Mesh當前通過TSF平臺在持續(xù)交付中,上文主要針對落地過程中遇到的典型功能性需求及技術方案演進進行了總結介紹,除此之外,中間件團隊在Service Mesh性能方面也有很多優(yōu)化和探索,主要包括減少envoy和mixer之間的網(wǎng)絡交互、優(yōu)化數(shù)據(jù)包在envoy節(jié)點內部從內核態(tài)到用戶態(tài)的拷貝次數(shù)、envoy 到envoy之間數(shù)據(jù)的轉發(fā)性能等,后續(xù)將針對性能優(yōu)化進行專項分享。
作者簡介:
單家駿,來自騰訊公司。騰訊云高級工程師,負責騰訊云中間件paas以及servicemesh的研發(fā)與架構,關注云原生與中間件技術。熱愛開源、崇尚技術,希望能夠使用技術使軟件的應用變得簡單、高效和美好。
總結
以上是生活随笔為你收集整理的腾讯云Service Mesh生产实践及架构演进的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: A quick introduction
- 下一篇: L200