Calico 的三种工作模式

Calico 的运行支持三种模式:

  1. vxlan(overlay)
  2. ipip(overlay)
  3. bgp(underlay)

模式概述

IPIP

  • 工作原理:在 tun0 设备上将 Pod 发来的数据包的 MAC 层去除,仅保留 IP 层,并使用宿主机的 IP 封装传输。
  • 优缺点:要求节点之间三层网络互通,支持跨网段通信;封装/解封操作会引入一定性能损耗。

VXLAN

  • 工作原理:通过 vxlan 设备将原始数据包封装为 UDP 数据包,源/目的 MAC 地址替换为本机与对端 vxlan 网卡的 MAC 地址。
  • 优缺点:同样要求节点三层互通,支持跨网段;但也存在封包开销问题。

BGP

  • 工作原理:不进行任何封装,直接通过三层路由转发。
  • 优缺点:利用 BGP 实现节点间三层互通,无需封装;但需底层物理网络支持 BGP。

CrossSubnet

VXLAN 和 IPIP 模式均支持配置 CrossSubnet,即:

  • 同子网节点间使用直连(BGP)通信;
  • 不同子网节点之间才进行封装传输。

Calico Pod 之间的通信

同节点 Pod 通信

部署测试的 Workload:

1
2
3
4
root@suse-o11y-01:~# kubectl get pod -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
busybox-96f94bdb4-m4v56 1/1 Running 0 55s 10.42.42.253 suse-o11y-01 <none> <none>
busybox-96f94bdb4-rcckg 1/1 Running 0 52s 10.42.42.254 suse-o11y-01 <none> <none>

在其中一个 Pod ping 另一个 Pod,网络通信没问题:

1
2
3
4
5
6
7
8
9
root@suse-o11y-01:~# kubectl exec -it busybox-96f94bdb4-m4v56 -- ping -c 3 10.42.42.254
PING 10.42.42.254 (10.42.42.254): 56 data bytes
64 bytes from 10.42.42.254: seq=0 ttl=63 time=0.476 ms
64 bytes from 10.42.42.254: seq=1 ttl=63 time=0.225 ms
64 bytes from 10.42.42.254: seq=2 ttl=63 time=0.182 ms

--- 10.42.42.254 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.182/0.294/0.476 ms

检查 Pod 里的路由信息,都是只有两条路由,根据下面的路由,所有流量都会匹配第一条默认路由,从 eth0 网卡到达网关 169.254.1.1

1
2
3
4
5
root@suse-o11y-01:~# kubectl exec -it busybox-96f94bdb4-m4v56 -- route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 169.254.1.1 0.0.0.0 UG 0 0 0 eth0
169.254.1.1 0.0.0.0 255.255.255.255 UH 0 0 0 eth0

但在 Pod 里查看网卡信息,是不存在 IP 为 169.254.1.1 的网卡的:

1
2
3
4
5
6
7
root@suse-o11y-01:~# kubectl exec -it busybox-96f94bdb4-m4v56 -- ip -4 a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
2: eth0@if68: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1450 qdisc noqueue qlen 1000
inet 10.42.42.253/32 scope global eth0
valid_lft forever preferred_lft forever

查看 Pod 的 ARP 缓存,可以发现网关 169.254.1.1 的 MAC 地址是 ee:ee:ee:ee:ee:ee

1
2
3
root@suse-o11y-01:~# kubectl exec -it busybox-96f94bdb4-m4v56 -- ip neigh
172.16.16.110 dev eth0 lladdr ee:ee:ee:ee:ee:ee used 0/0/0 probes 0 STALE
169.254.1.1 dev eth0 lladdr ee:ee:ee:ee:ee:ee used 0/0/0 probes 4 STALE

容器网络都是基于 Linux veth-pair 技术实现 Network namespace 间通信,所以在 Pod 和主机节点上使用一对 veth-pair 连接。

在 Pod 内,eth0@xxx 就是 veth-pair 的其中一端,可以通过下面的命令查看:

1
2
3
4
5
6
7
root@suse-o11y-01:~# kubectl exec -it busybox-96f94bdb4-m4v56 -- ip addr show dev eth0
2: eth0@if68: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1450 qdisc noqueue qlen 1000
link/ether ea:44:ad:6c:8c:ea brd ff:ff:ff:ff:ff:ff
inet 10.42.42.253/32 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::e844:adff:fe6c:8cea/64 scope link
valid_lft forever preferred_lft forever

