成熟的 Istio Ambient:跨各種 Kubernetes 供應商和 CNI 的相容性

工作負載 Pod 和 ztunnel 之間創新的流量重新導向機制。

2024 年 1 月 29 日 | 作者:Ben Leggett - Solo.io、Yuval Kohavi - Solo.io、Lin Sun - Solo.io

Istio 專案在 2022 年宣布了 ambient mesh - 其新的無 Sidecar 資料平面模式,並在 2023 年初發布了 alpha 實作

我們的 alpha 版本專注於在有限的配置和環境下驗證 ambient 資料平面模式的價值。然而,條件非常有限。Ambient 模式依賴於在工作負載 Pod 和 ztunnel 之間透明地重新導向流量,而我們最初使用的機制與幾種第三方容器網路介面 (CNI) 實作發生衝突。透過 GitHub 問題和 Slack 討論,我們了解到使用者希望能夠在 minikubeDocker Desktop 中使用 ambient 模式,以及使用 CiliumCalico 等 CNI 實作,並在內部提供 CNI 實作的服務(如 OpenShiftAmazon EKS)上使用。對於 ambient mesh 來說,獲得 Kubernetes 的廣泛支援已成為進入 beta 版的首要要求 — 人們期望 Istio 能夠在任何 Kubernetes 平台上以及與任何 CNI 實作一起使用。畢竟,如果不能隨處可用,ambient 就稱不上 ambient!

在 Solo,我們一直將 ambient 模式整合到我們的 Gloo Mesh 產品中,並針對這個問題提出了一個創新的解決方案。我們決定在 2023 年底上游我們的變更,以幫助 ambient 更快達到 beta 版,以便更多使用者可以在 Istio 1.21 或更新版本中操作 ambient,並在他們的平台上享受無 sidecar ambient mesh 的好處,而無論他們現有或偏好的 CNI 實作是什麼。

我們是如何走到這一步的?

服務網格和 CNI:情況很複雜

Istio 是一個服務網格,而所有服務網格嚴格來說都不是CNI 實作 - 服務網格需要每個 Kubernetes 叢集中都存在一個符合規格的主要 CNI 實作,並在其之上運作。

此主要 CNI 實作可能由您的雲端供應商提供(AKS、GKE 和 EKS 都提供自己的實作),或由 Calico 和 Cilium 等第三方 CNI 實作提供。有些服務網格也可能捆綁了自己的主要 CNI 實作,而它們明確要求該實作才能運作。

基本上,在您可以使用 mTLS 保護 Pod 流量並在服務網格層套用高階驗證和授權策略之前,您必須擁有一個功能完善的 Kubernetes 叢集,以及一個功能完善的 CNI 實作,以確保設定基本的網路路徑,使封包能夠從叢集中的一個 Pod 傳送到另一個 Pod(以及從一個節點傳送到另一個節點)。

雖然有些服務網格也可能提供並要求它們自己的內部主要 CNI 實作,而且有時可以在同一個叢集中並行執行兩個主要 CNI 實作(例如,一個由雲端供應商提供,另一個是第三方實作),但實際上,這會導致一系列相容性問題、奇怪的行為、功能集減少,以及由於每個 CNI 實作可能在內部採用的機制差異很大而造成的一些不相容性。

為了避免這種情況,Istio 專案選擇不提供或要求我們自己的主要 CNI 實作,甚至不要求「偏好的」CNI 實作 - 而是選擇支援與最廣泛的 CNI 實作生態系統進行 CNI 鏈接,並確保與託管產品的最大相容性、跨供應商支援以及與更廣泛的 CNCF 生態系統的組合性。

Ambient alpha 中的流量重新導向

istio-cni 元件是 sidecar 資料平面模式中的可選元件,通常用於消除使用者將 Pod 部署到網格時對 NET_ADMINNET_RAW 功能的需求istio-cni 是 ambient 資料平面模式中的必要元件。istio-cni 元件不是主要 CNI 實作,它是一個節點代理程式,用於擴充叢集中已有的任何主要 CNI 實作。

每當將 Pod 新增到 ambient mesh 時,istio-cni 元件會透過節點層級的網路命名空間,設定所有 Pod 與執行在 Pod 節點上的 ztunnel 之間的所有傳入和傳出流量的重新導向。sidecar 機制和 ambient alpha 機制的關鍵區別在於,後者 Pod 流量會重新導向出 Pod 網路命名空間,並進入共置的 ztunnel Pod 網路命名空間 - 必須經過主機網路命名空間,這也是實作此目的的大部分流量重新導向規則的地方。

當我們在多個具有自己預設 CNI 的實際 Kubernetes 環境中進行更廣泛的測試時,很明顯,在主機網路命名空間中捕獲和重新導向 Pod 流量(就像我們在 alpha 開發期間所做的那樣)將無法滿足我們的要求。使用這種方法,在這些不同的環境中以通用方式實現我們的目標根本不可行。

