服務網格——後 Kubernetes 時代的微服務(前言)

目錄

重要觀點

閱讀本文之前

Kubernetes vs Service Mesh

kube-proxy 組件

kube-proxy 的缺陷

Kubernetes Ingress vs Istio Gateway

xDS 協議

xDS 協議要點

Envoy

基本術語

Istio Service Mesh

Istio 中的流量管理

Kubernetes vs Envoy xDS vs Istio

總結


我想聽說過 Service Mesh 並試用過 Istio 的人可能都會有以下幾個疑問:

  1. 爲什麼 Istio 一定要綁定 Kubernetes 呢?
  2. Kubernetes 和 Service Mesh 分別在雲原生中扮演什麼角色?
  3. Istio 擴展了 Kubernetes 的哪些方面?解決了哪些問題?
  4. Kubernetes、Envoy(xDS 協議)與 Istio 之間又是什麼關係?
  5. 到底該不該上 Service Mesh?

本文試圖帶您梳理清楚 Kubernetes、Envoy(xDS 協議)以及 Istio Service Mesh 之間的關係及內在聯繫。本文介紹了 Kubernetes 中的負載均衡方式,Envoy 的 xDS 協議對於 Service Mesh 的意義以及爲什麼說有了 Kubernetes 還需要 Istio。

使用 Service Mesh 並不是說與 Kubernetes 決裂,而是水到渠成的事情。Kubernetes 的本質是通過聲明式配置對應用進行生命週期管理,而 Service Mesh 的本質是應用間的流量和安全性管理。假如你已經使用 Kubernetes 構建了穩定的微服務平臺,那麼如何設置服務間調用的負載均衡和流量控制?

Envoy 對於 Service Mesh 或者說 Cloud Native 最大的貢獻就是定義了 xDS,Envoy 雖然本質上是一個 proxy,但是它的配置協議被衆多開源軟件所支持,如 IstioLinkerdAWS App MeshSOFAMesh 等。

關於標題

2018年9月1日,Bilgin Ibryam 在 InfoQ 發表了一篇文章 Microservices in a Post-Kubernetes Era,中文版見後 Kubernetes 時代的微服務(譯文有些錯誤,僅供參考)。本文標題中雖然沒有明確指明”後 Kubernetes 時代的微服務“是什麼,但是從文中可以看出作者的觀點是:在後 Kubernetes 時代,服務網格(Service Mesh)技術已完全取代了使用軟件庫實現網絡運維(例如 Hystrix 斷路器)的方式。本文索性就借用該標題。

本節包含以下內容

  • 說明 kube-proxy 的作用。
  • Kubernetes 在微服務管理上的侷限性。
  • 介紹下 Istio Service Mesh 的功能。
  • 介紹下 xDS 包含哪些內容。
  • 比較了 Kubernetes、Envoy 和 Istio Service Mesh 中的一些概念。

重要觀點

如果你沒有心裏閱讀下文的所有內容,那麼可以先閱讀看下下面列出的本文中的一些主要觀點:

  • Kubernetes 的本質是應用的生命週期管理,具體說是部署和管理(擴縮容、自動恢復、發佈)。
  • Kubernetes 爲微服務提供了可擴展、高彈性的部署和管理平臺。
  • Service Mesh 的基礎是透明代理,通過 sidecar proxy 攔截到微服務間流量後再通過控制平面配置管理微服務的行爲。
  • Service Mesh 將流量管理從 Kubernetes 中解耦,Service Mesh 內部的流量無需 kube-proxy 組件的支持,通過爲更接近微服務應用層的抽象,管理服務間的流量、安全性和可觀察性。
  • Envoy xDS 定義了 Service Mesh 配置的協議標準。
  • Service Mesh 是對 Kubernetes 中的 service 更上層的抽象,它的下一步是 serverless。

閱讀本文之前

推薦大家在閱讀本文之前希望您對微服務、容器和 Kubernetes 有一定認識,如果您已經閱讀過以下幾篇文章將對您理解本文更有幫助,本文中也引用過了下面文章中的部分觀點。

Kubernetes vs Service Mesh

下圖展示的是 Kubernetes 與 Service Mesh 中的的服務訪問關係,本文僅針對 sidecar per-pod 模式,詳情請參考服務網格的實現模式

kubernetes vs service mesh

圖片 - kubernetes vs service mesh

Kubernetes 集羣的每個節點都部署了一個 kube-proxy 組件,該組件會與 Kubernetes API Server 通信,獲取集羣中的 service 信息,然後設置 iptables 規則,直接將對某個 service 的請求發送到對應的 Endpoint(屬於同一組 service 的 pod)上。

