Service Mesh 通用資料平面 API(UDPA)最新進展深度介紹

螞蟻金服分散式架構發表於2020-03-26

在2019年5月,CNCF 籌建通用資料平面 API 工作組(Universal Data Plane API Working Group / UDPA-WG),以制定資料平面的標準 API。

當時我寫了一個部落格文章 “CNCF 正在籌建通用資料平面 API 工作組,以制定資料平面的標準 API” 對此進行了介紹。當時 UDPA 還處於非常早期的籌備階段,資訊非常的少。

現在9個月過去了,我最近收集並整理了一下 UDPA 目前的情況和資訊,給大家介紹一下 UDPA 目前最新的進展(截止2020年2月24日)。

另外螞蟻金服開源的雲原生網路代理 MOSN 目前已經支援 xDS v2 API,後面也會逐步向著 UDPA 的方向去演進,相容標準 Istio,感興趣的讀者可以去了解下。

MOSN:github.com/mosn/mon

UDPA 介紹

首先快速介紹一下什麼是 UDPA:

  • UDPA :“Universal Data Plane API”的縮寫, “通用資料平面 API”
  • UDPA-WG:”Universal Data Plane API Working Group”的縮寫,這是 CNCF 下的一個工作組,負責制定 UDPA;

UDPA 的目標,援引自 github.com/cncf/udpa 的描述:

通用資料平面 API 工作組(UDPA-WG)的目標是召集對資料平面代理和負載均衡器的通用控制和配置 API 感興趣的業界人士。

UDPA 的願景,同樣援引:

通用資料平面 API(UDPA)的願景在 blog.envoyproxy.io/the-univers… 中闡明。我們將尋求一組 API,它們為 L4/L7 資料平面配置提供事實上的標準,類似於 SDN 中 L2/L3/L4 的 OpenFlow 所扮演的角色。 這些 API 將在 proto3 中規範定義,並通過定義良好的、穩定 API 版本控制策略,從現有的 Envoy xDS API 逐步演進。API 將涵蓋服務發現、負載均衡分配、路由發現、監聽器配置、安全發現、負載報告、執行狀況檢查委託等。 我們將對 API 進行改進和成型,以支援客戶端 lookaside 負載均衡(例如 gRPC-LB),Envoy 之外的資料平面代理,硬體 LB,移動客戶端以及其他範圍。我們將努力盡可能與供應商和實現無關,同時堅持支援已投入生產的 UDPA 的專案(到目前為止,Envoy 和 gRPC-LB)。

對 UDPA 感興趣的同學,可以通過以下兩個途徑進一步深入瞭解:

  • UDPA @ GitHub:UDPA 在 github 上的專案,UDPA API 定義的程式碼都在這裡;
  • Universal Data Plane API Working Group (UDPA-WG):CNCF 的 UDPA 工作組,可以通過加入工作組的方式瞭解更多資訊;

UDPA 和 xDS 的關係

在展開 UDPA 的細節之前,有必要先解釋清楚 UDPA 和 xDS 的關係,因為這對理解 UDPA 會有很大幫助。

在2019年11月的 EnvoyCon 上,Envoy 的開發者,也是目前 UDPA 最主要的負責人之一,來自 Google 的 Harvey Tuch,有一個演講非常詳細而清晰的解答了這個問題,這個演講的標題是:“The Universal Dataplane API (UDPA): Envoy’s Next Generation APIs”。

備註:這裡我直接援引這份演講的部分內容,以下兩張圖片均出自 [這份演講的PPT](static.sched.com/hosted_file… UDPA 2019.pdf) 。鳴謝 Harvey。

下圖展示了近年來 xDS 協議的演進歷程和未來規劃:

xDS 協議的演進歷程和未來規劃

  • 2017年,xDS v2 引入 proto3 和 gRPC,同年 Istio 專案啟動;
  • 2018和2019年,xDS v2 API 繼續發展,陸續引入了新的 API 定義,如 HDS / LRS / SDS 等,尤其是為了改進 Pilot 下發效能,開始引入增量推送機制;
  • xDS v3 API 原計劃於2019年年底推出,但目前看技術推遲,目前 v3 還是 alpha1 狀態,預計在即將釋出的 Istio 1.5 中會有更多的 v3 API 引入。同時 v3 API 也引入了 UDPA 的部分內容,但是由於 UDPA 目前進展緩慢,對 xDS 的影響並不大,主要還是 xDS 自身的發展,比如對 API 和技術債務的清理;
  • 但在2020年,預計 UDPA 會有很大的進展,尤其是下面我們將會展開的 UDPA-TP 和 UDPA-DM 的設計開始正式制定為 API 之後。而 xDS v4 預計將基於 UDPA ,因此 xDS v4 可能會迎來比較大的變動;

