本文是之前所寫內容的從新修訂並收錄於 ServiceMesher 社區的 Istio Handbook 中,其餘章節仍在編纂中。html
剛據說 Service Mesh 並試用過 Istio 的人可能都會有下面幾個疑問:node
這一節咱們將試圖帶您梳理清楚 Kubernetes、xDS 協議以及 Istio Service Mesh 之間的內在聯繫。此外,本節還將介紹 Kubernetes 中的負載均衡方式,xDS 協議對於 Service Mesh 的意義以及爲何說及時有了 Kubernetes 還須要 Istio。nginx
使用 Service Mesh 並非說與 Kubernetes 決裂,而是水到渠成的事情。Kubernetes 的本質是經過聲明式配置對應用進行生命週期管理,而 Service Mesh 的本質是提供應用間的流量和安全性管理以及可觀察性。假如你已經使用 Kubernetes 構建了穩定的微服務平臺,那麼如何設置服務間調用的負載均衡和流量控制?git
Envoy 創造的 xDS 協議被衆多開源軟件所支持,如 Istio、Linkerd、MOSN 等。Envoy 對於 Service Mesh 或雲原生來講最大的貢獻就是定義了 xDS,Envoy 本質上是一個 proxy,是可經過 API 配置的現代版 proxy,基於它衍生出來不少不一樣的使用場景,如 API Gateway、Service Mesh 中的 Sidecar proxy 和邊緣代理。github
本節包含如下內容api
若是你想要提早了解下文的全部內容,那麼能夠先閱讀下面列出的本文中的一些主要觀點:安全
kube-proxy
組件的支持,經過爲更接近微服務應用層的抽象,管理服務間的流量、安全性和可觀察性。下圖展現的是 Kubernetes 與 Service Mesh 中的的服務訪問關係(每一個 pod 一個 sidecar 的模式)。服務器
流量轉發markdown
Kubernetes 集羣的每一個節點都部署了一個 kube-proxy
組件,該組件會與 Kubernetes API Server 通訊,獲取集羣中的 service 信息,而後設置 iptables 規則,直接將對某個 service 的請求發送到對應的 Endpoint(屬於同一組 service 的 pod)上。網絡
服務發現
Istio Service Mesh 能夠沿用了 Kubernetes 中的 service 作服務註冊,還能夠經過控制平面的平臺適配器對接其餘服務發現系統,而後生成數據平面的配置(使用 CRD 聲明,保存在 etcd 中),數據平面的透明代理(transparent proxy)以 sidecar 容器的形式部署在每一個應用服務的 pod 中,這些 proxy 都須要請求控制平面來同步代理配置。之因此說是透明代理,是由於應用程序容器徹底無感知代理的存在,該過程 kube-proxy 組件同樣須要攔截流量,只不過 kube-proxy
攔截的是進出 Kubernetes 節點的流量,而 sidecar proxy 攔截的是進出該 Pod 的流量,詳見理解 Istio Service Mesh 中 Envoy Sidecar 代理的路由轉發。
Service Mesh 的劣勢
由於 Kubernetes 每一個節點上都會運行衆多的 Pod,將原先 kube-proxy
方式的路由轉發功能置於每一個 pod 中,將致使大量的配置分發、同步和最終一致性問題。爲了細粒度地進行流量管理,必將添加一系列新的抽象,從而會進一步增長用戶的學習成本,但隨着技術的普及,這樣的狀況會慢慢地獲得緩解。
Service Mesh 的優點
kube-proxy
的設置都是全局生效的,沒法對每一個服務作細粒度的控制,而 Service Mesh 經過 sidecar proxy 的方式將 Kubernetes 中對流量的控制從 service 一層抽離出來,能夠作更多的擴展。
在 Kubernetes 集羣中,每一個 Node 運行一個 kube-proxy
進程。kube-proxy
負責爲 Service
實現了一種 VIP(虛擬 IP)的形式。 在 Kubernetes v1.0 版本,代理徹底在 userspace 實現。Kubernetes v1.1 版本新增了 iptables 代理模式,但並非默認的運行模式。從 Kubernetes v1.2 起,默認使用 iptables 代理。在 Kubernetes v1.8.0-beta.0 中,添加了 ipvs 代理模式。關於 kube-proxy 組件的更多介紹請參考 kubernetes 簡介:service 和 kube-proxy 原理 和 使用 IPVS 實現 Kubernetes 入口流量負載均衡。
首先,若是轉發的 pod 不能正常提供服務,它不會自動嘗試另外一個 pod,固然這個能夠經過
liveness probes
來解決。每一個 pod 都有一個健康檢查的機制,當有 pod 健康情況有問題時,kube-proxy 會刪除對應的轉發規則。另外,nodePort
類型的服務也沒法添加 TLS 或者更復雜的報文路由機制。
Kube-proxy 實現了流量在 Kubernetes service 多個 pod 實例間的負載均衡,可是如何對這些 service 間的流量作細粒度的控制,好比按照百分比劃分流量到不一樣的應用版本(這些應用都屬於同一個 service,但位於不一樣的 deployment 上),作金絲雀發佈(灰度發佈)和藍綠髮布?Kubernetes 社區給出了 使用 Deployment 作金絲雀發佈的方法,該方法本質上就是經過修改 pod 的 label 來將不一樣的 pod 劃歸到 Deployment 的 Service 上。
上文說到 kube-proxy
只能路由 Kubernetes 集羣內部的流量,而咱們知道 Kubernetes 集羣的 Pod 位於 CNI 建立的外網絡中,集羣外部是沒法直接與其通訊的,所以 Kubernetes 中建立了 ingress 這個資源對象,它由位於 Kubernetes 邊緣節點(這樣的節點能夠是不少個也能夠是一組)的 Ingress controller 驅動,負責管理南北向流量,Ingress 必須對接各類 Ingress Controller 才能使用,好比 nginx ingress controller、traefik。Ingress 只適用於 HTTP 流量,使用方式也很簡單,只能對 service、port、HTTP 路徑等有限字段匹配來路由流量,這致使它沒法路由如 MySQL、Redis 和各類私有 RPC 等 TCP 流量。要想直接路由南北向的流量,只能使用 Service 的 LoadBalancer 或 NodePort,前者須要雲廠商支持,後者須要進行額外的端口管理。有些 Ingress controller 支持暴露 TCP 和 UDP 服務,可是隻能使用 Service 來暴露,Ingress 自己是不支持的,例如 nginx ingress controller,服務暴露的端口是經過建立 ConfigMap 的方式來配置的。
Istio Gateway 的功能與 Kubernetes Ingress 相似,都是負責集羣的南北向流量。Istio Gateway
描述的負載均衡器用於承載進出網格邊緣的鏈接。該規範中描述了一系列開放端口和這些端口所使用的協議、負載均衡的 SNI 配置等內容。Gateway 是一種 CRD 擴展,它同時複用了 sidecar proxy 的能力,詳細配置請參考 Istio 官網。
下面這張圖你們在瞭解 Service Mesh 的時候可能都看到過,每一個方塊表明一個服務的實例,例如 Kubernetes 中的一個 Pod(其中包含了 sidecar proxy),xDS 協議控制了 Istio Service Mesh 中全部流量的具體行爲,即將下圖中的方塊連接到了一塊兒。
xDS 協議是由 Envoy 提出的,在 Envoy v2 版本 API 中最原始的 xDS 協議指的是 CDS(Cluster Discovery Service)、EDS(Endpoint Discovery service)、LDS(Listener Discovery Service) 和 RDS(Route Discovery Service),後來在 v3 版本中又發展出了 Scoped Route Discovery Service(SRDS)、Virtual Host Discovery Service (VHDS)、Secret Discovery Service(SDS)、Runtime Discovery Service(RTDS)詳見 xDS REST and gRPC protocol。
下面咱們以各有兩個實例的 service,來看下 xDS 協議。
上圖中的箭頭不是流量進入 Proxy 後的路徑或路由,也不是實際順序,而是想象的一種 xDS 接口處理順序,其實 xDS 之間也是有交叉引用的。
支持 xDS 協議的代理經過查詢文件或管理服務器來動態發現資源。歸納地講,對應的發現服務及其相應的 API 被稱做
。Envoy 經過**訂閱(subscription)**方式來獲取資源,訂閱方式有如下三種:
path
參數中。ApiConfigSource
,指向對應的上游管理服務器的集羣地址。以上的 xDS 訂閱方式詳情請參考 xDS 協議解析。Istio 使用 gRPC 流式訂閱的方式配置全部的數據平面的 sidecar proxy。
文章中介紹了 Istio pilot 的整體架構、proxy 配置的生成、pilot-discovery 模塊的功能,以及 xDS 協議中的 CDS、EDS 及 ADS,關於 ADS 詳情請參考 Envoy 官方文檔。
最後總結下關於 xDS 協議的要點:
Envoy 是 Istio Service Mesh 中默認的 Sidecar,Istio 在 Enovy 的基礎上按照 Envoy 的 xDS 協議擴展了其控制平面,在講到 Envoy xDS 協議以前咱們還須要先熟悉下 Envoy 的基本術語。下面列舉了 Envoy 裏的基本術語及其數據結構解析,關於 Envoy 的詳細介紹請參考 Envoy 官方文檔,至於 Envoy 在 Service Mesh(不只限於 Istio) 中是如何做爲轉發代理工做的請參考網易雲劉超的這篇深刻解讀 Service Mesh 背後的技術細節 以及理解 Istio Service Mesh 中 Envoy 代理 Sidecar 注入及流量劫持,本文引用其中的一些觀點,詳細內容再也不贅述。
下面是您應該瞭解的 Enovy 裏的基本術語:
Envoy 中能夠設置多個 Listener,每一個 Listener 中又能夠設置 filter chain(過濾器鏈表),並且過濾器是可擴展的,這樣就能夠更方便咱們操做流量的行爲,例如設置加密、私有 RPC 等。
xDS 協議是由 Envoy 提出的,如今是 Istio 中默認的 sidecar proxy,但只要實現 xDS 協議理論上都是能夠做爲 Istio 中的 sidecar proxy 的,例如螞蟻金服開源的 MOSN。
Istio 是一個功能十分豐富的 Service Mesh,它包括以下功能:
Istio 中定義了以下的 CRD 來幫助用戶進行流量管理:
DestinationRule
所定義的策略,決定了通過路由處理以後的流量的訪問策略。簡單的說就是定義流量如何路由。這些策略中能夠定義負載均衡配置、鏈接池尺寸以及外部檢測(用於在負載均衡池中對不健康主機進行識別和驅逐)配置。EnvoyFilter
對象描述了針對代理服務的過濾器,這些過濾器能夠定製由 Istio Pilot 生成的代理配置。這個配置初級用戶通常不多用到。ServiceEntry
可以在 Istio 內部的服務註冊表中加入額外的條目,從而讓網格中自動發現的服務可以訪問和路由到這些手工加入的服務。在閱讀完上文對 Kubernetes 的 kube-proxy
組件、xDS 和 Istio 中流量管理的抽象概念以後,下面將帶您僅就流量管理方面比較下三者對應的組件/協議(注意,三者不能夠徹底等同)。
Kubernetes | xDS | Istio Service Mesh |
---|---|---|
Endpoint | Endpoint | - |
Service | Route | VirtualService |
kube-proxy | Route | DestinationRule |
kube-proxy | Listener | EnvoyFilter |
Ingress | Listener | Gateway |
Service | Cluster | ServiceEntry |
若是說 Kubernetes 管理的對象是 Pod,那麼 Service Mesh 中管理的對象就是一個個 Service,因此說使用 Kubernetes 管理微服務後再應用 Service Mesh 就是水到渠成了,若是連 Service 你也不想管了,那就用如 knative 這樣的 serverless 平臺,但這就是後話了。
Envoy/MOSN 的功能也不僅是作流量轉發,以上概念只不過是 Istio 在 Kubernetes 之上新增一層抽象層中的冰山一角,但由於流量管理是服務網格最基礎也是最重要的功能,因此這將成爲本書的開始。