微服務(wù):深入解讀Service Mesh背后的技術(shù)細節(jié)

作者:劉超,網(wǎng)易云首席解決方案架構(gòu)師

在Kubernetes稱為容器編排的標(biāo)準之后,Service Mesh開始火了起來,但是很多文章講概念的多,講技術(shù)細節(jié)的少,所以專門寫一篇文章,來解析Service Mesh背后的技術(shù)細節(jié)。

一、Service Mesh是Kubernetes支撐微服務(wù)能力拼圖的最后一塊

在上一篇文章為什么 kubernetes 天然適合微服務(wù)中我們提到,Kubernetes是一個奇葩所在,他的組件復(fù)雜,概念復(fù)雜,在沒有實施微服務(wù)之前,你可能會覺得為什么Kubernetes要設(shè)計的這么復(fù)雜,但是一旦你要實施微服務(wù),你會發(fā)現(xiàn)Kubernetes中的所有概念,都是有用的。

在我們微服務(wù)設(shè)計的是個要點中,我們會發(fā)現(xiàn)Kubernetes都能夠有相應(yīng)的組件和概念,提供相應(yīng)的支持。

其中最后的一塊拼圖就是服務(wù)發(fā)現(xiàn),與熔斷限流降級。

眾所周知,Kubernetes的服務(wù)發(fā)現(xiàn)是通過Service來實現(xiàn)的,服務(wù)之間的轉(zhuǎn)發(fā)是通過kube-proxy下發(fā)iptables規(guī)則來實現(xiàn)的,這個只能實現(xiàn)最基本的服務(wù)發(fā)現(xiàn)和轉(zhuǎn)發(fā)能力,不能滿足高并發(fā)應(yīng)用下的高級的服務(wù)特性,比較SpringCloud和Dubbo有一定的差距,于是Service Mesh誕生了,他期望講熔斷,限流,降級等特性,從應(yīng)用層,下沉到基礎(chǔ)設(shè)施層去實現(xiàn),從而使得Kubernetes和容器全面接管微服務(wù)。

二、以Istio為例講述Service Mesh中的技術(shù)關(guān)鍵點

就如SDN一樣,Service Mesh將服務(wù)請求的轉(zhuǎn)發(fā)分為控制面和數(shù)據(jù)面,因而分析他,也是從數(shù)據(jù)面先分析轉(zhuǎn)發(fā)的能力,然后再分析控制面如何下發(fā)命令。今天這篇文章重點講述兩個組件Envoy和Pilot

一切從Envoy開始

我們首先來看,如果沒有融入Service Mesh,Envoy本身能夠做什么事情呢?

Envoy是一個高性能的C++寫的proxy轉(zhuǎn)發(fā)器,那Envoy如何轉(zhuǎn)發(fā)請求呢?需要定一些規(guī)則,然后按照這些規(guī)則進行轉(zhuǎn)發(fā)。

規(guī)則可以是靜態(tài)的,放在配置文件中的,啟動的時候加載,要想重新加載,一般需要重新啟動,但是Envoy支持熱加載和熱重啟,一定程度上緩解了這個問題。

當(dāng)然最好的方式是規(guī)則設(shè)置為動態(tài)的,放在統(tǒng)一的地方維護,這個統(tǒng)一的地方在Envoy眼中看來稱為Discovery Service,過一段時間去這里拿一下配置,就修改了轉(zhuǎn)發(fā)策略。

無論是靜態(tài)的,還是動態(tài)的,在配置里面往往會配置四個東西。


一是listener,也即envoy既然是proxy,專門做轉(zhuǎn)發(fā),就得監(jiān)聽一個端口,接入請求,然后才能夠根據(jù)策略轉(zhuǎn)發(fā),這個監(jiān)聽的端口稱為listener

二是endpoint,是目標(biāo)的ip地址和端口,這個是proxy最終將請求轉(zhuǎn)發(fā)到的地方。