另一端则是在节点上,节点上的 calixxx@yyy 网卡就是每个 Pod veth-pair 的对端网卡,每 veth-pair 的接口均有相同的 inteface index,如上 Pod 的 interface index 是 68,那么在节点上就可以通过这个 interface index 查找到对端网卡:

1
2
3
root@suse-o11y-01:~# ip link show | egrep '^68:' -A 1
68: cali1d5453727e1@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UP mode DEFAULT group default qlen 1000
link/ether ee:ee:ee:ee:ee:ee brd ff:ff:ff:ff:ff:ff link-netns cni-6b6716bd-6825-e646-5d0a-c571b302d90f

所以 cali1d5453727e1 就是 Pod busybox-96f94bdb4-m4v56 在节点上的对端网卡,它与 Pod 内的 eth0 组成了一个 veth-pair,两张网卡也在同一个广播域,当 eth0169.254.1.1 发出 ARP 请求的时候,就会被 cali1d5453727e1 接收,但从上面的命令查看发现,cali1d5453727e1 也没有配置 IP 169.254.1.1,但依旧能回复 ARP 请求。

这是因为将 /proc/sys/net/ipv4/conf/<interface-dev>/proxy_arp 设置为 1 的时候,该网卡就会看起来像一个网关,会响应所有的 ARP 请求,并将自己的 MAC 地址告诉客户端。

通过命令查看,可以发现 cali1d5453727e1proxy_arp1,说明 cali1d5453727e1 收到 Pod 发出的 ARP 请求的时候,会将自己的 MAC 地址返回给 Pod:

1
2
root@suse-o11y-01:~# cat /proc/sys/net/ipv4/conf/cali1d5453727e1/proxy_arp
1

当 Pod 拿到 MAC 地址后就会进行封包,将报文转发到 cali1d5453727e1 网卡上,报文到达主机后,就会匹配主机路由:

1
2
root@suse-o11y-01:~# route -n | grep "10.42.42.254"
10.42.42.254 0.0.0.0 255.255.255.255 UH 0 0 0 cali9f5a511495b

可以发现发往 10.42.42.254(另一个 busybox Pod 的 IP)的报文直接通过 cali9f5a511495b,该网卡也就是另一个 busybox Pod 的 veth-pair 在主机上的一端。

报文通过 cali9f5a511495b 进入 Pod 内,进而完成了一次通信的全过程,流量图如下:

抓包进行验证,抓包前先在 Pod 内清理 ARP 缓存,避免获取不到 ARP 报文:

1
ip neigh flush dev eth0

通过 tcpdump 抓取对端网卡报文:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
root@suse-o11y-01:~# tcpdump -nn -i cali1d5453727e1 -e
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on cali1d5453727e1, link-type EN10MB (Ethernet), snapshot length 262144 bytes
# Pod 发起广播,获取 MAC 地址
16:36:58.621812 ea:44:ad:6c:8c:ea > ee:ee:ee:ee:ee:ee, ethertype ARP (0x0806), length 42: Request who-has 169.254.1.1 tell 10.42.42.253, length 28
# 回复 ARP 请求
16:36:58.621899 ee:ee:ee:ee:ee:ee > ea:44:ad:6c:8c:ea, ethertype ARP (0x0806), length 42: Reply 169.254.1.1 is-at ee:ee:ee:ee:ee:ee, length 28
# 三次 Ping 报文
16:37:00.913518 ea:44:ad:6c:8c:ea > ee:ee:ee:ee:ee:ee, ethertype IPv4 (0x0800), length 98: 10.42.42.253 > 10.42.42.254: ICMP echo request, id 68, seq 0, length 64
16:37:00.913668 ee:ee:ee:ee:ee:ee > ea:44:ad:6c:8c:ea, ethertype IPv4 (0x0800), length 98: 10.42.42.254 > 10.42.42.253: ICMP echo reply, id 68, seq 0, length 64
16:37:01.913851 ea:44:ad:6c:8c:ea > ee:ee:ee:ee:ee:ee, ethertype IPv4 (0x0800), length 98: 10.42.42.253 > 10.42.42.254: ICMP echo request, id 68, seq 1, length 64
16:37:01.913949 ee:ee:ee:ee:ee:ee > ea:44:ad:6c:8c:ea, ethertype IPv4 (0x0800), length 98: 10.42.42.254 > 10.42.42.253: ICMP echo reply, id 68, seq 1, length 64
16:37:02.914058 ea:44:ad:6c:8c:ea > ee:ee:ee:ee:ee:ee, ethertype IPv4 (0x0800), length 98: 10.42.42.253 > 10.42.42.254: ICMP echo request, id 68, seq 2, length 64
16:37:02.914179 ee:ee:ee:ee:ee:ee > ea:44:ad:6c:8c:ea, ethertype IPv4 (0x0800), length 98: 10.42.42.254 > 10.42.42.253: ICMP echo reply, id 68, seq 2, length 64