簡單總結說:xDS 將逐漸向 UDPA 靠攏,未來將基於 UDPA

下圖則展示了 Envoy 在 xDS 版本支援上的時間線:

1.png

目前看這個計劃在執行時稍微有一點點延誤,原計劃於2019年年底推出的 v3 的 stable 版本實際上是在1月中定稿的。(備註:具體可參考 Envoy PR api: freeze v3 API )。然後目前正在廣泛使用的 v2 API 將被標記為 depreated。而且在2020年底,v3 API 預計被 v4 API 取代(注意 v4 API 將會是基於 UDPA),而目前我們最熟悉的 v2 API 將計劃在2020年底移除,不再支援!

上圖也展示了未來 xDS 協議的大版本演進和更替的方式,總的來說規律是這樣:

  1. 一年一個大版本:2019 v2 -> 2020 v3 -> 2021 v4 ->2022 v5;
  2. 每個大版本都要經歷 alpha -> stable -> deprecated -> removed 四個階段,每個階段歷時一年;
  3. 穩定後 Envoy 會同時存在三個 API 大版本:正在使用的穩定版本,已經棄用的上一個穩定版本,準備開發的新的下一個大版本(但只會是Alpha);
  4. 釋出一個新的 stable 的大版本,就一定會 deprecated 上一個穩定的大版本,同時 remove 更前一個已經 deprecated 的大版本;

所謂 “長江後浪推前浪,前浪死在沙灘上”,又或者說,“江山代有新版出,各領風騷12個月”。

備註:Envoy 具體的穩定 API 版本控制策略,可以參見 Envoy 的設計文件 “Stable Envoy API versioning” ,不過這個文件長的有點過分,嫌長的同學可以直接看這個文件的縮減版本 API versioning guidelines。

UDPA API 進展

言歸正傳,我們來看一下 UDPA 目前的最新進展。從 github.com/cncf/udpa ,可以看到目前 UDPA 中已經定義好的部分 API 內容:

型別定義

目前只定義了一個型別 TypedStruct。

TypedStruct 包含任意 JSON 序列化後的 protocol buffer 訊息以及一個描述序列化訊息型別的URL。這與 google.protobuf.Any 非常相似,它使用 google.protobuf.Struct 作為值,而不是使用 protocol buffer 二進位制。

message TypedStruct {
  // 用於唯一標識序列化 protocol buffer 訊息的型別的URL
  // 這與 google.protobuf.Any 中描述的語義和格式相同:
  // https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/any.proto
  string type_url = 1;
  // 上述指定型別的JSON表示形式。
  google.protobuf.Struct value = 2;
}
複製程式碼

TypedStruct 定義的背景是:如何在 protocol buffer 的靜態型別報文中嵌入一個不透明的配置。這是一個普遍需求,涉及 google.protobuf.Any 和 google.protobuf.Struct 的差別和權衡使用。具體內容請見我之前翻譯的部落格文章 “[譯] 動態可擴充套件性和Protocol Buffer”,對此做了非常好的介紹和分析討論。

TypedStruct 可以說是到目前為止對此需求的最佳實踐,算是為這一話題正式畫上了句號。

資料定義

資料定義也只定義了一個資料 OrcaLoadReport。

其中 ORCA 是 Open Request Cost Aggregation 的縮寫,OrcaLoadReport 用於提交請求開銷彙總的負載報告。

ORCA 的簡短介紹:

如今,在 Envoy 中,可以通過考慮後端負載(例如 CPU)的本地或全域性知識來做出簡單的負載均衡決策。更復雜的負載均衡決策可能需要藉助特定於應用的知識,例如佇列深度,或組合多個指標。 這對於可能在多個維度上受到資源限制的服務(例如,CPU 和記憶體都可能成為瓶頸,取決於所應用的負載和執行環境,無法確定是哪個先觸及瓶頸)以及這些維度不在預定類別中的位置時很有用(例如,資源可能是“池中的可用執行緒數”,磁碟 IOPS 等)。

有關 Orca 的更詳細的資訊,請見設計文件 Open Request Cost Aggregation (ORCA) 。

目前 Envoy 正在實現對 ORCA 的支援,然後這個特性被作為 UPDA 標準的一部分直接在 UDPA API 中定義。 以下為 OrcaLoadReport 定義,可以看到包含有 CPU/記憶體的利用率和 RPS 資訊:

message OrcaLoadReport {
  // CPU利用率表示為可用CPU資源的一部分。 應該來自最新的樣本或測量。
  double cpu_utilization = 1 [(validate.rules).double.gte = 0, (validate.rules).double.lte = 1];
  // 記憶體利用率表示為可用記憶體資源的一部分。 應該來自最新的樣本或測量。
  double mem_utilization = 2 [(validate.rules).double.gte = 0, (validate.rules).double.lte = 1];
  // 端點已服務的總RPS。 應該涵蓋端點負責的所有服務。
  uint64 rps = 3;
  ...
}
複製程式碼