三是cluster,一個cluster是具有完全相同行為的多個endpoint,也即如果有三個容器在運行,就會有三個IP和端口,但是部署的是完全相同的三個服務(wù),他們組成一個Cluster,從cluster到endpoint的過程稱為負載均衡,可以輪詢等。

四是route,有時候多個cluster具有類似的功能,但是是不同的版本號,可以通過route規(guī)則,選擇將請求路由到某一個版本號,也即某一個cluster。

這四個的靜態(tài)配置的例子如下:

如圖所示,listener被配置為監(jiān)聽本地127.0.0.1的10000接口,route配置為某個url的前綴轉(zhuǎn)發(fā)到哪個cluster,cluster里面配置負載均衡策略,hosts里面是所有的endpoint。

如果你想簡單的將envoy使用起來,不用什么service mesh,一個進程,加上這個配置文件,就可以了,就能夠轉(zhuǎn)發(fā)請求了。

對于動態(tài)配置,也應(yīng)該配置發(fā)現(xiàn)中心,也即Discovery Service,對于上述四種配置,各對應(yīng)相應(yīng)的DS,所以有LDS, RDS, CDS, EDS。

動態(tài)配置的例子如下:

控制面Pilot的工作模式

數(shù)據(jù)面envoy可以通過加裝靜態(tài)配置文件的方式運行,而動態(tài)信息,需要從Discovery Service去拿。

Discovery Service就是部署在控制面的,在istio中,是Pilot。

如圖為Pilot的架構(gòu),最下面一層是envoy的API,就是提供Discovery Service的API,這個API的規(guī)則由envoy定,但是不是Pilot調(diào)用Envoy,而是Envoy去主動調(diào)用Pilot的這個API。

Pilot最上面一層稱為Platform Adapter,這一層是干什么的呢?這一層不是Kubernetes, Mesos調(diào)用Pilot,而是Pilot通過調(diào)用Kubernetes來發(fā)現(xiàn)服務(wù)之間的關(guān)系。

這是理解Istio比較繞的一個點。也即pilot使用Kubernetes的Service,僅僅使用它的服務(wù)發(fā)現(xiàn)功能,而不使用它的轉(zhuǎn)發(fā)功能,pilot通過在kubernetes里面注冊一個controller來監(jiān)聽事件,從而獲取Service和Kubernetes的Endpoint以及Pod的關(guān)系,但是在轉(zhuǎn)發(fā)層面,就不會再使用kube-proxy根據(jù)service下發(fā)的iptables規(guī)則進行轉(zhuǎn)發(fā)了,而是將這些映射關(guān)系轉(zhuǎn)換成為pilot自己的轉(zhuǎn)發(fā)模型,下發(fā)到envoy進行轉(zhuǎn)發(fā),envoy不會使用kube-proxy的那些iptables規(guī)則。這樣就把控制面和數(shù)據(jù)面徹底分離開來,服務(wù)之間的相互關(guān)系是管理面的事情,不要和真正的轉(zhuǎn)發(fā)綁定在一起,而是繞到pilot后方。

Pilot另外一個對外的接口是Rules API,這是給管理員的接口,管理員通過這個接口設(shè)定一些規(guī)則,這些規(guī)則往往是應(yīng)用于Routes, Clusters, Endpoints的,而都有哪些Clusters和Endpoints,是由Platform Adapter這面通過服務(wù)發(fā)現(xiàn)得到的。

自動發(fā)現(xiàn)的這些Clusters和Endpoints,外加管理員設(shè)置的規(guī)則,形成了Pilot的數(shù)據(jù)模型,其實就是他自己定義的一系列數(shù)據(jù)結(jié)構(gòu),然后通過envoy API暴露出去,等待envoy去拉取這些規(guī)則。