Istio Service Mesh 中沿用了 Kubernetes 中的 service 做服務註冊,通過 Control Plane 來生成數據平面的配置(使用 CRD 聲明,保存在 etcd 中),數據平面的透明代理(transparent proxy)以 sidecar 容器的形式部署在每個應用服務的 pod 中,這些 proxy 都需要請求 Control Plane 來同步代理配置,之所以說是透明代理,是因爲應用程序容器完全無感知代理的存在,該過程 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 一層抽離出來,可以做更多的擴展。

kube-proxy 組件

在 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 入口流量負載均衡

kube-proxy 的缺陷

在上面的鏈接中作者指出了 kube-proxy 的不足之處

首先,如果轉發的 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 上。

Kubernetes Ingress vs Istio Gateway

Kubernetes 中的 Ingress 資源對象跟 Istio Service Mesh 中的 Gateway 的功能類似,都是負責集羣南北流量(從集羣外部進入集羣內部的流量)。

kube-proxy 只能路由 Kubernetes 集羣內部的流量,而我們知道 Kubernetes 集羣的 Pod 位於 CNI 創建的外網絡中,集羣外部是無法直接與其通信的,因此 Kubernetes 中創建了 ingress 這個資源對象,它由位於 Kubernetes 邊緣節點(這樣的節點可以是很多個也可以是一組)的 Ingress controller 驅動,負責管理南北向流量(從集羣外部進入 Kubernetes 集羣的流量),Ingress 必須對接各種個 Ingress Controller 才能使用,比如 nginx ingress controllertraefik。Ingress 只適用於 HTTP 流量,使用方式也很簡單,只能對 service、port、HTTP 路徑等有限字段匹配來路由流量,這導致它無法路由如 MySQL、redis 和各種私有 RPC 等 TCP 流量。要想直接路由南北向的流量,只能使用 Service 的 LoadBalancer 或 NodePort,前者需要雲廠商支持而且可能需要付費,後者需要進行額外的端口管理。有些 Ingress controller 支持暴露 TCP 和 UDP 服務,但是隻能使用 Service 來暴露,Ingress 本身是不支持的,例如 nginx ingress controller,服務的暴露的端口是通過創建 ConfigMap 的方式來配置的。

Istio Gateway 描述的負載均衡器用於承載進出網格邊緣的連接。該規範中描述了一系列開放端口和這些端口所使用的協議、負載均衡的 SNI 配置等內容。Gateway 是一種 CRD 擴展,它同時複用了 Envoy proxy 的能力,詳細配置請參考 Istio 官網

xDS 協議

下面這張圖大家在瞭解 Service Mesh 的時候可能都看到過,每個方塊代表一個服務的示例,例如 Kubernetes 中的一個 Pod(其中包含了 sidecar proxy),xDS 協議控制了 Istio Service Mesh 中所有流量的具體行爲,即將下圖中的方塊鏈接到了一起。

Service Mesh 示意圖

圖片 - Service Mesh 示意圖

xDS 協議是由 Envoy 提出的,在 Envoy v2 版本 API 中最原始的 xDS 協議只指 CDS、EDS、LDS 和 RDS。

下面我們以兩個 service,每個 service 都有兩個實例的例子來看下 Envoy 的 xDS 協議。

Envoy xDS 協議

圖片 - Envoy xDS 協議

上圖中的箭頭不是流量在進入 Enovy Proxy 後的路徑或路由,而是想象的一種 Envoy 中 xDS 接口處理的順序並非實際順序,其實 xDS 之間也是有交叉引用的。

