后Kubernetes時(shí)代的微服務(wù)

聽說過服務(wù)網(wǎng)格并試用過Istio的人可能都會(huì)有以下5個(gè)疑問。
(1)為什么Istio 要綁定Kubernetes呢?
(2)Kubernetes和服務(wù)網(wǎng)格分別在云原生中扮演什么角色?
(3)Istio擴(kuò)展了Kubernetes的哪些方面?解決了哪些問題?
(4)Kubernetes、xDS協(xié)議(Envoy、MOSN等)與Istio之間是什么關(guān)系?
(5)到底該不該使用Service Mesh?
本文將帶讀者梳理清楚 Kubernetes、xDS協(xié)議與Istio服務(wù)網(wǎng)格之間的內(nèi)在聯(lián)系。此外,本文還將介紹Kubernetes中的負(fù)載均衡方式,xDS協(xié)議對(duì)于服務(wù)網(wǎng)格的意義,以及為什么說即使有了Kubernetes還需要Istio。
使用服務(wù)網(wǎng)格并非與Kubernetes決裂,而是水到渠成的事情。Kubernetes的本質(zhì)是通過聲明配置對(duì)應(yīng)用進(jìn)行生命周期管理,而服務(wù)網(wǎng)格的本質(zhì)是提供應(yīng)用間的流量和安全性管理,以及可觀察性。假如已經(jīng)使用Kubernetes構(gòu)建了穩(wěn)定的微服務(wù)平臺(tái),那么如何設(shè)置服務(wù)間調(diào)用的負(fù)載均衡和流量控制?
Envoy創(chuàng)造的xDS協(xié)議被眾多開源軟件所支持,如Istio、Linkerd、MOSN等。Envoy對(duì)服務(wù)網(wǎng)格或云原生而言最大的貢獻(xiàn)就是定義了xDS。Envoy本質(zhì)上是一個(gè)網(wǎng)絡(luò)代理,是通過API配置的現(xiàn)代版代理,基于它衍生出了很多不同的使用場(chǎng)景,如API 網(wǎng)關(guān)、服務(wù)網(wǎng)格中的Sidecar 代理和邊緣代理。
如果想要提前了解下文的所有內(nèi)容,則可以先閱讀下面列出的一些主要觀點(diǎn)。
Kubernetes的本質(zhì)是應(yīng)用的生命周期管理,具體來說,就是應(yīng)用的部署和管理(擴(kuò)縮容、自動(dòng)恢復(fù)、發(fā)布)。
Kubernetes為微服務(wù)提供了可擴(kuò)展、高彈性的部署和管理平臺(tái)。
服務(wù)網(wǎng)格的基礎(chǔ)是透明代理,先通過Sidecar 代理攔截到微服務(wù)間流量,再通過控制平面配置管理微服務(wù)的行為。
服務(wù)網(wǎng)格將流量管理從Kubernetes中解耦,服務(wù)網(wǎng)格內(nèi)部的流量無須kube-proxy組件的支持,通過接近微服務(wù)應(yīng)用層的抽象,管理服務(wù)間的流量,實(shí)現(xiàn)安全性和可觀察性功能。
xDS定義了服務(wù)網(wǎng)格配置的協(xié)議標(biāo)準(zhǔn)。
服務(wù)網(wǎng)格是對(duì)Kubernetes中的service更上層的抽象,它的下一步是serverless。
圖1所示為Kubernetes原生與Service Mesh的服務(wù)訪問關(guān)系(每個(gè)Pod中部署一個(gè)Sidecar的模式)。
圖1
▊ 流量轉(zhuǎn)發(fā)
Kubernetes集群的每個(gè)節(jié)點(diǎn)都部署了一個(gè)kube-proxy組件,該組件會(huì)先與Kubernetes API Server通信,獲取集群中的service信息,再設(shè)置iptables規(guī)則,直接將對(duì)某個(gè)service的請(qǐng)求發(fā)送到對(duì)應(yīng)的Endpoint(屬于同一組service的Pod)上。
▊ 服務(wù)發(fā)現(xiàn)
Istio服務(wù)網(wǎng)格不僅可以沿用Kubernetes中的service做服務(wù)注冊(cè),還可以通過控制平面的平臺(tái)適配器對(duì)接其他服務(wù)發(fā)現(xiàn)系統(tǒng),生成數(shù)據(jù)平面的配置(使用CRD聲明,保存在etcd中)。數(shù)據(jù)平面的透明代理(Transparent Proxy)以Sidecar容器的形式部署在每個(gè)應(yīng)用服務(wù)的Pod中,這些Proxy都需要請(qǐng)求控制平面同步代理配置。之所以說是透明代理,是因?yàn)閼?yīng)用程序容器完全沒有感知代理的存在,在該過程中kube-proxy組件一樣需要攔截流量,只不過kube-proxy組件攔截的是進(jìn)出Kubernetes節(jié)點(diǎn)的流量,而Sidecar Proxy攔截的是進(jìn)出該P(yáng)od的流量。圖2所示為Istio中的服務(wù)發(fā)現(xiàn)機(jī)制。