常見的一種人工規(guī)則是Routes,通過服務(wù)發(fā)現(xiàn),Pilot可以從Kubernetes那里知道Service B有兩個版本,一般是兩個Deployment,屬于同一個Service,管理員通過調(diào)用Pilot的Rules API,來設(shè)置兩個版本之間的Route規(guī)則,一個占99%的流量,一個占1%的流量,這兩方面信息形成Pilot的數(shù)據(jù)結(jié)構(gòu)模型,然后通過Envoy API下發(fā),Envoy就會根據(jù)這個規(guī)則設(shè)置轉(zhuǎn)發(fā)策略了。


另一個常用的場景就是負載均衡,Pilot通過Kubernetes的Service發(fā)現(xiàn)Service B包含一個Deployment,但是有三個副本,于是通過Envoy API下發(fā)規(guī)則,使得Envoy在這三個副本之間進行負載均衡,而非通過Kubernetes本身Service的負載均衡機制。

三、以Istio為例解析Service Mesh的技術(shù)細節(jié)

了解了Service Mesh的大概原理,接下來我們通過一個例子來解析其中的技術(shù)細節(jié)。

凡是試驗過Istio的同學(xué)都應(yīng)該嘗試過下面這個BookInfo的例子,不很復(fù)雜,但是麻雀雖小五臟俱全。


在這個例子中,我們重點關(guān)注ProductPage這個服務(wù),對Reviews服務(wù)的調(diào)用,這里涉及到路由策略和負載均衡。

Productpage就是個Python程序

productpage是一個簡單的用python寫的提供restful API的程序。

在里面定義了很多的route,來接收API請求,并做相應(yīng)的操作。

在需要請求其他服務(wù),例如reviews, ratings的時候,則需要向后方發(fā)起restful調(diào)用。

從代碼可以看出,productpage對于后端的調(diào)用,都是通過域名來的。

對于productpage這個程序來講,他覺得很簡單,通過這個域名就可以調(diào)用了,既不需要通過服務(wù)發(fā)現(xiàn)系統(tǒng)獲取這個域名,也不需要關(guān)心轉(zhuǎn)發(fā),更意識不到自己是部署在kubernetes上的,是否用了service mesh,所以服務(wù)之間的通信完全交給了基礎(chǔ)設(shè)施層。

通過Kubernetes編排productpage

有了productpage程序,接下來就是將他部署到kubernetes上,這里沒有什么特殊的,用的就是kubernetes默認的編排文件。

首先定義了一個Deployment,使用bookinfo的容器鏡像,然后定義一個Service,用于這個Deployment的服務(wù)發(fā)現(xiàn)。

通過Kubernetes編排reviews

這個稍微有些復(fù)雜,定義了三個Deployment,但是版本號分別為V1, V2, V3,但是label都是app: reviews。

最后定義了一個Service,對應(yīng)的label是app: reviews,作為這三個Deployment的服務(wù)發(fā)現(xiàn)。

istioctl對productpage進行定制化之一:嵌入proxy_init作為InitContainer

到目前為止,一切正常,接下來就是見證奇跡的時刻,也即istio有個工具istioctl可以對于yaml文件進行定制化

定制化的第一項就是添加了一個initContainer,這種類型的container可以做一些初始化的工作后,成功退出,kubernetes不會保持他長期運行。

在這個InitContainer里面做什么事情呢?

我們登錄進去發(fā)現(xiàn),在這個InitContainer里面運行了一個shell腳本。

就是這個shell腳本在容器里面寫入了大量的iptables規(guī)則。

首先定義的一條規(guī)則是ISTIO_REDIRECT轉(zhuǎn)發(fā)鏈,這條鏈不分三七二十一,都將網(wǎng)絡(luò)包轉(zhuǎn)發(fā)給envoy的15000端口。

但是一開始這條鏈沒有被掛到iptables默認的幾條鏈中,所以不起作用。

接下來就是在PREROUTING規(guī)則中,使用這個轉(zhuǎn)發(fā)鏈,從而進入容器的所有流量,都被先轉(zhuǎn)發(fā)到envoy的15000端口。