在主機網路命名空間中重新導向流量的基本問題在於,這正是叢集主要 CNI 實作必須設定流量路由/網路規則的位置。這造成了不可避免的衝突,最嚴重的是

雖然我們可以針對某些主要 CNI 實作按個案設計解決方案,但我們無法以永續的方式實現通用的 CNI 支援。我們考慮了 eBPF,但意識到任何 eBPF 實作都會遇到相同的基本問題,因為目前沒有標準化的方式可以安全地鏈結/擴充任意 eBPF 程式,而且我們仍然可能難以使用這種方法支援非 eBPF CNI。

解決挑戰

必須有一個新的解決方案 - 在節點的網路命名空間中進行任何形式的重新導向都會造成不可避免的衝突,除非我們犧牲我們的相容性要求。

在 sidecar 模式中,在 sidecar 和應用程式 Pod 之間設定流量重新導向很簡單,因為兩者都在 Pod 的網路命名空間中運作。這帶來了一個靈光一閃的想法:為什麼不模仿 sidecar,並在應用程式 Pod 的網路命名空間中設定重新導向?

雖然這聽起來像是個「簡單」的想法,但這怎麼可能呢?ambient 的一個關鍵要求是 ztunnel 必須在應用程式 Pod 之外的 Istio 系統命名空間中執行。經過一些研究,我們發現一個在一個網路命名空間中執行的 Linux 程序可以在另一個網路命名空間中建立和擁有監聽套接字。這是 Linux 套接字 API 的基本功能。但是,為了讓這在操作上可行並涵蓋所有 Pod 生命週期場景,我們必須對 ztunnel 以及 istio-cni 節點代理程式進行架構變更。

在原型設計和充分驗證這種新方法適用於我們所能存取的所有 Kubernetes 平台之後,我們對這項工作建立了信心,並決定向上游貢獻這種新的流量重新導向模型,這是一個在 Pod 內的工作負載 Pod 和 ztunnel 節點代理元件之間的流量重新導向機制,該機制從頭開始建構,與所有主要的雲端供應商和 CNI 高度相容。

關鍵的創新是將 Pod 的網路命名空間傳遞給共置的 ztunnel,以便 ztunnel 可以 Pod 的網路命名空間內啟動其重新導向套接字,同時仍然在 Pod 外部執行。使用這種方法,ztunnel 和應用程式 Pod 之間的流量重新導向方式與今天的 sidecar 和應用程式 Pod 非常相似,並且對於在節點網路命名空間中運作的任何 Kubernetes 主要 CNI 嚴格不可見。無論 CNI 使用 eBPF 還是 iptables,任何 Kubernetes 主要 CNI 都可以繼續強制執行和管理網路策略,而不會發生任何衝突。

Pod 內流量重新導向的技術深入探討

首先,讓我們複習一下封包如何在 Kubernetes 中在 Pod 之間傳輸的基本知識。

Linux、Kubernetes 和 CNI - 什麼是網路命名空間,為什麼它很重要?

在 Linux 中,容器是在隔離的 Linux 命名空間中執行的一個或多個 Linux 程序。Linux 命名空間只是一個核心旗標,用於控制在該命名空間內執行的程序能夠看到什麼。例如,如果您透過 ip netns add my-linux-netns 命令建立一個新的 Linux 網路命名空間,並在其中執行一個程序,則該程序只能看到在該網路命名空間內建立的網路規則。它看不到任何在其外部建立的網路規則 - 即使該機器上執行的所有內容仍然共用一個 Linux 網路堆疊。

Linux 命名空間在概念上與 Kubernetes 命名空間很相似 - 組織和隔離不同活動程序的邏輯標籤,並允許您建立關於特定命名空間中的內容可以看見什麼以及對其套用哪些規則的規則 - 它們只是在更低的層級上運作。

當在網路命名空間中執行的程序建立一個發往其他位置的 TCP 封包時,該封包必須首先由本機網路命名空間中的任何本機規則處理,然後離開本機網路命名空間,進入另一個命名空間。

例如,在沒有安裝任何網格的普通 Kubernetes 中,Pod 可能會建立一個封包並將其傳送到另一個 Pod,而該封包可能會(取決於網路的設定方式)

在 Kubernetes 中,容器執行期介面 (CRI) 負責與 Linux 核心溝通、為新的 Pod 建立網路命名空間,並在其中啟動程序。接著,CRI 會調用容器網路介面 (CNI),其負責在各種 Linux 網路命名空間中設定網路規則,以便讓進出新 Pod 的封包能夠到達它們應該去的地方。對於 Kubernetes 或容器執行期來說,CNI 使用何種拓撲或機制來完成此任務並不重要 - 只要封包到達它們應該去的地方,Kubernetes 就能正常運作,一切都沒問題。

我們為什麼要放棄先前的模型?

在 Istio 環境網格中,每個節點至少有兩個容器作為 Kubernetes DaemonSet 執行

在先前的環境網格實作中,這是將應用程式 Pod 加入到環境網格的方式

這表示對於環境網格中 Pod 建立的封包,該封包會離開來源 Pod,進入節點的主機網路命名空間,然後理想情況下會被攔截並重新導向到該節點的 ztunnel (在其自身的網路命名空間中執行),以便代理到目的地 Pod,而回程的過程也類似。

這種模型對於初始環境網格 alpha 實作來說,作為一個佔位符效果還不錯,但正如前面提到的,它有一個根本性的問題 - CNI 實作有很多種,而在 Linux 中,您可以透過許多根本不同且不相容的方式來設定封包如何從一個網路命名空間傳輸到另一個網路命名空間。您可以使用通道、覆蓋網路、通過主機網路命名空間或繞過它。您可以通過 Linux 使用者空間網路堆疊,或者您可以跳過它,並在核心空間堆疊中來回傳輸封包等等。對於每種可能的方法,可能都有一個 CNI 實作正在使用它。

這意味著使用先前的重新導向方法,有許多 CNI 實作根本無法與環境網格協同運作。由於它依賴主機網路命名空間封包重新導向 - 任何不透過主機網路命名空間路由封包的 CNI 都需要不同的重新導向實作。即使對於那些確實這樣做的 CNI,我們也會遇到不可避免且可能無法解決的衝突主機層級規則的問題。我們是在 CNI 之前攔截還是之後攔截?如果我們這樣做或那樣做,並且它們沒有預期到這種情況,某些 CNI 會中斷嗎?由於網路原則必須在主機網路命名空間中執行,因此網路原則在哪裡以及何時執行?我們是否需要大量的程式碼來為每個流行的 CNI 進行特殊處理?

Istio 環境流量重新導向:新模型

在新環境模型中,這是將應用程式 Pod 加入到環境網格的方式

這是一個基本圖表,顯示應用程式 Pod 加入到環境網格的流程

pod added to the ambient mesh flow

一旦 Pod 成功加入到環境網格中,網格中 Pod 之間的所有流量預設都會使用 mTLS 完全加密,這與 Istio 的慣例相同。

現在,流量將以加密流量的形式進出 Pod 網路命名空間 - 看起來環境網格中的每個 Pod 都具有強制執行網格策略並安全地加密流量的能力,即使在 Pod 中執行的使用者應用程式對兩者都沒有任何意識。

這是一個圖表,說明在新模型中,環境網格中 Pod 之間的加密流量如何流動

HBONE traffic flows between pods in the ambient mesh

而且,與以前一樣,來自網格外部的未加密明文流量仍然可以處理並強制執行策略,適用於需要這種情況的使用案例

Plain text traffic flow between meshed pods

新的環境流量重新導向:這為我們帶來什麼

新的環境捕獲模型的最終結果是,所有流量捕獲和重新導向都發生在 Pod 的網路命名空間內。對於節點、CNI 和其他所有東西來說,看起來 Pod 內有一個 Sidecar 代理,即使 Pod 中**根本沒有 Sidecar 代理執行**。請記住,CNI 實作的工作是將封包傳輸**到 Pod 和從 Pod 傳輸**。根據設計和 CNI 規格,它們不關心在該點之後封包會發生什麼。

這種方法自動消除了與各種 CNI 和網路原則實作的衝突,並大幅提高了 Istio 環境網格與所有主要 CNI 上所有主要託管 Kubernetes 產品的相容性。

總結

感謝我們可愛的社群在各種 Kubernetes 平台和 CNI 上測試此變更的大量努力,以及 Istio 維護者的多輪審查,我們很高興宣布實作此功能的 ztunnelistio-cni PR 已合併到 Istio 1.21 中,並且預設為環境網格啟用,因此 Istio 使用者可以在 Istio 1.21 或更新版本中,在任何 Kubernetes 平台和任何 CNI 上開始執行環境網格。我們已經在 GKE、AKS 和 EKS 以及它們提供的所有 CNI 實作,以及像 Calico 和 Cilium 這樣的協力廠商 CNI,以及像 OpenShift 這樣的平台上進行了測試,結果非常理想。

我們非常興奮能夠推動 Istio 環境網格向前發展,透過 ztunnel 和使用者應用程式 Pod 之間的這種創新的 Pod 內流量重新導向方法,在任何地方執行。隨著環境網格 beta 版的此項頂級技術障礙得到解決,我們迫不及待地想與 Istio 社群的其他人合作,以便盡快讓環境網格進入 beta 版!若要了解有關環境網格 beta 版進度的更多資訊,請加入 Istio Slack 中的 #ambient 和 #ambient-dev 頻道,或參加週三的每週環境網格貢獻者會議,或查看環境網格 beta 版專案板並協助我們解決問題!

分享此文章