Kubernetes:Ingress總結(二)

Blog:部落格園 個人
參考:Ingress | Kubernetes、《Kubernetes進階實戰》

Contour是Kubernetes Ingress控制器的另一款開源實現,它以高性能的Envoy代理程式作為數據平面,支援開箱即用的動態配置和多種高級路由機制,支援TCP代理,並且提供了自定義資源類型HTTPProxy資源以擴展IngressAPI,以更豐富的功能集部分解決了Ingress原始設計中的缺點,是Ingress控制器較為出色的實現之一。

Contour Ingress controller 由兩個組件組成:

  • Envoy : 提供高性能反向代理。
  • Contour : 充當 Envoy 的控制平面,為 Envoy 的路由配置提供統一的來源。

image-20220321134850499

官方文檔提供了部署方法:Getting Started with Contour (projectcontour.io)

Envoy

Envoy是專為大型現代SOA架構設計的應用代理和通訊匯流排,使用C++語言編寫,是高性能的HTTP/HTTPS協議代理,支援負載均衡、超時、重試、熔斷、限流和回退等多種高級路由功能,支援HTTP/2和gRPC,而且能夠作為HTTP/1.1和HTTP/2之間的雙向透明代理機制。Envoy原生支援動態配置和服務發現機制,能夠通過xDS API從控制平面(管理伺服器)獲取配置資訊,同時提供了良好的可觀測性,未來甚至會作為UPDA(Universal Data Plane API)的標準實現之一。

作為代理服務,Envoy使用「偵聽器」(listener)維護與下遊客戶端的連接,使用集群管理器管理上游伺服器集群,並根據偵聽器上配置的代理層級和路由策略「橋接」客戶端與後端伺服器。它支援配置任意數量的偵聽器和任意數量的上游集群,這些配置可使用靜態方式指定,也可分別基於不同的服務發現API動態生成。

image-20220321135105225

Envoy通過偵聽器監聽網路套接字以接收客戶端請求,並且支援在一個進程上啟用任意數量的偵聽器,從而賦予用戶按需配置Envoy監聽一至多個套接字的能力。每個偵聽器都應獨立配置一些網路(L3/L4)過濾器,在接收到請求後,偵聽器負責實例化指定過濾器鏈中的各個過濾器,並由這些過濾器處理後續的相關事件。一般說來,用戶可根據不同的過濾器鏈配置偵聽器以完成不同代理任務,例如HTTP代理、TCP代理、TLS客戶端認證、限速等。

HTTP是現代面向服務的架構中至關重要的組件,因此Envoy通過名為HTTP連接管理器的網路(L3/L4)過濾器實現HTTP協議的應用層代理,內置支援HTTP/1.1、WebSockets和HTTP/2幾類協議。另外,Envoy在傳輸層和應用層分別提供了對gRPC協議的原生支援,gRPC是來自Google的RPC框架,它基於HTTP/2構建和傳遞請求/響應報文。Envoy內置的HTTP過濾器中的Router負責為HTTP代理實現高級路由功能,包括將DNS域映射到特定的虛擬主機、URL重定向、URL重寫、重試、超時、基於權重或百分比進行流量分發、基於優先順序的路由和基於哈希策略的路由等。Envoy通過配置的路由資訊生成路由表,並由Router過濾器據此做出路由決策。

每個上游伺服器可由一個稱為端點的邏輯組件進行標識,它代表著此服務監聽的套接字,因此也可直接作為上游服務的標識符使用。一個集群可以包含一到多個端點,而一個端點也可隸屬於一到多個集群。

Envoy的集群管理器負責管理配置的所有上游集群,包括獲知上游主機健康可用狀態、負載狀態、連接類型以及適用的上游通訊協議(HTTP/1.1、HTTP/2)等,並向前端的過濾器堆棧暴露API,允許過濾器根據請求及處理結果按需建立與上游集群的L3/L4或L7的通訊連接。一旦在配置中定義了集群,集群管理器需要知道如何解析集群中的成員,即端點配置資訊。目前,Envoy支援的端點配置支援包括靜態配置、嚴格DNS、邏輯DNS、原始目標和EDS幾種。集群管理器可通過純靜態的配置資訊載入並初始化集群,也可通過集群發現服務(Cluster Discovery Service,CDS)API動態獲取相關的配置,而後一種方式允許將配置資訊存儲在集中式的配置服務中,從而減少重啟Envoy或重新分發配置的次數。

