CNI网络插件

CNI的接口并不是指HTTP,gRPC这种接口,CNI接口是指对可执行程序的调用(exec)可执行程序,Kubernetes 节点默认的CNI插件路径为/opt/cni/bin

root@k8smaster:/home/master# cd /opt/cni/bin
root@k8smaster:/opt/cni/bin# ls
bandwidth  calico-ipam  firewall     host-local  LICENSE   portmap    sbr     tuning
bridge     dhcp         flannel      install     loopback  ptp        static  vlan
calico     dummy        host-device  ipvlan      macvlan   README.md  tap     vrf

CNI 通过JSON格式的配置文件来描述网络配置,当需要设置容器网络时,由容器运行时负责执行CNI插件,并通过CNI插件的标准输入(stdin)来传递配置文件信息,通过标准输出(stdout)接收插件的执行结果。从网络插件功能可以分为五类:

Pod 网络创建全流程

阶段 1:Pod 调度与创建触发(步骤 1-2)
  1. Pod 调度:K8s 调度器(kube-scheduler)根据资源、亲和性等规则,把 Pod 调度到集群的某个 Worker 节点上。
  2. Kubelet 发起创建:节点上的 kubelet 监听到调度结果,调用 CRI(容器运行时接口,如 containerd/CRI-O) 插件,发起 Pod 创建请求。

阶段 2:Pod 网络命名空间与 CNI 调用(步骤 3-5)
  1. 创建 Pod Sandbox:CRI 插件先创建 Pod Sandbox(沙箱),核心是生成唯一的 Pod Sandbox ID,并创建独立的 Pod 网络命名空间(Network Namespace)

    🔍 关键原理:Pod Sandbox 是 Pod 的隔离载体,所有业务容器都会加入这个网络命名空间,实现「同 Pod 共享网络」。

  2. 调用 CNI 插件:CRI 插件拿着 Pod 网络命名空间Pod Sandbox ID,调用节点上的 CNI 插件,触发网络配置流程。
  3. CNI 插件配置 Pod 网络:CNI 插件按顺序执行网络配置,图中以 Flannel 为例的链路是:
    • Flannel CNI 插件:处理 Overlay 网络(如 VXLAN),打通跨节点 Pod 网络
    • Bridge CNI 插件:创建 Linux 网桥,把 Pod 虚拟网卡(veth pair)桥接到宿主机
    • 主机IPAM CNI 插件:从预分配的 Pod 网段中,为 Pod 分配唯一 IP 地址、子网、路由
    • 返回 Pod IP 地址:CNI 把配置好的 IP 等信息,通过标准输出(stdout)返回给 CRI,完成网络配置。

阶段 3:Pause 容器与业务容器启动(步骤 6-10)
  1. 创建 Pause 容器:CRI 创建 pause 容器(也叫 infra 容器),并将其加入 Pod 的网络命名空间。

    🔍 关键作用:

    • 持有 Pod 网络命名空间,防止命名空间被误删除
    • 为 Pod 内所有业务容器提供统一的网络栈(共享 IP、端口、路由)
    • 是 Pod 网络的「锚点」,业务容器启动后直接复用这个网络
  2. 拉取应用镜像:Kubelet 调用 CRI 插件,拉取业务应用的容器镜像。
  3. 容器运行时拉取镜像:容器运行时(如 containerd)实际执行镜像拉取,缓存到节点本地。
  4. 启动应用容器:Kubelet 调用 CRI 插件,发起业务容器的启动请求。
  5. 启动并配置应用容器:CRI 调用 containerd,把业务容器启动到 Pod 的 cgroup、namespace 中,复用 pause 容器的网络栈,最终 Pod 正常运行。
  1. 创建 Pod
  2. 先启动 Pause 容器
  3. CNI 给 Pause 配置网络(分配 IP、网卡)
  4. 业务容器启动,加入 Pause 的网络 namespace
  5. 业务容器共享 IP、localhost

非封装

封装

路由分发

把每个节点上 Pod 的 IP 网段信息,同步给集群里所有节点,让大家都知道「哪个 Pod 在哪个机器上」,实现跨节点直接通信。


网络策略与网格

网络策略:给 Pod 装个「防火墙」,只允许指定的 Pod 互相访问,拦掉不安全的流量;(比如A可以访问B,不让B访问A)

