目录
专栏介绍
作者与平台
您将学到什么?
学习特色
网络模型深度解析: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(N²) 增长,导致管理复杂和资源消耗。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 网络模型也将在性能、安全性、可观测性和易用性上不断突破,持续为分布式系统的繁荣发展提供强大的网络动力。