深度剖析!Istio共享代理新模式Ambient Mesh

語言: CN / TW / HK

作者GitHub ID:@hzxuzhonghu @zirain

9月,Istio社群宣佈Ambient Mesh開源,由此引發國內外眾多開發者的熱烈討論。實際上,通過與Istio TOC成員linsun(https://github.com/linsun)的交流,我們得知早在2021年,Solo.io已經開始共享代理的研究和設計,同樣也是在2021年Google內部也在探索共享代理模式。因此,兩家公司一拍即合,今年4~5月份開始以協作開發的方式,加速共享代理模式的發展。

目前Ambient Mesh已經發布預覽版本,感興趣的讀者可以按需體驗。由於篇幅限制,本文主要針對Ambient Mesh架構及四層流量治理的流程進行深度剖析,關於七層流量治理的詳解,請關注後續文章。

Ambient Mesh 是什麼  

簡單來講,Ambient Mesh是Istio服務網格的一種共享代理新模式。它是由 Google 和 Solo.io 聯合開發的一種新的資料面模式,旨在簡化操作、提升應用相容性並降低基礎設施成本。Ambient模式可在放棄引入 Sidecar 的情況下,保持 Istio 的零信任安全、流量管理和遙測等核心功能。

Ambient Mesh架構分析  

開始Ambient的架構之前,我們先簡單回顧一下Istio 的架構。其主要由兩部分組成,分別是控制面和資料面。控制面Istiod進行基本的配置生成和推送,管理著所有的資料面;資料面引入 Sidecar 代理,接管應用的入口和出口流量。

圖1 Istio架構

相比Sidecar,Ambient Mesh提供一種侵入性更低,升級管理更簡單的選擇。Ambient 將 Istio 的功能分成兩個不同的層次,安全覆蓋層(四層治理)和七層處理層(七層治理):

圖2 Ambient Mesh分層

  • 安全覆蓋層: 處理TCP路由、監控指標、訪問日誌,mTLS 隧道,簡單的授權

  • 七層處理層: 除安全覆蓋層的功能外,提供HTTP協議的路由、監控、訪問日誌、呼叫鏈、負載均衡、熔斷、限流、重試等流量管理功能以及豐富的七層授權策略

Ambient Mesh下的負載可與 Sidecar 模式下的負載無縫互通,允許使用者根據自己的需要來混合搭配使用兩種模式。

▍四層治理架構

在 Sidecar 模式下,Istio 通過 InitContainer Istio-CNI 實現流量攔截。Ambient Mesh下 Istio-CNI 是必選元件,下圖展示了基本的 Ambient Mesh四層治理架構:

圖3  Ambient Mesh四層治理架構

Istio-CNI 中,新增 Ambient 的處理模組,該模組會監聽 Namespace 以及 Pod 的變化,為所在節點的應用設定路由和iptables規則:

  • 路由: 設定路由表,將本節點應用發出的流量路由到 ztunnel,以及將本節點接收的流量路由到ztunnel。

  • iptables: 在ztunnel容器中設定iptables規則,將流量透明攔截至 ztunnel 對應的埠上。

ztunnel 是 Ambient 新引入的元件,以 Daemonset 的方式部署在每個節點上。ztunnel 為網格中的應用通訊提供 mTLS、遙測、身份驗證和 L4授權功能,不執行任何七層協議相關的處理。只有當ztunnel執行在工作負載相同的節點上時,控制面才會將工作負載證書頒發給該 ztunnel。因此 當ztunnel 被攻擊時,只有執行在該節點上的負載的證書可能被盜用,安全風險相對可控,這和其他實現良好的節點共享基礎設施類似。

七層流量治理架構

目前 Ambient Mesh需要通過定義一個 Gateway API 資源顯式對某個服務啟用七層處理。下圖展示了Ambient七層治理的架構:

圖4  Ambient Mesh七層治理架構

與Ambient四層治理相比,七層治理架構中新增了waypoint元件。Pilot 中新增了waypoint 的處理模組, 它監聽 ServiceAccount、Deployment、Gateway API物件的變化,然後調協相關的 waypoint物件:

  • ServiceAccount發生變化時,Pilot會嘗試更新當前名稱空間下所有的 waypoint

  • Deployment發生變化時,通過其OwnerReference 關聯的 Gateway物件,觸發waypoint的維護

  • Gateway發生變化時,更新關聯的 waypoint 代理

當前 Ambient建立 waypoint 代理需要依賴類似下面的Gateway API 資源 :

apiVersion: gateway.networking.k8s.io/v1alpha2
kind: Gateway
metadata:
name: productpage
annotations:
istio.io/service-account: bookinfo-productpage
spec:
gatewayClassName: istio-mesh

gatewayClassName 值必須設定為 istio-mesh,否則可能會被忽略。每個 ServiceAccount 都有自己專用的 waypoint 代理,這點與 Sidecar 模型非常相似。建議每個服務使用自己單獨的身份,避免帶來額外的安全風險。

Pilot會將 七層 流量規則通過 xDS 更新至 waypoint 代理,實現 七層 相關流量治理能力。waypoint 代理不一定保證與其所服務的工作負載位於同一節點,這似乎會帶來一定的效能問題。但是對於 Istio 來說,延遲更多來自於複雜的 七層 處理,預計最終Ambient模式的七層治理延遲與 Sidecar 模式接近。waypoint 代理通過單獨Deployment部署,因此可為其單獨配置所需要的 CPU、記憶體,設定相關 的HPA彈性伸縮策略,不再與應用耦合,提供更加靈活的擴充套件性並可以在一定程度上提升資源的使用率。

Ambient Mesh四層流量治理  

我們知道ztunnel只能進行四層的流量治理,四層負載均衡以及TLS流量加密、基本的認證和鑑權等,而不能進行更高階的七層路由和認證鑑權。這裡我們通過sleep應用訪問bookinfo的例子,深入理解Ambient Mesh的四層流量是如何路由的。本例子的實際環境背景如下,sleep和productpage應用分別執行在兩個不同的節點。

圖5 Ambient Mesh四層流量代理流程

  • 在sleep容器內訪問productpage服務,首先請求被攔截到同節點的ztunnel中,ztunnel做基本的四層負載均衡和TLS加解密,最後選擇一個目標例項(productpage容器的IP)將本次請求轉發出去。

  • 本次請求進入productpage容器所在的節點,首先被攔截到ztunnel, ztunnel負責TLS流量的解密,然後執行使用者指定的鑑權策略,最後將請求發往productpage容器。

以上就是Ambient Mesh流量轉發的一個基本流程,下面我們結合具體的xDS配置深入理解完整的通訊流程。

▍3.1 sleep傳送側流量處理

1. sleep訪問productpage的流量被同節點的tunnel以TPROXY(透明代理)方式攔截轉發到ztunnel(監聽127.0.0.1:15001),使用TPROXY的好處是保留原始的目的地址,ztunnel做轉發時必須依賴原始目的地址。

-A PREROUTING -i pistioout -p tcp -j TPROXY --on-port 15001 --on-ip 127.0.0.1 --tproxy-mark 0x400/0xfff

2. ztunnel通過"ztunnel_outbound"監聽器,監聽在15001埠。ztunnel_outbound監聽器與Istio Sidecar模式的監聽器完全不同,它包含所有本節點上的服務到整個網格其他服務的過濾器鏈。

圖6 ztunnel_outbound監聽器

可以看到所有的過濾器鏈都沒有設定匹配條件(預設全部匹配),那麼這時ztunnel怎麼根據流量特徵選擇目標過濾器鏈的呢?原來在監聽器根上還有一種設定過濾器匹配條件的方式,通過下面匹配到源地址為10.244.1.4,目的地址為10.96.179.71,目的埠為9080的流量,交由

" spiffe://cluster.local/ns/default/sa/sleep_to_http_productpage.default.svc.cluster.local_outbound_internal "過濾器處理。

圖7 ztunnel_outbound過濾器鏈匹配

3." spiffe://cluster.local/ns/default/sa/sleep_to_http_productpage.default.svc.cluster.local_outbound_internal "過濾器關聯到同名的Cluster。該Cluster一共包含兩個Endpoint例項,根據負載均衡演算法選擇某一個Endpoint,並且最重要的是將metadata(tunnel的destination和address)傳遞給名為" outbound_tunnel_lis_spiffe://cluster.local/ns/default/sa/bookinfo-productpage " 的監聽器處理。

圖8 outbound_internal內部Cluster配置

圖9 outbound_internal內部Cluster Endpoint

4. “ outbound_tunnel_lis_spiffe://cluster.local/ns/default/sa/slee p”監聽器通過“ set_dst_address ”過濾器根據上一步的選擇的Endpoint的metadata設定資料的目的地址。假如前面 outbound_internal Cluster 選擇的是 10.244.2.8:9080這個Endpoint ,那麼這裡的tunnel監聽器將把10.244.2.8:15008設定為目的地址。另外該監聽器,只有一個 TcpProxy ,關聯到名為

outbound_tunnel_clus_spiffe://cluster.local/ns/default/sa/ sleep ”的Cluster,那麼流量自然交由該Cluster處理。TCP過濾器上還設定了HTTP Connect隧道(承載傳送到 10.244.2.8:9080 的流量),供後面productpage所在節點的ztunnel使用。HTTP隧道是Ambient Mesh 元件之間安全通訊的承載協議。

圖10 outbound_tunnel監聽器配置

outbound_tunnel Cluster 的型別為“ ORIGINAL_DST ”,並且配置有 UpstreamTlsContext , 因此它負責流量TLS加密,然後直接傳送到目的地址,即 10.244.2.8:15008

圖11 outbound_tunnel cluster配置

▍3.2 productpage接收側流量處理

1. sleep訪問productpage的流量(目的地址是“10.244.2.8:15008”)到達productpage所在的節點,以TPROXY(透明代理)方式被攔截到ztunnel(監聽127.0.0.1:15008),使用TPROXY的好處是保留原始的目的地址,ztunnel做轉發時必須依賴原始目的地址。

10.244.2.8 via 192.168.126.2 dev istioin table 100 src 10.244.2.1


-A PREROUTING -i pistioin -p tcp -m tcp --dport 15008 -j TPROXY --on-port 15008 --on-ip 127.0.0.1 --tproxy-mark 0x400/0xfff

2. ztunnel上面“ztunnel_inbound”監聽器監聽在15008埠,因此流量首先經過ztunnel_inbound監聽器的處理。ztunnel_inbound監聽器上面設定了TLS,根據其配置與下游進行TLS握手,從而所有的ztunnel之間基於雙向TLS加密通訊。另外,從下面配置中可以看到,CONNECT 升級已經設定,那麼Envoy就會代理HTTP的Connect請求。除此之外,RouteMatch中設定了connectMatcher,意味著將HTTP Connect請求交由“virtual_inbound”Cluster處理。

圖12 ztunnel_inbound監聽器配置

3. virtual_inbound Cluster型別為ORIGINAL_DST,並且設定使用 x-envoy-original-dst-host HTTP Header重寫原始目的地址,而此Header恰恰由傳送側的“ outbound_tunnel_lis_spiffe://cluster.local/ns/default/sa/sleep ”監聽器設定,值為10.244.2.8:9080。因此本次請求通過virtual_inbound最終成功傳送給productpage容器。

圖13 virtual_inbound cluster配置

▍3.3 Ambient Mesh四層流量治理小結

圖14 完整的服務訪問四層代理

sleep訪問productpage的例項中,雖然我們使用的是HTTP協議,但是從Ambient所有的元件視角來看,其代理的為TCP流量。前面我們深入分析了ztunnel中每一個監聽器、每一個Cluster的工作原理,看起來可能會很複雜。故在此通過圖14進行一個概要的總結,我們發現在通訊的過程中,實際參加工作的模組並不多:

  1. 傳送側的路由、iptables:將流量攔截到ztunnel的15001埠

  2. 傳送側ztunnel:兩個監聽器和對應的兩個cluster

  3. 接收側的路由、iptables:將流量攔截到ztunnel的15008埠

  4. 接收ztunnel:virtual_inbound監聽器及關聯的cluster

未來展望  

Sidecar是 Istio 的特色,利用 Sidecar,對應用進行非常小的修改就可以享受服務網格帶來的好處,減少運維負擔。但是 Sidecar 模式也有一些限制:

1.侵入性: Sidecar 容器是以Admission Webhook的方式來注入,與應用容器屬於同一個Pod,因此Sidecar的升級,必須伴隨著業務容器的重建。對應用負載來可能是破壞性的(例如:長連線場景下滾動升級可能造成浪湧)。

2.資源利用率低: Sidecar 與應用一一對應,且必須預留足夠的CPU和記憶體,可能導致整個叢集資源利用率偏低;彈性擴縮容只能針對整個工作負載進行,無法單獨對 Sidecar 進行。

3. 流量中斷: 流量的捕獲和 HTTP 處理由 Sidecar 完成,成本高且可能破壞一些不相容 HTTP 的實現。

當前 Ambient Mesh已經較好地解決了 Sidecar 模式下應用和 Sidecar 的部署依賴問題,不再需要注入Sidecar;服務網格的能力是通過 ztunnel 和 waypoint proxy 提供的,應用和網格元件的部署和升級不再相互依賴。

另外,Ambient共享模式可以大大減少網格元件本身的資源開銷,這一點對資源敏感的使用者來說是一個巨大的福音。

但是Ambient目前仍處於預覽狀態,許多特性還在開發中,在官方文件中已經列出不少限制,此外,社群使用者在使用過程中也有新的發現:

  • 不支援IPV6

  • 與Calico CNI不相容,因為Ambient建立的iptables與Calico衝突

同時,目前基於 envoy 的 ztunnel 在 xDS 效率、多租戶、遙測方面可能存在效能問題,未來可能會基於rust重寫一個更加輕量、高效能的ztunnel。

長期來看,Sidecar模式依然會是Istio的主流模式。Ambient共享模式為Istio社群或者服務網格業界帶來了足夠的刺激,相信基於社群所有開發者的共同努力,Ambient共享模式將會成為Istio的第二選擇。