服务网格(Istio/Linkerd 这类),就是给每个 Pod 里塞一个 Sidecar 代理容器,所有 Pod 进出的网络流量,都强制走这个代理,由代理统一做流量管理、安全控制、可观测性,不用改业务代码,就能给微服务加全套网络能力。

Calico 是一个纯三层的虚拟网络,它没有复用docker的docker0网桥,而是自己实现的,calico 网络不对数据包进行额外封装,不需要NAT和端口映射

  • Calico 是一个纯三层的虚拟网络,三层 = IP 路由层。=>Calico 不靠二层广播、不靠隧道,完全靠 IP 路由让 Pod 通信。

  • 它没有复用 docker 的 docker0 网桥 =>docker0 是 Docker 自带的网桥,Flannel 会用。Calico 不用它,自己建路由,更干净、更快。

  • 而是自己实现的 =>Calico自己管理路由、网卡、策略,不依赖 Docker 网络。

  • calico 网络不对数据包进行额外封装,不像 Flannel 用 VXLAN 给包套一层外衣=>Calico:原包直接发,不套壳,速度快。

  • 不需要 NAT 和端口映射=>Pod IP 直接可路由,不用转来转去,也不用映射端口。

Calico 架构组件

1.全局存储层:etcd

  • 核心作用:Calico 的「分布式总数据库」,存储集群所有网络配置、路由规则、网络策略、节点状态等全局数据,保证多节点数据强一致性。

  • 协作逻辑:所有节点的 calico/node 组件都从 etcd 读取 / 同步配置,是 Calico 集群的「大脑中枢」。

2. 节点代理层:calico/node(每个 Worker 节点必装的核心 Pod)

这是 Calico 在每个节点上的核心代理,包含 3 个关键子组件:

组件核心作用
bird(BGP 客户端)Calico 的路由核心,基于 BGP 协议,负责在节点间同步 Pod 网段路由,实现跨节点 Pod 三层直接路由通信;同时从 etcd 同步全局路由规则。
confd配置同步代理,负责从 etcd 拉取网络策略、路由等配置,动态更新 birdfelix 的本地配置,保证节点配置与全局一致。
felix(Felix Agent)Calico 的「执行器」,核心职责:配置节点内核的 route 路由表,把 BGP 同步的 Pod 路由写入内核・配置 iptables 规则,实现 K8s NetworkPolicy 网络策略(Pod 访问控制)管理 Pod 网络接口,维护节点网络状态

3. 内核层:Linux 内核网络栈

  • route(路由表):由 felix 写入,记录「哪个 Pod 网段在哪个节点」,是 Pod 跨节点通信的路由依据,实现纯三层路由转发。

  • iptables:由 felix 配置,实现 Pod 级别的网络访问控制(NetworkPolicy),相当于 Pod 的「防火墙」,拦截非法流量。

  • ethX:节点的物理网卡,负责节点间的物理网络通信,是 Pod 跨节点流量的物理出口。

4. 业务层:Pod(工作负载)

  • 运行在节点上的业务容器,拥有独立的 Pod IP,所有网络流量都经过 Calico 组件配置的路由、iptables 规则转发。

5. 可选层:tunnel(隧道)

  • 对应 Calico 的 IPIP/VXLAN Overlay 模式:当底层网络不支持 BGP 三层路由时,启用隧道封装,实现跨节点 Pod 通信(图中虚线为备用隧道链路);纯 BGP 模式下可关闭,无额外封装开销。

完整工作流程(Pod 跨节点通信)

host-1 的 Pod 访问 host-2 的 Pod 为例:

  1. 配置同步host-1host-2calico/node 从 etcd 同步全局网络配置、Pod 网段信息。
  2. 路由同步:两个节点的 bird 组件通过 BGP 协议,互相宣告本节点的 Pod 网段,同步到对方的路由表。
  3. 路由写入felix 把 BGP 同步的路由规则,写入节点内核的 route 路由表。
  4. 流量转发host-1 的 Pod 发出的流量,经过内核路由表,通过 ethX 物理网卡,直接三层路由转发到 host-2
  5. 目标转发host-2 收到流量后,通过本地路由表转发到目标 Pod,同时 iptables 规则校验流量是否符合网络策略,合法则放行。
  6. (可选)隧道封装:若底层网络不支持 BGP,流量会通过 tunnel 做 IPIP/VXLAN 封装,再转发到目标节点。