由此可知,同节点 Calico Pod 之间的通信主要是基于 veth-pair 实现,还没应用到 IPIP/VXLAN 等技术。

跨节点 Pod 通信(VXLAN 模式)

VXLAN(虚拟扩展局域网)是一种网络虚拟化技术,通过在 UDP 之上封装第二层以太网帧,实现在三层网络上的二层网络扩展,从而允许创建多达 1600 万个隔离的虚拟网络,远超 VLAN 的 4096 个网络限制。VXLAN 报文格式如下:

  • VXLAN 标识头:VXLAN header 里主要关注 VNI(VXLAN 网络标识符),VNI 是一个 24 位的标识符,用来唯一标识一个虚拟二层网络,就像传统 VLAN 中的 VLAN ID 一样,VNI 用来区分不同的虚拟网络。
  • UDP 头:在外层新增 UDP 头,默认目的端口号是 4789。
  • IP 头:在外层新增 IP 头,源地址是当前节点物理网卡 IP,目的地址是对端节点物理网卡 IP。
  • MAC 头:源 MAC 是当前节点物理网卡 MAC 地址,目的 MAC 是对端节点物理网卡 MAC 地址。

RKE2 使用 Calico CNI 构建集群时,默认使用的就是 VXLAN 模式:

1
2
3
4
5
root@suse-o11y-01:~# kubectl get installations.operator.tigera.io default -oyaml | grep encapsulation
encapsulation: VXLAN
root@suse-o11y-01:~# kubectl get ippools.crd.projectcalico.org default-ipv4-ippool -oyaml | grep -E "vxlanMode|ipipMode"
ipipMode: Never
vxlanMode: Always

部署测试的 Workload:

1
2
3
4
root@suse-o11y-01:~# kubectl get pod -owide -l app=busybox
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
busybox-67979bccf7-2dlqd 1/1 Running 0 42s 10.42.83.245 suse-o11y-02 <none> <none>
busybox-67979bccf7-dx4ck 1/1 Running 0 40s 10.42.42.255 suse-o11y-01 <none> <none>

在其中一个 Pod ping 另一个 Pod,网络通信没问题:

1
2
3
4
5
6
7
8
9
root@suse-o11y-01:~# kubectl exec -it busybox-67979bccf7-dx4ck -- ping -c 3 10.42.83.245
PING 10.42.83.245 (10.42.83.245): 56 data bytes
64 bytes from 10.42.83.245: seq=0 ttl=62 time=1.090 ms
64 bytes from 10.42.83.245: seq=1 ttl=62 time=0.413 ms
64 bytes from 10.42.83.245: seq=2 ttl=62 time=0.430 ms

--- 10.42.83.245 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.413/0.644/1.090 ms

查看 Pod 内部的路由,可以看到仍然是只有两条路由,说明无论跨不跨节点,Pod 的流量都会先到达宿主机,然后再根据主机路由进行下一跳:

1
2
3
4
5
root@suse-o11y-01:~# kubectl exec -it busybox-67979bccf7-dx4ck -- route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 169.254.1.1 0.0.0.0 UG 0 0 0 eth0
169.254.1.1 0.0.0.0 255.255.255.255 UH 0 0 0 eth0

对端 Pod IP 为 10.42.83.245,在宿主机上查看路由:

1
2
root@suse-o11y-01:~# route -n | grep 10.42.83
10.42.83.192 10.42.83.192 255.255.255.192 UG 0 0 0 vxlan.calico

Calico 会根据配置为每个节点上分配一个子网段,每个节点上的 Calico Pod IP 都在该子网里,所以说每个节点上都会存在到其他节点的子网路由。如果集群中有 n 个节点,那么每个节点都会有 n-1 个类似上述的路由。

通过上述路由可知,所有目标地址在 10.42.83.192/26 范围内的包,都将通过 vxlan.calico 接口发送,并封装为 VXLAN 报文,发给远端的隧道端点 10.42.83.192

在对端宿主机查看,也可以看到 vxlan.calico 网卡的 IP 就是 10.42.83.192

1
2
3
4
5
root@suse-o11y-02:~# ip -4 a
...
5: vxlan.calico: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN group default qlen 1000
inet 10.42.83.192/32 scope global vxlan.calico
valid_lft forever preferred_lft forever

任何一个 VXLAN 设备创建时都会指定一个三层物理网络设备作为 VTEP, Calico 也不例外, 可通过以下命令进行查看:

1
2
3
4
root@suse-o11y-01:~# ip -d link show vxlan.calico
12: vxlan.calico: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/ether 66:a7:a3:40:15:da brd ff:ff:ff:ff:ff:ff promiscuity 0 minmtu 68 maxmtu 65535
vxlan id 4096 local 172.16.16.110 dev ens34 srcport 0 0 dstport 4789 nolearning ttl auto ageing 300 udpcsum noudp6zerocsumtx noudp6zerocsumrx addrgenmode eui64 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535

VXLAN 为 overlay 的容器网络,是个大二层互通的解决方案,但最终报文还是要借助物理网卡出去,该 vxlan.calico 也是基于物理网卡 ens34 创建的,所以说该网卡上的报文依然基于 ens34 转发。

Calico 会为每个节点都创建一个 vxlan.calico 的网卡,作为 VXLAN 报文的网关设备。报文根据路由到达该网卡时,原始数据包会作为 VXLAN 数据包的负载,同时设置上述说到的 VXLAN 标识头、UDP 头、IP 头、MAC 头,报文如下:

  • 原始报文:包含内层源/目 IP,内层源/目 MAC,以及对应报文负载:
    • 内层源/目 IP:即源/目 Pod IP。
    • 内层源/目 MAC:因为 Pod 流量会先到达 vxlan.calico 进行封装,所以源 MAC 就是 vxlan.calico 网卡的 MAC 地址,目的 MAC 同理,不同的是目的 MAC 不是通过 ARP 获取的,而是 Calico 在每个节点预设好的,由 Calico 负责维护,没有过期时间。
1
2
3
root@suse-o11y-01:~# ip n | grep vxlan
10.42.83.192 dev vxlan.calico lladdr 66:8b:ff:1c:ec:cf PERMANENT
10.42.74.128 dev vxlan.calico lladdr 66:7a:20:ab:88:b4 PERMANENT
  • 外层 IP:为源/目节点的物理网卡 IP 地址,源 IP 为当前节点物理网卡 IP 地址,目的 IP 通过 FDB(Forwarding Database 转发数据库)表查询,:
1
2
3
4
root@suse-o11y-01:~# bridge fdb show | grep vxlan.calico
# 当有了要发给 66:8b:ff:1c:ec:cf 这个 MAC 地址的包,会进行 VXLAN 封装,然后发送给这个 VTEP IP 172.16.16.111
66:8b:ff:1c:ec:cf dev vxlan.calico dst 172.16.16.111 self permanent
66:7a:20:ab:88:b4 dev vxlan.calico dst 172.16.16.112 self permanent
  • 外层 MAC:源/目节点物理网卡对应的 MAC 地址。

经过封装后的报文的源 IP 地址、目的 IP 地址都是主机的物理机网卡地址,所以只要两个主机节点能够通信,报文即可传输到对端节点。

当报文到达对端节点的时候,内核会根据 VXLAN 报文标识将报文传输到 vxlan.calico 上,然后再将先前封装的 VXLAN 标识头、UDP 头、IP 头、MAC 头去掉,去掉后即可匹配节点的路由:

1
2
root@suse-o11y-02:~# route -n | grep 10.42.83.245
10.42.83.245 0.0.0.0 255.255.255.255 UH 0 0 0 calid05d3ec87de

最后就会通过 Pod 与节点对应的 veth-pair 设备,将流量顺利转发到 Pod 中,流量图如下:

抓包验证:

1
root@suse-o11y-01:~# tcpdump -nnn -i ens34 -e udp -w vxlan.pcap

通过 Wireshark 查看报文,通过下面的方法进行过滤:

1
ip.src == 10.42.42.255 && ip.dst == 10.42.83.245

  • Calico VXLAN 网络模式的优势体现在采用 VXLAN 技术能够实现 1600 万虚拟网络,远超传统 4096 VLAN 限制,适合大规模集群。

  • 因为 VXLAN 中使用 VNI 标记报文,通过 UDP 封装报文,所以在传输过程中,底层网络设备只能看到外层的 IP 和 UDP 头部,无法解析内部的二层帧,从而确保不同虚拟网络的流量不会相互干扰。每个 VTEP 只处理与其关联的 VNI 流量,确保不同虚拟网络的流量在 VTEP 处得到隔离。

  • 另外 VXLAN 作为 Overlay 技术,允许跨三层网络进行通信,解决了传统 VLAN 只能在同子网内通信的限制。也就是说即使节点之间跨子网,不属于同一 VLAN,跨节点的 Pod 也可以正常通信,因为 VXLAN 报文通过封装后,最终从物理网卡传输。

跨节点 Pod 通信(IPIP 模式)

IP-in-IP 就是把一个 IP 数据包又套在一个 IP 包里,即把 IP 层封装到 IP 层的一个 tunnel 。它的作用其实基本上就相当于一个基于 IP 层的网桥。一般来说,普通的网桥是基于 MAC 层的,根本不需要 IP,而 IPIP 则是通过两端的路由做一个 tunnel,把两个本来不通的网络通过点对点连接起来。

IPIP 报文格式如下:

  • 外层 IP 头:在外层新增的 IP 头,源目地址是两端物理节点网卡的 IP。
  • 内层 IP 头:源目地址是两端 Pod 的 IP。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
0       3       7              15              23              31
+---------------------------------------------------------------+
|Version| IHL |Type of Service| Total Length |
+---------------------------------------------------------------+
| Identification | Flags | Fragment Offset |
+---------------------------------------------------------------+
| Time to Live | Protocol | Header Checksum |
+---------------------------------------------------------------+
| Source Address |
+---------------------------------------------------------------+
| Destination Address |
+---------------------------------------------------------------+
| Options | Options |
+---------------------------------------------------------------+

由于 RKE2 使用 Calico 构建集群的时候默认使用 VXLAN,所以要先切换模式到 IPIP:

如果是自建 RKE2,可以直接创建 HelmChartConfig 进行配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
cat <<EOF | kubectl apply -f -
apiVersion: helm.cattle.io/v1
kind: HelmChartConfig
metadata:
name: rke2-calico
namespace: kube-system
spec:
valuesContent: |-
installation:
calicoNetwork:
# IPIP 需要开启 BGP
bgp: Enabled
ipPools:
- cidr: 10.42.0.0/16
encapsulation: IPIP
nodeAddressAutodetectionV4:
firstFound: false
interface: ens34

需要手动修改 IPPool 使用的模式:

1
2
3
kubectl patch ippool default-ipv4-ippool \
--type=merge \
-p '{"spec": {"ipipMode": "Always", "vxlanMode": "Never"}}'

手动删除所有 calico-node Pod,然后检查配置是否正常:

1
2
3
4
5
root@suse-o11y-01:~# kubectl get installations.operator.tigera.io default -oyaml | grep encapsulation
encapsulation: IPIP
root@suse-o11y-01:~# kubectl get ippools.crd.projectcalico.org default-ipv4-ippool -oyaml | grep -E "vxlanMode|ipipMode"
ipipMode: Always
vxlanMode: Never

检查跨节点通信:

1
2
3
4
5
6
7
8
9
10
11
12
13
root@suse-o11y-01:~# kubectl get pod -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
busybox-67979bccf7-56zrv 1/1 Running 0 4m33s 10.42.83.247 suse-o11y-02 <none> <none>
busybox-67979bccf7-ns9vj 1/1 Running 0 4m33s 10.42.42.199 suse-o11y-01 <none> <none>
root@suse-o11y-01:~# kubectl exec -it busybox-67979bccf7-ns9vj -- ping -c 3 10.42.83.247
PING 10.42.83.247 (10.42.83.247): 56 data bytes
64 bytes from 10.42.83.247: seq=0 ttl=62 time=0.875 ms
64 bytes from 10.42.83.247: seq=1 ttl=62 time=0.363 ms
64 bytes from 10.42.83.247: seq=2 ttl=62 time=0.477 ms

--- 10.42.83.247 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.363/0.571/0.875 ms

查看 Pod 的路由,依旧是只有两条,所以 IPIP 模式也是同理,Pod 的流量需要到达宿主机后才能转发下一跳:

1
2
3
4
5
root@suse-o11y-01:~# kubectl exec -it busybox-67979bccf7-ns9vj -- route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 169.254.1.1 0.0.0.0 UG 0 0 0 eth0
169.254.1.1 0.0.0.0 255.255.255.255 UH 0 0 0 eth0

对端 Pod IP 为 10.42.83.247,在宿主机上查看路由:

1
2
root@suse-o11y-01:~# route -n | grep 10.42.83
10.42.83.192 172.16.16.111 255.255.255.192 UG 0 0 0 tunl0

Calico 会根据配置为每个节点上分配一个子网段,每个节点上的 Calico Pod IP 都在该子网里,所以说每个节点上都会存在到其他节点的子网路由。如果集群中有 n 个节点,那么每个节点都会有 n-1 个类似上述的路由。

通过上述路由可知,所有目标地址在 10.42.83.192/26 范围内的包,都将通过 tunl0 接口发送,网关 IP 为 172.16.16.111,即对端主机物理网卡的 IP,可以发现网关 IP 的表现与 vxlan.calico 不同。

IPIP 模式下同样也会在主机上创建一个 IPIP 设备,默认是 tunl0tunl0 网卡 IP 地址与本机 Pod IP 属于同一个网段:

1
2
3
4
5
root@suse-o11y-01:~# ip -4 a
...
73: tunl0@NONE: <NOARP,UP,LOWER_UP> mtu 1480 qdisc noqueue state UNKNOWN group default qlen 1000
inet 10.42.42.201/32 scope global tunl0
valid_lft forever preferred_lft forever

tunl0 是 Linux 支持的隧道设备接口,当有这个接口时,出这个主机的 IP 包就会本封装成 IPIP 报文。

报文根据路由到达 tunl0 网卡时,原始数据包会作为 IPIP 数据包的负载,同时设置外层 IP 报文,此时只要两个主机之间能够通信,报文就可以正常传输到对端节点。

当报文到达对端节点物理网卡的时候就会解封外层的 IP 报文,根据内层 IP 报文匹配路由:

1
2
root@suse-o11y-02:~# route -n | grep 10.42.83.247
10.42.83.247 0.0.0.0 255.255.255.255 UH 0 0 0 calid1b248f937e

最后就会根据 calid1b248f937e 对应的 veth-pair 对端设备,也就是 Pod 内的 eth0 网卡,将报文转发到 Pod 中,流量图如下:

抓包验证:

1
root@suse-o11y-01:~# tcpdump -nnn -i ens34 -w ipip.pcap

通过 Wireshark 查看报文,通过下面的规则进行过滤:

1
ip.src == 10.42.42.199 && ip.dst == 10.42.83.247

  • IPIP 网络模式与 VXLAN 都属于 Overlay 网络,即需要结合 Linux 内核技术对原始报文进行封包、解包。

  • IPIP 相较 VXLAN 其数据包更小,但是一般需要底层网络允许 IPIP 协议;对于 VXLAN 即需要底层网络允许 UDP 流量。

Author

Warner Chen

Posted on

2025-05-28

Updated on

2025-05-29

Licensed under

You need to set install_url to use ShareThis. Please set it in _config.yml.
You forgot to set the business or currency_code for Paypal. Please set it in _config.yml.

Comments

You forgot to set the shortname for Disqus. Please set it in _config.yml.