Envoy 通過查詢文件或管理服務器來動態發現資源。概括地講,對應的發現服務及其相應的 API 被稱作 xDS。Envoy 通過訂閱(subscription方式來獲取資源,訂閱方式有以下三種:

  • 文件訂閱:監控指定路徑下的文件,發現動態資源的最簡單方式就是將其保存於文件,並將路徑配置在 ConfigSource 中的 path 參數中。
  • gRPC 流式訂閱:每個 xDS API 可以單獨配置 ApiConfigSource,指向對應的上游管理服務器的集羣地址。
  • 輪詢 REST-JSON 輪詢訂閱:單個 xDS API 可對 REST 端點進行的同步(長)輪詢。

以上的 xDS 訂閱方式詳情請參考 xDS 協議解析。Istio 使用的 gRPC 流式訂閱的方式配置所有的數據平面的 sidecar proxy。

關於 xDS 協議的詳細分解請參考丁軼羣博士的這幾篇文章:

文章中介紹了 Istio pilot 的總體架構、Envoy 配置的生成、pilot-discovery 模塊的功能,以及 xDS 協議中的 CDS、EDS 及 ADS,關於 ADS 詳情請參考 Enovy 官方文檔

xDS 協議要點

最後總結下關於 xDS 協議的要點:

  • CDS、EDS、LDS、RDS 是最基礎的 xDS 協議,它們可以分別獨立更新的。
  • 所有的發現服務(Discovery Service)可以連接不同的 Management Server,也就是說管理 xDS 的服務器可以是多個。
  • Envoy 在原始 xDS 協議的基礎上進行了一些列擴充,增加了 SDS(祕鑰發現服務)、ADS(聚合發現服務)、HDS(健康發現服務)、MS(Metric 服務)、RLS(速率限制服務)等 API。
  • 爲了保證數據一致性,若直接使用 xDS 原始 API 的話,需要保證這樣的順序更新:CDS --> EDS --> LDS --> RDS,這是遵循電子工程中的先合後斷(Make-Before-Break)原則,即在斷開原來的連接之前先建立好新的連接,應用在路由裏就是爲了防止設置了新的路由規則的時候卻無法發現上游集羣而導致流量被丟棄的情況,類似於電路里的斷路。
  • CDS 設置 Service Mesh 中有哪些服務。
  • EDS 設置哪些實例(Endpoint)屬於這些服務(Cluster)。
  • LDS 設置實例上監聽的端口以配置路由。
  • RDS 最終服務間的路由關係,應該保證最後更新 RDS。

Envoy

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 注入及流量劫持,本文引用其中的一些觀點,詳細內容不再贅述。

Envoy proxy 架構圖

圖片 - Envoy proxy 架構圖

基本術語

下面是您應該瞭解的 Enovy 裏的基本術語:

  • Downstream(下游):下游主機連接到 Envoy,發送請求並接收響應,即發送請求的主機。
  • Upstream(上游):上游主機接收來自 Envoy 的連接和請求,並返回響應,即接受請求的主機。
  • Listener(監聽器):監聽器是命名網地址(例如,端口、unix domain socket 等),下游客戶端可以連接這些監聽器。Envoy 暴露一個或者多個監聽器給下游主機連接。
  • Cluster(集羣):集羣是指 Envoy 連接的一組邏輯相同的上游主機。Envoy 通過服務發現來發現集羣的成員。可以選擇通過主動健康檢查來確定集羣成員的健康狀態。Envoy 通過負載均衡策略決定將請求路由到集羣的哪個成員。

Envoy 中可以設置多個 Listener,每個 Listener 中又可以設置 filter chain(過濾器鏈表),而且過濾器是可擴展的,這樣就可以更方便我們操作流量的行爲,例如設置加密、私有 RPC 等。

xDS 協議是由 Envoy 提出的,現在是 Istio 中默認的 sidecar proxy,但只要實現 xDS 協議理論上都是可以作爲 Istio 中的 sidecar proxy 的,例如螞蟻金服開源的 SOFAMosn 和 nginx 開源的 nginmesh

Istio Service Mesh

Istio service mesh 架構圖

圖片 - Istio service mesh 架構圖

Istio 是一個功能十分豐富的 Service Mesh,它包括如下功能:

  • 流量管理:這是 Istio 的最基本的功能。
  • 策略控制:通過 Mixer 組件和各種適配器來實現,實現訪問控制系統、遙測捕獲、配額管理和計費等。
  • 可觀測性:通過 Mixer 來實現。
  • 安全認證:Citadel 組件做密鑰和證書管理。

Istio 中的流量管理

Istio 中定義瞭如下的 CRD 來幫助用戶進行流量管理:

  • Gateway:Gateway 描述了在網絡邊緣運行的負載均衡器,用於接收傳入或傳出的HTTP / TCP連接。
  • VirtualServiceVirtualService 實際上將 Kubernetes 服務連接到 Istio Gateway。它還可以執行更多操作,例如定義一組流量路由規則,以便在主機被尋址時應用。
  • DestinationRuleDestinationRule 所定義的策略,決定了經過路由處理之後的流量的訪問策略。簡單的說就是定義流量如何路由。這些策略中可以定義負載均衡配置、連接池尺寸以及外部檢測(用於在負載均衡池中對不健康主機進行識別和驅逐)配置。
  • EnvoyFilterEnvoyFilter 對象描述了針對代理服務的過濾器,這些過濾器可以定製由 Istio Pilot 生成的代理配置。這個配置初級用戶一般很少用到。
  • ServiceEntry:默認情況下 Istio Service Mesh 中的服務是無法發現 Mesh 外的服務的,ServiceEntry 能夠在 Istio 內部的服務註冊表中加入額外的條目,從而讓網格中自動發現的服務能夠訪問和路由到這些手工加入的服務。

Kubernetes vs Envoy xDS vs Istio

在閱讀完上文對 Kubernetes 的 kube-proxy 組件、Envoy xDS 和 Istio 中流量管理的抽象概念之後,下面將帶您僅就流量管理方面比較下三者對應的組件/協議(注意,三者不可以完全等同)。

Kubernetes Envoy 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 的功能也不只是做流量轉發,以上概念只不過是 Istio 在 Kubernetes 之上新增一層抽象層中的冰山一角,但因爲流量管理是服務網格最基礎也是最重要的功能,所以這將成爲本書的開始。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章