圖2
▊ 服務(wù)網(wǎng)格的劣勢(shì)
由于Kubernetes的每個(gè)節(jié)點(diǎn)都會(huì)運(yùn)行眾多的Pod,因此將原先kube-proxy方式的路由轉(zhuǎn)發(fā)功能置于每個(gè)Pod中,會(huì)導(dǎo)致大量的配置分發(fā)、同步和最終一致性問題。為了細(xì)粒度地進(jìn)行流量管理,必須添加一系列新的抽象,從而導(dǎo)致用戶的學(xué)習(xí)成本進(jìn)一步增加,但隨著技術(shù)的普及,該情況會(huì)慢慢得到緩解。
▊ 服務(wù)網(wǎng)格的優(yōu)勢(shì)
kube-proxy的設(shè)置都是全局生效的,無法對(duì)每個(gè)服務(wù)做細(xì)粒度的控制,而服務(wù)網(wǎng)格通過Sidecar Proxy的方式將Kubernetes中對(duì)流量的控制從service一層抽離出來,做更多的擴(kuò)展。
在Kubernetes集群中,每個(gè)Node運(yùn)行一個(gè)kube-proxy進(jìn)程。kube-proxy負(fù)責(zé)為service實(shí)現(xiàn)一種VIP(虛擬IP地址)的形式。
在Kubernetes v1.0版本中,代理完全在userspace代理模式中實(shí)現(xiàn)。
在Kubernetes v1.1版本中,新增了iptables代理模式,但不是默認(rèn)的運(yùn)行模式。從Kubernetes v1.2版本起,默認(rèn)使用iptables代理模式。在Kubernetes v1.8.0-beta.0版本中,添加了IPVS代理模式。
kube-proxy的缺陷
首先,如果轉(zhuǎn)發(fā)的Pod不能正常提供服務(wù),那么它不會(huì)自動(dòng)嘗試另一個(gè)Pod,不過這個(gè)問題可以通過liveness probes解決。每個(gè)Pod都有一個(gè)健康檢查機(jī)制,當(dāng)Pod健康狀況有問題時(shí),kube-proxy會(huì)刪除對(duì)應(yīng)的轉(zhuǎn)發(fā)規(guī)則。另外,nodePort類型的服務(wù)也無法添加TLS,或者更復(fù)雜的報(bào)文路由機(jī)制。
kube-proxy實(shí)現(xiàn)了流量在Kubernetes 服務(wù)中多個(gè)Pod實(shí)例間的負(fù)載均衡,但是如何對(duì)這些服務(wù)間的流量做細(xì)粒度的控制,比如,將流量按照百分比劃分到不同的應(yīng)用版本(這些應(yīng)用版本都屬于同一個(gè)服務(wù)的一部分,但位于不同的部署上),做金絲雀發(fā)布(灰度發(fā)布)和藍(lán)綠發(fā)布?Kubernetes社區(qū)給出了使用Deployment做金絲雀發(fā)布的方法,該方法本質(zhì)上就是通過修改Pod的label將不同的Pod 劃歸到Deployment的service上。
kube-proxy只能路由Kubernetes集群內(nèi)部的流量,而Kubernetes集群的Pod位于CNI創(chuàng)建的網(wǎng)絡(luò)中,集群外部是無法直接與其通信的,因此在Kubernetes中創(chuàng)建了Ingress這個(gè)資源對(duì)象,并由位于Kubernetes邊緣節(jié)點(diǎn)(這樣的節(jié)點(diǎn)可以有很多個(gè),也可以有一組)的Ingress Controller驅(qū)動(dòng),負(fù)責(zé)管理南北向流量。
Ingress必須對(duì)接各種Ingress Controller才能使用,比如,Nginx Ingress Controller、Traefik。Ingress只適用于HTTP流量,使用方式也很簡單,但只能對(duì)service、Port、HTTP路徑等有限字段匹配路由流量,這導(dǎo)致它無法路由如MySQL、Redis和各種私有RPC等TCP流量。
要想直接路由南北向的流量,只能使用service的LoadBalancer或NodePort,前者需要云廠商支持,后者需要進(jìn)行額外的端口管理。
有些Ingress Controller支持暴露TCP和UDP服務(wù),但是只能使用service來暴露,Ingress本身是不支持的,例如,Nginx Ingress Controller,服務(wù)暴露的端口是通過創(chuàng)建 ConfigMap的方式配置的。
Istio Gateway的功能與Kubernetes Ingress的功能類似,都是負(fù)責(zé)管理集群的南北向流量。
Istio Gateway可被看作網(wǎng)絡(luò)的負(fù)載均衡器,用于承載進(jìn)出網(wǎng)格邊緣的連接。
Istio Gateway規(guī)范描述了一系列開放端口和這些端口所使用的協(xié)議、負(fù)載均衡的SNI配置等內(nèi)容。
Istio 中的Gateway資源是一種CRD擴(kuò)展,它同時(shí)復(fù)用了Sidecar 代理功能,詳細(xì)配置請(qǐng)參考Istio官方網(wǎng)站。
圖3所示為Service Mesh的控制平面,讀者在了解服務(wù)網(wǎng)格時(shí)可能看到過,每個(gè)方塊代表一個(gè)服務(wù)的實(shí)例,例如,Kubernetes中的一個(gè)Pod(其中包含了Sidecar 代理)。xDS協(xié)議控制了Istio服務(wù)網(wǎng)格中所有流量的具體行為,即將圖1-3中的方塊鏈接到了一起。

