有讀者提問:Flannel
與 Calico
的區別。文字將解析一下這兩個元件。
Flannel
Flannel
的架構非常簡單,只有兩個元件:flanneld
和 flannel-cni-plugin
。
在功能特性上,Flannel
有三個部分:
- 使用
kubernetes API
或etcd
儲存資料。 IPAM
,給節點的 Pod 分配 IP 地址範圍(podCIDR
)。- 配置後端轉發資料包。
Flannel
支援以下後端機制進行資料包轉發:
VXLAN
:使用 Linux kernel 的VXLAN
封包並轉發,這種方式屬於Overlay
網路。host-gw
:Flannel
會直接在節點上建立 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 連通即可。
Flannel
在 VXLAN
模式下做的事情也是透過 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 API
或etcd
儲存資料。Typha
:作為資料儲存和Felix
例項之間的守護程序執行,減少資料儲存的負載以增加叢集規模。在大規模(100 個節點以上)的叢集中必不可少。Felix
:執行在每個節點上,控制節點的網路介面、路由、ACL 流量控制和安全策略、以及報告狀態等。BIRD
:在承載Felix
的每個節點上執行,從Felix
獲取路由並分發給網路中的BGP
對等點,用於主機間路由。confd
:監控資料儲存中 BGP 配置和 AS 號、日誌級別和 IPAM 等全域性預設值的變化,動態生成BIRD
配置檔案,並觸發 BIRD 載入新的配置。Dikastes
:可選,為 Istio 服務網格執行網路策略。作為 Istio Envoy 的 sidecar 代理在叢集上執行。CNI plugin
和IPAM plugin
。calicoctl
:命令列工具。
Calico
和 Flannel
一樣使用 kubernetes API
或 etcd
儲存資料,不同的是 Calico
在資料儲存與消費者之間增加了一箇中間層 Typha
,減少了儲存側的負擔,以支援更大規模的叢集。
Calico
和 Flannel
一樣都支援 IPAM
(給節點分配 podCIDR
),不同的是 Flannel
是靜態的,而 Calico
可以動態分配。
網路模型
Calico
支援 Overlay
的網路模型,包括 VXLAN
和 IP-in-IP
(IPIP
在 Flannel
中處於實驗性階段),它同樣是使用 vishvananda/netlink
這個第三方庫去配置系統核心,由核心進行封包和轉發。換句話說,如果兩者都使用 VXLAN
,那麼封包和轉發效能沒有任何差別。
Calico
支援 non-overlay
模式,類似於 Flannel
中的 host-gw
,但 Calico
的實現方式有區別,每個節點負責路由自己的 Pod 子網,並透過 BGP
協議將路由資訊分發給其他節點,能夠實現更靈活的路由控制,支援更復雜的網路拓撲。
Calico
透過 BGP
協議可以支援 Pod IP 在叢集外部可路由,而 Flannel
並不支援這點。
此外,Calico
針對不同的雲供應商環境做了貼心的適配,並且額外支援 eBPF
、Prometheus
監控、network policy
網路策略和流量管控(Flannel
並不支援這些)。
總結
Flannel
的架構非常簡單,在小規模叢集上能夠很好的工作。
Calico
的架構更加複雜,不僅支援 Flannel
具備的所有功能,還提供了更多的網路模型(如 IPIP
、BGP
),並支援 eBPF
、監控、網路策略和流量管控等諸多功能,適用於更大規模的叢集。
(我是凌虛,關注我,無廣告,專注技術,不煽動情緒,歡迎與我交流)
參考資料:
- https://github.com/flannel-io/flannel
- https://docs.tigera.io/calico/latest/networking/determine-bes...