Kubernetes 网络是集群运转的基石,其模型与传统虚拟机网络有着根本性的差异——k8s 强制要求一个扁平网络模型,让集群中每个 Pod 都能直接与任何其他 Pod 通信。本文将从网络模型原则、三层通信机制、CNI 规范到主流插件选型,系统性地梳理 k8s 网络的核心知识。
前言
在 Kubernetes 集群中,网络不仅仅是基础设施,更是整个声明式体系得以运转的前提条件。与传统的虚拟机网络不同,k8s 并不依赖 NAT 或端口映射来实现容器间通信,而是强制要求一个**扁平网络(Flat Network)**模型——集群中的每个 Pod 都必须能直接到达任何其他 Pod,无需地址转换。
这种设计哲学让网络对应用变得透明:开发者不需要关心端口映射、不需要处理 NAT 穿透,只需要像在传统物理网络上一样使用标准的 Socket API。但这背后,k8s 网络的实现远比看起来复杂——同 Pod 通信、同 Node 通信、跨 Node 通信,每一层都有独特的机制。
本文将从 k8s 网络模型的三大原则出发,逐层剖析通信机制,深入 CNI 规范,并对比主流 CNI 插件的选型策略。
一、k8s 网络模型三大原则
k8s 的网络模型由三个基本要求定义,它们是 k8s 网络的"宪法":
| 原则 | 含义 | 核心影响 |
|---|---|---|
| 每个 Pod 拥有独立 IP(IP-per-Pod) | 每个 Pod 分配一个独立 IP,Pod 内所有容器共享该 IP | 容器无需单独管理网络,Pod 是网络身份的最小单元 |
| 所有 Pod 之间可以直接通信(No NAT between Pods) | 任何 Pod 可以直接与任何其他 Pod 通信,不经过 NAT | 应用使用标准 Socket,无需感知容器网络拓扑 |
| Node 与 Pod 之间可以直接通信(No NAT between Node and Pod) | Node 可以直接访问其上及集群中任何 Pod 的 IP,反之亦然 | Node 上的 kubelet、kube-proxy 可以直接与 Pod 通信 |
为什么这三条原则如此重要?
它们的核心价值在于让网络变得透明(Transparent):
- 应用开发者无需关心端口映射——不需要像 Docker 那样把容器端口映射到主机端口
- 不需要 NAT 穿透——Pod IP 在集群全局唯一且可达,应用直接使用 Pod IP 通信
- 标准化的网络模型——无论底层是 AWS、GCP 还是自建机房,k8s 都保证相同的网络语义
核心认知:k8s 定义了网络应该是什么样(WHAT),但不负责实现(HOW)。具体如何达成这三条原则,完全交给 CNI 插件来完成。
二、同 Pod 内容器通信
同一个 Pod 内的多个容器共享同一个 Network Namespace,这是理解 k8s 网络的起点。
2.1 共享网络命名空间
Pod 内所有容器共享:
- 同一个 IP 地址——对外只有一个网络身份
- 同一个端口空间——容器间不能监听同一端口
- 同一个 Network Namespace——网络设备、路由表、iptables 规则全部共享
因此,同 Pod 内的容器之间通信极为简单——直接通过 localhost 即可。
2.2 典型场景
主应用容器监听 8080 端口,Sidecar 健康检查容器通过 localhost:8080/health 访问:
apiVersion: v1
kind: Pod
metadata:
name: web-with-sidecar
spec:
containers:
- name: web
image: nginx:1.25
ports:
- containerPort: 8080
- name: health-check
image: busybox:1.36
command: ['sh', '-c', 'while true; do wget -qO- http://localhost:8080/health || exit 1; sleep 10; done']
2.3 Pause 容器的作用
这一切之所以能工作,是因为 Pause 容器的存在:
- kubelet 首先创建 Pause 容器(沙箱容器),由它创建并持有 Pod 的 Network Namespace
- Pod 内所有业务容器启动时,加入 Pause 容器的 Network Namespace
- Pause 容器作为网络命名空间的"锚点",即使业务容器重启,Pod 的网络身份(IP、路由等)保持不变
┌────────────────────────────────────────────┐
│ Pod (10.244.1.5) │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Pause │ │ Web │ │ Sidecar │ │
│ │ (netns │ │ 容器 │ │ 容器 │ │
│ │ 持有者) │ │ │ │ │ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ │ │
│ └────── 共享 Network Namespace ──────┘ │
│ │
│ 所有容器通过 localhost 互相通信 │
└────────────────────────────────────────────┘
注意:同 Pod 内容器的端口不能冲突。如果两个容器都需要监听 80 端口,则必须将其中一个改为其他端口,否则会启动失败。
三、同 Node Pod 间通信
不同 Pod 运行在各自的 Network Namespace 中,即使它们在同一个 Node 上,也无法直接通信。k8s 通过 veth pair + 网桥 机制解决这一问题。
3.1 核心机制
| 机制 | 说明 |
|---|---|
| veth pair | 虚拟以太网设备对,一端放在 Pod 的 netns 中(命名为 eth0),另一端留在宿主机上(命名为 vethXXX) |
| 网桥(Bridge / cbr0) | 宿主机上的虚拟二层交换机,所有 veth pair 的宿主机端都连接到网桥上 |
3.2 数据流
Pod A (netns) 宿主机 Pod B (netns)
┌──────────┐ ┌───────────────────┐ ┌──────────┐
│ eth0 │── veth pair ──│ vethA cbr0 vethB │── veth pair ──│ eth0 │
│10.244.1.2│ │ 网桥 │ │10.244.1.3│
└──────────┘ └───────────────────┘ └──────────┘
数据流:
Pod A (eth0) → vethA → cbr0 (网桥) → vethB → Pod B (eth0)
整个过程就像一台虚拟交换机连接了所有本地 Pod——网桥(cbr0)扮演二层交换机的角色,根据 MAC 地址将帧从 vethA 转发到 vethB。
3.3 关键细节
- 网桥工作在二层,只关心 MAC 地址转发,不涉及路由
- 同 Node 上 Pod 间通信不需要经过宿主机的路由表,直接走网桥转发
- 性能接近本地进程间通信,延迟极低
四、跨 Node Pod 间通信
这是 k8s 网络最核心的挑战。k8s 自身不实现跨 Node 通信,而是将实现权完全交给 CNI 插件。目前主流方案分为两大阵营:
叠加网络(Overlay Network / VXLAN)
原理
将 Pod 到 Pod 的原始数据包封装在 Node 到 Node 的外层包中传输,在物理网络之上叠加一层虚拟的二层网络。
VXLAN 封装过程:
原始包:[Pod A IP:10.244.1.2] → [Pod B IP:10.244.2.3] | Payload
↓ 封装
VXLAN 包:[Node A IP:192.168.1.10] → [Node B IP:192.168.1.11] | UDP:4789 | VXLAN Header | 原始包
VXLAN 在原始二层帧前添加了 50 字节的头部(VXLAN Header + UDP + Outer IP),将 Pod 的原始数据包作为载荷封装在 Node 间的 UDP 报文中传输。
特点
| 维度 | 说明 |
|---|---|
| 优点 | 部署简单,对底层网络无要求,任何支持 IP 的网络都能运行 |
| 缺点 | 封装/解封装有性能开销(约 5%~15%),MTU 减小 50 字节 |
| 原理 | 在物理 L3 网络上构建虚拟 L2 网络,Pod 感知不到底层网络拓扑 |
路由方案(Routing / BGP)
原理
使用真实的路由代替封装。每个 Node 通过 BGP(Border Gateway Protocol)学习其他 Node 的 Pod CIDR,然后通过路由表直接转发。
BGP 路由方式:
Node A 路由表:
10.244.2.0/24 via 192.168.1.11 (Node B 的 Pod 网段 → Node B)
10.244.3.0/24 via 192.168.1.12 (Node C 的 Pod 网段 → Node C)
数据流:
Pod A (10.244.1.2) → Node A 查路由表 → 物理网络直接转发 → Node B → Pod B (10.244.2.3)
特点
| 维度 | 说明 |
|---|---|
| 优点 | 无封装开销,性能更好,原生路由 |
| 缺点 | 需要 BGP 支持,配置较复杂,路由表条目随 Node 数量线性增长 |
| 原理 | 直接利用物理网络的路由能力,Pod IP 在物理网络中可达 |
方案对比
| 方案 | 原理 | 性能 | 配置复杂度 | MTU | 适用场景 |
|---|---|---|---|---|---|
| VXLAN(Overlay) | 封装 Pod 包到 Node 包中 | 有封装开销(5%~15%) | 低,即插即用 | 减少 50 字节 | 任何网络环境,快速部署 |
| BGP(Routing) | 通过路由表直接转发 | 接近原生网络性能 | 较高,需 BGP 支持 | 无影响 | 支持 BGP 的网络,性能敏感场景 |
五、CNI 概念
什么是 CNI
CNI(Container Network Interface) 是一个规范和插件系统,用于配置容器网络。它由 CoreOS 最初提出,现已成为 CNCF 项目。CNI 定义了一个简洁的插件接口,容器运行时(如 containerd、CRI-O)通过调用 CNI 插件来完成容器的网络配置。
k8s 本身不实现网络,它只定义网络模型(三大原则),具体实现完全由 CNI 插件完成。
CNI 接口规范
CNI 定义了三个核心操作:
| 操作 | 说明 |
|---|---|
| ADD | 为容器创建并配置网络接口(创建 veth pair、分配 IP、设置路由等) |
| DEL | 清理并移除容器的网络接口(释放 IP、删除 veth pair 等) |
| CHECK | 验证容器的网络接口是否仍然正确配置(CNI 1.0+ 新增) |
CNI 配置格式
CNI 使用 JSON 格式的配置文件,通常位于 /etc/cni/net.d/ 目录下:
{
"cniVersion": "1.0.0",
"name": "k8s-pod-network",
"type": "calico",
"ipam": {
"type": "host-local",
"ranges": [{"subnet": "10.244.0.0/16"}]
}
}
| 字段 | 说明 |
|---|---|
cniVersion | CNI 规范版本 |
name | 网络名称 |
type | 插件类型(对应 CNI 插件的可执行文件名) |
ipam | IP 地址管理配置,指定 IP 分配方式和子网 |
k8s 与 CNI 的交互流程
1. kubelet 创建 Pod 沙箱(Pause 容器)
│
▼
2. kubelet 调用 CNI 插件,执行 ADD 操作
│
▼
3. CNI 插件创建 veth pair、分配 IP、设置路由
│
▼
4. kubelet 在 Pod 的 Network Namespace 中启动业务容器
│
▼
5. Pod 删除时,kubelet 调用 CNI 插件,执行 DEL 操作
关键:CNI 插件是可执行文件,kubelet 通过命令行调用它,传入 JSON 格式的配置和网络命名空间路径。CNI 插件执行完网络配置后,将结果以 JSON 格式返回给 kubelet。
六、主流 CNI 插件
Flannel
解决的问题:最简跨 Node 通信
Flannel 提供了最简单的方式来实现跨 Node Pod 通信——开箱即用,几乎不需要额外配置。
方案
| 项目 | 说明 |
|---|---|
| 默认方案 | VXLAN overlay 网络 |
| 替代方案 | host-gw(同一二层网络下的直接路由,性能更好但要求所有 Node 在同一 L2 网段) |
数据面
- VXLAN 模式:封装 Pod 包到 Node 包中传输
- host-gw 模式:在宿主机路由表中添加直接路由条目,不封装
局限
- 不支持 NetworkPolicy——无法实现 Pod 级别的网络隔离
- 不支持加密——跨 Node 流量明文传输
- 仅适用于简单的扁平网络场景
适用场景
小规模集群、快速 POC / 学习环境、网络需求简单的场景。
Calico
解决的问题:安全隔离与大规模部署
Calico 提供了 NetworkPolicy 网络安全能力,并能支撑大规模生产集群的网络需求。
方案
| 项目 | 说明 |
|---|---|
| 跨 Node 通信 | BGP 路由——每个 Node 通过 BGP 协议向其他 Node 宣告自己的 Pod CIDR |
| 策略执行 | iptables / eBPF——在数据面实现 NetworkPolicy 的流量控制 |
| 降级方案 | IP-in-IP 封装——当 BGP 直连路由不可达时(如跨子网),使用 IP-in-IP 封装 |
数据面
Calico 提供两种数据面模式:
iptables 模式(默认,成熟稳定)
- 使用 iptables 实现路由和 NetworkPolicy 策略执行
- 生态成熟,经过大规模生产验证
- 大规模集群中 iptables 规则数量膨胀,性能下降
eBPF 模式(较新,性能更好)
- 使用 eBPF 程序在内核中处理数据包
- 绕过 iptables,减少包处理路径
- 性能优于 iptables 模式,但功能仍在完善中
优势
- 完整的 NetworkPolicy 支持:同时支持 ingress 和 egress 策略,实现 Pod 级别的网络隔离
- BGP 原生路由:无需封装,直接利用物理网络路由,性能接近原生
- 大规模支撑:BGP 天然支持大规模网络,已在多个超大规模生产集群中验证
- IP-in-IP 降级:BGP 直连不可达时自动降级为 IP-in-IP 封装,保证连通性
当前地位
生产环境存量最多的 CNI 插件,很多托管 K8s 服务(如 EKS、AKS)的默认选项。
适用场景
生产环境、安全敏感型工作负载、大规模集群。
Cilium
解决的问题:性能瓶颈与可观测性
Cilium 解决了 iptables 数据面的性能瓶颈,并提供了传统 CNI 无法实现的深度网络可观测性。
方案
eBPF 数据面——完全基于 eBPF(Extended Berkeley Packet Filter)实现数据面。eBPF 程序运行在 Linux 内核中,在数据包到达传统网络栈之前就完成处理,绕过了 iptables 和大部分内核网络栈。
传统数据面(iptables):
网卡 → netfilter/iptables → 路由 → conntrack → 应用
↑ 规则匹配,链式遍历,O(n) 复杂度
Cilium 数据面(eBPF):
网卡 → eBPF 程序 → 应用
↑ 内核直接执行,哈希查找,O(1) 复杂度
数据面
eBPF——完全在内核中运行,绕过 iptables 和大部分网络栈。
优势
高性能
eBPF 在内核中直接处理数据包,相比 iptables 的链式规则遍历,eBPF 使用哈希表查找策略匹配,性能提升 10%~30%。在大规模集群(数千 Node、数万 Pod)中,性能优势更加明显。
深度可观测性(Hubble)
Cilium 内置了 Hubble 可观测性平台,提供:
- 实时网络流量可视化——Service Map 展示服务间调用关系
- 网络策略命中分析——可视化哪些策略放行/拒绝了流量
- L7 流量指标——HTTP、gRPC、Kafka 等协议级别的指标
- DNS 解析追踪——监控 Pod 的 DNS 查询
L7 策略
传统 CNI 只能做 L3/L4 级别的策略(IP + 端口),Cilium 可以执行 L7 级别的策略:
- HTTP:限制特定路径(如只允许 GET /api/v1/*)
- gRPC:限制特定方法调用
- Kafka:限制特定 Topic 的生产和消费
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: l7-rule
spec:
endpointSelector:
matchLabels:
app: web
egress:
- toEndpoints:
- matchLabels:
app: api
toPorts:
- ports:
- port: "8080"
rules:
http:
- method: GET
path: "/api/v1/.*"
透明加密
基于 WireGuard 实现 Node 间流量加密,无需修改应用代码,Cilium 在内核层自动完成加密/解密。
Cluster Mesh
支持多集群互联,不同 k8s 集群的 Pod 可以直接通信,实现跨集群的服务发现和负载均衡。
当前地位
增速最快的 CNI 插件。GKE Dataplane V2 默认使用 Cilium,社区热度已超过 Calico,是未来趋势。
适用场景
性能敏感型工作负载、可观测性需求强、需要 L7 策略、新集群部署。
对比表格
| 插件 | 数据面方案 | NetworkPolicy | L7 策略 | 可观测性 | 加密 | 适用场景 |
|---|---|---|---|---|---|---|
| Flannel | VXLAN / host-gw | ❌ | ❌ | ❌ | ❌ | 小规模、快速验证 |
| Calico | BGP + iptables / eBPF | ✅ | ❌ | ❌ | ✅(WireGuard) | 生产环境、大规模 |
| Cilium | eBPF | ✅ | ✅ | ✅(Hubble) | ✅(WireGuard) | 高性能、可观测性、新部署 |
小结
k8s 网络全景回顾:
网络模型(三大原则)
│
│ IP-per-Pod · No NAT between Pods · No NAT between Node and Pod
│
▼
三层通信机制
│
├── 同 Pod 通信:共享 Network Namespace,localhost 直连
├── 同 Node 通信:veth pair + 网桥(cbr0),二层转发
└── 跨 Node 通信:CNI 插件实现(VXLAN 叠加 / BGP 路由)
│
▼
CNI 规范
│
│ 定义插件接口:ADD / DEL / CHECK
│ k8s 调用 CNI 插件完成 Pod 网络配置
│
▼
CNI 插件选型
│
├── Flannel → 最简跨 Node 通信,学习/POC
├── Calico → 安全隔离 + 大规模生产,当前主流
└── Cilium → eBPF 高性能 + 可观测性,未来趋势
核心洞察:k8s 定义了网络应该是什么样(扁平、IP-per-Pod),CNI 插件负责如何实现。选型策略——Flannel 用来学习,Calico 用于当前生产,Cilium 面向未来。