服務定義

服務定義依然也只定義了一個服務 OpenRcaService。

OpenRcaService 是一個帶外(Out-of-band/OOB)負載報告服務,它不在請求路徑上。OpenRcaService 定期以足夠的頻率對報告進行取樣,以提供與請求的關聯。OOB 報告彌補了帶內(in-band)報告的侷限性。

service OpenRcaService {
  rpc StreamCoreMetrics(OrcaLoadReportRequest) returns (stream udpa.data.orca.v1.OrcaLoadReport);
}
複製程式碼

註解定義

UDPA 目前定義了四個註解(Annotation):

  • MigrateAnnotation:用於標記在前後版本中的和遷移相關的 API 變更,包括 rename / oneof_promotion / move_to_package 等多種語義;
  • SensitiveAnnotation:將某個欄位標記為“敏感”欄位,例如個人身份資訊,密碼或私鑰;
  • StatusAnnotation:標記狀態,比如將某個檔案標記為“work_in_progress/進行中”;
  • VersioningAnnotation:用於記錄版本資訊,比如通過 previous_message_type 表示當前 message 在上一個版本中的型別;

還有一個 ProtodocAnnotation 在提出設計後,存在分歧,暫時還沒有正式加入 UDPA。這個註解的目的是標記當前尚未實現的 UDPA 訊息;

UDPA API 總

從上面列出的 UDPA API 列表可以看到,目前 UDPA 中正式推出的 API 內容非常的少,也就:

  • 一個 TypedStruct 型別定義;
  • 一個 OpenRcaService 服務定義和配套的 OracLoadReport 資料定義;
  • 4個註解;

考慮到 UDPA 推出的時間是 2019年5月份,迄今有9個月的時間,這個進展有些出乎意料。

翻了一遍 github.com/cncf/udpa 上的內容,包括所有的 commit 和 PR ,發現活躍的開發者主要是兩位同學:Google 的 htuch 和 Tetrate公司的 Lizan。然後 cncf/UDPA 專案的 star 數量也非常低,才 55 個 star,可以認為社群基本上沒什麼人關注。

但是,稍後當我看到 UDPA 的設計文件時,才發現原來 UDPA 的精華都在設計中,只是進度原因還未能正式出成型的 API。

UDPA 設計

我們來重點看一下 UDPA 的設計,主要的設計文件有兩份:

  • UDPA-TP strawman: UDPA 設計之傳輸協議(TransPort),是用於 UDPA 的下一代傳輸協議;
  • UDPA-DM: L7 routing strawman: UDPA 設計之資料模型(Data Model),是對通過 UDPA-TP 傳輸的資源定義;

UDPA 對此的解釋是:

Envoy v2 xDS API 當前正在轉向通用資料平面 API(Universal Dataplane API/UDPA)。重點是傳輸協議與資料模型的關注點分離。

關於傳輸協議與資料模型的關注點分離,一個典型的例子是“集裝箱運輸機制”(類比 UDPA-TP )和 “集裝箱中標準規格”(類比 UDPA-DM)。在 UDPA 的設計中,資料模型的定義和傳輸協議的實現是分離的,這意味著只要設計不同的資料模型,就可以重用一套統一的傳輸協議。因此,UDPA 的可擴充套件性就變得非常強大。

對此,我個人有些驚喜,因為去年年底我和彥林同學在商討通過 MCP/xDS/UDPA 協議融合註冊中心和控制平面時,就發現這三者的工作機制非常類似。考慮到後續可能會有各種不同的資源需要定義並在這個工作機制上做資源同步和分發,當時有過類似的想法,希望能把底層這套資源同步機制標準化,以便重用:

MCP/xDS/UDPA 關係和標準化

目前看來,UDPA-TP 已經在朝這個目標邁出了堅實的步伐。當然如果能再往前邁進一步就更好了:這個底層資源同步的工作機制,沒有必要限制在 UDPA 的範疇,完全可以變成一個用途更加廣泛的通用機制。

下面來詳細看一下 UDPA-TP 和 UDPA-DM 的設計,以下內容來自 UDPA 的兩份設計文件以及個人的解讀。

UDPA-TP 設計

