跳到正文
复制成功
请遵守本站许可
报告
章节_文章 // 现场报告

文章编号: RL-CNI与跨节点网

2026.09.23

CNI 与跨节点网络:Flannel、Calico、Cilium

Chavy
Chavy
#Kubernetes#CNI#网络#跨节点通信
档案

摘要:理解 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 地址分配、跨节点路由、流量转发和网络策略等能力,由具体插件及其配套组件实现。

网络系统需要解决:

  1. 为 Pod 配置 IP 地址。
  2. 将 Pod 网络命名空间连接到节点网络。
  3. 让同节点和跨节点 Pod 可以互相通信。
  4. 正确处理路由、封装或其他转发机制。
  5. 在需要时执行 NetworkPolicy 等访问控制。

这些工作并不是全部由 Kubernetes 核心组件直接完成的,而是由容器运行时、CNI 插件、节点内核及相关控制组件协同实现。

现代 Kubernetes 中,具体由哪个组件调用 CNI、如何分配 IP 地址以及如何维护网络状态,取决于容器运行时与插件的实现。

2. Pod IP 是谁分配的?#

在 Kubernetes 中,每个普通 Pod 通常有自己的 IP 地址。这个地址一般由 CNI 插件或其配套的 IPAM(IP Address Management,IP 地址管理)组件分配。

假设集群有两个节点:

节点节点 IPPod 网段
Node A192.168.1.1010.244.1.0/24
Node B192.168.1.2010.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:

PRTCL // BASH
Terminal window
kubectl get pods -A -o wide

查看节点地址:

PRTCL // BASH
Terminal window
kubectl get nodes -o wide

3. 同一个节点上的 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 或其他机制。

可以把它理解为:

  1. Pod A 产生一个 IP 数据包。
  2. 数据包从 Pod 的网络接口发出。
  3. Linux 网络设备和路由规则决定下一步转发方向。
  4. 数据包进入 Pod B 的网络命名空间。
  5. Pod B 中的目标进程收到数据。

关键点:Pod 之间的通信最终依赖 Linux 网络栈及 CNI 配置的网络数据面,而不是 Kubernetes API Server 逐个转发数据包。

API Server 管理集群状态,不承担普通 Pod 网络流量的逐包转发。

4. 跨节点通信:Overlay 与 Underlay#

现在让 Pod A 访问位于 Node B 的 Pod B。

两个 Pod 的 IP 分属不同子网:

PRTCL // TEXT
Pod A:10.244.1.10
Pod B:10.244.2.20

Node 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 模式#

假设:

PRTCL // TEXT
Node A:192.168.1.10
Pod A :10.244.1.10
Node B:192.168.1.20
Pod B :10.244.2.20

Pod 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.1010.244.2.20
外层封装192.168.1.10192.168.1.20

底层网络只需要负责把外层数据包送到目标节点;内部 Pod 地址则由 Overlay 网络处理。

2. Flannel 的优缺点#

优点:

  • 架构相对简单。
  • VXLAN 模式可以运行在普通 IP 网络之上。
  • 对希望快速建立 Pod 网络的集群较友好。

局限:

  • Overlay 封装会增加额外开销。
  • 网络策略通常需要额外组件提供。
  • 排查问题时,需要区分内部 Pod 数据包和外层节点数据包。

3. 如何检查 Flannel?#

在集群中执行:

PRTCL // BASH
Terminal window
kubectl get pods -n kube-system -o wide
kubectl get nodes -o wide

在 Linux 节点上查看:

PRTCL // BASH
Terminal window
ip -d link show
ip route
ip neigh show

如果使用 VXLAN 后端,可以检查相关 VXLAN 接口和路由。具体接口名称会因配置而不同,不应假定所有环境都叫 flannel.1。

6. Calico:路由与网络策略#

Calico 不只是一个 Overlay 网络插件,它还提供网络策略、路由管理等能力,并支持不同的数据面与网络部署模式。

常见方案包括:

  • 基于 Linux 路由的网络。
  • 基于 IP-in-IP 或 VXLAN 等方式的 Overlay 网络。
  • 基于 eBPF 的数据面模式。

因此,不能简单地把 Calico 等同于某一种封装技术。

1. Calico 的路由型网络#

假设 Pod 网段如下:

PRTCL // TEXT
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?#

PRTCL // BASH
Terminal window
kubectl get pods -n calico-system
kubectl get pods -n kube-system
kubectl 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:

PRTCL // BASH
Terminal window
cilium status
cilium connectivity test

也可以检查 Pod:

PRTCL // BASH
Terminal window
kubectl get pods -A -o wide

这些命令需要对应的工具和权限。cilium connectivity test 可能创建测试资源并运行连通性检查,建议在可控环境中执行。

8. 三种方案如何选择?#

维度FlannelCalicoCilium
主要定位简单的 Pod 网络连接网络、路由与策略eBPF 网络、安全与可观测性
常见数据面VXLAN、直接路由等路由、Overlay、eBPF 等eBPF,可配合路由或 Overlay
网络策略通常需配合其他实现支持支持
Service 实现通常配合 kube-proxy可依配置选择可使用 eBPF 实现
学习重点Overlay、节点网络路由、策略、网络模式eBPF、策略与数据面
运维考虑结构较简单模式与策略配置较丰富对内核和排障能力要求较高

选择时不要只看性能宣传,还要考虑:

  • 是否需要细粒度网络策略。
  • 是否需要高效的流量观测。
  • 底层网络是否允许 Overlay 封装。
  • 内核版本是否符合要求。
  • 团队是否具备相应的运维能力。
  • 现有集群是否已经依赖特定 CNI 的功能。

对于初学者,建议先用 Flannel 理解基本 Pod 网络,再用 Calico 理解路由与 NetworkPolicy,最后学习 Cilium 和 eBPF 数据面。

9. CNI 配置目录#

在节点上检查:

PRTCL // BASH
Terminal window
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 创建失败且没有 IPCNI 调用失败、IPAM 耗尽或配置错误

排障时建议按这个顺序:

  1. 确认源 Pod 和目标 Pod 正常运行。
  2. 确认 Pod IP 与所在 Node。
  3. 检查源节点的路由和网络接口。
  4. 检查 CNI 插件日志和配置。
  5. 检查节点之间的底层网络和防火墙。
  6. 检查 NetworkPolicy 与 MTU。

不要一开始就重启所有网络组件。先确定故障发生在 Pod 网络、节点网络还是应用层,效率会高很多。

11. 知识检查清单#

你需要记住以下概念:

  • CNI:定义并支持容器网络配置的插件接口。
  • IPAM:负责管理 IP 地址分配。
  • Pod IP:Pod 的网络地址。
  • Overlay:在底层网络之上封装虚拟网络流量。
  • Underlay:利用底层网络路由直接传输流量。
  • Flannel、Calico、Cilium:实现 Pod 网络的不同方案,各自支持的能力取决于具体配置。

12. 官方资料与学习建议#

学习建议:先用 Flannel 理解跨节点网络,再学 Calico 的路由和策略,最后研究 Cilium 的 eBPF 数据面。 如果你的生产集群已经采用其中某一种插件,则应优先深入当前实际使用的方案。

归档于 2026.09.23
// 档案结束
Classified
章节_06
协议编号: CC-BY-NC-SA-4.0

CNI 与跨节点网络:Flannel、Calico、Cilium

作者:Chavy发布日期:2026.09.23

基于 CC BY-NC-SA 4.0

© 2026 Chavy
Powered by Astro