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

語言: CN / TW / HK
摘要:今年9月份,Istio社區宣佈Ambient Mesh開源,由此引發國內外眾多開發者的熱烈討論。

本文分享自華為雲社區《深度剖析!Istio共享代理新模式Ambient Mesh》,作者:華為云云原生團隊。

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

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

1.Ambient Mesh 是什麼

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

2.Ambient Mesh架構分析

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

圖1 Istio架構

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

圖2 Ambient mesh分a層

 安全覆蓋層:處理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彈性伸縮策略,不再與應用耦合,提供更加靈活的擴展性並可以在一定程度上提升資源的使用率。

3.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/sleep”監聽器通過“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

4. 未來展望

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的第二選擇。

 

點擊關注,第一時間瞭解華為雲新鮮技術~