解讀 Istio Ambient Waypoint Proxy 部署模型
本文闡述了 Istio Ambient Waypoint Proxy 的多種部署模式,解釋了按節(jié)點部署的弊端,并通過實例說明了最佳實踐。
Ambient 模式是 Istio 在 2022 年引入的新型無邊車數據平面,并于今年 5 月達到 Beta[2] 狀態(tài)。Istio 社區(qū)正努力在下一個 Istio v1.24 版本中將 Ambient 推向 GA(一般可用)狀態(tài)。Ambient 將 Istio 的功能分為兩個獨立的層:安全覆蓋層和第 7 層處理層。在與許多試用 Ambient 的用戶合作時,我想澄清關于 waypoint proxy 的一些常見問題和困惑。它是一個可選的基于 Envoy 的組件,負責處理其管理的工作負載的 L7 事務。
Waypoint Proxy 的常見部署模式是什么?
理解 Waypoint Proxy
你可以將 waypoint proxy 簡單地視為一組目的地的網關,這些目的地可以是來自一個或多個命名空間的一個或多個服務和工作負載。除了處理集群內部的 L7 流量外,它與你的入口或出口網關沒有太大區(qū)別。這也是為什么在部署 waypoint proxy 時需要使用 Kubernetes 的 Gateway 資源的原因。
我非常喜歡 waypoint 架構的靈活性,你可以選擇適合自己需求的架構。以下是一些常見的模式:
A: 針對命名空間的 Waypoint Proxy
最常見的模式是,每個團隊在集群中擁有一個命名空間,并管理該命名空間內的服務和部署。在這種模式下,我們期望每個團隊都有自己的 waypoint proxy,供命名空間內的服務使用。按照這種模式,我們將默認的 waypoint 部署設計為命名空間范圍,供命名空間內的所有服務使用。在下圖中,服務 A、B、C 位于同一命名空間內。所有到服務 A、B 或 C 的 Ambient Mesh 客戶端流量將通過命名空間的 waypoint proxy,由客戶端的 ztunnel 進行編程。
Istio Ambient Waypoint 代理部署模型
注意:為簡潔起見,省略了目的地端的 ztunnel
B: 針對部分服務的 Waypoint Proxy
如果你不希望到服務 B 的流量經過 waypoint proxy 怎么辦?一個常見的原因是,你只需要對服務 B 的流量進行 L4 層的控制,這樣在調用它時就不需要通過 waypoint proxy。例如,你有一個調用 MySQL 數據庫服務的 Web 服務,只需要對其進行 L4 控制。另一個例子是,當服務是 “內部” 的,只被命名空間內的其他服務調用,你只需要對跨命名空間邊界的服務進行授權策略。例如,在著名的 Bookinfo 應用程序 [3] 中,你可以為 productpage 服務啟用零信任,拒絕除端口 9080 上 GET 方法的流量之外的所有流量。對于所有內部服務,如 reviews 或 details 服務,你可以繼續(xù)允許命名空間內的所有流量。
另一個用例是,服務 A 的流量非常大,你希望有一個專用的 waypoint proxy 來處理其 L7 處理,以便調整資源配置來應對高負載。你可以配置服務 B 或 C 使用不同的 waypoint,避免受到服務 A 的影響,或根據需要跳過它。我們將在下面的部分中詳細討論這一點。
Istio ambient waypoint 代理部署模型
C: 多個命名空間共享一個 Waypoint Proxy
你也可以通過為命名空間添加 istio.io/use-waypoint 標簽,并在 Gateway 資源中配置 allowRoutes,來讓多個命名空間共享一個 waypoint proxy。如果你運行的是小型集群,想要優(yōu)化資源效率,并且對嘈雜鄰居問題不太擔心,你可能希望為整個集群使用一個 waypoint proxy。這種情況下的一個常見例子是所謂的 K8S-at-the-edge[4]。
“當應用程序跨越太多命名空間時,使用 waypoint 為多個命名空間服務更具資源效率,通過提升無邊車服務網格的概念,并在不同的命名空間中使用集中式的 L7 功能,而不影響性能和應用可用性”,Ahmad Al-Masry[5],DevSecOps 工程經理說道。
另一個例子是,一個團隊擁有幾個組成單一信任域的命名空間,你希望通過共享一個 waypoint proxy 來降低資源成本。在下圖中,ns-1 和 ns-2 命名空間中的所有服務都使用部署在 ns-1 命名空間中的 waypoint proxy:
Istio ambient waypoint 代理部署模型
由于 ns-2 與 ns-1 共享相同的 waypoint proxy,任何在 ns-1 中部署并附加到整個 waypoint 的策略都會影響兩個命名空間。例如,如果你部署了一個附加到整個 waypoint 的 AuthorizationPolicy,該策略將在兩個命名空間中的所有服務上由 waypoint 執(zhí)行。
為什么不簡單地為每個節(jié)點部署一個 Waypoint Proxy?
雖然將 waypoint proxy 配置為上述不同目的地范圍的網關非常好,但你可能會想,為什么不保持簡單,為每個節(jié)點部署一個 waypoint proxy 作為 Kubernetes DaemonSet[6] 來處理該節(jié)點的所有 L7 處理呢?
Waypoint proxy 需要高度可配置,因為應用程序可能有完全不同的性能要求和運行時自定義。例如,你可以插入針對特定服務的外部授權策略或 WASM 擴展。一個租戶的錯誤 Envoy 配置可能會導致節(jié)點代理崩潰,影響該節(jié)點上的所有工作負載。
此外,需要在 waypoint proxy 上有大量處理的嘈雜鄰居可能會導致另一個應用程序性能不佳,僅僅因為該應用程序也部署在同一節(jié)點上。通過為 waypoint proxy 每個節(jié)點部署 Envoy,實際上是強制節(jié)點上的所有應用程序共享相同的故障域,而不管它們的應用延遲或運行時要求。Envoy 沒有租戶控制,你無法劃分其 CPU 或內存來防止嘈雜鄰居搶占其他應用程序。具有復雜 L7 策略的高流量應用程序將需要更多的 CPU 和 waypoint 的內存。Kubernetes DaemonSet 的資源預留是固定的,無法在不增加所有 waypoint pod 的 CPU 和內存的情況下,根據流量負載水平水平或垂直擴展特定的 DaemonSet pod。成本分攤在此模型中也很困難,你無法正確地將 waypoint 引起的資源成本歸因于每個租戶。
讓我們通過一個具體的例子來說明。我在兩個命名空間中部署了 Bookinfo 應用程序,每個命名空間都有其默認配置的命名空間 waypoint。我將每個命名空間的 waypoint proxy 配置為與各自的 productpage pod 共置。在每個命名空間中,我部署了一個簡單的 L7 AuthorizationPolicy,只允許特定命名空間執(zhí)行 GET 方法:
Istio ambient waypoint 代理部署模型
注意:為簡潔起見,省略了源和目的地端的 ztunnel
當我從 Fortio 向第一個命名空間的 productpage 服務發(fā)送 6500 RPS 的請求,并在 3 秒后向第二個命名空間的 productpage 服務發(fā)送相同的請求時,平均響應時間分別為 30.8ms 和 30.4ms,如下圖所示:
命名空間 1
命名空間 1:通過其 waypoint 向第一個命名空間的 productpage 服務發(fā)送 6500 QPS,650 個連接的 Fortio 測試
命名空間 2
命名空間 2:通過其 waypoint 向第二個命名空間的 productpage 服務發(fā)送 6500 QPS,650 個連接的 Fortio 測試
由于兩個 Bookinfo 應用程序都有非常大的負載,每個應用程序都有自己的 waypoint proxy 是合理的,這樣它們不會相互爭搶資源。那么,如果 waypoint proxy 改為按節(jié)點部署會怎樣?
我可以手動將 waypoint proxy 作為 DaemonSet 部署,使用非常復雜的 Envoy 配置。在運行兩個 productpage pod 的節(jié)點上,waypoint proxy pod 將被兩個 productpage pod 使用。然而,這需要深入了解 Envoy 配置,這方面我并不擅長。一種簡單的測試方法是,將兩個命名空間配置為使用相同的 waypoint proxy,這對于不需要非常高負載或專用 waypoint proxy 的應用程序是推薦的(參見前面的模式 C 了解更多信息)。注意:對于這種情況,我不推薦模式 C,因為兩個 Bookinfo 應用程序的負載非常大。
在確保 ns-1 命名空間中的 waypoint proxy pod 也部署在與兩個 productpage pod 相同的節(jié)點上后,我進行了一個簡單的更改,將兩個命名空間都配置為使用 ns-1 命名空間中的 waypoint proxy。這使我能夠快速測試一個 waypoint proxy pod,被部署在同一節(jié)點上的兩個 productpage pod 使用,就像我將 waypoint 作為 DaemonSet 部署一樣。
5_Istio ambient waypoint proxy deployment model ex
當我從 Fortio 負載客戶端向第一個命名空間的 productpage 服務發(fā)送 6500 RPS 時,平均響應時間從 30ms 增加到了 59ms!在 3 秒后向第二個命名空間的 productpage 發(fā)送相同的負載(基本上重復之前的測試,但這次使用共享的 waypoint),它報告了 32% 的錯誤,從之前的 0% 增加了!當它們共享同一節(jié)點上的同一個 waypoint proxy 時,對兩者的影響有多大!由于兩個應用程序在高負載下都變得非常嘈雜,waypoint proxy 達到了其默認的 CPU 限制(2 核)和 上游連接限制 [7](1024),因此許多稍后開始的來自第二個命名空間的請求以高比例的錯誤失敗。Kubernetes 工作節(jié)點仍然有充足的 CPU,在峰值時有約 50% 的 CPU 和 6% 的內存利用率。
命名空間 1.2
命名空間 1:通過共享的 waypoint 向第一個命名空間的 productpage 服務發(fā)送 6500 QPS,650 個連接的 Fortio 測試
命名空間 2.1
命名空間 2:通過共享的 waypoint 向第二個命名空間的 productpage 服務發(fā)送 6500 QPS,650 個連接的 Fortio 測試
這個實驗表明,在節(jié)點上使用相同的 waypoint proxy 共享相同的故障域,可能很容易在嘈雜的鄰居下觸發(fā)故障場景,而這些可以通過為非常繁忙的租戶提供專用的 waypoint 來避免。雖然在測試中使用了非常嘈雜的鄰居,但也可能是錯誤的 Envoy 配置或特定的 Envoy 擴展,在多個租戶共享相同的故障域時觸發(fā)類似的問題。
引用鏈接
[1] Istio Ambient Waypoint Proxy Deployment Model Explained: https://www.solo.io/blog/istio-ambient-waypoint-proxy-deployment-model-explained/
[2] Beta: https://istio.io/latest/blog/2024/ambient-reaches-beta/
[3] Bookinfo 應用程序: https://istio.io/latest/docs/examples/bookinfo/
[4] K8S-at-the-edge: https://events.linuxfoundation.org/kubecon-cloudnativecon-europe/co-located-events/kubernetes-on-edge-day/#about
[5] Ahmad Al-Masry: https://www.linkedin.com/in/ahmad-al-masry-9ab90858/
[6] DaemonSet: https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/
[7] 上游連接限制: https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/cluster/v3/circuit_breaker.proto#envoy-v3-api-field-config-cluster-v3-circuitbreakers-thresholds-max-connections