圖3
xDS協(xié)議是由Envoy提出的,在Envoy v2版本的API中最原始的xDS協(xié)議指的是CDS(Cluster Discovery Service)、EDS(Endpoint Discovery Service)、LDS(Listener Discovery Service)和RDS(Route Discovery Service),后來在Envoy v3版本中xDS協(xié)議又發(fā)展出了Scoped Route Discovery Service(SRDS)、Virtual Host Discovery Service(VHDS)、Secret Discovery Service(SDS)、Runtime Discovery Service(RTDS)。
下面通過兩個(gè)服務(wù)的通信了解xDS協(xié)議,如圖4所示。

圖4
圖4中的箭頭不是流量進(jìn)入Proxy后的路徑或路由,也不是實(shí)際順序,而是虛擬的一種xDS接口處理順序。其實(shí)在各個(gè)xDS協(xié)議之間也是有交叉引用的。
支持xDS協(xié)議的代理可以通過查詢文件或管理服務(wù)器動(dòng)態(tài)發(fā)現(xiàn)資源。概括地講,這些發(fā)現(xiàn)服務(wù)及其相應(yīng)的API被稱作xDS。Envoy通過訂閱(Subscription)方式獲取資源,訂閱方式有以下3種。
文件訂閱:監(jiān)控指定路徑下的文件。發(fā)現(xiàn)動(dòng)態(tài)資源的最簡單方式就是將其保存于文件中,并將路徑配置在configSource中的path參數(shù)中。
gRPC流式訂閱:每個(gè)xDS API可以單獨(dú)配置ApiConfigSource,指向?qū)?yīng)的上游管理服務(wù)器的集群地址。
輪詢REST-JSON輪詢訂閱:單個(gè)xDS API可以對(duì)REST端點(diǎn)進(jìn)行同步(長)輪詢。
Istio使用gRPC流式訂閱的方式配置所有的數(shù)據(jù)平面的Sidecar Proxy。下面總結(jié)關(guān)于xDS協(xié)議的要點(diǎn)。
CDS、EDS、LDS、RDS是最基礎(chǔ)的xDS協(xié)議,都可以獨(dú)立更新。
所有的發(fā)現(xiàn)服務(wù)(Discovery Service)可以連接不同的管理服務(wù),也就是說管理xDS的服務(wù)器可以有多個(gè)。
Envoy在原始xDS協(xié)議的基礎(chǔ)上進(jìn)行了一系列擴(kuò)充,增加了SDS(密鑰發(fā)現(xiàn)服務(wù))、ADS(聚合發(fā)現(xiàn)服務(wù))、HDS(健康發(fā)現(xiàn)服務(wù))、MS(Metric服務(wù))、RLS(速率限制服務(wù))等API。
為了保證數(shù)據(jù)一致性,若直接使用xDS原始API,則需要保證按照CDS → EDS → LDS → RDS的順序更新。這是遵循電子工程中的先合后斷(Make-Before-Break)原則的,即在斷開原來的連接之前先建立好新的連接,應(yīng)用在路由里就是為了防止在設(shè)置了新的路由規(guī)則時(shí)無法發(fā)現(xiàn)上游集群而導(dǎo)致流量被丟棄的情況,類似于電路里的斷路。
CDS用于設(shè)置服務(wù)網(wǎng)格中有哪些服務(wù)。
EDS用于設(shè)置哪些實(shí)例(Endpoint)屬于這些服務(wù)(Cluster)。
LDS用于設(shè)置實(shí)例上監(jiān)聽的端口以配置路由。
RDS是最終服務(wù)間的路由關(guān)系,應(yīng)該保證最后更新RDS。
Envoy是Istio服務(wù)網(wǎng)格中默認(rèn)的Sidecar,Istio在Envoy的基礎(chǔ)上按照 Envoy的xDS協(xié)議擴(kuò)展了其控制平面。在講解Envoy xDS協(xié)議之前還需要先熟悉下Envoy的基本術(shù)語。下面列舉了Envoy中的基本術(shù)語及其數(shù)據(jù)結(jié)構(gòu)解析。
Downstream(下游):下游主機(jī)連接到Envoy,發(fā)送請(qǐng)求并接收響應(yīng),即發(fā)送請(qǐng)求的主機(jī)。
Upstream(上游):上游主機(jī)接收來自Envoy的連接和請(qǐng)求,并返回響應(yīng),即接收請(qǐng)求的主機(jī)。
Listener(監(jiān)聽器):監(jiān)聽器是命名網(wǎng)地址(例如,端口、UNIX Domain Socket等),下游客戶端可以連接這些監(jiān)聽器。Envoy暴露一個(gè)或多個(gè)監(jiān)聽器給下游主機(jī)連接。
Cluster(集群):集群是指Envoy連接的一組邏輯相同的上游主機(jī)。Envoy通過服務(wù)發(fā)現(xiàn)來發(fā)現(xiàn)集群的成員,并且可以通過主動(dòng)健康檢查確定集群成員的健康狀態(tài)。Envoy通過負(fù)載均衡策略決定將請(qǐng)求路由到集群的哪個(gè)成員。
Envoy中可以設(shè)置多個(gè)Listener,每個(gè)Listener中又可以設(shè)置filterchain(過濾器鏈表),而且過濾器是可擴(kuò)展的,這樣就可以更方便地操作流量了,例如,設(shè)置加密、私有RPC等。
xDS協(xié)議是由Envoy提出的,目前是Istio中默認(rèn)的Sidecar 代理。但是,只要實(shí)現(xiàn)了xDS協(xié)議,理論上就可以作為Istio中的Sidecar 代理,例如,螞蟻集團(tuán)開源的MOSN。
Istio是一個(gè)功能十分豐富的Service Mesh實(shí)現(xiàn)產(chǎn)品,包括如下功能。
流量管理:這是Istio最基本的功能。
策略控制:通過Mixer組件和各種適配器可以實(shí)現(xiàn)訪問控制系統(tǒng)、遙測(cè)捕獲、配額管理和計(jì)費(fèi)等策略控制。
可觀測(cè)性:通過Mixer實(shí)現(xiàn)。
安全認(rèn)證:通過Citadel組件做密鑰和證書管理。
Istio中定義了如下的CRD來幫助用戶進(jìn)行流量管理。
Gateway:描述了在網(wǎng)絡(luò)邊緣運(yùn)行的負(fù)載均衡器,用于接收傳入或傳出的HTTP / TCP連接。
VirtualService:實(shí)際上可以將Kubernetes服務(wù)連接到Istio Gateway上,并且可以執(zhí)行更多操作,例如,定義一組流量路由規(guī)則,以便在主機(jī)被尋址時(shí)應(yīng)用。
DestinationRule:決定了經(jīng)過路由處理之后的流量的訪問策略。簡單來說,就是定義流量如何路由。這些策略中可以定義負(fù)載均衡配置、連接池尺寸及外部檢測(cè)(用于在負(fù)載均衡池中對(duì)不健康主機(jī)進(jìn)行識(shí)別和驅(qū)逐)配置。
EnvoyFilter:描述了針對(duì)代理服務(wù)的過濾器,這些過濾器可以定制由Istio Pilot生成的代理配置。初級(jí)用戶一般很少用到這個(gè)配置。
ServiceEntry:在默認(rèn)情況下,Istio服務(wù)網(wǎng)格中的服務(wù)是無法發(fā)現(xiàn)Mesh以外的服務(wù)的。ServiceEntry能夠在Istio內(nèi)部的服務(wù)注冊(cè)表中加入額外的條目,從而讓服務(wù)網(wǎng)格中的服務(wù)能夠訪問和路由到這些被手動(dòng)加入的服務(wù)。
通過前面的介紹,讀者已經(jīng)對(duì)Service Mesh已經(jīng)有了初步的認(rèn)識(shí)。Istio作為一個(gè)開源的Service Mesh實(shí)現(xiàn)產(chǎn)品,一經(jīng)推出就備受矚目,成為各大廠商和開發(fā)者爭相追捧的對(duì)象。因此,Istio很有可能會(huì)成為繼Kubernetes之后的又一個(gè)明星級(jí)產(chǎn)品。
Istio官方文檔是這樣定義的:
“它是一個(gè)完全開源的服務(wù)網(wǎng)格,以透明的方式構(gòu)建在現(xiàn)有的分布式應(yīng)用中。它也是一個(gè)平臺(tái),擁有可以集成任何日志、遙測(cè)和策略系統(tǒng)的API接口。Istio多樣化的特性使你能夠成功且高效地運(yùn)行分布式微服務(wù)架構(gòu),并提供保護(hù)、連接和監(jiān)控微服務(wù)的統(tǒng)一方法。”
從官方定義可以看出,Istio提供了一種完整的解決方案,可以使用統(tǒng)一的方式管理和監(jiān)測(cè)微服務(wù)應(yīng)用。
同時(shí),它具有管理流量、實(shí)施訪問策略、收集數(shù)據(jù)等方面的功能,而且所有的這些都對(duì)應(yīng)用透明,幾乎不需要修改業(yè)務(wù)代碼就能實(shí)現(xiàn)。
有了Istio,用戶幾乎可以不再使用其他的微服務(wù)框架,也不需要自己去實(shí)現(xiàn)服務(wù)治理等功能。只要把網(wǎng)絡(luò)層委托給Istio,它就能幫用戶完成這一系列的功能。
簡單來說,Istio就是一個(gè)提供了服務(wù)治理功能的服務(wù)網(wǎng)格。
Service Mesh是一種服務(wù)治理技術(shù),其核心功能是對(duì)流量進(jìn)行控制。
從這一點(diǎn)來說,Service Mesh和現(xiàn)有的服務(wù)治理產(chǎn)品在功能上是有重合的。如果一個(gè)企業(yè)使用的微服務(wù)應(yīng)用已經(jīng)具有了非常完善的服務(wù)治理功能,則不一定非得引入Service Mesh。
但是,如果企業(yè)使用的系統(tǒng)不具有完善的治理功能,或者系統(tǒng)架構(gòu)中的痛點(diǎn)正好可以被Service Mesh解決,則Service Mesh是最佳選擇。
相對(duì)于基于公共庫的服務(wù)治理產(chǎn)品,Service Mesh最大的特性就是對(duì)應(yīng)用透明。用戶不僅可以將自己的微服務(wù)應(yīng)用無縫地接入網(wǎng)格,而且無須修改業(yè)務(wù)邏輯。目前Istio提供了以下4個(gè)重要的功能。
為HTTP、gRPC、WebSocket和TCP流量自動(dòng)負(fù)載均衡。
通過豐富的路由規(guī)則、重試、故障轉(zhuǎn)移和故障注入對(duì)流量行為進(jìn)行細(xì)粒度控制。
提供完善的可觀察性方面的功能,包括對(duì)所有網(wǎng)格控制下的流量進(jìn)行自動(dòng)化度量、日志記錄和追蹤。
提供身份認(rèn)證和授權(quán)策略,在集群中實(shí)現(xiàn)安全的服務(wù)間通信。
Istio獨(dú)立于平臺(tái),被設(shè)計(jì)為可以在各種環(huán)境中運(yùn)行,包括跨云、內(nèi)部環(huán)境、Kubernetes等。目前Istio支持的平臺(tái)有:
(1)部署在Kubernetes集群的服務(wù)。
(2)在Consul中注冊(cè)的服務(wù)。
(3)在獨(dú)立的虛擬機(jī)中運(yùn)行的服務(wù)。
本文節(jié)選自《深入理解Istio:云原生服務(wù)網(wǎng)格進(jìn)階實(shí)戰(zhàn)》一書,歡迎閱讀此書了解更多相關(guān)內(nèi)容!

下單立減50,快快掃碼搶購吧!
如果喜歡本文 歡迎 在看丨留言丨分享至朋友圈 三連 熱文推薦
▼點(diǎn)擊閱讀原文,了解本書詳情~

