網易開源 Istio 擴展項目 Slime 簡介——基於 Istio 的智能服務網格管理器

語言: CN / TW / HK

最近我在研究 Istio 生態中的開源項目, Slime 這個項目開源與 2021 年初,是由網易數帆微服務團隊開源的一款基於 Istio 的智能網格管理器。Slime 基於 Kubernetes Operator 實現,可作為 Istio 的 CRD 管理器,無須對 Istio 做任何定製化改造,就可以定義動態的服務治理策略,從而達到自動便捷使用 Istio 和 Envoy 高階功能的目的。

Slime 試圖解決的問題

Slime 項目的誕生主要為了解決以下問題:

  1. 網格內所有服務配置全量下到所有 Sidecar Proxy,導致其消耗大量資源使得應用性能變差的問題
  2. 如何在 Istio 中實現高階擴展的問題:比如擴展 HTTP 插件;根據服務的資源使用率做到自適應限流

Slime 解決以上問題的答案是構建 Istio 的控制平面,具體做法是:

  • 構建可拔插控制器
  • 數據平面監控
  • CRD 轉換

通過以上方式 Slime 可以實現 配置懶加載插件管理器

Slime 架構

Slime 內部分為三大模塊,其架構圖如下所示。

Slime 內部三大組件為:

  1. slime-boot :在 Kubernetes 上部署 Slime 模塊的 operator。
  2. slime-controller :Slime 的核心組件,監聽 Slime CRD 並將其轉換為Istio CRD。
  3. slime-metric :用於獲取服務 metrics 信息的組件, slime-controller 會根據其獲取的信息動態調整服務治理規則。

目前 Slime 內置了三個控制器子模塊:

  1. 配置懶加載(按需加載) :用户無須手動配置 SidecarScope ,Istio 可以按需加載服務配置和服務發現信息;
  2. HTTP 插件管理 :使用新的 CRD—— pluginmanager/envoyplugin 包裝了可讀性,摒棄了可維護性較差的 envoyfilter ,使得插件擴展更為便捷;
  3. 自適應限流 :結合監控信息自動調整限流策略;

什麼是 SidecarScope?

SidecarScope 是在 Istio 1.1 版本中引入的,它並不是一個直接面向用户的配置項,而是 Sidecar 資源的包裝器,具體來説就是Sidecar 資源中的 egress 選項。通過該配置可以減少 Istio 向 Sidecar 下發的數據量,例如只向某個命名空間中的某些服務下發某些 hosts 的訪問配置,從而提高應用提高性能。

使用 Slime 作為 Istio 的控制平面

為了解決這些問題,Slime 在 Istio 之上構建了更高層次的抽象,相當於為 Istio 構建了一層管理平面,其工作流程圖如下所示。

具體步驟如下:

  1. Slime Operator 根據管理員的配置在 Kubernetes 中完成 Slime 組件的初始化;
  2. 開發者創建符合 Slime CRD 規範的配置並應用到 Kubernetes 集羣中;
  3. Slime 查詢 Prometheus 中保存的相關服務的監控數據,結合 Slime CRD 中自適應部分的配置,將 Slime CRD 轉換為 Istio CRD,同時將其推送到 Global Proxy 中;
  4. Istio 監聽 Istio CRD 的創建;
  5. Istio 將 Sidecar Proxy 的配置信息推送到數據平面相應的 Sidecar Proxy 中;

以上只是一個對 Slime 工作流程的一個籠統的介紹,更多詳細信息請參考 Slime GitHub

配置懶加載

為了解決數據平面中 Sidecar Proxy 資源消耗過大及網絡延遲問題,Slime 使用了配置懶加載(按需加載 Sidecar 配置)的方案。該方案的核心思想是向每個 Sidecar Proxy 中只下發其所 Pod 中服務所需的配置,而不是將網格中的所有服務信息全量下發。所以 Slime 需要獲取每個服務的調用關係這樣才能得到其所需的 Sidecar Proxy 配置。

Slime 實現 Sidecar Proxy 配置懶加載的方法是:

ServiceFence

使用 Global Proxy 初始化服務調用拓撲