UDPA-TP 的設計文件,在開始部分列出了 UDPA-TP 的關鍵設計動機,具體包括:

  • 在保留 Core v2 xDS 中存在的概念性 pub-sub 模型的同時,還支援高階功能,例如 LRS/HDS;
  • 支援 Envoy Mobile 和其他 DPLB 客戶端的大規模擴充套件;
  • 簡單的客戶端和簡單的管理伺服器實現;
  • 使增量更新資源高效而簡單(備註:增量更新是目前 Istio/Envoy 正在努力實現的重點特性);
  • 支援資源聯邦(備註:和我之前構想的通過 MCP 協議聚合多個註冊中心/配置中心的思路一致,當現實中存在多個資源的來源時,就必須提供機制來聚合這些資源並提供一個全域性的檢視);
  • 使 API 資源的子資源變得簡單且實現成本低,並且使其可以增量更新和可聯合;
  • 維護對一致性模型的支援;
  • 消除 v2 xDS 奇怪之處;
  • ACK/NACK 與訂閱訊息的合併。在 v2 xDS 中,DiscoveryRequest 既是訂閱請求,又是對先前訊息的潛在確認。這導致了一些複雜的實現和除錯體驗(備註:這會造成 UDPA 互動模式和 xDS 的不同);
  • CDS/LDS 是與 EDS/RDS 不同的 API 層。在 v2 xDS 中,EDS/RDS 是準增量的,而 CDS/LDS 是最新狀態;
  • 從概念上講,在 Envoy v2 xDS API 基礎上小範圍變更。我們不希望對 UDPA 管理伺服器實現者造成重大的概念和實現開銷(備註:個人理解,這應該是目前 UDPA 沒有大張旗鼓的制定各種 API 的原因,UDPA 和 xDS,包括和 xDS 的實際實現者 Envoy 的關係過於緊密,因此需要考慮從 xDS 到 UDPA 的過渡,不能簡單的推出一套全新的 API);

以下是 UDPA 的術語,對於後面理解 UDPA 非常有幫助:

  • DPLB:data plane load balancer 的縮寫。涵蓋諸如代理(例如 Envoy)或客戶端 RPC 庫(例如 gRPC 和 Envoy Mobile)的用例。DPLB 是 UDPA 客戶端。他們負責啟動到管理伺服器的 UDPA 流(備註:注意,DPLB 不僅僅包含以 Envoy 為代表的 service mesh sidecar,也包括了以 SDK 形式存在的類庫如 gRPC,而  gRPC 目前已經在實現對 xDS 介面的支援);
  • Management server/管理伺服器:能夠提供 UDPA 服務的實體,管理伺服器可以僅是 UDPA 伺服器,也可以是 UDPA 客戶端和伺服器(在聯邦的情況下);
  • UDPA:通用資料平面 API,其中包括資料模型(UDPA-DM)和傳輸協議(UDPA-TP);
  • UDPA-TP:UDPA API 的基準傳輸協議;
  • UDPA-DM:UDPA API 的資料模型;
  • UaaS:UDPA-as-a-service,雲託管的 UDPA 管理服務(備註:Google 在 GCP 上提供的 Google Traffic Director 和 AWS 提供的 App Mesh,可以視為就是 UaaS 雛形);

然後是和聯邦相關的術語:

  • Federation/聯邦:多個 UDPA 管理伺服器的互操作以生成 UDPA 配置資源;
  • Direct federation/直接聯邦:當 DPLB 直接連線到多個 UDPA 管理伺服器並能夠從這些流中合成其配置資源時;
  • Indirect federation/間接聯邦:當 DPLB 一次最多連線一個 UDPA 管理伺服器(對於某些給定的資源型別),並且 UDPA 管理伺服器執行所有與聯邦有關的工作時;
  • Advanced DPLB/高階 DPLB:支援直接聯邦的 DPLB(需要 UDPA-Fed-TP);
  • Simple DPLB/簡單 DPLB:不支援直接聯邦的 DPLB,即僅基線 UDPA-TP;
  • UDPA-Fed-DM:UDPA-DM 的超集,具有用於聯邦的其他資源型別;
  • UDPA-Fed-TP:支援聯邦的 UDPA-TP 的超集;

下圖可以幫助理解這些術語:

UDPA 術語

(備註:圖中可能有誤,simple UDPA management server 和 Advanced UDPA management server 之間應該是 “UDPA-TP”, 而不應該是 “UDPA-Fed-TP”。)

UDPA-TP 傳輸協議提供了在管理伺服器和 DPLB 客戶端之間傳輸命名和版本化資源的方法,我們稱這些實體為 UDPA-TP 端點。UDPA-TP 端點可以是客戶端和管理伺服器,也可以是兩個管理伺服器(例如,在聯邦配置時)。上圖說明了使用 UDPA 在 UDPA-TP 端點之間傳送資源的各種方式。

