目錄
專欄介紹
作者與平臺
您將學到什么?
學習特色
網絡模型深度解析:CNI、Pod通信與NetworkPolicy
第一部分:CNI 插件原理 - 網絡基礎設施的構建者
1.1 CNI 規范:標準化網絡接入的基石
1.2 Flannel:簡單高效的覆蓋網絡方案
1.3 Calico:高性能、安全、可擴展的網絡與策略方案
1.4 Flannel vs Calico:深度對比
第二部分:Pod 通信與跨節點路由 - 數據包的旅程
2.1 同節點 Pod 通信 (Intra-Node Communication)
2.2 跨節點 Pod 通信 (Inter-Node Communication) - Flannel (VXLAN)
2.3 跨節點 Pod 通信 (Inter-Node Communication) - Calico (純 BGP)
2.4 跨節點路由總結與對比
第三部分:網絡策略 (NetworkPolicy) - 微服務安全的守護者
3.1 NetworkPolicy 核心概念與模型
3.2 NetworkPolicy 實現原理 - 以 Calico 為例
3.3 NetworkPolicy 最佳實踐與常見場景
總結
專欄介紹
作者與平臺
作者:庸子
用戶ID:2401_86478612
第一發表平臺:CSDN
歡迎來到《Kubernetes架構師之路:系統化學習與實踐》專欄!在這個容器化技術主導的時代,Kubernetes已成為云原生應用編排的事實標準,掌握Kubernetes已成為每位開發者和運維工程師的必備技能。
本專欄采用系統化學習方法,從基礎概念到高級實踐,循序漸進地帶您全面掌握Kubernetes技術棧。無論您是剛接觸容器技術的初學者,還是希望深入理解Kubernetes架構的資深工程師,這里都將為您提供清晰的學習路徑和實用的實戰指導。
您將學到什么?
- 基礎理論:深入理解容器、容器編排、Kubernetes核心概念和架構設計
- 核心組件:掌握etcd、API Server、Controller Manager、Scheduler等核心組件的工作原理
- 資源管理:學會Pod、Deployment、Service、Ingress等核心資源的創建與管理
- 網絡與存儲:理解Kubernetes網絡模型和存儲方案,解決實際部署中的網絡與存儲問題
- 高可用與擴展:構建高可用的Kubernetes集群,實現應用的自動擴展與故障恢復
- 監控與日志:掌握集群監控、日志收集與應用性能優化方法
- CI/CD集成:學習如何將Kubernetes與CI/CD流程結合,實現自動化部署
- 安全實踐:了解Kubernetes安全模型,掌握RBAC、網絡策略等安全配置
學習特色
- 系統化知識體系:從零開始,構建完整的Kubernetes知識框架
- 實戰導向:每個知識點都配有實際操作案例,讓您"學以致用"
- 問題驅動:針對實際部署中常見的問題提供解決方案
- 最新版本覆蓋:基于最新穩定版Kubernetes,緊跟技術發展趨勢
- 架構師視角:不僅教您"如何做",更解釋"為什么這樣設計"
無論您是想提升個人競爭力,還是為企業構建高效的云原生基礎設施,本專欄都將助您成為真正的Kubernetes專家。讓我們一起開啟這段激動人心的Kubernetes學習之旅!
立即訂閱,開啟您的Kubernetes架構師成長之路!
Kubernetes 的網絡模型是其核心優勢之一,它提供了一個扁平、無 NAT、Pod 間可直接通信的環境。然而,實現這一看似簡單的模型背后,卻隱藏著復雜的架構和精心設計的組件。本文將深入剖析 Kubernetes 網絡的三大支柱:CNI 插件原理(聚焦 Flannel 與 Calico 的對比)、Pod 通信機制(特別是跨節點路由)以及 NetworkPolicy 的實現,力求在 15000 字的篇幅內,揭示其深度技術細節、設計哲學與工程實踐。
第一部分:CNI 插件原理 - 網絡基礎設施的構建者
1.1 CNI 規范:標準化網絡接入的基石
CNI (Container Network Interface) 并非 Kubernetes 獨創,而是一個由 CNCF (Cloud Native Computing Foundation) 托管的開放標準。其核心目標是解耦容器運行時與網絡實現,定義了一套通用的接口規范,讓容器運行時(如 Docker, containerd, CRI-O)能夠通過調用符合 CNI 標準的可執行文件(插件),為容器配置網絡。
核心工作流程:
- 觸發時機: 當 Kubelet 需要為 Pod 創建網絡命名空間(
netns
)時(即 PodADDED
事件),或刪除 Pod 網絡命名空間時(PodDELETED
事件)。 - 調用插件: Kubelet 根據配置(通常位于
/etc/cni/net.d/
目錄下的.conf
或.conflist
文件)找到對應的 CNI 插件可執行文件(如flannel
,calico-ipam
,calico
)。 - 傳遞參數: Kubelet 通過環境變量和標準輸入(stdin)向插件傳遞關鍵信息:
-
- 環境變量:
CNI_COMMAND
:ADD
(創建網絡) 或DEL
(刪除網絡)。 CNI_CONTAINERID
: 容器 ID。CNI_NETNS
: 容器網絡命名空間的路徑(如/var/run/netns/<nsname>
)。CNI_IFNAME
: 容器內要創建的虛擬網卡名稱(默認eth0
)。CNI_ARGS
: 額外的參數(如K8S_POD_NAMESPACE
,K8S_POD_NAME
,K8S_POD_UID
)。
- 環境變量:
- 標準輸入 (stdin): 一個 JSON 格式的網絡配置對象,包含:
cniVersion
: CNI 規范版本。name
: 網絡名稱。type
: 插件類型(如flannel
,calico
,bridge
)。ipam
: IP 地址管理配置(類型、子網、路由等)。dns
: DNS 配置(nameservers, domain, search)。- 插件特定的配置(如 Flannel 的
subnetFile
, Calico 的etcd_endpoints
)。 - 插件執行:
ADD
操作:插件進入容器的netns
。 - 創建虛擬網卡對(veth pair):一端在容器內(
eth0
),另一端在宿主機上(如veth<random>
)。 - 為容器內的
eth0
分配 IP 地址、設置路由(根據 IPAM 配置)。 - 將宿主機端的 veth 設備連接到指定的網絡接口(如網橋、OVS 交換機)或進行路由配置。
- 可選:設置 ARP、iptables 規則等。
- 通過標準輸出(stdout)返回一個 JSON 結果,包含分配的 IP 地址、網關、DNS、路由等信息。
DEL
操作:插件根據傳入的參數,找到并刪除為該容器創建的網絡資源:刪除 veth pair、釋放 IP 地址、清理相關的路由/iptables 規則等。- 無需返回結果。
-
- 結果處理: Kubelet 接收插件返回的結果(
ADD
時),將其記錄到 Pod 的狀態中(status.podIP
),或執行清理(DEL
時)。
CNI 插件生態:
- 主插件 (Main Plugin): 負責創建網絡接口、連接到網絡(如
bridge
,vlan
,macvlan
,ipvlan
,ptp
,host-local
,flannel
,calico
,weave-net
,cilium
)。 - IPAM 插件 (IP Address Management): 負責分配和管理 IP 地址(如
host-local
(基于本地文件/目錄)、dhcp
、static
、calico-ipam
(集成到 Calico 數據庫))。 - 元插件 (Meta Plugin): 調用其他 CNI 插件組合實現更復雜功能(如
flannel
實際上是一個元插件,它調用bridge
或host-local
IPAM;multus
用于多網絡)。
1.2 Flannel:簡單高效的覆蓋網絡方案
設計哲學: Flannel 的核心目標是簡單、易用、快速部署。它通過創建一個**覆蓋網絡(Overlay Network)**來解決跨節點 Pod 通信問題,將不同節點上的 Pod 置于一個邏輯上的大二層網絡中。
核心組件與工作原理:
- etcd/Consul (后端存儲): Flannel 使用 etcd 或 Consul 存儲關鍵的網絡配置信息,主要是:
- 網絡配置:整個集群的 Overlay 網絡 CIDR(如
10.244.0.0/16
)。 - 子網分配:每個節點被分配一個唯一的子網(如
10.244.1.0/24
,10.244.2.0/24
)。這個信息由flanneld
守護進程啟動時向 etcd 注冊并獲取。
- 網絡配置:整個集群的 Overlay 網絡 CIDR(如
- flanneld 守護進程: 在每個 Kubernetes 節點上運行,是 Flannel 的核心。
- 啟動: 讀取配置(
/etc/sysconfig/flanneld
或命令行參數),連接 etcd。 - 子網租約: 向 etcd 申請并租用一個子網(Lease)。租約信息包含子網 CIDR 和該節點的公網 IP(或用于 Overlay 通信的 IP)。
- 后端實現選擇: Flannel 支持多種后端(Backend)數據封裝/路由方式,通過
-backend
參數指定:vxlan
(默認推薦): 使用 VXLAN (Virtual eXtensible LAN) 隧道技術。- 原理: 在宿主機內核創建一個 VXLAN 隧道設備(
flannel.1
)。當需要發送跨節點 Pod 流量時:- 源 Pod (
10.244.1.2
) 發送數據包給目標 Pod (10.244.2.3
)。 - 數據包到達源節點宿主機網絡棧。
- 源節點根據目標 IP (
10.244.2.3
) 查詢 Flannel 維護的路由表(由flanneld
根據 etcd 中的子網信息生成)。路由表指示目標子網10.244.2.0/24
通過flannel.1
設備可達。 - 內核 VXLAN 模塊接管:
- 將原始 Pod 數據包(源 IP:
10.244.1.2
, 目標 IP:10.244.2.3
)作為 Payload。 - 封裝一個 UDP 包:
- 源 IP:源節點宿主機 IP(如
192.168.1.101
)。 - 目標 IP:目標節點宿主機 IP(如
192.168.1.102
)。 - 源端口:隨機端口。
- 目標端口:
8472
(VXLAN 默認端口)。 - VXLAN Header:包含 VNI (VXLAN Network Identifier),用于標識不同的 VXLAN 網絡(Flannel 通常使用
1
)。
- 源 IP:源節點宿主機 IP(如
- 封裝一個 Ethernet II 幀(源/目標 MAC 為宿主機網卡 MAC)。
- 將原始 Pod 數據包(源 IP:
- 封裝后的 UDP 包通過宿主機物理網卡發送到目標節點。
- 目標節點收到 UDP 包,內核 VXLAN 模塊解封裝,提取出原始 Pod 數據包。
- 目標節點根據目標 IP (
10.244.2.3
) 查詢本地路由,將數據包轉發到目標 Pod 所在的 veth pair,最終到達目標 Pod。
- 源 Pod (
- 優點: 對底層網絡要求低(只需三層可達),支持大規模集群,性能相對較好(內核級封裝)。
- 缺點: 有封裝開銷(增加 50-54 字節頭部),MTU 需調整(通常設置為
1400
或1450
),網絡路徑變長。
- 原理: 在宿主機內核創建一個 VXLAN 隧道設備(
host-gw
(主機網關): 利用節點作為網關。- 原理:
flanneld
在每個節點上創建指向其他節點子網的路由條目。例如,在節點 A 上添加路由:ip route add 10.244.2.0/24 via 192.168.1.102 dev eth0
。- 通信流程:源 Pod (
10.244.1.2
) 發送數據包給目標 Pod (10.244.2.3
)。 - 數據包到達源節點宿主機。
- 源節點查詢路由表,發現目標子網
10.244.2.0/24
的下一跳是目標節點 IP (192.168.1.102
)。 - 源節點直接將原始 Pod 數據包(源 IP:
10.244.1.2
, 目標 IP:10.244.2.3
)通過物理網卡發送給目標節點(目標 MAC 是目標節點網卡的 MAC)。 - 目標節點收到數據包,查詢本地路由,將數據包轉發到目標 Pod。
- 通信流程:源 Pod (
- 優點: 性能最佳(無封裝開銷,直接路由),MTU 無需調整。
- 缺點: 要求所有節點在同一個二層網絡(L2)中,或者底層網絡支持直接路由到 Pod IP(通常需要配置靜態路由或動態路由協議如 BGP)。擴展性受限于二層網絡規模或路由表大小。
- 原理:
udp
(早期/兼容): 使用用戶態的 TAP 設備和 UDP 封裝。- 原理:
flanneld
創建一個 TAP 設備(flannel0
),所有 Pod 流量都經過這個設備。flanneld
在用戶態讀取數據包,封裝成 UDP 包(源/目標端口8285
),再通過物理網卡發送。目標節點的flanneld
接收 UDP 包,解封裝后寫入本地的 TAP 設備。 - 優點: 兼容性好,對內核無特殊要求。
- 缺點: 性能最差(用戶態切換開銷大),已基本被
vxlan
取代。
- 原理:
alloc
(僅測試): 只分配子網,不創建網絡設備。ipip
(較少用): 使用 IPIP 隧道(IP in IP),類似 VXLAN 但更簡單(無 UDP 端口和 VNI),性能略好于 UDP 但差于 VXLAN,同樣有 MTU 問題。
- 啟動: 讀取配置(
- CNI 集成: Flannel 提供了一個 CNI 插件(通常是
/opt/cni/bin/flannel
)。這個插件本身不創建網絡設備,它的主要作用是:- 讀取
flanneld
寫入的配置文件(通常是/run/flannel/subnet.env
),獲取當前節點的子網信息(FLANNEL_SUBNET
)、MTU(FLANNEL_MTU
)和后端類型(FLANNEL_NETWORK
)。 - 根據后端類型,調用其他 CNI 插件來完成實際的網絡配置:
- 對于
vxlan
/host-gw
/udp
/ipip
:調用bridge
插件(創建cni0
網橋)和host-local
IPAM 插件(從FLANNEL_SUBNET
中分配 Pod IP)。 - 將
veth
設備的一端插入cni0
網橋。 - 設置 Pod 內部的 IP 地址、路由(默認路由指向網橋 IP)。
- 設置
FLANNEL_MTU
到 Pod 的eth0
接口。
- 對于
- 返回配置結果給 Kubelet。
- 讀取
Flannel 架構總結:
- 中心化存儲 (etcd): 管理全局網絡配置和子網分配。
- 節點守護進程 (flanneld): 負責子網租約、后端網絡配置(創建隧道設備/路由)、生成 CNI 所需的配置文件。
- CNI 插件 (flannel): 輕量級適配器,調用
bridge
和host-local
完成容器網絡接入,利用flanneld
提供的信息。 - 后端 (vxlan/host-gw): 實現跨節點數據包的封裝或路由。
1.3 Calico:高性能、安全、可擴展的網絡與策略方案
設計哲學: Calico 的目標是提供高性能、原生三層路由、細粒度網絡策略的解決方案。它摒棄了傳統的覆蓋網絡,致力于利用標準的 BGP (Border Gateway Protocol) 和 Linux 內核網絡功能,構建一個純三層、可擴展、安全的 Pod 網絡。
核心組件與工作原理:
- etcd/Kubernetes API (數據存儲): Calico 可以使用獨立的 etcd 集群,或者更常見地,直接使用 Kubernetes API 作為其數據存儲后端(
Datastore
模式)。存儲的信息包括:- IP 池(IPPool):定義可分配給 Pod 的 IP 地址范圍(如
192.168.0.0/16
)。 - 節點(Node):記錄每個節點的信息,包括其 BGP AS 號、IP 地址、隧道 IP(如果啟用 IPIP)。
- 工作負載端點(WorkloadEndpoint):每個 Pod 的網絡端點信息,包含其 IP、MAC、所屬節點、命名空間、標簽等。
- 網絡策略(NetworkPolicy):定義的訪問控制規則。
- BGP 對等體(BGP Peer):配置的 BGP 鄰居信息。
- IP 池(IPPool):定義可分配給 Pod 的 IP 地址范圍(如
- Felix (節點代理): 在每個 Kubernetes 節點上運行,是 Calico 的核心執行引擎。
-
- 職責:接口管理: 創建和管理 Calico 使用的網絡接口(如
tunl0
用于 IPIP)。 - 路由編程: 根據從
Datastore
獲取的信息(主要是其他節點的 Pod CIDR 和 BGP 路由信息),在 Linux 內核的路由表中動態添加/刪除路由條目。這是 Calico 實現跨節點通信的關鍵。 - ACL 編程: 將 NetworkPolicy 規則翻譯成 Linux 內核的 iptables 或 nftables 規則,實現 Pod 間的訪問控制。
- IP 地址管理: 配置 Pod 網絡接口的 IP 地址(通過調用 CNI 或直接操作)。
- 狀態報告: 向
Datastore
報告節點狀態和健康信息。
- 職責:接口管理: 創建和管理 Calico 使用的網絡接口(如
-
- BIRD (BGP 守護進程): 在每個節點上運行(或作為 Felix 的子進程),是一個標準的 BGP 路由器。
-
- 職責:建立 BGP 會話: 與集群內其他節點的 BIRD 建立 iBGP(內部 BGP)會話(通常使用同一個 AS 號)。
- 路由分發: 將本節點上運行的 Pod 的 IP 地址(或整個 Pod CIDR,取決于配置)作為路由信息,通過 BGP 協議宣告(Advertise) 給集群內的其他節點。
- 路由學習: 接收并學習其他節點宣告的 Pod IP/CIDR 路由。
- 最佳路徑選擇: 根據 BGP 路徑屬性(如 AS_PATH)選擇到達目標 Pod IP 的最佳下一跳。
- 外部連接: 可配置與物理網絡中的 BGP 路由器(如 ToR 交換機)建立 eBGP(外部 BGP)會話,將 Pod IP 路由宣告到物理網絡,實現 Pod IP 的外部可達性(可選)。
-
- confd (配置生成器 - 可選/舊版): 監聽
Datastore
中的變化(如 BGP Peer 配置),動態生成 BIRD 的配置文件(bird.cfg
)并重載 BIRD。在新版本中,Felix 可能直接管理 BIRD 配置。- CNI 插件 (calico, calico-ipam):
calico-ipam
: Calico 的 IPAM 插件。它直接從Datastore
中管理的 IPPool 里為 Pod 分配 IP 地址。支持多種分配模式(如順序、隨機)。 calico
: Calico 的主 CNI 插件。當 Kubelet 調用它時:- 調用
calico-ipam
為 Pod 分配 IP。 - 在 Pod 的
netns
中創建 veth pair。 - 將宿主機端的 veth 設備連接到 Calico 的網絡接口(通常是直接路由,不依賴網橋)。
- 為 Pod 內的
eth0
設置 IP 地址、路由(默認路由指向 Felix 配置的網關,通常是節點 IP)。 - 關鍵點: Calico 默認不創建網橋。Pod 的 veth 設備直接連接到節點的根網絡命名空間。Felix 負責在節點上配置到所有其他 Pod IP 的直接路由。
- 返回配置結果給 Kubelet。
- 調用
- CNI 插件 (calico, calico-ipam):
- IPIP 模式: Calico 默認使用 純三層路由(BGP)。但在某些場景下(如節點不在同一二層網絡且無法配置物理路由),可以啟用 IPIP (IP in IP) 隧道模式。
- 原理: 類似 Flannel 的
ipip
后端。Felix 會在每個節點創建一個tunl0
隧道設備。當需要發送跨節點 Pod 流量時:- 源節點根據 Felix 配置的路由表,發現目標 Pod IP 需要通過
tunl0
發送。 - 內核 IPIP 模塊將原始 Pod 數據包(源 IP:
PodA_IP
, 目標 IP:PodB_IP
)封裝在一個新的 IP 包中:- 新 IP 包源 IP:源節點 IP。
- 新 IP 包目標 IP:目標節點 IP。
- 協議號:
4
(IPIP)。
- 封裝后的 IP 包通過物理網絡發送到目標節點。
- 目標節點內核 IPIP 模塊解封裝,提取原始 Pod 數據包。
- 目標節點根據目標 IP (
PodB_IP
) 查詢本地路由(由 Felix 配置),將數據包發送到目標 Pod。
- 源節點根據 Felix 配置的路由表,發現目標 Pod IP 需要通過
- 啟用方式: 在 IPPool 配置中設置
ipipMode: Always
或CrossSubnet
(僅在跨子網時使用 IPIP)。 - 影響: 啟用 IPIP 會引入封裝開銷(增加 20 字節),影響 MTU(通常設置為
1480
),但解決了跨子網路由問題,性能仍優于 VXLAN(無 UDP 頭部)。
- 原理: 類似 Flannel 的
- BGP 路由模式: 這是 Calico 的核心優勢和默認模式。
- 全互聯 (Full Mesh): 在集群內部,Calico 默認配置所有節點之間建立 iBGP 會話,形成一個全互聯的 BGP 拓撲。每個節點都將自己負責的 Pod CIDR(或具體 Pod IP)宣告給所有其他節點。
- 路由反射器 (Route Reflector - RR): 當節點數量很大時(如 > 50),全互聯的 BGP 會話數量會呈 O(N2) 增長,導致管理復雜和資源消耗。Calico 支持部署 BGP Route Reflector。節點只需與 RR 建立 iBGP 會話,RR 負責在節點之間反射路由信息,大大減少會話數量(O(N))。RR 可以是專用節點,也可以復用 Kubernetes Master 節點(需注意高可用)。
- eBGP 對接物理網絡: Calico 節點可以與物理網絡設備(如 ToR 交換機)建立 eBGP 會話。節點將 Pod IP 路由宣告給物理設備,物理設備再將這些路由宣告到更廣的網絡中。這使得:
- Pod IP 可以被外部網絡直接路由訪問(無需 NAT)。
- 外部流量可以直接路由到 Pod IP(無需經過 NodePort 或 LoadBalancer 的額外跳轉)。
- 簡化了網絡架構,減少了 SNAT/DNAT 的性能損耗。
- 無覆蓋網絡: 在純 BGP 模式下(無 IPIP),Pod 之間的通信完全依賴物理網絡的三層路由能力。數據包從源 Pod 發出,經過源節點路由,直接通過物理網絡路由到目標節點,再由目標節點路由到目標 Pod。沒有隧道封裝,性能接近物理網絡。
Calico 架構總結:
- 數據存儲 (etcd/K8s API): 集中管理所有網絡狀態、策略和配置。
- 節點代理 (Felix): 核心大腦,負責路由編程(Linux 路由表)、策略編程(iptables/nftables)、接口管理、狀態報告。
- BGP 路由器 (BIRD): 路由引擎,負責通過 BGP 協議在節點間(iBGP)或與物理網絡(eBGP)分發和學習 Pod IP 路由。
- CNI 插件 (calico/calico-ipam): 負責 Pod 網絡接入和 IP 地址分配,利用 Felix 和 BGP 提供的路由基礎設施。
- 路由模式: 純 BGP(高性能,要求底層路由) 或 BGP + IPIP(兼容性更好,有封裝開銷)。
- 策略引擎: Felix 將 NetworkPolicy 轉化為高效的內核級 ACL。
1.4 Flannel vs Calico:深度對比
特性維度 | Flannel | Calico | 深度解析與權衡 |
核心原理 | 覆蓋網絡 (Overlay) | 純三層路由 (BGP) / IPIP 隧道 | Flannel 通過隧道(VXLAN/UDP/IPIP)或主機網關(host-gw)在現有網絡上構建一個邏輯二層網絡,隔離了 Pod 網絡和物理網絡。Calico 則致力于將 Pod 網絡融入物理網絡的三層路由體系,利用 BGP 實現高效路由。 |
性能 | 中等 (vxlan/udp/ipip) / 優秀 (host-gw) | 優秀 (純 BGP) / 良好 (IPIP) | Flannel host-gw 和 Calico 純 BGP 性能最佳,無封裝開銷,接近物理網絡性能。Flannel vxlan/udp/ipip 和 Calico IPIP 因隧道封裝(增加 20-54 字節頭部)和內核/用戶態處理開銷,性能有損耗(通常 10%-30%)。Calico 純 BGP 在大規模下性能優勢更明顯。 |
網絡模型 | 二層 Overlay (vxlan/udp/ipip) / 三層直連 (host-gw) | 純三層 (BGP/IPIP) | Flannel 在 Overlay 模式下,Pod 通信邏輯上是二層廣播域,物理上是三層封裝。host-gw 模式下是純三層,但依賴底層 L2 或靜態路由。Calico 始終是三層模型,Pod IP 就是路由表中的目標地址。 |
復雜度 | 低 | 中高 | Flannel 部署配置極其簡單( |
擴展性 | 良好 (vxlan) / 受限 (host-gw)** | 優秀 (BGP + RR) | Flannel vxlan 基于 L3 Overlay,擴展性很好,支持大規模集群。host-gw 受限于 L2 域大小或靜態路由維護能力。Calico 基于 BGP,天然具備互聯網級的擴展能力,通過 Route Reflector 可輕松支持數千節點規模。 |
對底層網絡要求 | 低 (vxlan/udp/ipip - 只需 L3 可達) / 高 (host-gw - 需 L2 或靜態路由) | 高 (純 BGP - 需 L3 路由支持或 eBGP 對接) / 中 (IPIP - 只需 L3 可達) | Flannel Overlay 模式對底層網絡要求最低,只要節點間 IP 可通即可。host-gw 要求苛刻。Calico 純 BGP 要求底層網絡能夠路由 Pod IP 流量(要么節點在同一 L2,要么物理設備支持動態路由或配置靜態路由到節點)。IPIP 模式降低了對底層的要求,只需 L3 可達。 |
網絡策略 (NetworkPolicy) | 不支持原生 (需集成 Canal/Cilium 等) | 原生支持,功能強大且高效 | Flannel 本身不實現 NetworkPolicy。若需策略,需部署其他 CNI(如 Canal = Flannel + Calico Felix,或 Cilium)。Calico 原生、深度集成 NetworkPolicy,由 Felix 直接翻譯為內核 iptables/nftables 規則,性能高,支持豐富的規則(基于標簽、命名空間、端口、協議、IP 段等)。 |
IP 地址管理 (IPAM) | 簡單 (host-local) | 強大 (calico-ipam) | Flannel 通常使用 |
外部網絡集成 | 困難 (通常需要 SNAT/DNAT) | 優秀 (通過 eBGP 宣告 Pod IP 路由) | Flannel 的 Pod IP 是私有 Overlay 地址,外部無法直接訪問。暴露服務需依賴 Kubernetes Service (NodePort/LoadBalancer) 或 Ingress,涉及 SNAT/DNAT。Calico 通過 eBGP 將 Pod IP 路由宣告到物理網絡,Pod IP 可被外部網絡直接路由訪問,無需 NAT,簡化架構,提升性能(尤其對東西向流量)。 |
MTU 處理 | 需手動調整 (通常 | 需手動調整 (純 BGP 無需, IPIP 需 | 所有隧道方案(Flannel vxlan/udp/ipip, Calico IPIP)都因封裝頭導致有效 MTU 減小,必須在 CNI 配置或網絡插件中設置正確的 MTU(通常比物理網絡 MTU 小 20-50 字節),否則可能導致分片或連接問題。Flannel host-gw 和 Calico 純 BGP 無此問題。 |
適用場景 | 中小規模集群、開發測試環境、對網絡策略要求不高、追求簡單快速部署 | 大規模生產環境、對性能要求高、需要細粒度網絡策略、需要外部直接路由 Pod IP、網絡架構復雜 | Flannel 是入門和中小型集群的理想選擇,開箱即用,滿足基本需求。Calico 是企業級生產環境的首選方案之一,尤其適合性能敏感、安全要求高、網絡規模大或需要深度網絡集成的場景。其復雜度帶來的管理成本在大型環境中是值得的。 |
選擇建議:
- 選 Flannel: 集群規模小(< 50 節點)、團隊網絡經驗有限、追求極致部署簡便性、當前或可預見的未來不需要 NetworkPolicy、對性能要求不是極端苛刻、底層網絡環境簡單(如公有云 VPC 內同一子網)。
- 選 Calico: 集群規模大(> 50 節點或有擴展計劃)、對網絡性能有高要求(尤其東西向流量)、必須使用 NetworkPolicy 實現安全隔離、需要 Pod IP 被外部網絡直接路由訪問(避免 NAT 性能損耗和復雜性)、底層網絡支持 BGP 或愿意配置 IPIP、團隊具備一定的 BGP 和網絡排錯能力。
- 折中方案 (Canal): 如果既想要 Flannel 的簡單部署(Overlay),又需要 Calico 的 NetworkPolicy,可以選擇 Canal 項目。它將 Flannel 作為網絡數據平面,同時部署 Calico 的 Felix 來提供 NetworkPolicy 功能。但性能和擴展性受限于 Flannel 的 Overlay 后端。
第二部分:Pod 通信與跨節點路由 - 數據包的旅程
理解了 CNI 如何構建網絡基礎設施后,我們深入探究 Pod 之間是如何通信的,特別是跨越不同物理節點時,數據包是如何被正確路由的。我們將結合 Flannel (VXLAN) 和 Calico (純 BGP) 兩種典型模式進行剖析。
2.1 同節點 Pod 通信 (Intra-Node Communication)
無論使用哪種 CNI 插件,同節點上的 Pod 通信機制是相似的,且相對簡單直接。
核心組件:
-
- cni0 網橋 (Flannel) / 直接路由 (Calico):Flannel: Flannel CNI 調用
bridge
插件在節點上創建一個 Linux 網橋(通常叫cni0
)。每個 Pod 的 veth pair 的宿主機端(vethxxx
)都會被插入到這個網橋中。網橋擁有一個 IP 地址(如10.244.0.1
),作為該節點子網的網關。 - Calico: Calico 默認不創建網橋。Pod 的 veth pair 的宿主機端(
calixxx
)直接存在于節點的根網絡命名空間。Felix 會在節點上配置一條到該 Pod IP 的直連路由(ip route add <Pod_IP>/32 dev <veth_device>
)。
- cni0 網橋 (Flannel) / 直接路由 (Calico):Flannel: Flannel CNI 調用
- veth pair (Virtual Ethernet Pair): 連接 Pod 網絡命名空間和節點根命名空間的虛擬以太網對。一端在 Pod 內(
eth0
),另一端在節點上(vethxxx
或calixxx
)。它們像一根虛擬網線,數據包從一端進入,必從另一端出去。 - Pod 路由表: Pod 內部通常只有一條默認路由,指向其網關:
- Flannel:
default via 10.244.0.1 dev eth0
(網橋 IP)。 - Calico:
default via 169.254.1.1 dev eth0
(Calico 使用一個特殊的 link-local 地址169.254.1.1
作為網關,Felix 會確保這個地址在節點上可達,通常指向節點自身的 IP 或一個虛擬接口)。
- Flannel:
通信流程 (以 Pod A -> Pod B 為例,同節點):
- Pod A 發送數據包: Pod A (
10.244.0.2
) 的應用想發送數據給 Pod B (10.244.0.3
)。 - Pod A 路由決策: Pod A 查詢自己的路由表。目標 IP
10.244.0.3
與10.244.0.2
在同一子網(10.244.0.0/24
),因此無需經過網關。Pod A 直接通過 ARP 解析目標 IP10.244.0.3
對應的 MAC 地址。- ARP 解析:Flannel: Pod A 發送 ARP 請求(Who has
10.244.0.3
? Tell10.244.0.2
)。這個請求通過 veth pair 到達cni0
網橋。網橋會泛洪這個 ARP 請求到所有連接的端口(包括所有其他 Pod 的 veth 端)。Pod B 收到 ARP 請求后,回復自己的 MAC 地址。網橋學習到10.244.0.3
對應的 MAC 地址在哪個端口(Pod B 的 veth 端)。 - Calico: Pod A 發送 ARP 請求。請求通過 veth pair 到達節點根命名空間。節點內核(或由 Felix 代理的 ARP 響應)會直接回復
10.244.0.3
的 MAC 地址(即 Pod B 的eth0
MAC)。Calico 通常會配置proxy_arp
或使用 Felix 主動響應 ARP,避免泛洪。
- ARP 解析:Flannel: Pod A 發送 ARP 請求(Who has
- 數據包發送: Pod A 構造二層幀:源 MAC = Pod A eth0 MAC, 目標 MAC = Pod B eth0 MAC, 源 IP =
10.244.0.2
, 目標 IP =10.244.0.3
。數據包通過 veth pair 發送到節點。- 節點內轉發:Flannel: 數據包到達
cni0
網橋。網橋查詢其 MAC 地址表(通過之前的 ARP 學習),知道目標 MAC 地址對應的端口是 Pod B 的 veth 端。網橋直接將數據幀轉發到該端口。 - Calico: 數據包到達節點根命名空間。節點內核查詢路由表,發現有一條到
10.244.0.3/32
的直連路由,下一跳是caliyyy
設備(Pod B 的 veth 端)。內核直接將數據包發送到該設備。
- 節點內轉發:Flannel: 數據包到達
- 到達 Pod B: 數據包通過 Pod B 的 veth pair 進入 Pod B 的網絡命名空間,最終被 Pod B 的應用接收。
關鍵點: 同節點通信主要依賴 Linux 網橋(Flannel)或直連路由(Calico)和 veth pair,數據包始終在節點內核空間完成轉發,不涉及物理網絡,延遲極低,帶寬接近內存帶寬。
2.2 跨節點 Pod 通信 (Inter-Node Communication) - Flannel (VXLAN)
這是 Flannel 解決的核心問題。假設 Pod A (10.244.1.2
) 在 Node 1 上,Pod B (10.244.2.3
) 在 Node 2 上。Flannel 使用 VXLAN 后端。
核心組件 (Node 1 & Node 2):
- flanneld: 運行在每個節點,負責:
- 向 etcd 注冊/獲取子網(Node 1:
10.244.1.0/24
, Node 2:10.244.2.0/24
)。 - 創建并管理 VXLAN 隧道設備
flannel.1
。 - 根據 etcd 中的信息,在節點上維護路由表。
- 向 etcd 注冊/獲取子網(Node 1:
- VXLAN 隧道設備 (
flannel.1
): 一個虛擬網絡接口,由內核 VXLAN 模塊管理。它有自己的 MAC 地址和 IP 地址(通常是一個169.254.x.x
或10.244.x.x
地址,但主要用于封裝/解封裝)。
節點路由表 (由 flanneld 維護):Node 1 路由表關鍵條目: 10.244.0.0/16 dev flannel.1 scope link 10.244.1.0/24 dev cni0 scope link # 本節點子網 10.244.2.0/24 via 10.244.2.0 dev flannel.1 onlink # Node 2 子網,下一跳是 Node 2 的隧道 IP ... (其他節點子網類似) Node 2 路由表關鍵條目: 10.244.0.0/16 dev flannel.1 scope link 10.244.2.0/24 dev cni0 scope link # 本節點子網 10.244.1.0/24 via 10.244.1.0 dev flannel.1 onlink # Node 1 子網,下一跳是 Node 1 的隧道 IP ... (其他節點子網類似)
-
- 注意:
via <IP> dev flannel.1
表示目標子網10.244.2.0/24
的流量需要通過flannel.1
設備發送,并且下一跳(VXLAN VTEP IP)是10.244.2.0
(這個地址是 flanneld 為 Node 2 分配的隧道端點 IP,通常存儲在 etcd 中,Node 1 的 flanneld 會讀取它)。
- 注意:
- ARP 表 (由 flanneld/FDB 維護): 內核需要知道目標 VTEP IP (
10.244.2.0
) 對應的物理 MAC 地址(即 Node 2 物理網卡eth0
的 MAC)。flanneld 會通過 etcd 獲取 Node 2 的物理 IP (192.168.1.102
),然后 Node 1 內核會通過 ARP 解析192.168.1.102
得到其 MAC。內核會將這個映射(VTEP IP -> 物理 MAC)存儲在 Forwarding Database (FDB) 中,用于 VXLAN 封裝。
通信流程 (Pod A -> Pod B):
- Pod A 發送數據包: Pod A (
10.244.1.2
) 發送數據包給 Pod B (10.244.2.3
)。數據包:源 IP=10.244.1.2
, 目標 IP=10.244.2.3
。 - Pod A 路由決策: Pod A 查詢路由表,目標 IP
10.244.2.3
不在本地子網 (10.244.1.0/24
),因此走默認路由,發送到網關 (10.244.1.1
,即cni0
網橋 IP)。 - 到達 Node 1 網橋: 數據包通過 veth pair 到達 Node 1 的
cni0
網橋。 - Node 1 路由決策 (關鍵): Node 1 內核收到數據包(目標 IP=
10.244.2.3
),查詢節點路由表。找到最長匹配的路由:10.244.2.0/24 via 10.244.2.0 dev flannel.1
。這表示:- 該數據包需要從
flannel.1
設備發出。 - 下一跳(VTEP IP)是
10.244.2.0
。
- 該數據包需要從
- VXLAN 封裝 (Node 1 內核): 內核 VXLAN 模塊接管數據包:
- 原始數據包 (Inner Packet): 源 IP=
10.244.1.2
, 目標 IP=10.244.2.3
(以及 L4 頭部)。- VXLAN 封裝:VXLAN Header: 添加 VXLAN 頭部,包含 VNI (通常為 1)。
- UDP 頭部: 源端口(內核隨機選擇),目標端口=
8472
(VXLAN 標準端口)。 - Outer IP Header: 源 IP = Node 1 物理 IP (
192.168.1.101
),目標 IP = Node 2 物理 IP (192.168.1.102
)。注意: 目標 IP192.168.1.102
是如何得到的?內核根據下一跳 VTEP IP (10.244.2.0
) 查詢 FDB 表,找到對應的物理 MAC 地址(Node 2 eth0 MAC),然后根據 Node 1 的路由表(目標192.168.1.102
的路由,通常是直連或默認路由)確定 Outer IP 的目標 IP。 - Outer Ethernet Header: 源 MAC = Node 1 eth0 MAC, 目標 MAC = Node 2 eth0 MAC (通過 ARP 解析
192.168.1.102
得到)。
- 封裝后的數據包:
[Eth(Node1MAC->Node2MAC)] [IP(192.168.1.101->192.168.1.102)] [UDP(SrcPort->8472)] [VXLAN(VNI=1)] [IP(10.244.1.2->10.244.2.3)] [L4...]
- 原始數據包 (Inner Packet): 源 IP=
- 物理網絡傳輸: 封裝后的數據包通過 Node 1 的物理網卡
eth0
發送到物理網絡(交換機、路由器)。物理網絡設備只看到 Outer IP Header (192.168.1.101 -> 192.168.1.102
),像處理普通 IP 包一樣將其路由到 Node 2。 - 到達 Node 2: 數據包到達 Node 2 的物理網卡
eth0
。 - VXLAN 解封裝 (Node 2 內核): Node 2 內核收到數據包:
- 識別目標 UDP 端口是
8472
,交給 VXLAN 模塊處理。 - VXLAN 模塊檢查 VNI (1),確認是自己的隧道。
- 剝離 Outer Ethernet, Outer IP, UDP, VXLAN Header。
- 提取 出原始數據包:源 IP=
10.244.1.2
, 目標 IP=10.244.2.3
。
- 識別目標 UDP 端口是
- Node 2 路由決策: Node 2 內核得到原始數據包(目標 IP=
10.244.2.3
),查詢節點路由表。找到最長匹配的路由:10.244.2.0/24 dev cni0 scope link
。這表示目標 IP 在本節點子網內,需要通過cni0
網橋發送。 - Node 2 內轉發: 數據包被發送到
cni0
網橋。網橋查詢 MAC 地址表(或通過 ARP),找到目標 IP10.244.2.3
對應的 MAC 地址(Pod B eth0 MAC)所在的端口(Pod B 的 veth 端),將數據幀轉發到該端口。 - 到達 Pod B: 數據包通過 Pod B 的 veth pair 進入 Pod B 的網絡命名空間,被 Pod B 的應用接收。
關鍵點: Flannel VXLAN 通過隧道封裝,將 Pod IP 包裹在宿主機 IP 包中傳輸。核心在于:
- 路由表:
flanneld
維護的到其他節點子網的路由,指向flannel.1
設備和下一跳 VTEP IP。 - FDB 表: 內核維護的 VTEP IP 到物理 MAC 的映射,用于確定 Outer IP 的目標 IP。
- 封裝/解封裝: 由內核 VXLAN 模塊高效完成,用戶態
flanneld
不參與數據平面轉發。 - 性能影響: 封裝開銷(50+ 字節)、MTU 問題、內核處理開銷(相對較小)。
2.3 跨節點 Pod 通信 (Inter-Node Communication) - Calico (純 BGP)
Calico 純 BGP 模式展現了其設計的高效性。假設 Pod A (192.168.1.2
) 在 Node 1 上,Pod B (192.168.2.3
) 在 Node 2 上。Calico 使用 BGP 全互聯模式。
核心組件 (Node 1 & Node 2):
- Felix: 運行在每個節點,負責:
- 配置 Pod 網絡接口(veth)。
- 編程路由表: 根據從 Datastore (K8s API) 獲取的信息(其他節點的 Pod CIDR 和 BGP 學習到的路由),在 Linux 內核路由表中動態添加/刪除路由條目。
- 編程 iptables/nftables 規則(用于 NetworkPolicy)。
- BIRD: 運行在每個節點,作為 BGP 路由器:
- 與集群內所有其他節點建立 iBGP 會話(AS 號相同)。
- 宣告路由: 將本節點上運行的 Pod 的 IP 地址(或整個 Pod CIDR,取決于配置
ipInIP: Disabled
和advertiseClusterIPs: true/false
)作為路由信息,通過 BGP 協議宣告給其他節點。例如,Node 1 宣告192.168.1.0/24
。 - 學習路由: 接收并學習其他節點宣告的 Pod IP/CIDR 路由。例如,Node 1 學習到 Node 2 宣告的
192.168.2.0/24
。 - 安裝路由: BIRD 將學習到的最佳 BGP 路由安裝到 Linux 內核的路由表中。
節點路由表 (由 Felix + BIRD 維護):Node 1 路由表關鍵條目: 192.168.1.0/24 dev cali123 scope link # 本節點 Pod CIDR,直連路由 (Felix) 192.168.2.0/24 via 192.168.1.102 dev eth0 proto bird # Node 2 Pod CIDR,BIRD 學習并安裝,下一跳是 Node 2 IP ... (其他節點 Pod CIDR 類似) Node 2 路由表關鍵條目: 192.168.2.0/24 dev cali456 scope link # 本節點 Pod CIDR,直連路由 (Felix) 192.168.1.0/24 via 192.168.1.101 dev eth0 proto bird # Node 1 Pod CIDR,BIRD 學習并安裝,下一跳是 Node 1 IP ... (其他節點 Pod CIDR 類似)
-
- 關鍵: 路由條目
via <Node_IP> dev eth0 proto bird
表明目標 Pod CIDR 的流量需要通過物理網卡eth0
發送,下一跳直接是目標節點的物理 IP 地址。沒有隧道設備!
- 關鍵: 路由條目
- 物理網絡: 必須能夠支持路由 Pod IP 流量。這意味著:
- 所有節點在同一個 L2 廣播域(如同一交換機下),或者
- 物理網絡設備(路由器、三層交換機)配置了到達各個節點 Pod CIDR 的路由(靜態路由或通過 BGP/OSPF 等動態路由協議學習)。在純 BGP 模式下,Calico 依賴物理網絡的三層可達性。
通信流程 (Pod A -> Pod B):
- Pod A 發送數據包: Pod A (
192.168.1.2
) 發送數據包給 Pod B (192.168.2.3
)。數據包:源 IP=192.168.1.2
, 目標 IP=192.168.2.3
。 - Pod A 路由決策: Pod A 查詢路由表,目標 IP
192.168.2.3
不在本地網絡(通常 Pod 網關是169.254.1.1
),走默認路由,發送到網關。 - 到達 Node 1 根命名空間: 數據包通過 veth pair (
cali123
) 到達 Node 1 的根網絡命名空間。 - Node 1 路由決策 (關鍵): Node 1 內核收到數據包(目標 IP=
192.168.2.3
),查詢節點路由表。找到最長匹配的路由:192.168.2.0/24 via 192.168.1.102 dev eth0 proto bird
。這表示:- 該數據包需要從物理網卡
eth0
發出。 - 下一跳直接是 Node 2 的物理 IP 地址 (
192.168.1.102
)。
- 該數據包需要從物理網卡
- Node 1 發送數據包: Node 1 內核構造二層幀:
- 源 MAC = Node 1 eth0 MAC。
- 目標 MAC = 下一跳 (
192.168.1.102
) 的 MAC 地址。Node 1 內核通過 ARP 解析192.168.1.102
得到其 MAC 地址(Node 2 eth0 MAC)。 - 源 IP =
192.168.1.2
(Pod A IP)。 - 目標 IP =
192.168.2.3
(Pod B IP)。 - 注意: 數據包沒有被封裝!它就是一個標準的 IP 包,源和目標 IP 都是 Pod IP。
- 物理網絡傳輸: Node 1 將這個原始 IP 包通過
eth0
發送到物理網絡。- 場景一 (L2 網絡): 如果節點在同一個 L2 域,交換機根據目標 MAC (Node 2 eth0 MAC) 直接將幀轉發到 Node 2。
- 場景二 (L3 網絡): 如果節點在不同 L3 子網,物理路由器收到包:
- 查看目標 IP (
192.168.2.3
)。 - 查詢自己的路由表。假設路由器通過 BGP 從 Node 2 學習到了
192.168.2.0/24
的路由,下一跳是 Node 2 (192.168.1.102
)。 - 路由器將包轉發給下一跳(Node 2)。在轉發過程中,路由器會重寫二層幀頭:源 MAC 改為路由器出口 MAC,目標 MAC 改為 Node 2 eth0 MAC。但IP 包頭保持不變(源 IP=
192.168.1.2
, 目標 IP=192.168.2.3
)。
- 查看目標 IP (
- 到達 Node 2: 數據包(原始 IP 包)到達 Node 2 的物理網卡
eth0
。 - Node 2 路由決策: Node 2 內核收到數據包(目標 IP=
192.168.2.3
),查詢節點路由表。找到最長匹配的路由:192.168.2.0/24 dev cali456 scope link
。這表示目標 IP 在本節點 Pod CIDR 內,需要通過cali456
設備(Pod B 的 veth 端)發送。 - Node 2 內轉發: Node 2 內核直接將數據包發送到
cali456
設備。 - 到達 Pod B: 數據包通過 Pod B 的 veth pair 進入 Pod B 的網絡命名空間,被 Pod B 的應用接收。
關鍵點: Calico 純 BGP 模式實現了真正的三層路由:
- 無封裝: Pod IP 包在物理網絡中裸奔,沒有額外的隧道頭部,性能最優,MTU 無需調整。
- 路由驅動: BGP 協議負責在節點間分發 Pod CIDR 路由信息。BIRD 將這些路由安裝到內核路由表。
- 直接路由: 節點路由表中的條目直接指向目標節點的物理 IP 作為下一跳。數據包的 IP 頭在整個傳輸過程中(除了最后一跳的 ARP 解析)保持不變。
- 依賴物理網絡: 這是該模式最大的前提和潛在限制。物理網絡必須能夠正確路由 Pod IP 流量。在公有云環境中,通常需要配合云平臺的路由表(如 AWS Route Table, GCP Custom Route)或使用 IPIP 模式。在私有數據中心,需要網絡設備支持 BGP 或配置靜態路由。
- eBGP 集成: 通過與物理網絡設備建立 eBGP 會話,Calico 可以將 Pod IP 路由宣告到整個物理網絡,實現 Pod IP 的全局可達性,這是其區別于 Overlay 方案的重大優勢。
2.4 跨節點路由總結與對比
特性 | Flannel (VXLAN) | Calico (純 BGP) | 深度解析 |
數據包路徑 | Pod -> Node1 (veth/bridge) -> VXLAN Encap -> Physical Network -> Node2 -> VXLAN Decap -> Node2 (bridge/veth) -> Pod | Pod -> Node1 (veth) -> Physical Network (L3 Routing) -> Node2 (veth) -> Pod | Flannel 數據包在 Node1 和 Node2 經歷了封裝/解封裝過程,路徑更長。Calico 數據包在物理網絡中以原始 Pod IP 形式被路由,路徑最短,效率最高。 |
封裝開銷 | 有 (50+ 字節:VXLAN+UDP+Outer IP+Outer Eth) | 無 | Flannel 的封裝開銷增加了網絡負載,降低了有效帶寬,并可能導致分片(需調整 MTU)。Calico 無此開銷,帶寬利用率最高。 |
MTU | 需調整 (通常 1400/1450) | 無需調整 (使用物理網絡 MTU) | Flannel 必須在 CNI 配置或網絡插件中設置小于物理 MTU 的值,否則可能導致 TCP 性能下降或連接問題。Calico 直接使用物理網絡 MTU,無此煩惱。 |
路由表維護 | 集中式 (etcd) + 節點 (flanneld 寫路由) | 分布式 (BGP 協議) + 節點 (Felix/BIRD) | Flannel 路由信息由 |
下一跳 | VTEP IP (如 10.244.2.0) -> 隧道設備 (flannel.1) | 目標節點物理 IP (如 192.168.1.102) -> 物理網卡 (eth0) | Flannel 的下一跳是邏輯隧道端點,需要額外的 FDB 表解析到物理地址。Calico 的下一跳直接是物理地址,路由決策更直接高效。 |
對物理網絡依賴 | 低 (只需 L3 可達) | 高 (需 L3 路由支持 Pod IP) | Flannel VXLAN 對底層網絡要求最低,只要節點 IP 能通即可工作。Calico 純 BGP 要求物理網絡能路由 Pod IP 流量,部署限制更多,但網絡架構更扁平、高效。 |
性能 | 中等 (封裝/解封裝開銷) | 優秀 (接近物理網絡極限) | 在同等硬件條件下,Calico 純 BGP 的吞吐量和延遲通常顯著優于 Flannel VXLAN,尤其在大包傳輸和高并發場景下。 |
外部訪問 | 困難 (需 NAT) | 容易 (通過 eBGP 宣告路由) | Flannel 的 Pod IP 是私有地址,外部無法直接訪問。Calico 通過 eBGP 將 Pod IP 路由宣告到物理網絡,Pod IP 可被外部直接路由訪問,無需 NAT,簡化架構。 |
結論: 跨節點路由是 Kubernetes 網絡的核心挑戰。Flannel 通過 VXLAN 等隧道技術提供了一種通用、易部署的解決方案,犧牲了一定的性能換取了對底層網絡的低依賴。Calico 則通過 BGP 和純三層路由,追求極致性能和網絡集成度,但要求更高的網絡規劃和管理能力。選擇哪種方案,取決于集群規模、性能要求、網絡環境復雜度和團隊運維能力。理解數據包在兩種模式下的完整旅程,是進行網絡優化和故障排查的基礎。
第三部分:網絡策略 (NetworkPolicy) - 微服務安全的守護者
在微服務架構中,服務間通信是常態,但并非所有服務都應該能夠相互訪問。NetworkPolicy 是 Kubernetes 提供的原生網絡策略 API,用于定義 Pod 組之間如何通信以及哪些通信是被允許的。它實現了命名空間級別的微分段(Micro-segmentation),是構建零信任網絡(Zero Trust Network)的關鍵組件。
3.1 NetworkPolicy 核心概念與模型
設計目標: 提供一種聲明式、基于標簽選擇器的方式,定義 Pod 之間的入站(Ingress)和出站(Egress)網絡訪問規則。
核心資源: NetworkPolicy
(屬于 networking.k8s.io/v1
API Group)。
關鍵字段解析:
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata:name: <policy-name> # 策略名稱namespace: <namespace> # 策略所屬命名空間 spec:podSelector: {} # **核心:選擇此策略應用到的目標 Pod 組**# matchLabels: {key: value} # 基于標簽選擇# matchExpressions: # 基于標簽表達式選擇policyTypes: # 指定策略類型(Ingress, Egress 或兩者)- Ingress- Egressingress: # **入站規則列表**:允許哪些流量訪問目標 Pod- from: # 流量來源列表(OR 關系)- podSelector: {} # 來源 Pod 選擇器(當前命名空間)# matchLabels: {key: value}- namespaceSelector: {} # 來源命名空間選擇器# matchLabels: {key: value}- namespaceSelector: {} # 可組合:來源是特定命名空間中符合標簽的 PodmatchLabels: {project: myproject}podSelector:matchLabels: {role: frontend}- ipBlock: # 來源 IP 段(CIDR)cidr: 192.168.1.0/24except: # 排除的 IP 段- 192.168.1.1/32ports: # 允許的目標端口列表(AND 關系,需與 from 匹配)- protocol: TCPport: 80- protocol: UDPport: 53egress: # **出站規則列表**:允許目標 Pod 訪問哪些外部資源- to: # 流量目標列表(OR 關系)- podSelector: {} # 目標 Pod 選擇器(當前命名空間)- namespaceSelector: {} # 目標命名空間選擇器- namespaceSelector: {} # 可組合:目標是特定命名空間中符合標簽的 Pod- ipBlock: # 目標 IP 段(CIDR)cidr: 10.0.0.0/8ports: # 允許的目標端口列表(AND 關系,需與 to 匹配)- protocol: TCPport: 443
核心語義與行為:
- 默認行為 (Deny All): 這是 NetworkPolicy 最重要也最容易被誤解的規則!
- 如果一個 Pod 沒有被任何 NetworkPolicy 的
podSelector
選中,那么它不受任何 NetworkPolicy 限制,可以自由訪問任何地方,也可以被任何地方訪問(相當于網絡完全開放)。- 一旦一個 Pod 被至少一個 NetworkPolicy 的
podSelector
選中,那么:入站 (Ingress): 只有 明確匹配該 Pod 關聯的 NetworkPolicy 中ingress
規則的流量才被允許。所有其他入站流量都被拒絕! (Deny All Ingress) - 出站 (Egress): 只有 明確匹配該 Pod 關聯的 NetworkPolicy 中
egress
規則的流量才被允許。所有其他出站流量都被拒絕! (Deny All Egress)
- 一旦一個 Pod 被至少一個 NetworkPolicy 的
- 關鍵點: NetworkPolicy 是疊加性的。一個 Pod 可以被多個 NetworkPolicy 選中。最終生效的規則是所有選中該 Pod 的 NetworkPolicy 規則的并集。但默認拒絕的語義始終存在:未被任何策略明確允許的流量,一律拒絕。
- 如果一個 Pod 沒有被任何 NetworkPolicy 的
podSelector
(目標選擇): 定義策略保護誰。它選擇當前命名空間中的一組 Pod 作為策略的應用對象。只有被選中的 Pod 才會遵循此策略的規則(并受默認拒絕約束)。policyTypes
(策略類型): 明確指定策略是用于控制入站 (Ingress
)、出站 (Egress
) 還是兩者。如果省略,Kubernetes 會根據spec.ingress
和spec.egress
字段是否存在來推斷,但顯式指定是最佳實踐。ingress
(入站規則):from
(來源): 定義允許訪問目標 Pod 的流量來源。from
下的多個子項(podSelector
,namespaceSelector
,ipBlock
)是 OR 關系。例如,from: [podSelector: {app: db}, namespaceSelector: {env: dev}]
表示允許來自app=db
的 Pod 或者 來自env=dev
命名空間中任何 Pod 的訪問。ports
(端口): 定義允許訪問的目標端口。ports
下的多個端口規則是 OR 關系。例如,ports: [{protocol: TCP, port: 80}, {protocol: TCP, port: 443}]
表示允許訪問 TCP 80 或者 TCP 443。from
+ports
: 一條完整的ingress
規則(- from: ... ports: ...
)表示:允許來自from
定義的來源,訪問ports
定義的端口。多個ingress
規則是 OR 關系。
egress
(出站規則):to
(目標): 定義允許目標 Pod 訪問的外部資源。to
下的多個子項(podSelector
,namespaceSelector
,ipBlock
)是 OR 關系。ports
(端口): 定義允許訪問的目標端口。ports
下的多個端口規則是 OR 關系。to
+ports
: 一條完整的egress
規則(- to: ... ports: ...
)表示:允許目標 Pod 訪問to
定義的資源的ports
定義的端口。多個egress
規則是 OR 關系。
namespaceSelector
與podSelector
組合: 這是實現跨命名空間策略的關鍵。例如:
ingress: - from:- namespaceSelector:matchLabels:project: myprojectpodSelector:matchLabels:role: frontend
- 表示:允許來自標簽為
project=myproject
的命名空間中,標簽為role=frontend
的 Pod 的訪問。注意:podSelector
在這里選擇的是源命名空間中的 Pod,而不是目標命名空間中的 Pod。 ipBlock
: 用于基于 IP 段(CIDR)控制流量,常用于:- 允許/拒絕來自特定外部 IP 段的訪問(如辦公網 IP)。
- 允許 Pod 訪問特定的外部服務 IP(如數據庫 IP)。
- 注意:
ipBlock
規則只適用于 IP 層,它不感知 Pod 的標簽或命名空間。當ipBlock
與podSelector
/namespaceSelector
混用時,需要小心理解其語義(通常是 OR 關系)。except
字段用于排除 CIDR 中的特定 IP。
3.2 NetworkPolicy 實現原理 - 以 Calico 為例
NetworkPolicy 是一個 API 資源,其本身不執行任何網絡控制。它的實現完全依賴于底層的 CNI 網絡插件。不同的 CNI 插件(Calico, Cilium, Kube-router, Canal 等)有不同的實現機制,但核心思想都是將聲明式的 NetworkPolicy 規則翻譯成底層的網絡訪問控制列表(ACL)。我們以功能強大且廣泛使用的 Calico 為例,深入剖析其實現原理。
Calico 實現架構:
- Kubernetes API Server: 用戶創建
NetworkPolicy
資源。 - Calico Controller (Kube-controllers): 一個獨立的控制器(通常以 Deployment 運行),監聽 Kubernetes API Server 中的
NetworkPolicy
,Pod
,Namespace
,Service
等資源變化。 - Calico Datastore (etcd/K8s API): Controller 將監聽到的 Kubernetes 資源狀態轉換并同步到 Calico 的 Datastore 中。例如,一個 Kubernetes
NetworkPolicy
會被轉換為一個或多個 Calico 原生的NetworkPolicy
或Profile
資源。 - Felix (節點代理): 運行在每個節點上,監聽 Calico Datastore 的變化。當它檢測到 NetworkPolicy 相關的資源(如
NetworkPolicy
,WorkloadEndpoint
,Profile
)發生變化時:- 計算策略: Felix 結合當前節點上運行的 Pod 信息(WorkloadEndpoint)和 Datastore 中的策略規則,計算出需要應用到每個 Pod(更準確地說是每個 veth 接口)上的具體訪問控制規則。
- 編程 ACL: Felix 將計算出的規則翻譯成 Linux 內核的 iptables (或可選的 nftables) 規則,并動態地加載到節點的內核網絡棧中。這些規則直接作用于 Pod 的 veth 接口或節點上的
chain
。
- Linux Kernel (iptables/nftables): 最終執行者。當網絡數據包流經 Pod 的 veth 接口或節點網絡棧時,內核會按照 Felix 編程的 iptables/nftables 規則進行匹配和決策(允許
ACCEPT
或拒絕DROP
)。
iptables 實現深度解析:
Calico 主要利用 Linux iptables 的 filter 表來實現 NetworkPolicy。它精心設計了一系列的 chain 和 規則。
核心 Chain 結構 (簡化版):
FORWARD
鏈 (節點根命名空間): 所有跨節點或從節點發往 Pod 的流量(即非本機進程發起且非發往本機進程的流量)都會經過此鏈。Calico 在此鏈的開頭插入規則,將流量跳轉到 Calico 專門處理 Pod 流量的鏈。- 規則示例:
-A FORWARD -m comment --comment "cali:..." -j cali-FORWARD
- 規則示例:
cali-FORWARD
鏈: Calico 的主入口鏈。它根據數據包的方向(入站到 Pod 還是出站自 Pod)進行分流:- 入站流量 (到 Pod): 數據包目標 IP 是某個 Pod IP。規則:
-A cali-FORWARD -m set --match-set cali40:some-pod-ip-hash dst -j cali-from-wl-dispatch
(跳轉到cali-from-wl-dispatch
)。 - 出站流量 (從 Pod): 數據包源 IP 是某個 Pod IP。規則:
-A cali-FORWARD -m set --match-set cali40:some-pod-ip-hash src -j cali-to-wl-dispatch
(跳轉到cali-to-wl-dispatch
)。 - 其他流量: 通常直接
ACCEPT
或返回FORWARD
鏈繼續處理。
- 入站流量 (到 Pod): 數據包目標 IP 是某個 Pod IP。規則:
cali-from-wl-dispatch
鏈 (入站分發): 根據目標 Pod IP,將流量精確分發到處理該特定 Pod 入站策略的鏈。- 規則示例:
-A cali-from-wl-dispatch -m set --match-set cali40:some-pod-ip-hash dst -j cali-fw-some-pod-name
(跳轉到cali-fw-some-pod-name
)。
- 規則示例:
cali-fw-<pod-name>
鏈 (特定 Pod 入站策略): 這是真正執行該 Pod 入站 NetworkPolicy 規則的地方。Felix 根據應用于該 Pod 的所有 NetworkPolicy 的ingress
規則,在此鏈中生成對應的 iptables 規則。- 默認拒絕 (Deny All): 鏈的最后一條規則通常是
-j DROP
。這實現了“未被明確允許即拒絕”的核心語義。 - 允許規則: 在
DROP
規則之前,Felix 會插入匹配 NetworkPolicyingress
規則的ACCEPT
規則。例如:- 允許來自
app=frontend
Pod 的 TCP 80 流量:
- 允許來自
- 默認拒絕 (Deny All): 鏈的最后一條規則通常是
-A cali-fw-pod-x -m set --match-set cali40:frontend-pod-ips src -p tcp --dport 80 -j ACCEPT
-
- (這里
cali40:frontend-pod-ips
是一個 ipset,包含了所有app=frontend
Pod 的 IP)。- 允許來自
namespace=dev
中任何 Pod 的流量:
- 允許來自
- (這里
-A cali-fw-pod-x -m set --match-set cali40:dev-namespace-pod-ips src -j ACCEPT
-
- (ipset 包含
dev
命名空間中所有 Pod IP)。- 允許來自 IP 段
192.168.1.0/24
的流量:
- 允許來自 IP 段
- (ipset 包含
-A cali-fw-pod-x -s 192.168.1.0/24 -j ACCEPT
cali-to-wl-dispatch
鏈 (出站分發): 類似入站分發,根據源 Pod IP,將流量分發到處理該特定 Pod 出站策略的鏈。- 規則示例:
-A cali-to-wl-dispatch -m set --match-set cali40:some-pod-ip-hash src -j cali-tw-some-pod-name
。
- 規則示例:
cali-tw-<pod-name>
鏈 (特定 Pod 出站策略): 執行該 Pod 出站 NetworkPolicy 規則。- 默認拒絕 (Deny All): 鏈末尾
-j DROP
。 - 允許規則: 在
DROP
之前插入匹配egress
規則的ACCEPT
規則。例如:- 允許訪問
app=database
Pod 的 TCP 3306 流量:
- 允許訪問
- 默認拒絕 (Deny All): 鏈末尾
-A cali-tw-pod-y -m set --match-set cali40:database-pod-ips dst -p tcp --dport 3306 -j ACCEPT
-
-
- 允許訪問外部 IP
10.0.0.5
的 TCP 443 流量:
- 允許訪問外部 IP
-
-A cali-tw-pod-y -d 10.0.0.5/32 -p tcp --dport 443 -j ACCEPT
關鍵技術點:
- ipset 高效匹配: Calico 大量使用 ipset 來存儲和匹配 IP 地址集合(如某個標簽選擇器選中的所有 Pod IP,某個命名空間的所有 Pod IP)。ipset 是基于哈希的高效數據結構,匹配速度遠快于在 iptables 中寫多條
-s <ip>/32
規則,尤其當規則涉及大量 Pod 時,性能優勢巨大。Felix 會動態維護這些 ipset。 - 規則順序與性能: iptables 規則是順序匹配的。Calico Felix 在生成規則時,會盡量優化規則順序,將匹配頻率高或范圍小的規則放在前面,以提高整體匹配效率。默認拒絕的
DROP
規則始終在最后。 - 狀態檢測 (Connection Tracking): 對于 TCP 等有狀態的協議,Calico 依賴 Linux 內核的 連接跟蹤(conntrack) 機制。一旦一個連接被
ACCEPT
規則允許,其后續的返回包通常會被 conntrack 自動識別為ESTABLISHED
/RELATED
狀態,并被允許通過,無需再次匹配完整的策略規則。這大大提高了性能。Calico 會在策略鏈中插入類似-m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
的規則(通常在靠前位置)。 - 多策略疊加: 當一個 Pod 被多個 NetworkPolicy 選中時,Felix 會將所有策略的規則合并到該 Pod 對應的
cali-fw-<pod-name>
和cali-tw-<pod-name>
鏈中。由于規則是 OR 關系,只要匹配任意一條ACCEPT
規則,流量就會被允許。最終的DROP
規則保證了未被任何策略允許的流量被拒絕。 - Service 訪問: NetworkPolicy 默認不感知 Kubernetes Service 的 ClusterIP。Pod 訪問 Service 的 ClusterIP 流量,會被 kube-proxy 的 iptables/IPVS 規則DNAT 成具體的 Pod IP。因此,在 NetworkPolicy 看來,流量是直接發往目標 Pod IP 的。策略需要允許訪問目標 Pod IP(或標簽) 才能生效。策略中不能直接寫 Service 的 ClusterIP 或名稱。這是一個常見的陷阱。解決方法是在策略中通過
podSelector
選擇后端 Pod,或者如果后端 Pod 標簽一致,直接使用該標簽。
其他 CNI 插件實現簡述:
- Cilium: 基于 eBPF 技術。它在內核層面(XDP 或 TC hook 點)實現高性能的網絡策略。eBPF 程序直接在數據包進入內核網絡棧的早期階段執行,無需經過 iptables,性能極高,尤其適合高吞吐、低延遲場景。Cilium 還支持基于 HTTP/7 層的策略(如 HTTP 方法、路徑、頭),這是傳統 iptables 難以高效實現的。
- Kube-router: 主要使用 iptables 實現 NetworkPolicy,同時提供 IPVS 服務代理和 BGP 路由功能。其實現原理與 Calico 的 iptables 模式類似,但架構更輕量(將 Felix、BIRD、IPVS 等功能集成在一個 DaemonSet 中)。
- Canal: 結合 Flannel(網絡數據平面)和 Calico Felix(策略引擎)。其 NetworkPolicy 實現原理與 Calico 的 iptables 模式完全相同,因為策略部分就是用的 Calico Felix。
3.3 NetworkPolicy 最佳實踐與常見場景
1. 遵循最小權限原則:
- 默認拒絕: 在生產環境中,強烈建議為關鍵命名空間(如
production
,payment
)或所有命名空間配置默認拒絕所有的 NetworkPolicy。這是零信任的基礎。
```yamlapiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata:name: default-deny-allnamespace: productionspec:podSelector: {} # 選擇該命名空間所有 PodpolicyTypes:- Ingress- Egress```
- 按需開放: 只為必要的通信添加明確的允許規則。避免使用過于寬泛的規則(如允許所有 TCP 流量)。
2. 合理使用標簽和命名空間:
- 標簽 (Labels): 是 NetworkPolicy 選擇 Pod 的核心。為 Pod 打上清晰、有意義、穩定的標簽(如
app
,component
,tier
,version
)。避免使用易變或無意義的標簽。 - 命名空間 (Namespaces): 是邏輯隔離和環境劃分的天然邊界。利用
namespaceSelector
實現跨命名空間的訪問控制。例如,只允許testing
命名空間的 Pod 訪問staging
命名空間的特定服務。 - 組合選擇器: 靈活運用
podSelector
和namespaceSelector
的組合,實現精細的跨命名空間策略。
3. 常見場景示例:
- 場景一:允許前端 Pod 訪問后端 Pod 的特定端口。
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata:name: frontend-to-backendnamespace: default spec:podSelector:matchLabels:app: backend # 保護后端 PodpolicyTypes:- Ingressingress:- from:- podSelector:matchLabels:app: frontend # 允許來自前端 Podports:- protocol: TCPport: 8080 # 允許訪問后端 8080 端口
- 場景二:允許命名空間 A 中的 Pod 訪問命名空間 B 中的 Pod。
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata:name: ns-a-to-ns-bnamespace: ns-b # 保護 ns-b 中的 Pod spec:podSelector: {} # ns-b 中所有 PodpolicyTypes:- Ingressingress:- from:- namespaceSelector:matchLabels:name: ns-a # 允許來自 ns-a 命名空間中任何 Pod
- 場景三:允許 Pod 訪問外部數據庫 IP (Egress)。
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata:name: pod-to-dbnamespace: default spec:podSelector:matchLabels:app: myapp # 限制 myapp Pod 的出站policyTypes:- Egressegress:- to:- ipBlock:cidr: 10.10.20.30/32 # 數據庫 IPports:- protocol: TCPport: 3306 # 數據庫端口# 通常還需要允許 DNS 查詢- to: []ports:- protocol: UDPport: 53
- 場景四:允許 Pod 訪問 Kubernetes API Server (Egress)。
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata:name: allow-api-servernamespace: default spec:podSelector:matchLabels:app: needs-api # 需要訪問 API 的 PodpolicyTypes:- Egressegress:- to:- ipBlock:cidr: <KUBERNETES_SERVICE_IP>/32 # API Server ClusterIP (如 10.96.0.1)ports:- protocol: TCPport: 443 # API Server 端口# 或者直接允許訪問 API Server 的 Pod IP(如果知道且穩定)# - to:# - ipBlock:# cidr: <API_SERVER_POD_IP>/32# ports:# - protocol: TCP# port: 6443
- 場景五:隔離命名空間,僅允許特定入站。
# 1. 默認拒絕所有入站和出站 apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata:name: default-deny-allnamespace: secure-ns spec:podSelector: {}policyTypes:- Ingress- Egress# 2. 允許來自 Ingress Controller 的流量 (假設 Ingress Controller 在 ingress-ns 命名空間) apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata:name: allow-ingressnamespace: secure-ns spec:podSelector: {} # 所有 PodpolicyTypes:- Ingressingress:- from:- namespaceSelector:matchLabels:name: ingress-nspodSelector:matchLabels:app: ingress-controller # 假設 Ingress Controller 有此標簽ports:- protocol: TCPport: 80 # HTTP- protocol: TCPport: 443 # HTTPS# 3. 允許 DNS 和 API Server 訪問 (Egress) apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata:name: allow-dns-apinamespace: secure-ns spec:podSelector: {}policyTypes:- Egressegress:- to: [] # 允許訪問任何 IP 的 DNS (UDP 53)ports:- protocol: UDPport: 53- to:- ipBlock:cidr: <KUBERNETES_SERVICE_IP>/32ports:- protocol: TCPport: 443
4. 調試與排錯:
-
- 確認策略生效:檢查 Pod 是否被策略選中:
kubectl describe pod <pod-name> -n <ns>
,查看是否有NetworkPolicy
相關的 Annotation(如k8s.v1.cni.cncf.io/networks-status
)或使用kubectl get networkpolicy
查看策略的podSelector
。 - 檢查 CNI 插件日志:查看 Calico Felix (
kubectl logs -n calico-system <felix-pod>
)、Cilium Agent (kubectl logs -n kube-system <cilium-agent>
) 等日志,看策略是否被正確加載和翻譯。 - 檢查節點上的 ACL:對于 Calico iptables 模式,登錄節點執行
sudo iptables -L -v -n | grep cali
查看規則和計數器。計數器 (pkts, bytes
) 增長表示規則被匹配。sudo ipset list
查看 ipset 內容。 - 測試連通性:使用
kubectl exec
進入源 Pod,ping
/curl
/telnet
目標 Pod IP/端口。 - 使用
kubectl port-forward
暴露服務進行測試。 - 使用
tcpdump
在源 Pod、目標 Pod、節點 veth 接口上抓包,觀察數據包是否被發送、是否到達、是否被丟棄(無響應或 ICMP Port Unreachable)。 - 常見問題:策略未生效: Pod 未被任何策略選中(檢查
podSelector
和 Pod 標簽);CNI 插件未正確安裝或配置;策略語法錯誤。 - 允許的流量被拒絕: 規則寫錯(端口、協議、IP、標簽);Service 訪問未轉換為后端 Pod IP 訪問(策略需允許目標 Pod IP);conntrack 表滿或狀態異常;MTU 問題導致分片被丟棄;底層網絡問題。
- 默認拒絕過于嚴格: 忘記允許 DNS 查詢(UDP 53)、訪問 Kubernetes API Server、節點本地服務(如 kubelet metrics)等必要出站流量。
- 確認策略生效:檢查 Pod 是否被策略選中:
5. 性能考慮:
- 規則數量: 過于復雜或數量龐大的 NetworkPolicy 規則會增加 iptables/nftables/eBPF 規則集的規模,可能影響數據包處理性能。盡量保持策略簡潔。
- ipset 效率: Calico/Cilium 等使用 ipset 的插件在處理大量 Pod IP 時性能較好。避免在策略中直接寫大量單個 IP。
- eBPF 優勢: 對于對網絡性能要求極高的場景,Cilium 的 eBPF 實現通常比 iptables 有顯著性能優勢。
- 監控: 監控節點上的 CPU 使用率(特別是軟中斷
si
)、網絡吞吐量、延遲。監控 CNI 插件自身的指標(如 Calico Felix 的 Prometheus 指標)。
總結
Kubernetes 的網絡模型是其強大生命力的關鍵支撐。通過本文的深度解析,我們揭示了其核心組件的精妙設計與復雜交互:
- CNI 插件: 作為網絡基礎設施的構建者,Flannel 以其簡單易用、覆蓋網絡的特性成為入門和中小規模集群的理想選擇,而 Calico 則憑借純三層 BGP 路由、原生高性能策略、靈活的外部集成能力,成為大規模、高性能、高安全要求生產環境的標桿。理解它們的架構差異(Overlay vs Routing)、性能權衡(封裝開銷 vs 路由依賴)和適用場景,是進行技術選型和網絡優化的基礎。
- Pod 通信與跨節點路由: 從同節點的高效網橋/直連路由,到跨節點的復雜路徑,我們追蹤了數據包的完整旅程。Flannel VXLAN 通過隧道封裝跨越了底層網絡的限制,而 Calico 純 BGP 則利用標準路由協議將 Pod 網絡無縫融入物理網絡,實現了接近物理極限的性能。掌握不同模式下的路由表維護、封裝/解封裝過程、MTU 處理和對物理網絡的依賴,是進行網絡規劃和故障排查的核心技能。
- NetworkPolicy: 作為微服務安全的守護者,NetworkPolicy 提供了聲明式、基于標簽的網絡微分段能力。其“默認拒絕”的核心語義是實現零信任網絡的基石。通過 Calico 等插件的實現,我們看到策略如何被翻譯成高效的內核級 ACL(如 iptables/nftables 或 eBPF)。遵循最小權限原則、合理運用標簽與命名空間、掌握常見場景的配置方法以及有效的調試手段,是構建安全、合規、可運維的 Kubernetes 網絡環境的關鍵。
Kubernetes 網絡的深度和廣度遠超本文所及,涉及 SDN、內核網絡、服務網格、云原生網絡等更廣闊的領域。然而,深入理解 CNI、Pod 通信和 NetworkPolicy 這三大支柱,就如同掌握了 Kubernetes 網絡世界的“牛頓定律”,為探索更高級的主題、解決復雜的網絡問題、構建高性能高可用的云原生應用奠定了堅實的基礎。隨著云原生技術的持續演進,Kubernetes 網絡模型也將在性能、安全性、可觀測性和易用性上不斷突破,持續為分布式系統的繁榮發展提供強大的網絡動力。