摘要:今年9月份,Istio社群宣佈Ambient Mesh開源,由此引發國內外眾多開發者的熱烈討論。
本文分享自華為雲社群《深度剖析!Istio共用代理新模式Ambient Mesh》,作者:華為云云原生團隊。
今年9月份,Istio社群宣佈Ambient Mesh開源,由此引發國內外眾多開發者的熱烈討論。實際上,通過與Istio TOC成員linsun(https://github.com/linsun)的交流,我們得知早在2021年,http://Solo.io已經開始共用代理的研究和設計,同樣也是在2021年Google內部也在探索共用代理模式。因此,兩家公司一拍即合,今年4~5月份開始以共同作業開發的方式,加速共用代理模式的發展。
目前Ambient Mesh已經發布預覽版本,感興趣的讀者可以按需體驗。由於篇幅限制,本文主要針對Ambient Mesh架構及四層流量治理的流程進行深度剖析,關於七層流量治理的詳解,請關注後續文章。
簡單來講,Ambient Mesh是Istio服務網格的一種共用代理的新模式。它是由 Google 和 http://Solo.io 聯合開發的一種新的資料面模式,旨在簡化操作、提升應用相容性並降低基礎設施成本。Ambient模式可在放棄引入 Sidecar 的情況下,保持 Istio 的零信任安全、流量管理和遙測等核心功能。
開始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彈性伸縮策略,不再與應用耦合,提供更加靈活的擴充套件性並可以在一定程度上提升資源的使用率。
我們知道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設定深入理解完整的通訊流程。
(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設定
(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設定
圖14 完整的服務存取四層代理
sleep存取productpage的範例中,雖然我們使用的是HTTP協定,但是從Ambient所有的元件視角來看,其代理的為TCP流量。前面我們深入分析了ztunnel中每一個監聽器、每一個Cluster的工作原理,看起來可能會很複雜。故在此通過圖14進行一個概要的總結,我們發現在通訊的過程中,實際參加工作的模組並不多:
Sidecar是 Istio 的特色,利用 Sidecar,對應用進行非常小的修改就可以享受服務網格帶來的好處,減少運維負擔;但是 Sidecar 模式也有一些限制:
當前 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的第二選擇。