Linux 提供了 namespace 机制来实现系统资源的隔离,network namespace 提供了对网络资源的隔离。
如图所示:
我们希望把 netns1 和现有 VXLAN (10.0.1.0/24) 打通,一般情况下,netns1 的 veth 发出的 ARP 请求会到达位于 main netns 的另一端的 veth,然后如果 main netns 中有对应的 IP 就会回应 ARP 查询请求,否则就没有回应,例如 10.0.1.102 位于另一个 VTEP,如果 netns1 往外发出针对 10.0.1.102 的 ARP 查询请求 (who is 10.0.1.102, tell 10.0.1.103) 那么肯定收不到回复,这也就导致 netns1 ping 不通 10.0.1.102。而且,假如 10.0.1.102 发出一个 ARP 查询请求询问 10.0.1.103 的 MAC 地址,则这个 ARP 查询请求最多只会到达 server1 的 main netns, 到不了 10.0.1.103,因此 10.0.1.102 也无法主动向 10.0.1.103 发送数据。
要解决这个问题,我们学习 calico 的做法:
在 Linux,VXLAN 虚拟网卡的 ARP proxy 功能可以在它创建时设定,也可以在创建后设定,默认为关闭,需要我们显式地启用它。
我们首先启动两个虚拟机,它们位于同一个网段:
$ multipass launch --name vm1
$ multipass launch --name vm2
创建 VXLAN 虚拟网卡:
# 在 vm1 执行
$ sudo ip link add vxlan1 type vxlan id 101 remote 192.168.64.36
$ sudo ip link set vxlan1 up
$ sudo ip link set lo up
$ sudo ip addr add 10.0.1.101/24 dev vxlan1
$ sudo sysctl -w net.ipv4.icmp_echo_ignore_broadcasts=0
# 载 vm2 执行
$ sudo ip link add vxlan1 type vxlan id 101 remote 192.168.64.35
$ sudo ip link set vxlan1 up
$ sudo ip link set lo up
$ sudo ip addr add 10.0.1.102/24 dev vxlan1
$ sudo sysctl -w net.ipv4.icmp_echo_ignore_broadcasts=0
具体 VM 的 IP 地址可以通过 multipass list
命令查看。
在任意一台 vm 执行:
$ ping -I vxlan1 224.0.0.1
PING 224.0.0.1 (224.0.0.1) from 10.0.1.102 vxlan1: 56(84) bytes of data.
64 bytes from 10.0.1.102: icmp_seq=1 ttl=64 time=0.090 ms
64 bytes from 10.0.1.101: icmp_seq=1 ttl=64 time=1.03 ms
64 bytes from 10.0.1.102: icmp_seq=2 ttl=64 time=0.090 ms
64 bytes from 10.0.1.101: icmp_seq=2 ttl=64 time=1.74 ms
^C
--- 224.0.0.1 ping statistics ---
2 packets transmitted, 2 received, +2 duplicates, 0% packet loss, time 1073ms
rtt min/avg/max/mdev = 0.090/0.736/1.740/0.694 ms
会看到 VXLAN 网络本身已经通了。
加下来我们在 vm1 上建立一个 netns,以复现文章开头提到的那种情况:
$ sudo ip netns add ns1
$ sudo ip -n ns1 link set lo up
$ sudo ip link add veth1 netns ns1 type veth peer ns1-veth1-peer
$ sudo ip -n ns1 link set veth1 up
$ sudo ip link set ns1-veth1-peer up
$ sudo ip -n ns1 addr add 10.0.1.103/24 dev veth1