Aeraki — 在 Istio 服務網格中管理任何 Layer-7 協定
Aeraki 提供一個框架,讓 Istio 除了 HTTP 之外,還能支援更多 Layer-7 協定。
Aeraki [Air-rah-ki] 在希臘語中是「微風」的意思。當 Istio 在服務網格中連接微服務時,Aeraki 提供一個框架,讓 Istio 除了 HTTP 和 gRPC 之外,還能支援更多 Layer-7 協定。我們希望這股微風能幫助 Istio 航行得更遠。
服務網格中缺乏協定支援
我們現在在服務網格方面面臨一些挑戰
- Istio 和其他流行的服務網格實作,除了 HTTP 和 gRPC 之外,對於 Layer-7 協定的支援非常有限。
- Envoy RDS(路由探索服務)專為 HTTP 設計。其他協定(如 Dubbo 和 Thrift)只能使用監聽器內嵌路由進行流量管理,這會在路由變更時中斷現有的連線。
- 將專有協定引入服務網格需要付出很大的努力。您需要編寫一個 Envoy 過濾器來處理資料平面的流量,以及一個控制平面來管理這些 Envoy。
這些障礙使得使用者很難(如果不是不可能的話)管理微服務中其他廣泛使用的 Layer-7 協定的流量。例如,在一個微服務應用程式中,我們可能會遇到以下協定
- RPC:HTTP、gRPC、Thrift、Dubbo、專有 RPC 協定 …
- 訊息傳遞:Kafka、RabbitMQ …
- 快取:Redis、Memcached …
- 資料庫:MySQL、PostgreSQL、MongoDB …
如果您已經在遷移到服務網格上投入了大量精力,那麼您當然希望充分利用它 — 管理微服務中所有協定的流量。
Aeraki 的方法
為了解決這些問題,我們創建了一個開源專案 Aeraki Mesh,提供一種非侵入式、可擴展的方式,在 Istio 服務網格中管理任何 Layer-7 流量。
如本圖所示,Aeraki 框架由以下元件組成
- Aeraki:Aeraki 為運營人員提供高層次、使用者友善的流量管理規則,將這些規則轉換為 Envoy 過濾器配置,並利用 Istio 的
EnvoyFilter
API 將配置推送到 Sidecar 代理。Aeraki 還充當資料平面中 MetaProtocol 代理的 RDS 伺服器。與專注於 HTTP 的 Envoy RDS 相反,Aeraki RDS 旨在為所有 Layer-7 協定提供通用的動態路由能力。 - MetaProtocol 代理:MetaProtocol 代理 為 Layer-7 協定提供常見的功能,例如負載平衡、熔斷、負載平衡、路由、速率限制、故障注入和身分驗證。Layer-7 協定可以建立在 MetaProtocol 之上。要將新協定添加到服務網格中,您唯一需要做的就是實作 編解碼器介面 和幾行配置。如果您有內建功能無法滿足的特殊要求,MetaProtocol 代理還具有應用程式級過濾器鏈機制,允許使用者編寫自己的 Layer-7 過濾器,將自訂邏輯添加到 MetaProtocol 代理中。
Dubbo 和 Thrift 已經基於 MetaProtocol 實作。更多協定正在開發中。如果您使用封閉原始碼的專有協定,您也可以透過簡單地為其編寫一個 MetaProtocol 編解碼器來在您的服務網格中管理它。
大多數請求/回應樣式、無狀態協定都可以建立在 MetaProtocol 代理之上。然而,某些協定的路由策略太「特殊」而無法在 MetaProtocol 中正規化。例如,Redis 代理使用槽號將客戶端查詢對應到特定的 Redis 伺服器節點,並且槽號是根據請求中的金鑰計算得出的。只要 Envoy 代理端有可用的 Envoy 過濾器,Aeraki 仍然可以管理這些協定。目前,對於此類協定,Aeraki 支援 Redis 和 Kafka。
深入探討 MetaProtocol
讓我們來看看 MetaProtocol 是如何工作的。在引入 MetaProtocol 之前,如果我們要代理特定協定的流量,我們需要編寫一個 Envoy 過濾器,該過濾器能理解該協定,並新增程式碼來操作流量,包括路由、標頭修改、故障注入、流量鏡像等。
對於大多數請求/回應樣式的協定,流量操作的程式碼非常相似。因此,為了避免在不同的 Envoy 過濾器中重複這些功能,Aeraki 框架在一個地方實作了 Layer-7 協定代理的大部分常見功能 — MetaProtocol 代理過濾器。
這種方法顯著降低了編寫新 Envoy 過濾器的門檻:現在您只需要實作編解碼器介面,而無需編寫功能完整的過濾器。除此之外,控制平面已經到位 — Aeraki 在控制平面上工作,為基於 MetaProtocol 建構的所有協定提供 MetaProtocol 配置和動態路由。
MetaProtocol 代理中有兩個重要的資料結構:Metadata 和 Mutation。Metadata 用於路由,而 Mutation 用於標頭操作。
在請求路徑上,解碼器(編解碼器實作的解碼方法)使用從請求中解析的鍵值對填充 Metadata 資料結構,然後將 Metadata 傳遞到 MetaProtocol 路由器。路由器在匹配從 Aeraki 通過 RDS 收到的路由配置和 Metadata 後,選擇適當的上游叢集。
如果需要修改請求:新增標頭或變更標頭的值,自訂過濾器可以使用任意鍵值對填充 Mutation 資料結構。然後將 Mutation 資料結構傳遞到編碼器(編解碼器實作的編碼方法)。編碼器負責將鍵值對寫入連線協定。
回應路徑與請求路徑相似,只是方向不同。
範例
如果您需要基於 MetaProtocol 實作應用程式協定,您可以按照以下步驟操作(以 Thrift 為例)
資料平面
實作 編解碼器介面 來編碼和解碼協定套件。您可以參考 Dubbo 編解碼器 和 Thrift 編解碼器 作為編寫您自己的實作。
使用 Aeraki
ApplicationProtocol
CRD 定義協定,如這個 YAML 片段所示
apiVersion: metaprotocol.aeraki.io/v1alpha1
kind: ApplicationProtocol
metadata:
name: thrift
namespace: istio-system
spec:
protocol: thrift
codec: aeraki.meta_protocol.codec.thrift
控制平面
您不需要實作控制平面。Aeraki 監控服務和流量規則,為 Sidecar 代理生成配置,並透過 EnvoyFilter
和 MetaProtocol RDS 將配置傳送到資料平面。
協定選擇
與 Istio 類似,協定由服務埠前綴識別。請使用以下模式命名服務埠:tcp-metaprotocol-{應用程式協定}-xxx。例如,Thrift 服務埠應命名為 tcp-metaprotocol-thrift。
流量管理
您可以透過 MetaRouter
CRD 變更路由。例如:將 20% 的請求傳送到 v1,將 80% 的請求傳送到 v2
apiVersion: metaprotocol.aeraki.io/v1alpha1
kind: MetaRouter
metadata:
name: test-metaprotocol-route
spec:
hosts:
- thrift-sample-server.thrift.svc.cluster.local
routes:
- name: traffic-spilt
route:
- destination:
host: thrift-sample-server.thrift.svc.cluster.local
subset: v1
weight: 20
- destination:
host: thrift-sample-server.thrift.svc.cluster.local
subset: v2
weight: 80
如果您需要在服務網格中管理 HTTP 以外的協定,希望這能有所幫助。如果您有任何疑問,請聯絡 zhaohuabing。