服務發現是面向服務架構的基石。為了更好地適配雲原生環境,Envoy內置了一個層次化的動態配置API用於集中式管理配置資訊,該API可藉助服務發現服務(Service Discovery Service,即服務發現自身作為一種服務)機制支援多種服務發現方式,從而為Envoy提供以下配置資訊的動態發現和更新。

  • 端點發現服務(Endpoint Discovery Service,EDS):用於為Envoy動態添加、更新和刪除Service端點,這些端點通常是指上游集群後端提供特定服務的主機的套接字;EDS事實上是v1時代的SDS(Service Discovery Service)的替代品,而且,SDS在v2版本中專用於指代Secret Discovery Service。
  • 集群發現服務(Cluster Discovery Service,CDS):用於動態添加、更新和刪除Upstream集群,其中,每個集群本身都有自己的端點發現(v1版本中的服務發現)機制。
  • 路由發現服務(Route Discovery Service,RDS):用於動態添加或更新HTTP路由表。
  • 密鑰發現服務(Secret Discovery Service,SDS):傳遞TLS密鑰資訊,從而LDS/ CDS能將主要偵聽器和集群配置通過密鑰管理系統與密鑰資訊在傳送時相分離。
  • 偵聽器發現服務(Listener Discovery Service,LDS):用於動態添加、更新和刪除整個偵聽器,包括其完整的L4或L7過濾器堆棧。
  • 健康發現服務(Health Discovery Service,HDS):配置Envoy成為分散式健康狀態檢查網路的成員,負責將健康狀態檢查的相關資訊報告給上級或集中式的健康狀態檢查服務。
  • 聚合發現服務(Aggregated Discovery Service,ADS):構建在單個EnvoyAPI提供的數據平面服務之上的多個管理API(例如Istio、Linkerd等);同時操作Envoy API時,使用單個管理伺服器處理單個Envoy的所有更新操作有助於確保Envoy的數據一致性;此API允許所有其他API通過單個管理伺服器的單個gRPC雙向流進行編組,從而實現確定性排序。
  • 另外還有ALS(gRPC Access Log Service)、RTDS(Runtime DiscoveryService)、RLS(Rate Limit Service)和CSDS(Client Status DiscoveryService)等,這些API統稱為xDS,相較於v1版本來說,它是一種新的REST-JSON API,其中JSON/YAML格式是基於proto3規範的JSON映射機制派生而來的。另外,xDS API通過gRPC流式傳輸進行更新,該方式有著較低資源需求,因而能降低更新延遲。

HTTPProxy

除了能實現類似於Ingress資源的流量分發等基礎功能,HTTPProxy還封裝了Envoy相當一部分高級路由功能的API,例如基於標頭的路由、流量鏡像和流量分割等多種高級路由功能,能幫助用戶實現諸如金絲雀部署、藍綠部署和A/B測試等功能。

HTTPProxy支援在單個路由規則中同時指定多個後端服務,默認情況下,所有流量將以等量切分的方式平均分發到多個後端之上,每個後端內部再按照代理伺服器配置的調度演算法進行二級負載均衡。同時,HTTPProxy也允許用戶為每個後端服務使用weight欄位指定一個特定流量百分比,從而將流量以指定的比例在不同的後端服務間進行分發。

image-20220321140330336

基於流量分割的流量切分是完成灰度發布的常用手段。上線應用的新版本時,無論是出於產品穩定性還是用戶接受程度等因素的考慮,直接以新代舊都充滿風險。因此,灰度發布是應用程式在生產環境安全上線的一種重要手段,而對於Envoy來說,灰度發布僅是其流量治理功能的一種典型應用,結合分割策略便能實現常見的金絲雀部署、藍綠部署和A/B測試等應用場景。