核心特性对应架构

1. 纯三层路由(无封装、无 NAT)
  • bird BGP 路由 + 内核 route 表实现,Pod IP 直接可路由,无需 Overlay 封装、无需 NAT / 端口映射,性能极高。

2. 网络策略(NetworkPolicy)
  • felix 配置节点 iptables 规则实现,在 Pod 流量进出节点时做访问控制,是 K8s 原生网络策略的底层实现。

3. 高可用与一致性
  • etcd 分布式存储 + confd 配置同步保证,多节点数据一致,单节点故障不影响集群网络。

VXLAN

VXLAN 是一种基于三层 IP 网络构建二层(局域网)通信的隧道技术,它把二层的数据包包在三层 UDP 包里发送,核心作用是在底层不通的网络间建立「虚拟局域网」。

IPIP模式

=>Linux 原生内核支持
=>IPIP隧道的工作原理是将源主机的IP数据包封装在一个新的IP数据包中,新的IP数据包的
目的地址是隧道的另一端。在隧道的另一端,接收方将解封装原始IP数据包,并将其传递
到目标主机。

IPIP隧道可以在不同的网络之间建立连接,例如在IPv4网络和IPv6网络之间建立连接。

IPIP 就是把一个完整的 IP 包,直接套在另一个 IP 包里发过去,在 Linux 内核里实现的轻量级隧道,用来跨网段打通两个网络。

  • Linux 原生内核支持不用装额外软件,Linux 系统自带 IPIP 隧道功能,Calico、Flannel 都能直接用。

  • 将源主机的 IP 数据包封装在一个新的 IP 数据包中

    • 里面一层:原始 Pod IP 包
    • 外面一层:节点物理 IP 包相当于:给数据包再穿了一件 IP 外套
  • 新 IP 包的目的地址是隧道另一端外套上写的是对端节点的物理 IP,路由器只看外层,直接转发到目标节点。

  • 隧道另一端解封装原始 IP 包,传给目标到了对端节点,脱掉外层 IP 外套,露出里面原本的 Pod IP 包,再发给目标 Pod。

  • 可以在不同网络之间建立连接只要节点之间三层 IP 能通,就能用 IPIP 建隧道,不管底层网段是否互通。

1.完整流量路径(node01 pod1 访问 node02 pod2)

这张图的红色箭头就是完整的 “快递路线”,分 6 个步骤

步骤 1:Pod 发出

pod1 (10.244.42.68) 通过 eth0 发出流量。

步骤 2:进入 Calico 虚拟网卡

流量到达节点内的虚拟网卡 cali-pod1

步骤 3:IPIP 封装(核心步骤)

流量被转发到 tunl0 网卡,Linux 内核在这一步做 IPIP 封装

  • 内层包:原始的 Pod IP 包(源 10.244.42.68,目的 10.244.103.67)
  • 外层包:内核套上一层新的 IP 头
    • 源 IP:node01 物理 IP (192.168.0.81)
    • 目的 IP:node02 物理 IP (192.168.0.82)
步骤 4:物理网络发送

封装后的包通过 ens33 物理网卡,经过底层交换机 / 路由器(S/R),发送到 node02。

步骤 5:对端解封装

node02 收到 UDP/IP 包后,到达 ens33,再转发到 tunl0内核自动拆掉外层 IP 包,还原出原始 Pod 包。

步骤 6:送达目标 Pod

解封装后的原始包,通过 cali-pod2 转发到 pod2eth0

2.数据包封装前后对比

3.IPIP模式总结:

数据包封包:封包,在tunl0设备上将pod发来的数据包的mac层去掉,留下ip层封包。
外层数据包目的ip地址根据路由得到。
优点:只要k8s节点间三层互通,可以跨网段,对主机网关路由没有特殊要求。
缺点:需要进行IPIP的数据包封包和解包会存在一定的性能损耗

4.Calico IPIP 模式配置与验证全解析

一、配置方法:Calico 开启 IPIP 模式

这是在 calico-node DaemonSet 中配置的环境变量,核心是开启 IPIP、关闭 VXLAN