Slime 在數據平面中部署 Global Proxy(也叫做 Global Sidecar,但其與應用的 Pod 不是一對一的關係,筆者更傾向於稱其為 Global Proxy),該代理同樣使用 Envoy 構建,在每個需要啟動配置懶加載的命名空間中部署一個或在整個網格中只部署一個,所有缺失服務發現信息的調用(你也可以手動配置服務調用關係),都會被兜底路由劫持到 Global Proxy,經過其首次轉發後,Slime 便可感知到被調用方的信息,然後根據其對應服務的 VirtualService,找到服務名和真實後端的映射關係,將兩者的都加入 SidecarScope,以後該服務的調用就不再需要經過 Global Proxy 了。

使用 ServiceFence 維護服務調用拓撲

在使用 Global Proxy 初始化服務調用拓撲後,一旦服務調用鏈有變動的話怎麼辦?對此 Slime 創建了 ServiceFence 的 CRD。使用 ServiceFence 可以維護服務名和後端服務的映射關係。Slime 根據其對應服務的 VirtualService,找到 Kubernetes 服務名和真實後端(host)的映射關係,將兩者的都加入 Sidecar 的配置中。ServiceFence 管理生成的 SidecarScope 的生命週期,自動清理長時間不用的調用關係,從而避免上述問題。

如何開啟配置懶加載

配置懶加載功能對於終端用户是透明的,只需要 Kubernetes Service 上打上 istio.dependency.servicefence/status:"true" 的標籤,表明該服務需要開啟配置懶加載,剩下的事情交給 Slime Operator 來完成即可。

HTTP 插件管理

Istio 中的插件擴展只能通過 EnvoyFilter 來實現,因為它是 xDS 層面的配置,管理和維護這樣的配置需要耗費大量的精力,也極容易出錯。因此,Slime 在 EnvoyFilter 的基礎上做了一層面向插件的抽象。

Slime 共有兩個 CRD 用於 HTTP 插件管理,分別是:

  • PluginManager :配置為哪些負載開啟哪些插件,插件的配置順序即為執行順序;
  • EnvoyPlugin :EnvoyPlugin 不關心每個插件的具體配置,具體配置會被放在 EnvoyFilter 資源的 patch.typed_config 結構中透傳),EnvoyPlugin 的核心思想是將插件配置在需要的維度中做聚合,從而限定插件的生鮮範圍。這樣做一方面更加貼合插件使用者的習慣,另一方面也降低了上層配置的宂餘,

關於 Slime 中插件管理的詳細使用方式請見 Slime GitHub

自適應限流

Envoy 內置的限流組件功能單一,只能以實例維度配置限流值,無法做到根據應用負載的自適應限流。Slime 通過與 Prometheus metric server 對接,實時的獲取監控情況,來動態配置限流值。

Slime 自適應限流的流程圖如下所示。

Slime 的自適應限流的流程分為兩部分,一部分為 SmartLimiter 到 EnvoyFilter 的轉換,另一部分為獲取監控數據。目前 Slime 支持從 Kubernetes Metric Server 獲取服務的CPU、內存、副本數等數據。Slime 還對外提供了一套監控數據接口(Metric Discovery Server),通過 MDS,可以將自定義的監控指標同步給限流組件。

Slime 創建的 CRD SmartLimiter 用於配置自適應限流。其的配置是接近自然語義,例如希望在 CPU 超過 80% 時觸發服務 A 的訪問限制,限額為 30QPS,對應的SmartLimiter 定義如下:

apiVersion: microservice.netease.com/v1alpha1
kind: SmartLimiter
metadata:
  name: a
  namespace: default
spec:
  descriptors:
  - action:
      fill_interval:
        seconds: 1
      quota: "30/{pod}"    # 30為該服務的額度,將其均分給每個 pod,加入有 3 個 pod,則每個 pod 的限流為 10
    condition: "{cpu}>0.8" # 根據監控項{cpu}的值自動填充該模板

更多

Slime 開源於 2021 年初,本文發稿時該項目仍處於初級階段,本文大量參考了楊笛航在雲原生社區中的分享 Slime:讓 Istio 服務網格變得更加高效與智能 及 Slime 的 GitHub 。感興趣的讀者可以關注下這個項目的 GitHub,進一步瞭解它。

另外歡迎關注服務網格和 Istio 的朋友加入 雲原生社區 Istio SIG ,一起參與討論和交流。

參考