eBPF會成為服務網格的未來嗎?


服務網格現狀

服務網格為服務提供了復雜的應用層網絡管理,如服務發現、流量路由、彈性(超時/重試/斷路)、認證/授權、可觀察性(日志/度量/追蹤)等。

在分布式應用的早期,這些要求是通過直接將所需的邏輯嵌入到應用中來解決的,比如spring cloud等微服務框架。服務網格將這些功能從應用程序中提取出來,作為基礎設施的一部分透明的提供給所有應用程序使用,因此不再需要修改每個應用程序。

在早期,服務網格的功能通常是以庫的形式實現的,要求網格中的每個應用程序都要鏈接到以應用程序的語言框架編寫的庫。類似的事情也發生在互聯網的早期:曾幾何時,應用程序還需要運行自己的 TCP/IP 協議棧!正如我們將在這篇文章中討論的那樣,服務網格正在發展成為一種內核責任,就像網絡堆棧一樣。

告別 sidecar

今天,服務網絡通常使用一種叫做sidecar模型的架構實現的,通過在每一個應用pod上添加一個代理sidecar容器,如Envoy或Linkerd,這些代理也被稱為服務網格的數據平面。

這種方式優點是支持異構系統的服務治理,如果許多服務是用不同的語言編寫部署的,或者如果你正在運行不可變的第三方應用程序,這就很有好處,因為它對服務的治理是無侵入式的。同時治理模塊升級對用戶應用是透明的。

缺點也是比較明顯的:

  • 服務治理進程本身占用的系統資源也不可被忽略,20個服務,每個服務5個pod就會有100個代理容器,這種純粹的重復都會耗費資源。

    來自redhat.com/architect/why-when-service-mesh——每個微服務都有自己的代理sidecar
  • 服務網格將服務治理從應用中分離出來變成獨立的進程,這樣便增加了兩跳網絡的通信成本,勢必會對整體時延有所增加。

    服務網格的進化

用eBPF解鎖內核級服務網格

引入eBPF

由於sidecar模式的缺點,如何減少代理帶來的資源占用以及應用到代理之間的網絡延遲成為Service Mesh能否推廣的關鍵。理想的服務網格是作為Linux的一部分透明的提供服務,就像今天的TCP一樣。

為什么我們以前沒有在內核中創建一個服務網格?或者Linux社區不直接解決這些需求?我們知道,Linux內核的發展是非常緩慢而嚴謹的,它必須確保用戶使用的版本是安全的。它如果有bug,那可能就是災難級的,所以新版本的內核需要幾年的時間才能進入用戶手中。與之相對應的雲原生技術棧,它的發展,更新迭代是非常迅速的。

而eBPF的出現改變了這個狀況,它是一種內核技術,它允許自定義程序在內核中運行,從而動態地擴展Linux內核功能。

eBPF有一個巨大的優勢,eBPF代碼可以在運行時插入到現有的 Linux 內核中,類似於 Linux 內核模塊,但與內核模塊不同,它可以以安全和可移植的方式進行。這使得 eBPF 的實現能夠隨着服務網格社區的發展而繼續發展,從而使 Linux 內核能夠跟上快速發展的雲原生技術棧。

image-20220302130123264

告別服務代理,全面擁抱eBPF?

看起來eBPF能做的事情有很多,那我們可以用eBPF將所有功能寫入到操作系統內核嗎?

簡短的回答:這將是相當困難的,而且可能也不是一個正確的做法。eBPF 采用的是一個事件-處理器模型,因此其運行方式有一些限制。你可以把 eBPF 模型看成是內核的 “Function as a service”。例如,eBPF 代碼的執行路徑必須是完全確定的,會在執行前進行驗證,以確保其可以在內核中安全運行。eBPF 程序不能有任意的循環,否則驗證程序將不知道程序何時停止執行。簡而言之,eBPF 是圖靈不完整的。