环境变量配置值作用
CALICO_IPV4POOL_IPIPAlways强制开启 IPv4 池的 IPIP 隧道,所有 Pod 跨节点流量走 IPIP 封装
CALICO_IPV4POOL_VXLANNever彻底关闭 IPv4 池的 VXLAN 隧道,禁用 VXLAN 封装
CALICO_IPV6POOL_VXLANNever关闭 IPv6 池的 VXLAN 隧道(按需配置)

二、查看验证:确认 IPIP 模式生效
1. 验证 tunl0 隧道网卡创建(左侧命令)

执行 ifconfig tunl0(或 ip addr show tunl0),确认节点上已创建 Calico 专用的 IPIP 隧道虚拟网卡:

[root@k8s-master01 ~]# ifconfig tunl0
tunl0: flags=193<UP,RUNNING,NOARP>  mtu 1480
        inet 10.244.32.128  netmask 255.255.255.255
        tunnel  txqueuelen 1000  (IPIP Tunnel)
        ...
  • 关键信息tunl0 网卡正常 UP,标注 (IPIP Tunnel),MTU 为 1480(IPIP 封装占用 20 字节,比物理网卡 1500 小 20),说明 IPIP 隧道已成功创建。
2. 验证 BGP 邻居建立(右侧命令)

执行 calicoctl node status,确认 BGP 后端进程(BIRD/GoBGP)正常运行,且节点间 BGP 邻居已建立:

[root@k8s-master01 ~]# calicoctl node status
Calico process is running.

IPv4 BGP status
+--------------+---------------+-------+----------+-------------+
| PEER ADDRESS | PEER TYPE     | STATE | SINCE    | INFO        |
+--------------+---------------+-------+----------+-------------+
| 192.168.127.4 | node-to-node mesh | up   | 01:57:10 | Established |
| 192.168.127.5 | node-to-node mesh | up   | 01:57:08 | Established |
+--------------+---------------+-------+----------+-------------+

BGP模式

边界网关协议(Border Gateway Protocol,BGP)是互联网上一个核心的去中心化自治路由协议。它通过维护IP路由表或‘前缀’表来实现自治系统(AS)之间的可达性,属于矢量路由协议。BGP不使用传统的内部网关协议(IGP)的指标,而使用基于路径、网络策略或规则集来决定路由。因此,它更适合被称为矢量性协议,而不是路由协议。BGP,通俗的讲就是讲接入到机房的多条线路(如电信、联通、移动等)融合为一体,实现多线单IP,BGP机房的优点:服务器只需要设置一个IP地址,最佳访问路由是由网络上的骨干路由器根据路由跳数与其它技术指标来确定的,不会占用服务器的任何系统。

BGP 就是互联网上用来 “交换路由信息” 的核心协议,让各个网络之间互相告诉对方:我这里有哪些 IP 段、怎么走最快,从而实现全网互通。

  1. 边界网关协议,互联网核心的去中心化路由协议BGP 是互联网的 “交通规则总管”,没有它,不同运营商、不同机房就没法互通。

  2. 通过维护 IP 路由表 / 前缀表实现自治系统 AS 之间可达每个网络(AS)都有自己的 IP 段,BGP 负责把这些网段信息广播给全世界,让大家知道 “去哪找这些 IP”。

  3. 属于矢量路由协议,不用 IGP 指标,用路径、策略决定路由不像内网路由只看距离、跳数,BGP 看的是整条路怎么走、走哪家运营商、走哪条线路最优。

  4. 通俗讲:把电信、联通、移动多条线路融合成一个 IP一个服务器只需要 1 个 IP,访问者是电信就走电信线路,是联通就走联通线路,自动选最优。

  5. BGP 机房优点:单 IP、自动选最优路由、不占服务器资源服务器不用管线路,骨干路由器自动判断怎么走最快,完全不耗服务器性能。

在 K8s 里,BGP 就是让每个节点互相广播自己的 Pod 网段,让所有节点知道 “哪个 Pod 在哪个机器上”,实现跨节点直接路由,不用隧道、不用封装,速度最快。

说白了就是:

  • BGP = 路由广播协议
  • 告诉别人:我有哪些 IP 段
  • 自动选最优路径
  • Calico 用它实现无封装高性能网络

完整流量路径(node01 pod1 访问 node02 pod2)
步骤 1:Pod 发出流量

