




















作者:尹正杰
版权声明:原创作品,谢绝转载!否则将追究法律责任。
| 网络模式 | 二层依赖 | 性能 | 租户隔离 | 推荐场景 |
|---|---|---|---|---|
| 纯 BGP(ipip=Never) | 必须二层互通 | 最优 | 弱 | 同机房同网段、高性能集群 |
| IPIP CrossSubnet | 无需 | 优 | 弱 | 企业内部标准集群(首选) |
| IPIP Always | 无需 | 良 | 弱 | 公有云、跨公网、网络复杂 |
| VXLAN Always/CrossSubnet | 无需 | 中 | 强 | 多租户、混合云、Flannel 兼容 |
| 双隧道 IPIP+VXLAN | 无需 | 差 | 强 | 仅测试,不推荐上生产 |
Calico 核心分为路由模式(BGP)、隧道模式、混合模式三大类。
Calico主流组网一共5种标准工作模式,外加部分衍生组合:
- 纯 BGP 路由模式(无隧道)
- IPIP 隧道模式(细分 3 种子模式)
- VXLAN 隧道模式
- IPIP + VXLAN 双隧道混合
- BGP + 隧道 混合模式(CrossSubnet 本质属于这类)
Calico 网络模式还会结合 BGP 启用 / 关闭 区分使用形态:
启用 BGP(默认):
节点间路由自动学习,路由收敛快,适合固定节点集群。
关闭 BGP(纯隧道):
完全依靠隧道转发,不建立 BGP 邻居,适配公有云(禁止 BGP)、安全策略严格的环境。
节点间通过BGP协议互相同步Pod网段路由,无任何隧道封装,报文裸跑在底层物理网络。
依赖:集群所有节点 二层互通(同网段 / 同 VLAN)
转发:宿主机内核路由直接转发Pod流量
spec:
ipipMode: Never
vxlanMode: Never
✅ 性能最优:无封装开销、延迟最低、CPU 占用小
✅ 架构简单,排障直观
❌ 强制要求节点二层可达,不能跨三层 / 跨公网 / 跨 VLAN
❌ 物理网络需允许 BGP 邻居建立
机房本地集群、节点同网段、物理网络可控、追求极致性能。
基于 IP-in-IP 内核隧道,把原始 IP 包封装在外层 IP 头中,三层网络即可互通。
ipipMode 控制行为,包含三个子模式Always,CrossSubnet,Never。
IPIP 通用优缺点
- 1.封装开销小(仅两层 IP 头),比 VXLAN 快
- 2.MTU 需调小(常规物理 MTU 1500 → Calico 建议 1440)
- 3.明文传输,无租户隔离能力
工作逻辑:
所有跨节点Pod流量全部走IPIP隧道封装
同节点 Pod 直连,不封装
特点
兼容性最强,不依赖二层、不依赖 BGP(可关闭 BGP)
公有云、跨机房、跨 VLAN 首选
全程封装,有固定小包开销
Calico 最常用生产模式
同物理子网节点:走 BGP 裸路由(无隧道,高性能)
跨物理子网节点:自动启用 IPIP 隧道封装
特点
兼顾性能 + 兼容性,大规模多子网集群标配。
即回到上面「纯 BGP 路由模式」,关闭 IPIP。
Calico 从 v3.17+ 正式完善 VXLAN 支持,标准 L2 Overlay,主流云原生通用隧道。
由 vxlanMode 控制,同样分三种:Always / CrossSubnet / Never。
原理
- 1.报文封装:外层 IP + UDP + VXLAN 头 + 原始二层帧
- 2.依靠 VNI(24 位)实现多租户网络隔离
- 3.节点三层可达即可,不依赖二层
关键配置:
spec:
ipipMode: Never
vxlanMode: Always
✅ 强大租户隔离(多集群 / 多租户场景友好)
✅ 标准 VXLAN,交换机 / 云厂商通用,生态极广
❌ 封装头更大,性能略低于 IPIP
❌ MTU 压缩更多(建议 1430)
多租户集群、和 Flannel 混合组网、云平台强推 VXLAN 的环境。
同时开启 IPIP + VXLAN,属于双 Overlay 组合。
关键配置:
spec:
ipipMode: Always
vxlanMode: Always
双重封装,开销最大、延迟最高
极少生产使用,一般仅测试 / 特殊网络隔离场景
不推荐业务集群使用
这不是独立新模式,是业务主流选型:
底层保留 BGP 路由能力
同子网:BGP 直路由
跨子网:自动启用 IPIP/VXLAN 隧道
分为两类:
BGP + IPIP(CrossSubnet) → 绝大多数企业内部集群首选
BGP + VXLAN(CrossSubnet) → 多租户 / 云环境首选
可关闭集群 BGP(calicoctl patch bgpconfig),纯隧道运行,彻底脱离 BGP 依赖
角色:
大脑、指挥中心
工作:
收集全网拓扑、地址信息、策略,生成路由 / ACL 规则,把规则推送到节点内核。
运行进程:
Calico 里是 BIRD(BGP 路由)、calicoctl、calico-apiserver、Felix (下发配置)
报文:
控制报文(BGP 握手、路由更新),流量极小。
角色:
高速搬运工
工作:
内核根据控制面下发好的路由表、iptables/ipset 规则,转发实际业务数据包(Pod 互访、南北流量)。
载体:
Linux 内核、网卡、tunl0/vxlan.calico 隧道网卡、iptables/nftables
报文:
业务真实数据包,集群绝大多数流量。
一句话区分:
控制面:商量怎么走路;数据面:实际在路上跑车。
BIRD:
基于 BGP 协议,和集群所有节点 BIRD 建立邻居,同步各节点的 Pod Block 段(192.168.x.0/26),算出最优路由条目,把路由信息交给 Felix。
不管 IPIP/VXLAN 开不开,BIRD (BGP) 永远运行,这就是为什么你calicoctl node status总能看到 BGP 邻居 Established。
Felix:
接收 BIRD 路由 + Kubernetes NetworkPolicy,翻译成 Linux 内核可识别的路由、iptables 规则,写入内核。
Felix 只负责下发规则,不转发任何 Pod 数据包。
内核拿到 Felix 下发的规则后,根据ipipMode/vxlanMode决定数据包从哪个网卡出去。
ipipMode:Never(纯 BGP 无隧道)
路由:192.168.xx.0/26 via 节点IP dev 物理网卡(eth0)
数据面:Pod 包不封装,裸 IP 从物理网卡直发到目标节点,BGP 直连转发。
ipipMode:Always
路由:192.168.xx.0/26 via 节点IP dev tunl0
数据面:Pod 原始 IP 包在内核被 IPIP 协议封装(外层包头 = 源节点 IP→目标节点 IP),从tunl0隧道设备发出,经物理网卡传输;对端内核解封装,转发到目标 Pod。
BGP(控制面)还在同步路由,但数据面全部走隧道封装,不走裸包直连,这就是之前的关键点。
| 模式 | 控制面 BGP | 数据面转发行为 |
|---|---|---|
| Always | BGP 正常建邻、同步路由 | 所有跨节点 Pod 包 → tunl0 封装转发 |
| CrossSubnet | BGP 正常建邻、同步路由 | 同子网:物理网卡裸包;跨子网:tunl0 封装 |
| Never | BGP 正常建邻、同步路由 | 全部物理网卡裸包,无隧道 |
补充关键误区:
- 1.开启IPIP≠关闭BGP:
BGP 永远是 Calico 默认控制面路由协议,只是数据面转发载体变成隧道。
- 2.VXLAN 和 IPIP 是数据面封装技术,和 BGP 控制面协议互不冲突,可以共存。
1.查看ippools信息
[root@master231 ~]# kubectl get ippools.crd.projectcalico.org -o yaml
apiVersion: v1
items:
- apiVersion: crd.projectcalico.org/v1
kind: IPPool
metadata:
annotations:
projectcalico.org/metadata: '{"creationTimestamp":"2026-06-01T03:09:25Z"}'
creationTimestamp: "2026-06-01T03:09:25Z"
generation: 1
name: default-ipv4-ippool
resourceVersion: "1680"
uid: 3558bfc5-b3ec-4e55-8267-5f957edb9f5f
spec:
allowedUses:
- Workload
- Tunnel
assignmentMode: Automatic
blockSize: 26
cidr: 192.168.0.0/16
ipipMode: Always
natOutgoing: true
nodeSelector: all()
vxlanMode: Never
kind: List
metadata:
resourceVersion: ""
[root@master231 ~]#
2.根据结果分析如下
关键配置清清楚楚:
ipipMode: Always # 开启了 IPIP 隧道
所有节点之间的 Pod 通信全部走 IPIP 隧道
这是公有云 / 跨子网集群最常用的模式
vxlanMode: Never # 没开 VXLAN
没有使用 VXLAN
也就是说,IPIP Always模式下,数据面没有“直连物理网卡的BGP路由”,所有Pod流量都被隧道封装了。
1.查看任意节点是否有tunl0网卡
[root@master231 ~]# kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
master231 Ready,SchedulingDisabled master 23h v1.33.11 10.0.0.231 <none> Ubuntu 24.04.4 LTS 6.8.0-117-generic containerd://2.1.1
master232 Ready,SchedulingDisabled master 15h v1.33.11 10.0.0.232 <none> Ubuntu 24.04.4 LTS 6.8.0-117-generic containerd://2.1.1
master233 Ready,SchedulingDisabled master 17h v1.33.11 10.0.0.233 <none> Ubuntu 24.04.4 LTS 6.8.0-117-generic containerd://2.1.1
worker66 Ready node 23h v1.33.11 10.0.0.66 <none> Ubuntu 24.04.4 LTS 6.8.0-117-generic containerd://2.1.1
worker77 Ready node 23h v1.33.11 10.0.0.77 <none> Ubuntu 24.04.4 LTS 6.8.0-117-generic containerd://2.1.1
[root@master231 ~]#
[root@master231 ~]# ip a | grep tunl0
4: tunl0@NONE: <NOARP,UP,LOWER_UP> mtu 1480 qdisc noqueue state UNKNOWN group default qlen 1000
inet 192.168.160.128/32 scope global tunl0
[root@master231 ~]#
[root@master231 ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host noprefixroute
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 00:0c:29:99:1b:83 brd ff:ff:ff:ff:ff:ff
altname enp2s1
altname ens33
inet 10.0.0.231/24 brd 10.0.0.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fe99:1b83/64 scope link
valid_lft forever preferred_lft forever
3: kube-ipvs0: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN group default
link/ether 1e:aa:75:05:2b:b7 brd ff:ff:ff:ff:ff:ff
inet 10.200.0.1/32 scope global kube-ipvs0
valid_lft forever preferred_lft forever
4: tunl0@NONE: <NOARP,UP,LOWER_UP> mtu 1480 qdisc noqueue state UNKNOWN group default qlen 1000
link/ipip 0.0.0.0 brd 0.0.0.0
inet 192.168.160.128/32 scope global tunl0
valid_lft forever preferred_lft forever
[root@master231 ~]#
2.其他节点测试验证
[root@master232 ~]# ip a | grep tunl0
4: tunl0@NONE: <NOARP,UP,LOWER_UP> mtu 1480 qdisc noqueue state UNKNOWN group default qlen 1000
inet 192.168.249.0/32 scope global tunl0
[root@master232 ~]#
[root@master233 ~]# ip a | grep tunl0
4: tunl0@NONE: <NOARP,UP,LOWER_UP> mtu 1480 qdisc noqueue state UNKNOWN group default qlen 1000
inet 192.168.40.64/32 scope global tunl0
[root@master233 ~]#
[root@worker66 ~]# ip a | grep tunl0
4: tunl0@NONE: <NOARP,UP,LOWER_UP> mtu 1480 qdisc noqueue state UNKNOWN group default qlen 1000
inet 192.168.65.128/32 scope global tunl0
[root@worker66 ~]#
[root@worker77 ~]# ip a | grep tunl0
5: tunl0@NONE: <NOARP,UP,LOWER_UP> mtu 1480 qdisc noqueue state UNKNOWN group default qlen 1000
inet 192.168.165.0/32 scope global tunl0
[root@worker77 ~]#
[root@worker88 ~]# ip a | grep tunl0
4: tunl0@NONE: <NOARP,UP,LOWER_UP> mtu 1480 qdisc noqueue state UNKNOWN group default qlen 1000
inet 192.168.126.0/32 scope global tunl0
[root@worker88 ~]#
1.修改前查看路由信息(任意工作节点流量都经过'tunl0'网卡)
[root@worker66 ~]# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.0.0.254 0.0.0.0 UG 0 0 0 eth0
10.0.0.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
192.168.65.128 0.0.0.0 255.255.255.192 U 0 0 0 *
192.168.160.128 10.0.0.231 255.255.255.192 UG 0 0 0 tunl0
192.168.165.0 10.0.0.77 255.255.255.192 UG 0 0 0 tunl0
192.168.249.0 10.0.0.232 255.255.255.192 UG 0 0 0 tunl0
[root@worker66 ~]#
2.修改ipipMode的工作模式为CrossSubnet
[root@master231 ~]# kubectl patch ippools.crd.projectcalico.org default-ipv4-ippool \
--type merge \
-p '{"spec":{"ipipMode":"CrossSubnet","vxlanMode":"Never"}}'
3.验证配置是否生效
[root@master231 ~]# kubectl get ippools.crd.projectcalico.org default-ipv4-ippool -o yaml | grep -E "ipipMode|vxlanMode"
ipipMode: CrossSubnet
vxlanMode: Never
[root@master231 ~]#
4.验证节点路由信息(任意工作节点流量都经过'eth0'网卡)
[root@worker66 ~]# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.0.0.254 0.0.0.0 UG 0 0 0 eth0
10.0.0.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
192.168.40.64 10.0.0.233 255.255.255.192 UG 0 0 0 eth0
192.168.65.128 0.0.0.0 255.255.255.192 U 0 0 0 *
192.168.160.128 10.0.0.231 255.255.255.192 UG 0 0 0 eth0
192.168.165.0 10.0.0.77 255.255.255.192 UG 0 0 0 eth0
192.168.249.0 10.0.0.232 255.255.255.192 UG 0 0 0 eth0
[root@worker66 ~]#
温馨提示:
你现在已经是 Calico IPIP CrossSubnet 工作模式
同子网节点:
流量直接走物理网卡(BGP 高性能转发)
跨子网节点:
才会自动走 IPIP 隧道(tunl0)
所谓的同子网和跨子网针对的是宿主机物理网卡IP,和 Pod 网段 192.168.0.0/16 毫无关系
同子网节点:
所有机器物理 IP:10.0.0.x,网关一致、二层互通。
跨子网节点:
nodeA:10.0.1.10/24
nodeB:10.0.2.20/24
两个网段靠网关路由打通,不在一个广播域。
1 先确认环境
- A.先检查k8s集群所有的节点是否在同一个子网,如果都在一个子网,则可以直接使用Never性能最优,直接跳过后续的检查步骤;
- B.如果有跨子网节点 → 必须提前在物理路由器 / 三层交换机加静态路由或BGP对接,否则切换后跨子网Pod会断。
2 切换ipipMode的Never的工作模式
[root@master231 ~]# kubectl patch ippool default-ipv4-ippool \
-p '{"spec":{"ipipMode":"Never","vxlanMode":"Never"}}' --type=merge
3.查看验证
[root@master231 ~]# kubectl get ippools.crd.projectcalico.org default-ipv4-ippool -o yaml | grep -E "ipipMode|vxlanMode"
ipipMode: Never
vxlanMode: Never
[root@master231 ~]#
VXLAN,有三种工作模式,通过修改vxlanMode的值来生效,其有效值为:
Never:
不用 VXLAN,纯 BGP。
CrossSubnet:
同子网直接路由,跨子网才 VXLAN 封装
Always:
所有跨节点 Pod 流量都走 VXLAN 封装
VXLAN 用 UDP 4789,防火墙 / 安全组要放行。
其实切换的逻辑和上面的ipipMode的方式一样。
具体操作:
1.切换vxlanMode的CrossSubnet的工作模式
[root@master231 ~]# kubectl patch ippools.crd.projectcalico.org default-ipv4-ippool \
--type merge \
-p '{"spec":{"ipipMode":"Never","vxlanMode":"CrossSubnet"}}'
2.测试验证
[root@master231 ~]# kubectl get ippools.crd.projectcalico.org default-ipv4-ippool -o yaml | grep -E "ipipMode|vxlanMode"
ipipMode: Never
vxlanMode: CrossSubnet
[root@master231 ~]#
3.检查各节点是否多出了vxlan网卡
[root@worker66 ~]# ip a | grep vxlan
10: vxlan.calico: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN group default qlen 1000
inet 192.168.65.130/32 scope global vxlan.calico
[root@worker66 ~]#
1.切换前先查看下本地路由【注意,同子网流量走的是eth0网卡哟】
[root@worker66 ~]# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.0.0.254 0.0.0.0 UG 0 0 0 eth0
10.0.0.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
192.168.40.64 10.0.0.233 255.255.255.192 UG 0 0 0 eth0
192.168.40.65 10.0.0.233 255.255.255.255 UGH 0 0 0 eth0
192.168.65.128 0.0.0.0 255.255.255.192 U 0 0 0 *
192.168.160.128 10.0.0.231 255.255.255.192 UG 0 0 0 eth0
192.168.160.129 10.0.0.231 255.255.255.255 UGH 0 0 0 eth0
192.168.165.0 10.0.0.77 255.255.255.192 UG 0 0 0 eth0
192.168.165.3 10.0.0.77 255.255.255.255 UGH 0 0 0 eth0
192.168.249.0 10.0.0.232 255.255.255.192 UG 0 0 0 eth0
192.168.249.1 10.0.0.232 255.255.255.255 UGH 0 0 0 eth0
[root@worker66 ~]#
2.切换vxlanMode的Always的工作模式
[root@master231 ~]# kubectl patch ippools.crd.projectcalico.org default-ipv4-ippool \
--type merge \
-p '{"spec":{"ipipMode":"Never","vxlanMode":"Always"}}'
3.测试验证
[root@master231 ~]# kubectl get ippools.crd.projectcalico.org default-ipv4-ippool -o yaml | grep -E "ipipMode|vxlanMode"
ipipMode: Never
vxlanMode: Always
[root@master231 ~]#
4.查看路由信息【注意,同子网流量走的是vxlan.calico网卡哟】
[root@worker66 ~]# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.0.0.254 0.0.0.0 UG 0 0 0 eth0
10.0.0.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
192.168.40.64 192.168.40.65 255.255.255.192 UG 0 0 0 vxlan.calico
192.168.40.65 0.0.0.0 255.255.255.255 UH 0 0 0 vxlan.calico
192.168.65.128 0.0.0.0 255.255.255.192 U 0 0 0 *
192.168.160.128 192.168.160.129 255.255.255.192 UG 0 0 0 vxlan.calico
192.168.160.129 0.0.0.0 255.255.255.255 UH 0 0 0 vxlan.calico
192.168.165.0 192.168.165.3 255.255.255.192 UG 0 0 0 vxlan.calico
192.168.165.3 0.0.0.0 255.255.255.255 UH 0 0 0 vxlan.calico
192.168.249.0 192.168.249.1 255.255.255.192 UG 0 0 0 vxlan.calico
192.168.249.1 0.0.0.0 255.255.255.255 UH 0 0 0 vxlan.calico
[root@worker66 ~]#
| 维度 | IPIP | VXLAN(推荐) |
|---|---|---|
| 封装协议 | IP-over-IP(协议 4) | UDP 4789 |
| 公有云放行 | ❌ 多默认拦截 | ✅ 几乎全放行 |
| NAT 穿透 | 弱 | 强 |
| 依赖 BGP | ✅ 必须 | ❌ 完全不依赖 |
| 典型云厂商支持 | Azure ❌,部分云受限 | AWS/Azure/GCP/ 阿里云 ✅ |
| 性能开销 | 略小 | 稍大(约 50 字节头),但通常无感Calico |
- 只有私有云、底层网络完全可控、能开BGP、防火墙放行协议4才用IPIP。
- 公有云用IPIP大概率直接不通或不稳定
公有云、底层不可控 → 用 VXLAN(Always),别用 IPIP。
VXLAN:UDP 4789、NAT 强、不依赖 BGP、云厂商全支持。
IPIP:协议 4、易被拦截、依赖 BGP、公有云不推荐。
1.全部节点同网段(你当前 10.0.0.x/24):推荐 Never,性能拉满;
2.集群未来会新增多网段节点 / 无法修改上层路由:固定 CrossSubnet(现阶段同网段跑 Never 性能,跨网段自动隧道),业界默认最优;
3.公有云、底层网络不可控:优先 Always/VXLAN,被动妥协。很多云厂商、安全组、防火墙默认拦截 IPIP 协议,直接不通。比如 Azure 明确不支持 IPIP。
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。