事實上,基於標頭的流量分割算是「基於請求內容」灰度部署的一種實現,而流量分割則是「基於流量比例」進行灰度部署的方式。與Kubernetes的Deployment控制器的滾動更新機制相比,HTTPProxy允許用戶按需指定要切分的流量比例,而非按照Pod數量來固定分割的方式。

HTTPProxy中的負載均衡策略是路由規則中的定義,每個路由規則都可以為其後端調用的服務按需指定最為合用的負載均衡機制。目前,HTTPProxy暴露了Envoy在集群上支援的部分調度演算法,主要有如下幾個。

  • RoundRobin:按順序輪詢選擇上游端點,此為默認策略。
  • WeightedLeastRequest:加權最少連接,但該演算法僅隨機選擇兩個健康的端點,並從中挑選出負載少的端點作為調度目標。
  • Random:從後端健康端點中隨機挑選端點。
  • Cookie:粘性會話調度機制,把來自某客戶端的所有請求始終調度給同一個後端端點。

工作原理

Contour 同時支援 Ingress 資源對象和 IngressRoute 資源對象(通過 CRD 創建),這些對象都是為進入集群的請求提供路由規則的集合。這兩個對象的結構和實現方式有所不同,但它們的核心意圖是相同的,都是為進入集群的請求提供路由規則。如不作特殊說明,後面當我們描述 「Ingress」 時,它將同時適用於 IngressIngressRoute 對象。

通常情況下,當 Envoy 配置了 CDS 的 endpoint 時,它會定期輪詢端點,然後將返回的 JSON 片段合併到其運行配置中。如果返回到 Envoy 的集群配置代表當前的 Ingress 對象的集合,則可以將 Contour 視為從 Ingress 對象到 Envoy 集群配置的轉換器。隨著 Ingress 對象的添加和刪除,Envoy 會動態添加並刪除相關配置,而無需不斷重新載入配置。

在實踐中,將 Ingress 對象轉換為 Envoy 配置更加微妙,需要將 Envoy 中的 xDS 配置(包括 CDSEDSRDS)映射到 Kubernetes 中。Contour 至少需要觀察 IngressServiceEndpoint 這幾個資源對象以構建這些服務的響應,它通過 client-gocache/informer 機制免費獲得這些 watchers。這些 watchers 提供添加,更新和刪除對象的邊緣觸發通知,也可以通過 watch API 在本地快取快取對象,以便後續查詢。

Contour 將收集到的這些對象處理為虛擬主機及其路由規則的有向非循環圖(DAG),這表明 Contour 將有權構建路由規則的頂級視圖,並將群集中的相應服務和TLS秘鑰連接在一起。一旦構建了這個新的數據結構,我們就可以輕鬆實現 IngressRoute 對象的驗證,授權和分發。改數據結構導出的 png 圖片如下圖所示:

img

Envoy API 調用和 Kubernetes API 資源之間的映射關係如下:

  • CDS : 集群發現服務。映射為 Kubernetes 中的 Service 以及一部分 Ingress 對象的 TLS 配置。
  • EDS : 服務發現服務。映射為 Kubernetes 中的 Endpoint。Envoy 使用 EDS 自動獲取 Cluster 成員,這與 Endpoint 對象中包含的資訊非常匹配。Envoy 使用 Contour 在 EDS 響應中返回的名稱查詢 EDS
  • RDS : 路由發現服務。映射為 Kubernetes 中的 Ingress。提供了虛擬主機名和前綴路由資訊的 RDS 與 Ingress 匹配得更好。

總結

基於Kubernetes內置的Ingress發布服務時,底層使用的是IngressNginx還是Contour控制器並沒有本質上的區別。但Contour提供的CRD資源類型HTTPProxy能夠提供更為完整的路由功能集,大大豐富了Ingress的特性表現。HTTPProxy封裝了Envoy的部分API,從而支援流量切分、流量鏡像、基於標頭的路由、自定義使用的負載均衡策略、超時和重試、後端端點的健康狀態檢測等高級功能。