其中,UDPA管理伺服器分為兩種:

  • 簡單(simple):實際上只是對不透明資源的快取(幾乎不瞭解 UDPA-DM),主要功能是從上游高階 UDPA 管理伺服器獲取資源,並分發資源給 DPLB,自身不產生資源;
  • 高階(advanced):對 UDPA-DM 有感知,通常是用來獲取資訊並轉換為標準化的資源(典型如 Istio 中的 Pilot)。可以直接分發資源給到 DPLB,也可以傳送資源給簡單 UDPA 管理伺服器,然後由簡單 UDPA 管理伺服器再分發給 DPLB;

而對應的 DPLB 客戶端也分為兩種:

  • 簡單(simple):對於任何配置源,簡單的 DPLB 在任何時間點最多隻能與一臺管理伺服器進行對話;
  • 高階(advanced):將實現對 UDPA-Fed-TP 的支援,並能夠直接作為聯邦端點參與;

簡單 DPLB 雖然只能連線一臺管理伺服器,但是也是可以實現聯邦的:簡單 DPLB 連線的管理伺服器可以實現聯邦,然後為 DPLB 實現了間接聯邦(備註:上圖中的簡單 DPLB 就是例子,兩個 Advanced UDPA management server 之間做了聯邦)。

UDPA-TP 設計解讀

在解讀 UDPA-TP 的設計之前,我們回顧一下 Istio 經典的元件和架構圖,下面分別是 Istio 1.0 和 Istio 1.1 的架構圖:

Istio 1.0 和 Istio 1.1 的架構圖

考慮到 Mixer 和 Citadel 兩個元件和 UDPA 的關係相比沒那麼大, 我們重點看 Proxy / Pilot / Galley:

  • Proxy在 Istio 中就是 Envoy(我們的 MOSN 正在努力成為候選方案),直接對等 UDPA 中的 DPLB 的概念。但是 Istio 中的 Proxy,功能上只和上圖中的 Simple DPLB 對齊。相比之下,UDPA-TP 設計中增加了一個能夠連線多個 UDPA management server 進行聯邦的 Advanced DPLB;
  • Pilot 和 Galley,從和 DPLB 的連線關係看,分別對應著 UDPA-TP 設計中的 Simple UDPA management server 和 Advanced UDPA management server。但從實際實現的功能看,目前 Pilot 的職責遠遠超過了  Simple UDPA management server 的設計,而 Galley 的功能則遠遠少於 Advanced UDPA management server。如果未來 Istio 的架構和元件要向 UDPA 的設計靠攏,則顯然 Pilot 和 Galley 的職責要發生巨大調整;
  • 最大的差異還是在於 UDPA-TP 中引入了聯邦的概念,而且同時支援在 DPLB 和 Advanced UDPA management server 上做聯邦。尤其是 DPLB 要實現聯邦功能,則必然會讓 DPLB 的功能大為增加,相應的 DPLB 和 UDPA management server 的通訊協議 (目前是 xDS)也將為聯邦的實現增加大量內容;

對照 UDPA-TP 的設計:

對照 UDPA-TP 的設計

UDPA-TP 的設計目前應該還沒有對應具體的實現產品,而且我也還沒有找到 UDPA-Fed-TP 詳細的 API 設計。資料來源太少,所以只能簡單的做一些個人的初步解讀:

  • 首先,Simple UDPA management server 的引入是一大亮點,功能足夠簡單而且專注,聚焦在將資料(在 UDPA 中體現為資源)分發給 DPLB (如大家熟悉的資料平面)。毫無疑問,Simple UDPA management server 的重點必然會在諸如容量 / 效能 / 下發效率 / 穩定性等關鍵效能指標,彌補目前 Istio 設計中 Pilot 下發效能贏弱的短板。從這個角度說,我傾向於將 Simple UDPA management server 理解為一個新的元件,介於 DPLB 和 Pilot 之間。 小結:解決容量和效能問題

  • 其次,Advanced UDPA management server 引入了聯邦的概念, 上面的圖片顯示是為了在兩個不同的雲供應商(Cloud Provider X 和 Cloud Provider Y)和本地(On-premise)之間進行聯邦,這是典型的混合雲的場景。而我的理解是,聯邦不僅僅用於多雲,也可以用於多資料來源,比如打通多個不同的註冊中心,解決異構互通問題。 小結:解決多資料來源的全域性聚合問題

  • 然後,比較費解的是引入了 Advanced DPLB 的概念,而且從圖上看,使用場景還非常複雜:1. 第一個 DPLB 是間接聯邦的典型場景,還比較簡單 2. 第二個 DPLB 除了以同樣的方式做了間接聯邦,還直接通過 UDPA-Fed-TP 協議和 On-Premise 的 Advanced UDPA management server 連線,實現了直接聯邦 3. 第三個 DPLB 則更復雜,做了三個 management server 的聯邦 。 小結:複雜的場景必然帶來複雜的機制,背後推動力待查。