envoy作為一個代理,已經(jīng)被配置好了,將請求轉(zhuǎn)發(fā)給productpage程序。

productpage程序接受到請求,會轉(zhuǎn)向調(diào)用外部的reviews或者ratings,從上面的分析我們知道,productpage只是做普通的域名調(diào)用。

當(dāng)productpage往后端進行調(diào)用的時候,就碰到了output鏈,這個鏈會使用轉(zhuǎn)發(fā)鏈,將所有出容器的請求都轉(zhuǎn)發(fā)到envoy的15000端口。

這樣無論是入口的流量,還是出口的流量,全部用envoy做成了漢堡包。

envoy根據(jù)服務(wù)發(fā)現(xiàn)的配置,知道reviews或者ratings如何訪問,于是做最終的對外調(diào)用。

這個時候iptables規(guī)則會對從envoy出去的流量做一個特殊處理,允許他發(fā)出去,不再使用上面的output規(guī)則。

istioctl對productpage進行定制化之二:嵌入proxy容器作為sidecar

istioctl做的第二項定制化是,嵌入proxy容器作為sidecar。

這個似乎看起來更加復(fù)雜,但是進入容器我們可以看到,啟動了兩個進程。

一個是我們熟悉的envoy,他有一個配置文件是/etc/istio/proxy/envoy-rev0.json

我們再前面講述envoy的時候說過,有了配置文件,envoy就能夠轉(zhuǎn)發(fā)了,我們先來看看配置文件里面都有啥。


在這里面配置了envoy的管理端口,等一下我們會通過這個端口查看envoy被pilot下發(fā)了哪些轉(zhuǎn)發(fā)策略。

然后就是動態(tài)資源,也即從各種discovery service去拿轉(zhuǎn)發(fā)策略。

還有就是靜態(tài)資源,也即靜態(tài)配置的,需要重啟才能加載的。


這就是pilot-agent的作用,他是envoy的一個簡單的管理器,因為有些靜態(tài)資源,如果TLS的證書,envoy還不支持動態(tài)下發(fā),因而需要重新靜態(tài)配置,然后pilot-agent負責(zé)將envoy進行熱重啟加載。

好在envoy有良好的熱重啟機制,重啟的時候,會先啟動一個備用進程,將轉(zhuǎn)發(fā)的統(tǒng)計數(shù)據(jù)通過shared memory在兩個進程間共享。

深入解析pilot的工作機制


Pilot的工作機制展開后如圖所示。

istio config是管理員通過管理接口下發(fā)的轉(zhuǎn)發(fā)規(guī)則。

Service Discovery模塊對于Kubernetes來講,就是創(chuàng)建了一個controller來監(jiān)聽Service創(chuàng)建和刪除的事件,當(dāng)service有變化時,會通知pilot,pilot會根據(jù)變化更新下發(fā)給envoy的規(guī)則。

pilot將管理員輸入的轉(zhuǎn)發(fā)策略配置和服務(wù)發(fā)現(xiàn)的當(dāng)前狀態(tài),變成pilot自己的數(shù)據(jù)結(jié)構(gòu)模型,然后暴露成envoy的api,由于是envoy來調(diào)用,因而要實現(xiàn)一個服務(wù)端,這里有l(wèi)ds, rds, cds, eds。

接下來我們看,在pilot上配置route之后會發(fā)生什么?

如圖,我們將所有的流量都發(fā)給版本1。

我們查看envoy的管理端口,可以看到只配置了reviews的v1。

當(dāng)我們修改路由為v1和v3比例是五十比五十。

可以看到envoy的管理端口,路由有了兩個版本的配置,也對應(yīng)后端的兩個ip地址。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,797評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,179評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,628評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,642評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 71,444評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,948評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,040評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,185評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,717評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,602評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,794評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,316評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,045評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,418評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,671評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,414評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 47,750評論 2 370

推薦閱讀更多精彩內(nèi)容