摘要:理解 CNI 的接口与配置流程、Pod IP 分配、同节点及跨节点通信,比较 Overlay、Underlay 与 Flannel、Calico、Cilium 的实现侧重。
1. CNI 接口、配置流程与能力边界
CNI 是 Container Network Interface(容器网络接口)。
可以先把它理解为一套网络配置接口和插件规范:容器运行时通过它调用网络插件,为 Pod 配置网络连接。
例如,创建一个 Pod 时,Kubernetes 的相关组件会协同完成以下工作:
flowchart TB
N0["创建 Pod<br/>API Server 接收资源声明"]
N1["Scheduler<br/>选择运行 Pod 的 Node"]
N2["Node 上的 kubelet 与容器运行时<br/>协调 Pod Sandbox 创建与网络配置"]
N3["CNI 网络插件<br/>配置网络接口、地址和路由等"]
N0 --> N1
N1 --> N2
N2 --> N3
这里有个细节值得记住:CNI 不负责 Kubernetes 的整个网络系统,它主要定义容器网络配置的插件接口。 IP 地址分配、跨节点路由、流量转发和网络策略等能力,由具体插件及其配套组件实现。
网络系统需要解决:
- 为 Pod 配置 IP 地址。
- 将 Pod 网络命名空间连接到节点网络。
- 让同节点和跨节点 Pod 可以互相通信。
- 正确处理路由、封装或其他转发机制。
- 在需要时执行 NetworkPolicy 等访问控制。
这些工作并不是全部由 Kubernetes 核心组件直接完成的,而是由容器运行时、CNI 插件、节点内核及相关控制组件协同实现。
现代 Kubernetes 中,具体由哪个组件调用 CNI、如何分配 IP 地址以及如何维护网络状态,取决于容器运行时与插件的实现。
2. Pod IP 是谁分配的?
在 Kubernetes 中,每个普通 Pod 通常有自己的 IP 地址。这个地址一般由 CNI 插件或其配套的 IPAM(IP Address Management,IP 地址管理)组件分配。
假设集群有两个节点:
| 节点 | 节点 IP | Pod 网段 |
|---|---|---|
| Node A | 192.168.1.10 | 10.244.1.0/24 |
| Node B | 192.168.1.20 | 10.244.2.0/24 |
Pod 分别获得:
- Pod A:
10.244.1.10 - Pod B:
10.244.2.20
这里的地址只是示例,实际网段由集群配置决定。
flowchart LR
subgraph G0["Node A<br/>192.168.1.10"]
direction LR
N0["Pod A<br/>10.244.1.10"]
N1["本地路由 / CNI 数据面"]
end
subgraph G1["Node B<br/>192.168.1.20"]
direction LR
N2["Pod B<br/>10.244.2.20"]
N3["本地路由 / CNI 数据面"]
end
N0 <--> N1
N1 <-->|"跨节点通信由 CNI 与底层网络共同实现"| N3
N3 <--> N2
这里需要区分三个地址:
- Node IP:节点自身的网络地址。
- Pod IP:Pod 的集群网络地址。
- Service ClusterIP:Service 使用的虚拟服务地址。
三者的作用不同,不能混为一谈。
1. IPAM 如何分配地址?
IPAM 负责管理地址分配,具体机制取决于 CNI 方案。常见方式包括:
- 为每个节点分配一个 Pod 子网,再从中分配 Pod IP。
- 通过集中式或分布式机制分配 IP。
- 从外部 IP 地址管理系统获取地址。
当 Pod 被删除后,地址何时释放、是否可能重新分配,取决于插件的地址管理实现。
可以使用以下命令查看 Pod IP:
kubectl get pods -A -o wide查看节点地址:
kubectl get nodes -o wide3. 同一个节点上的 Pod 如何通信?
假设 Pod A 和 Pod B 都运行在 Node A 上。
Linux 中常见的一种网络实现是使用 veth pair 将 Pod 的网络命名空间连接到宿主机网络。
flowchart TB
N0["Pod A 网络命名空间<br/>eth0 · 10.244.1.10"]
N1["veth pair / Linux Bridge 或其他转发机制"]
N2["Pod B 网络命名空间<br/>eth0 · 10.244.1.11"]
N0 <--> N1
N1 <--> N2
这是典型的 Linux Bridge 类网络示意图,并不是所有 CNI 都采用这种拓扑。某些方案会直接使用路由、eBPF 或其他机制。
可以把它理解为:
- Pod A 产生一个 IP 数据包。
- 数据包从 Pod 的网络接口发出。
- Linux 网络设备和路由规则决定下一步转发方向。
- 数据包进入 Pod B 的网络命名空间。
- Pod B 中的目标进程收到数据。
关键点:Pod 之间的通信最终依赖 Linux 网络栈及 CNI 配置的网络数据面,而不是 Kubernetes API Server 逐个转发数据包。
API Server 管理集群状态,不承担普通 Pod 网络流量的逐包转发。
4. 跨节点通信:Overlay 与 Underlay
现在让 Pod A 访问位于 Node B 的 Pod B。
两个 Pod 的 IP 分属不同子网:
Pod A:10.244.1.10Pod B:10.244.2.20Node A 需要知道如何到达 10.244.2.20。不同 CNI 会使用不同方案。
1. 方案一:Overlay 网络
Overlay 是在现有底层网络上建立一层虚拟网络。
例如,Flannel 的 VXLAN 模式可以将 Pod 网络数据包封装到 UDP/IP 数据包中,通过节点之间的底层网络传输。
flowchart TB
subgraph G0["底层网络传输"]
direction TB
N2["Node A"]
N3["Node B"]
N4["Pod A"]
N5["Pod B"]
end
N0["Pod A<br/>源地址 10.244.1.10"]
N1["Node A<br/>封装原始 Pod 数据包"]
N6["Node B<br/>解封装并转发给目标 Pod"]
N7["Pod B<br/>目标地址 10.244.2.20"]
N0 --> N1
N1 --> N2
N2 -->|"外层 IP"| N3
N4 -->|"内部数据包"| N5
N2 -.->|"封装"| N4
N3 --> N6
N6 --> N7
VXLAN 可以理解为“在外层包裹一层网络头部”,让底层网络把数据包送到目标节点,再由目标节点还原内部数据包。
优点:
- 不要求底层网络直接认识每个 Pod 子网。
- 可以利用现有的节点 IP 网络。
- 适合底层网络路由能力有限的环境。
需要注意:
- 增加封装开销。
- 需要考虑 MTU。
- 节点之间的 UDP 端口和网络路径必须可达。
2. 方案二:Underlay 路由
Underlay 方案利用底层路由网络直接传递 Pod 流量,而不一定需要 Overlay 隧道。
例如,Calico 可以在适当配置下通过 BGP 或静态路由传播 Pod 子网的可达信息。
flowchart TB
N0["Pod A"]
N1["Node A 路由表"]
N2["底层网络 / 路由设备"]
N3["Node B"]
N4["Pod B"]
N0 --> N1
N1 -->|"目标网段 10.244.2.0/24"| N2
N2 --> N3
N3 --> N4
这种方式通常需要底层网络知道 Pod 子网应该经过哪台节点,或者由节点本身通过路由协议学习相应路由。
优点:
- 可以减少隧道封装开销。
- 路由路径较直观。
- 在路由基础设施完善的环境中具有较好的扩展性。
但它需要正确的路由规划和底层网络配合。Calico 也支持 Overlay,因此不能简单地说 Calico 一定使用 Underlay。
5. Flannel:简单的 Pod 网络连接
Flannel 是一种常见的 Kubernetes 网络方案,设计重点是为不同节点上的 Pod 提供可达的网络。
它有多种后端实现,常见的包括 VXLAN 和直接路由模式。
1. Flannel VXLAN 模式
假设:
Node A:192.168.1.10Pod A :10.244.1.10
Node B:192.168.1.20Pod B :10.244.2.20Pod A 向 Pod B 发送数据时,Flannel VXLAN 模式可以通过外层节点 IP 封装内部 Pod 数据包。
flowchart TB
subgraph G0["原始数据包"]
direction TB
N1["源 10.244.1.10"]
N2["目的 10.244.2.20"]
end
subgraph G1["底层节点网络"]
direction TB
N4["Node A"]
N5["Node B<br/>外层目的 IP:192.168.1.20"]
end
N0["Pod A"]
N3["Node A:VXLAN 封装<br/>将内部 Pod 数据包封装到外层 UDP/IP 数据包中"]
N6["Node B:VXLAN 解封装<br/>恢复内部 Pod 数据包并转发给 Pod B"]
N0 --> N3
N0 -.->|"发送"| N1
N1 -->|"内部 Pod 数据包"| N2
N3 --> N4
N4 --> N5
N5 --> N6
这里有两个不同的 IP 层次:
| 层次 | 源地址 | 目的地址 |
|---|---|---|
| 内部数据包 | 10.244.1.10 | 10.244.2.20 |
| 外层封装 | 192.168.1.10 | 192.168.1.20 |
底层网络只需要负责把外层数据包送到目标节点;内部 Pod 地址则由 Overlay 网络处理。
2. Flannel 的优缺点
优点:
- 架构相对简单。
- VXLAN 模式可以运行在普通 IP 网络之上。
- 对希望快速建立 Pod 网络的集群较友好。
局限:
- Overlay 封装会增加额外开销。
- 网络策略通常需要额外组件提供。
- 排查问题时,需要区分内部 Pod 数据包和外层节点数据包。
3. 如何检查 Flannel?
在集群中执行:
kubectl get pods -n kube-system -o widekubectl get nodes -o wide在 Linux 节点上查看:
ip -d link showip routeip neigh show如果使用 VXLAN 后端,可以检查相关 VXLAN 接口和路由。具体接口名称会因配置而不同,不应假定所有环境都叫 flannel.1。
6. Calico:路由与网络策略
Calico 不只是一个 Overlay 网络插件,它还提供网络策略、路由管理等能力,并支持不同的数据面与网络部署模式。
常见方案包括:
- 基于 Linux 路由的网络。
- 基于 IP-in-IP 或 VXLAN 等方式的 Overlay 网络。
- 基于 eBPF 的数据面模式。
因此,不能简单地把 Calico 等同于某一种封装技术。
1. Calico 的路由型网络
假设 Pod 网段如下:
Node A:Pod 网段 10.244.1.0/24
Node B:Pod 网段 10.244.2.0/24在直接路由型部署中,节点可以通过路由表将目标 Pod 网段的流量转发到对应节点。
例如,Node A 需要知道:
flowchart LR
N0["10.244.2.0/24"]
N1["Node B"]
N0 -->|"通过 Node B 到达"| N1
当路由与底层网络都配置正确时,内部 Pod 数据包可以不经过 VXLAN 这类 Overlay 封装。
flowchart TB
subgraph G0["路由信息"]
direction TB
N2["目标网段 10.244.2.0/24"]
N3["Node B"]
end
N0["Pod A<br/>10.244.1.10"]
N1["Node A 路由"]
N4["底层网络<br/>根据部署方式转发原始 IP 数据包"]
N5["Node B"]
N6["Pod B<br/>10.244.2.20"]
N0 --> N1
N1 --> N4
N1 -.->|"查询"| N2
N2 -.->|"路由指向"| N3
N4 --> N5
N5 --> N6
但直接路由不是所有环境都能直接使用:底层网络必须具备相应的可达性,路由通告和防火墙也必须正确配置。
2. Calico NetworkPolicy
Calico 的一个重要优势是网络访问控制能力。
例如,你可以定义:
flowchart TB
N0["Frontend Pod"]
N1["Backend Pod"]
N2["Database Pod"]
N0 -->|"允许 TCP 8080"| N1
N1 -->|"允许 TCP 5432"| N2
它可以与 Kubernetes NetworkPolicy 配合,也提供 Calico 自己的策略资源,用于更丰富的网络访问控制场景。
3. 如何检查 Calico?
kubectl get pods -n calico-systemkubectl get pods -n kube-systemkubectl get nodes -o wide实际 Namespace 取决于安装方式,也可能使用 kube-system。
如果安装了 Calico 的诊断工具,可以进一步查看节点状态、路由和策略。不要直接修改自动生成的路由或防火墙规则,应该先确认 Calico 的实际运行模式。
7. Cilium:以 eBPF 为核心的数据面
Cilium 与 Flannel、传统 Calico 部署的一个重要区别是,它能够使用 eBPF 在 Linux 内核中实现许多网络数据面功能。
eBPF 允许受验证和约束的程序在特定内核执行点运行。Cilium 利用它实现网络转发、策略执行和可观测性等功能。
1. Cilium 的网络路径
在典型的 Cilium eBPF 数据面中,部分原本由传统 iptables 规则完成的功能,可以由 eBPF 程序处理。
flowchart TB
N0["Pod A"]
N1["Linux 网络接口 / eBPF 程序"]
N2["Service 负载均衡"]
N3["网络策略检查"]
N4["路由、隧道或其他转发路径"]
N5["Pod B"]
N0 --> N1
N1 --> N2
N1 --> N3
N1 --> N4
N4 --> N5
这只是逻辑示意。实际程序挂载位置和转发路径会随 Cilium 配置、内核能力及是否启用 Overlay 等因素变化。
Cilium 并不意味着完全不需要 Linux 路由、邻居表或其他内核网络机制;具体仍然取决于部署模式。
2. Cilium 的主要能力
- eBPF 网络数据面。
- Kubernetes Service 负载均衡。
- 基于身份与标签的网络策略。
- 网络流量可观测性。
- 在适用配置下替代传统 kube-proxy 的 Service 实现。
它的优势是能够将网络、安全和可观测性能力结合起来;需要考虑的成本则包括内核兼容性、架构复杂度和团队的运维经验。
3. 如何检查 Cilium?
如果集群安装了 Cilium CLI:
cilium statuscilium connectivity test也可以检查 Pod:
kubectl get pods -A -o wide这些命令需要对应的工具和权限。cilium connectivity test 可能创建测试资源并运行连通性检查,建议在可控环境中执行。
8. 三种方案如何选择?
| 维度 | Flannel | Calico | Cilium |
|---|---|---|---|
| 主要定位 | 简单的 Pod 网络连接 | 网络、路由与策略 | eBPF 网络、安全与可观测性 |
| 常见数据面 | VXLAN、直接路由等 | 路由、Overlay、eBPF 等 | eBPF,可配合路由或 Overlay |
| 网络策略 | 通常需配合其他实现 | 支持 | 支持 |
| Service 实现 | 通常配合 kube-proxy | 可依配置选择 | 可使用 eBPF 实现 |
| 学习重点 | Overlay、节点网络 | 路由、策略、网络模式 | eBPF、策略与数据面 |
| 运维考虑 | 结构较简单 | 模式与策略配置较丰富 | 对内核和排障能力要求较高 |
选择时不要只看性能宣传,还要考虑:
- 是否需要细粒度网络策略。
- 是否需要高效的流量观测。
- 底层网络是否允许 Overlay 封装。
- 内核版本是否符合要求。
- 团队是否具备相应的运维能力。
- 现有集群是否已经依赖特定 CNI 的功能。
对于初学者,建议先用 Flannel 理解基本 Pod 网络,再用 Calico 理解路由与 NetworkPolicy,最后学习 Cilium 和 eBPF 数据面。
9. CNI 配置目录
在节点上检查:
ls -l /etc/cni/net.d/ls -l /opt/cni/bin/常见情况下:
/etc/cni/net.d/保存 CNI 配置。/opt/cni/bin/保存 CNI 插件可执行文件。
但实际目录和部署方式可能因容器运行时、发行版和插件安装方式而异。
10. 常见故障:跨节点 Pod 无法通信
| 现象 | 优先检查 |
|---|---|
| 同节点通信正常,跨节点失败 | 节点间路由、隧道、底层防火墙 |
| Pod IP 无法访问 | CNI 配置、Pod 接口、路由、网络策略 |
| VXLAN 模式跨节点失败 | UDP 端口、节点 IP、隧道接口、MTU |
| 大请求失败,小请求正常 | MTU、路径 MTU 发现、分片或丢包 |
| 只有某些 Pod 不通 | NetworkPolicy、端点状态、节点分布 |
| Pod 创建失败且没有 IP | CNI 调用失败、IPAM 耗尽或配置错误 |
排障时建议按这个顺序:
- 确认源 Pod 和目标 Pod 正常运行。
- 确认 Pod IP 与所在 Node。
- 检查源节点的路由和网络接口。
- 检查 CNI 插件日志和配置。
- 检查节点之间的底层网络和防火墙。
- 检查 NetworkPolicy 与 MTU。
不要一开始就重启所有网络组件。先确定故障发生在 Pod 网络、节点网络还是应用层,效率会高很多。
11. 知识检查清单
你需要记住以下概念:
- CNI:定义并支持容器网络配置的插件接口。
- IPAM:负责管理 IP 地址分配。
- Pod IP:Pod 的网络地址。
- Overlay:在底层网络之上封装虚拟网络流量。
- Underlay:利用底层网络路由直接传输流量。
- Flannel、Calico、Cilium:实现 Pod 网络的不同方案,各自支持的能力取决于具体配置。
12. 官方资料与学习建议
学习建议:先用 Flannel 理解跨节点网络,再学 Calico 的路由和策略,最后研究 Cilium 的 eBPF 数据面。 如果你的生产集群已经采用其中某一种插件,则应优先深入当前实际使用的方案。