對於 UDPA-TP 的設計,我個人有些不太理解,主要是對於聯邦的使用場景上,我的疑慮在於:真的有這麼複雜的場景嗎?尤其是將聯邦的功能引入到 DPLB,這必然會使得 xDS/UDPA 協議不得不為此提供聯邦 API 支援,而 Envoy/MOSN 等的實現難度也要大為提升。因此,除非有特別強烈的需求和場景推動,否則最好能在複雜度和功能性之間做好平衡。

我個人更傾向於類似下面的設計:

UDPA-TP 個人傾向設計

  • 維持 DPLB 和 Simple UDPA management server 的簡單性;
  • DPLB 只對接 Simple UDPA management server,協議固定為 UDPA-TP,聯邦對 DPLB 透明(只實現間接聯邦);
  • Simple UDPA management server 重點在於容量和效能的提升,包括目前正在進行中的支援各種資源的增量更新;
  • Advanced UDPA management server 負責完成聯邦,包括和其他環境的 Advanced UDPA management server 做聯邦,以及從本地的其他註冊中心聚合資料;

總之,我個人更傾向於讓 DPLB 和 Simple UDPA management server 保持簡單和高效能,而將複雜功能交給 Advanced UDPA management server 。後續我會重點關注 UDPA 在聯邦功能的實現,如有新進展儘量及時撰文分享。

UDPA 的資源定義和設計

在 UDPA-TP 的設計中,根據資源的來源,資源被劃分為兩類型別:

  • Configuration Resources/配置資源:控制平面生成,由管理伺服器分發到 DPLB。平常大家熟悉的,通過 xDS 協議傳輸的 Listener / Route / Cluster / Endpoint 等資源就屬於這種型別;
  • Client Resources/客戶資源:DPLB 生成,準備交給控制平面使用。前面 UDPA 中定義的 OracLoadReport  就是典型例子,這是最近才有的新特性,由 DPLB 收集統計資訊和狀態,彙報給到控制平面,以便控制平面在決策時可以有多完善的參考資訊;

資源在定義時,將有三個重要屬性:

  • 名稱/Name:對於給定型別是唯一的,而且資源名稱是結構化的,其路徑層次結構如下:/ ,例如 com.acme.foo/service-a 。注意 namespace 的引入,是後面的資源聯邦和所有權委派的基礎;
  • 型別/Type:資源型別由 Type URL 提供的字串來表示;
  • 版本/Version:對於給定的命名資源,它可能在不同的時間點具有不同的版本。在資源定義中帶上版本之後,檢測資源是否有更新就非常方便了;

以下是資源定義的例項(只是示意,暫時還沒正式成為 UDPA API 的內容):

message Resource {
  // 資源的名稱,以區別於其他同型別的資源。
  // 遵循反向DNS格式,例如 com.acme.foo/listener-a
  string name = 1;
  // 資源級別版本
  string version = 2;
  // 資源有效負載。
  // 通過 Any 的 type URL 指定資源型別
  google.protobuf.Any resource = 3;
  // 資源的TTL。
  // 此時間段後,資源將在DPLB上失效。
  // 當管理伺服器的連線丟失時,將支援資源的優雅降級,例如端點分配。
  // 使用新的TTL接收到相同的資源 name/version/type 將不會導致除了重新整理TTL之外的任何狀態更改。
  // 按需資源可能被允許過期,並且可能在TTL過期時被重新獲取。
  // TTL重新整理訊息中的resource欄位可能為空,name/version/type用於標識要重新整理的資源。
  google.protobuf.Duration ttl = 4;
  // 資源的出處(所有權,來源和完整性)。
  Provenance origin_info = 5;
}
複製程式碼

UDPA-TP 設計中的其他內容,如安全 / 錯誤處理 / 傳輸 / 使用者故事 等,就不一一展開了,這些設計目前看離正式成為 API 還有點遠。如有興趣可以直接翻閱 UDPA-TP 的設計文件。

UDPA-DM 設計

UDPA 設計的一個核心內容就是將傳輸(TransPort)與資料模型(Date Model)的關注點分離,前面介紹了  UDPA-TP 的設計,可以說目前還在進行中,並未完全定型。

而 UDPA-DM 的設計,感覺進度上比 UDPA-TP 還要更早期,這多少有點出乎意料:原以為 UDPA 會基於 xDS 現有的成熟 API 定義,快速推出一套覆蓋常見通用功能的 API ,甚至直接把 xDS 中的部分內容清理乾淨之後搬過來。但事實是:目前 UDPA-DM 中已經定義的 API 內容非常少,僅有 L7 Routing ,而且還在設計中,其他大家熟悉的 Listener / Cluster / Endpoint / Security / RatingLimit 等API都還沒有看到。

而 UDPA-DM 的設計和實現方式,也因為資料較少而有些不夠明朗。在 UDPA-DM 的設計文件的開頭,有如下一段描述:

As a starting point, we recognize that the UDPA-DM is not required to be as expressive as any given DPLB client’s full set of capabilities, instead it should be possible to translate from UDPA-DM to various DPLB native configuration formats. We envisage UDPA-DM as a lingua franca that captures a large amount of useful functionality that a DPLB may provide, making it possible to build common control planes and ecosystems around UDPA capable DPLBs. 首先,我們認識到 UDPA-DM 不需要像任何已有的 DPLB 客戶端那樣,全部能力都具備表現力,而是應該可以從 UDPA-DM 轉換為各種 DPLB 原生配置格式。我們將 UDPA-DM 設想為一種通用語言,它具備大量 DPLB 應該提供的有用的功能,從而有可能在支援 UDPA 的 DPLB 周圍構建通用的控制平面和生態系統。 The UDPA-DM will be a living standard. We anticipate that it will initially cover some obvious common capabilities shared by DPLBs, while leaving other behaviors to proxy specific API fields. Over time, we expect that the UDPA-DM will evolves via a stable API versioning policy to accommodate functionalities as we negotiate a common representation. UDPA-DM 將成為事實標準。我們期望它最初將涵蓋 DPLB 共有的一些顯而易見的通用功能,同時將其他行為留給代理特定的API欄位。隨著時間的推移,我們期望 UDPA-DM 將通過穩定的API版本控制策略來發展,以容納各種功能,而我們將協商通用的表示形式。

對這兩段文字描述的理解,我是有一些困惑的,主要在清楚解 UDPA-DM 的定義和具體的 DPLB 原生實現(典型如 Envoy 的 xDS)之間的關係。下面這張圖是我畫的:

具體的 DPLB 原生實現

  • 左邊的圖是轉換方案:按照第一段文字的描述,UDPA-DM 是做通用定義,然後轉換(Translate)為各種 DPLB 的原生配置格式。這意味著 UDPA-DM API 和實際的 DPLB 原生配置格式可能會有非常大的不同,甚至有可能是完全不一樣的格式定義。這個關係有點類似 Istio API 和 xDS API 的關係,也類似於 SMI (微軟推出的 Service Mesh Interface)和 xDS 的關係;
  • 右邊的圖是子集方案:按照第二段文字的描述,UDPA-DM 是做通用定義,但是不會做轉換,其他 DPLB 會直接複用這些 UDPA-DM 的 API 定義,然後補充自身特有的 API 定義。這樣 UDPA-DM 會以通用子集的形式出現,逐漸擴大範圍,然後其他 API 會逐漸將自身的 API 中和 UDPA-DM 重疊的部分替換為 UDPA-DM API,只保留自身特有的擴充套件 API;

前面談到 xDS 的演進路線, v3 / v4 會逐漸向 UDPA 靠攏,尤其 v4 會基於 UDPA 來。目前由於 UDPA API 遠未成型,而 xDS v3 中對 UDPA API 的使用非常少(基本只用到了 annotation 定義),因此目前到底是哪個方案尚不明朗。

以下是 UDPA-DM 設計文件中描述的 UDPA-DM 的關鍵設計:

  • 描述 L7 路由層,該層描述主要 L7 DPLB 之間的常見行為,包括 Envoy,HAproxy,Nginx,Google Cloud Platform URL mapping 和 Linkerd;
  • 為代理 /LB 的特有擴充套件提供靈活性,用於不適合通用抽象的行為。即逃生艙口(escape hatch)(備註:類似 SQL 方言);
  • 提供 L7 路由表的可伸縮性和有效的對數評估(logarithmic evaluation)。例如,Envoy v2 xDS 是嚴格線性評估的路由表,具有明顯的擴充套件限制。對於可以支援 UDPA-TP 這個特性的 DPLB,應該可以按需獲取路由表段;
  • 在 v2 Envoy xDS API 中支援線性匹配路由表的舊有使用者;
  • 刪除多 xDS 樣式 API 的需求,例如 RDS,VHDS 和 SRDS;
  • 資源的可組合性;應該有可能支援 UDPA 聯邦用例,帶有諸如虛擬主機這種被獨立管理的資源等;

下面重點看 L7 Routing 的設計。

Routing API 設計

Routing API 中有三個術語:

  • 服務/Service:描述後端服務的不透明字串(或在 Envoy 的術語中,為叢集/Cluster)。當前文件未提供有關服務表示的任何進一步詳細說明,這留待以後的工作;
  • 路由表/Route table:一組匹配條件,用於 HTTP 請求和相關操作。操作可以包括重定向或轉發到特定服務;
  • L7 路由/L7 routing:根據路由表評估給定的 HTTP 請求;

在 UDPA-DM 的 Routing API 設計中,針對請求匹配的方式,相比 xDS 做了重大的改動,主要體現在除了線性匹配之外,還支援分層匹配。

這裡先解釋一下線性匹配和分層匹配這兩種路由時需要用到的請求匹配方式:

  • 線性(Linear):其中路由表類似於[([Match], Action)] 型別。在此模型中,路由表是匹配 criteria-action 條件的有序列表。每個匹配的 criteria 是匹配 criteria 的邏輯”與”,例如:
    • If :authority == foo.com AND path == / AND x-foo == bar THEN route to X
    • If :authority == bar.com AND x-baz == wh00t THEN route to Y
  • 分層(Hierarchical):其中路由表類似於樹結構,每個節點具有(MatchCriteria, [(Value, Action)]) 型別。通過這種結構,任何給定的節點都會只評估單個匹配條件,例如:authority 的值。分層匹配能提供相對高效的實現。

目前 xDS v2 API 使用的是線性匹配方式,而 UDPA-DM 的 Routing API 會引入分層匹配,形成線性-分層的混合匹配方式,如下圖所示:

UDPA-DM Routing API 分層匹配

設計文件對這個混合匹配模型有如下說明:

The model does not map directly to any given DPLB today but borrows from some Envoy concepts and should have an efficient realization. It may be possible to use HAproxy ACLs to model this topology. 目前該模型並沒有直接對映到任何給定的 DPLB,而是借鑑了 Envoy 的一些概念,這個模型應該會有一個有效的實現。可能會使用 HAproxy ACL 對這種拓撲進行建模。

由於目前 Routing API 並沒有完成設計,也沒有正式成為 UDPA 的 API,而在最新剛定稿的 xDS v3 協議中,RoutesDiscoveryService 和 ScopedRoutesDiscoveryService 也都沒有引入這個新的模型,因此預期這個模型將在2020年繼續完成設計和定稿,可能在年底的 xDS v4 中會有所體現。然後,UDPA-DM 和 xDS 之間到底會是轉換模型,還是子集模型,屆時就清楚了。

由於 Routing API 尚未設計完成,所以這裡不詳細展開 Routing API 的定義了。Routing API 的相關資料如下,有興趣的同學可以關注(然而已經很長時間沒有新的進展了):

  • Issue 討論 [WiP] L7 routing straw man;
  • 在 PR 中提交的 Routing API 定義檔案 udpa/config/v1alpha/routing.proto:可以自行和 xDS v3 的 API 做一個比較;

總結

UDPA 目前還處於早期設計階段,關鍵的 UDPA-TP 和 UDPA-DM 的設計有推出草稿但是遠未完成,內容也和我們期望的一個完整的通用資料平面 API 有很長的距離。而且專案進展並不理想,感覺重視程度和人力投入都有限。

附言

最近因為想了解一下 UDPA 的進展,所以做了 UDPA 的調研和學習,比較遺憾的是 UDPA 的資料非常匱乏,除了我本文列出來的幾個官方網站和設計文件之外,基本就只有 Harvey 的演講。

調研完成之後發現 UDPA 的進展不如人意,尤其是最近的工作幾乎停滯,關鍵的 UDPA-TP 和 UDPA-DM 的設計未能完稿,xDS v3 中也只引用了極少的 UDPA API 定義。這篇總結文章差點因此難產,因為未知/待定/未完成的內容太多,而且由於缺乏資料輸入,很多資訊也只是我個人的理解和想法,按說這不是一個嚴謹的深度介紹文章應有的態度。

但考慮到目前 UDPA 的資料實在是太少,本著“有比沒有好”的想法,我硬著頭皮完成了這篇文章。後續如果有新的輸入,我會及時完善或者修訂本文,也歡迎對 UDPA 有興趣和了解的同學聯絡我討論和指導。

參考資料

  • github.com/cncf/udpa :UDPA 在 github 的專案,API 定義來自這裡
  • Universal Data Plane API Working Group (UDPA-WG): UDPA 設計文件,但是內容很少
  • Universal Data Plane API Working Group (UDPA-WG):CNCF 下的 UDPA 工作組,加入之後能看到一些資料
  • UDPA-TP strawman: UDPA-TP 的設計文件
  • UDPA-DM: L7 routing strawman: UDPA-DM 的設計文件
  • Stable Envoy API versioning :Envoy 官方文件,講述 Envoy 的穩定API版本控制策略
  • CNCF 正在籌建通用資料平面 API 工作組,以制定資料平面的標準 API:我去年寫的 UDPA 介紹文章
  • The Universal Dataplane API (UDPA): Envoy’s Next Generation APIs:Harvey Tuch 的演講,幫助理解 xDS 和 UDPA 的關係

公眾號:金融級分散式架構(Antfin_SOFA)

相關文章