pod1 (10.244.42.65) 通过 eth0 发出访问 pod2 (10.244.103.65) 的数据包。

步骤 2:进入 Calico 虚拟网卡

流量通过 veth 对,到达节点内的 cali2009xsji11 虚拟网卡,进入宿主机网络栈。

步骤 3:内核路由转发(核心!无封装)

宿主机内核查询路由表,命中 BGP 同步的路由规则:10.244.103.65 via 192.168.66.12 dev ens33

  • 要去 10.244.103.65 这个 Pod,下一跳是 node02 的物理 IP 192.168.66.12,从 ens33 发出去
  • 全程不做任何封装,原始 Pod 包直接转发
步骤 4:物理网络直达

原始包通过 ens33 物理网卡,经交换机(S)三层路由,直接发送到 node02。

步骤 5:目标节点路由转发

node02 收到包后,内核查询本地路由表,知道 10.244.103.65 是本节点的 Pod,通过 calia93ixsji11 虚拟网卡,转发到 pod2eth0,完成通信。

BGP vs VXLAN

查看当前 Calico 模式

# 查看 Calico 安装资源(看 backend 是 bird 还是 vxlan)
kubectl get installation -o yaml

# 或者查看 configmap
kubectl get cm calico-config -o yaml -n kube-system

配置切换为 VXLAN 模式

修改 Installation 资源:

kubectl edit installation default

修改以下内容:

  1. 设置 calico_backend"vxlan"
  2. 注释掉 bird 相关参数,启用 VXLAN
  3. 配置 IP 池(IPIP 设为 Never,VXLAN 设为 Always)

等效的环境变量配置(DaemonSet 中):

yaml

- name: CALICO_IPV4POOL_IPIP
  value: "Never"  # 关闭 IPIP
- name: CALICO_IPV4POOL_VXLAN
  value: "Always" # 强制开启 VXLAN

重启 Calico 节点 Pod 使配置生效

# 滚动重启所有 calico-node
kubectl rollout restart daemonset calico-node -n kube-system

# 等待重启完成
kubectl get pods -n kube-system | grep calico-node

验证 VXLAN 模式生效

# 1. 查看 VXLAN 虚拟网卡
ifconfig vxlan.calico
# 预期:出现 vxlan.calico 网卡,MTU 通常 1450

# 2. 检查 BGP 进程是否关闭(关键验证)
calicoctl node status
# 预期输出:None of the BGP backend processes (BIRD or GoBGP) are running.

# 3. 查看节点路由表(VXLAN 模式下路由表会简化)
ip route
# 预期:不再有大量 bird 宣告的 BGP 路由

验证 BGP 模式(反向验证)

如果切回 BGP 模式:

# 修改 backend 为 bird
kubectl patch installation default --type merge -p '{"spec":{"calicoBackend":"bird"}}'

# 重启
kubectl rollout restart daemonset calico-node -n kube-system

# 验证状态
calicoctl node status
# 预期:BGP processes are running.

IPIP 模式 vs VXLAN 模式 vs BGP 模式

维度IPIP 模式(本图配置)VXLAN 模式BGP 纯路由模式
网络类型Overlay 覆盖网络(轻量)Overlay 覆盖网络Underlay 三层路由
封装方式IP-in-IP 封装(仅加一层 IP 头)VXLAN UDP 封装(加 VXLAN 头 + UDP 头)无封装,原包直传
BGP 依赖强依赖,必须运行 BGP 进程同步路由不依赖,BGP 进程可关闭强依赖,必须运行 BGP 进程
隧道设备tunl0(Linux 原生 IPIP 隧道设备)vxlan.calico(VXLAN 虚拟网卡)
性能高(封装开销极小,仅 20 字节)中等(封装开销大,约 50 字节)极高(无封装开销)
底层网络要求节点间 IP 三层可达即可节点间 IP 三层可达即可节点间需三层路由互通,支持 BGP
适用场景私有云 / 公有云,兼顾性能与兼容性公有云、大二层网络、大规模集群私有云、物理机、极致性能要求

Calico 可以通过配置开启 IPIP 隧道模式,关闭 VXLAN,依赖 BGP 同步路由,用轻量 IP 封装实现跨节点 Pod 通信,兼顾性能与兼容性

更多推荐