圖靈完備是針對一套數據操作規則而言的概念,數據操作規則可以是一門編程語言,也可以是計算機里具體實現了的指令集。
當這套規則可以實現圖靈機的所有功能時,即可以計算出一切可計算問題,就稱它具有圖靈完備性。
圖靈不完備的語言常見原因有循環或遞歸受限(無法寫不終止的程序,如 while(true){}; ), 無法實現類似數組或列表這樣的數據結構(不能模擬紙帶). 這會使能寫的程序有限。圖靈不完備不是沒有意義的,有些場景我們需要限制語言本身. 如限制循環和遞歸, 可以保證該語言能寫的程序一定是終止的,就像我們的eBPF一樣,這也是圖靈完備可能帶來的壞處。

在許多方面,eBPF是O(1)復雜性的理想選擇(例如檢查一個數據包,操作一些比特,然后發送它)。實現像HTTP/2和gRPC這樣復雜的協議可能是O(n)復雜度,而且非常難以調試。那么,這些L7功能可以駐留在哪里?

Envoy代理已經成為服務網狀結構實現的事實上的代理,並且對我們大多數客戶需要的第7層功能有非常好的支持。雖然eBPF和Kernel可以用來改善網絡的執行(短路最佳路徑、卸載TLS/mTLS、可觀察性收集等),但復雜的協議協商、解析和用戶擴展可以保留在用戶空間。對於第7層的復雜情況,Envoy仍然是服務網狀結構的數據平面。

因此 eBPF 是優化服務網格的一種強大方式,同時我們認為 Envoy 代理是數據平面的基石。

優化服務網格

Per-Node or Sidecar?

為了減少每個應用運行一個代理帶來的資源消耗,可以采用共享代理模式,即一個節點中的所有工作負載使用一個共享代理,這種模型可以提供內存和配置開銷的優化,對大型集群而言,內存開銷時需要首要考慮的問題,這將是非常有意義的。當我們的代理從sidecar模型轉向per-node時,代理為多個程序提供連接,代理必須具有多租戶感知。這與我們從使用單個虛擬機轉向使用容器時發生的過渡完全相同。由於我們不再使用在每個虛擬機中運行的完全獨立的操作系統副本,而開始與多個應用程序共享操作系統,Linux 必須具有多租戶感知。這就是命名空間和 cgroup 存在的原因。好在Envoy 已經有了命名空間的初步概念,它們被稱為監聽器。監聽器可以攜帶單獨的配置並獨立運行。

但共享代理模型並不適用於所有人。許多企業用戶認為,因為采用邊車代理可以獲得更好的租戶和工作負載隔離,可以減少出現問題時的故障域,一些額外的內存開銷是值得的。

代理數量

除了這兩種方式來優化內存上的開銷外,還可以讓每個節點上的每個服務賬戶共享一個代理以及帶有微型代理的共享遠程代理。

img img

使用eBPF優化網絡性能

由於eBPF工作在內核層,這使得它可以繞過內核的部分網絡堆棧,使網絡性能得到顯著改善。

image-20220302130203858

在服務網格的情況下,代理在傳統網絡中作為 sidecar 運行,數據包到達應用程序的路徑相當曲折:入站數據包必須穿越主機 TCP/IP 棧,通過虛擬以太網連接到達 pod 的網絡命名空間。從那里,數據包必須穿過 pod 的網絡堆棧到達代理,代理將數據包通過回環接口轉發到應用程序。考慮到流量必須在連接的兩端流經代理,與非服務網格流量相比,這將導致延遲的顯著增加。

基於 eBPF 的 Kubernetes CNI 實現,如 Cilium,可以使用 eBPF 程序,明智地鈎住內核中的特定點,沿着更直接的路線重定向數據包。這是可能的,因為 Cilium 知道所有的 Kubernetes 端點和服務的身份。當數據包到達主機時,Cilium 可以將其直接分配到它所要去的代理或 Pod 端點。

通過per-node模型+eBPF進行網絡加速,我們的服務網格模型看起來將會是這樣:

未命名文件 (1)

eBPF在雲原生中的應用才剛剛開始,一切皆有可能!

參考鏈接:

https://www.zhaohuabing.com/post/2021-12-19-ebpf-for-service-mesh/

https://cloudnative.to/blog/how-ebpf-streamlines-the-service-mesh/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM