Kubernetes 叢集網路:Flannel 與 Calico 的區別

凌虚發表於2024-11-30

有讀者提問:FlannelCalico 的區別。文字將解析一下這兩個元件。

Flannel

Flannel 的架構非常簡單,只有兩個元件:flanneldflannel-cni-plugin

在功能特性上,Flannel 有三個部分:

  • 使用 kubernetes APIetcd 儲存資料。
  • IPAM,給節點的 Pod 分配 IP 地址範圍(podCIDR)。
  • 配置後端轉發資料包。

Flannel 支援以下後端機制進行資料包轉發:

  • VXLAN:使用 Linux kernel 的 VXLAN 封包並轉發,這種方式屬於 Overlay 網路。
  • host-gwFlannel 會直接在節點上建立 IP 路由,這種方式依賴節點之間的 L2(二層網路)的連通性。
  • WireGuard:使用 kernel 的 WireGuard 封裝並加密資料包。
  • UDP:僅除錯使用。
  • 還有一些實驗性後端,本文不做贅述。

網路模型

host-gw

host-gw 單詞縮寫的意思是使用 host 主機的 gateway。這種方式不會額外地封裝資料包,但要求節點之間的 L2 連通性。

使用 host-gw 時,Flannel 做的事情就是透過 github.com/vishvananda/netlink 這個第三方庫去配置主機路由表,即執行 ip route ... 命令,例如:

ip route add <destination> via <gateway> dev <device>

假設我們有以下三個節點:

  • node01:主機 IP 是 192.168.1.1,podCIDR 是 10.244.1.0/24
  • node02:主機 IP 是 192.168.1.2,podCIDR 是 10.244.2.0/24
  • node03:主機 IP 是 192.168.1.3,podCIDR 是 10.244.3.0/24

那麼使用 host-gw 時,Flannel 會把 node01 的主機路由表配置為類似以下形式:

# node01 本地路由
10.244.1.0/24 dev flannel.1 proto kernel scopee link

# node02 路由
10.244.2.0/24 via 192.168.1.2 dev eth0

# node03 路由
10.244.3.0/24 via 192.168.1.3 dev eth0

node02 節點上同樣配置類似的主機路由表:

# node01 路由
10.244.1.0/24 via 192.168.1.1 dev eth0

# node02 本地路由
10.244.2.0/24 dev flannel.1 proto kernel scopee link

# node03 路由
10.244.3.0/24 via 192.168.1.3 dev eth0

其它節點類似。

node01 節點上的 Pod 想要向 node02 節點上的 Pod 傳送資料時,會先根據以上路由表得知目標 IP 地址,然後透過 ARP 協議得到該地址對應的 MAC 地址(L2 資料鏈路層地址),再把資料包封裝為資料幀傳輸。

L2 的連通性要求節點之間能夠在資料鏈路層直接通訊,這通常意味著節點必須位於同一廣播域(如同一個子網)。此時,資料幀可以透過二層裝置(如交換機)基於目標 MAC 地址直接轉發,而無需三層裝置(如路由器)進行 IP 層轉發。廣播域的範圍決定了 L2 通訊的有效範圍。

如果節點位於不同子網或透過路由器連線,儘管源節點可以透過路由表得知目標 IP 地址,但由於目標 IP 不在本地子網,源節點需要透過 ARP 獲取下一跳路由器的 MAC 地址,而非目標節點的 MAC 地址。資料幀首先傳送到路由器,路由器在轉發時根據目標網路重新封裝幀。這種場景下,host-gw 模式依賴的直接二層轉發機制無法實現。

host-gw 模式資料轉發上能得到更高的效能,沒有額外的封包過程,L2 直連,但是由於每個節點都要配置全量的主機路由表,當節點數量龐大、節點上下線頻繁時會有不小的挑戰。

更多關於 L2 直連的規模問題,可以參考 Concerns over Ethernet at scale

VXLAN

如果無法保證 L2 的直接連通性,則需要使用 VXLAN 這種 Overlay 的方式,在原有資料幀之外進行一層額外的封裝。

此時,即使節點位於不同的子網,或透過路由器等裝置組網都沒有關係,但是 VXLAN 要求 L3 必須連通,即透過節點的 IP 地址能夠進行通訊。因此,VXLAN 也稱為 L2 over L3,不用管下層 L2 是什麼樣的,只要 L3 連通即可。

FlannelVXLAN 模式下做的事情也是透過 github.com/vishvananda/netlink 這個第三方庫去執行 ip link ... 命令:

ip link add <vxlan-name> type vxlan id <vxlan-id> dev <device> ...

這也就是說 Flannel 本身不進行任何資料包的封裝和轉發,是系統核心在做實際的工作。

Calico

Calico 的架構則更加複雜,由多個元件構成。

其中:

  • Calico API server:使用者可以使用 kubectl 直接管理 Calico 資源。
  • Calico kube-controllers:監控資源並執行操作。
  • Datastore plugin:使用 kubernetes APIetcd 儲存資料。
  • Typha:作為資料儲存和 Felix 例項之間的守護程序執行,減少資料儲存的負載以增加叢集規模。在大規模(100 個節點以上)的叢集中必不可少。
  • Felix:執行在每個節點上,控制節點的網路介面、路由、ACL 流量控制和安全策略、以及報告狀態等。
  • BIRD:在承載 Felix 的每個節點上執行,從 Felix 獲取路由並分發給網路中的 BGP 對等點,用於主機間路由。
  • confd:監控資料儲存中 BGP 配置和 AS 號、日誌級別和 IPAM 等全域性預設值的變化,動態生成 BIRD 配置檔案,並觸發 BIRD 載入新的配置。
  • Dikastes:可選,為 Istio 服務網格執行網路策略。作為 Istio Envoy 的 sidecar 代理在叢集上執行。
  • CNI pluginIPAM plugin
  • calicoctl:命令列工具。

CalicoFlannel 一樣使用 kubernetes APIetcd 儲存資料,不同的是 Calico 在資料儲存與消費者之間增加了一箇中間層 Typha,減少了儲存側的負擔,以支援更大規模的叢集。

CalicoFlannel 一樣都支援 IPAM(給節點分配 podCIDR),不同的是 Flannel 是靜態的,而 Calico 可以動態分配。

網路模型

Calico 支援 Overlay 的網路模型,包括 VXLANIP-in-IPIPIPFlannel 中處於實驗性階段),它同樣是使用 vishvananda/netlink 這個第三方庫去配置系統核心,由核心進行封包和轉發。換句話說,如果兩者都使用 VXLAN,那麼封包和轉發效能沒有任何差別。

Calico 支援 non-overlay 模式,類似於 Flannel 中的 host-gw,但 Calico 的實現方式有區別,每個節點負責路由自己的 Pod 子網,並透過 BGP 協議將路由資訊分發給其他節點,能夠實現更靈活的路由控制,支援更復雜的網路拓撲。

Calico 透過 BGP 協議可以支援 Pod IP 在叢集外部可路由,而 Flannel 並不支援這點。

此外,Calico 針對不同的雲供應商環境做了貼心的適配,並且額外支援 eBPFPrometheus 監控、network policy 網路策略和流量管控(Flannel 並不支援這些)。

總結

Flannel 的架構非常簡單,在小規模叢集上能夠很好的工作。

Calico 的架構更加複雜,不僅支援 Flannel 具備的所有功能,還提供了更多的網路模型(如 IPIPBGP),並支援 eBPF、監控、網路策略和流量管控等諸多功能,適用於更大規模的叢集。


(我是凌虛,關注我,無廣告,專注技術,不煽動情緒,歡迎與我交流)


參考資料:

  • https://github.com/flannel-io/flannel
  • https://docs.tigera.io/calico/latest/networking/determine-bes...

相關文章