作为一个网络盲程序猿,要整理这样的文章还是稍稍有点吃力。文章中有不对的地方,还望路过的大神斧正,感激不尽!
VXlAN是搭建在三层网络上的虚拟二层网络。呃,暂停一下,我这里有几个问题需要回答一下:首先,什么是二层网络和三层网络?然后,为什么要在三层网络上搭建虚拟二层网络?
二层网络通常是指能直接使用Mac地址进程通讯的网络,比如:几台计算机和一台二层交换机组成的局域网就是一个典型的二级网络。是不是很简单,三层网络更简单:由几个二层网络和路由器组成的网络就是三层网络。(手动滑稽)
以上图为例来做一个简单的说明:A、B、C、D四台主机属于一个子网,192.168.1.0/24网段,网关是路由器端口2的IP地址192.168.1.254;E、F、G、H四台主机属于另一个子网,192.168.2.0/24网段,网关是路由器端口3的IP地址192.168.2.254;
A、B、C、D和二层交换机-1、二层交换机-2组成一个二层网络区域-A;E、F、G、H和二层交换机-3、二层交换机-4组成另一个二层网络区域-B。区域-A、区域-B和路由器组成一个三层网络。
以太网协议中规定,在同一个局域网内的主机直接通讯必须知道对方的MAC地址。而TCP/IP协议中,网络层与传输层只关系目标主机的IP地址。这就导致在以太网中使用IP协议时,数据链路层的以太网协议接到上层IP协议提供的数据中,只包含目的主机的IP地址。于是需要一种方法,根据目的主机的IP地址,获得其MAC地址。这就是ARP协议要做的事情。所谓地址解析(address resolution)就是主机在发送帧前将目标IP地址转换成目标MAC地址的过程。
另外,当发送主机和目的主机不在同一个局域网中时,即便的MAC地址,两者也不能直接通信,必须经过路由转发才可以。所以此时,发送主机通过ARP协议获得的将不是目的主机的真实MAC地址,而是一台可以通往局域网外的路由器的MAC地址。于是此后发送主机发往目的主机的所有帧,都将发往该路由器,通过它向外发送。
先来看在同一子网内的情况,A向C发送报文:A发现C的IP与本机处于同一网段,于是A查询本地ARP缓存。由于在初始状态下,ARP缓存为空,根据C的IP地址192.168.1.3无法匹配上对应的数据。于是A发起ARP广播,试图在局域网内找到IP地址为192.168.1.3的主机C,ARP报文如下(ff:ff:ff:ff:ff:ff
是广播时用的MAC地址):
源MAC | 目标MAC | 源IP | 目标IP |
---|---|---|---|
xx…xx:aa | ff:ff:ff:ff:ff:ff | 192.168.1.1 | 192.168.1.3 |
接下来,二层交换机-1收到ARP报文,了解到和端口1连接到是主机A,于是二层交换机-1将端口1连接主机A的信息缓存到本地MAC地址列表(MAC Address-Table)中:
MAC地址 | 端口 |
---|---|
xx…xx:aa | FE0/1 |
紧接着,二层交换机-1将ARP报文转发到端口1之外的所有端口。主机B收到端口之后,发现目标IP与本地IP不一样,丢弃ARP报文;二层交换机-2收到ARP报文之后,处理方式与二层交换机一致:缓存并转发;主机D和路由器收到ARP报文,比对后直接丢弃。只有主机C收到ARP报文之后,发现与本地IP一致,于是将主机A的IP地址和MAC地址保存到本地ARP缓存,然后响应ARP请求,因为本地ARP缓存中已经有主机C的信息,所以ARP响应以单播的方式发出,报文如下:
源MAC | 目标MAC | 源IP | 目标IP |
---|---|---|---|
xx…xx:cc | xx…xx:aa | 192.168.1.3 | 192.168.1.1 |
在ARP响应报文发往主机A的过程中,二层交换机-1和二层交换机-2又以同样的方式学习了主机C的MAC地址和端口信息。
之后,主机A和主机C之间就可以直接通过MAC地址进程通讯了,通讯流程与ARP响应流程类似。
再来看一下跨网络如何进行通信,A向E发送报文:AE的IP地址与本地IP不在同一个局域网内,于是A查询本地路由表,根据目标地址192.168.2.1进行匹配,没有与之匹配的记录,于是返回默认网关192.168.1.254。然后主机A发起ARP请求,以获得网关的MAC地址,ARP只会在同一个局域网内转发,路由器并不会将ARP报文转发到其他端口。获得网关的MAC地址之后,主机A会将数据报文发给网关:
源MAC | 目标MAC | 源IP | 目标IP |
---|---|---|---|
xx…xx:aa | xx…xx:22 | 192.168.1.1 | 192.168.2.1 |
注意:与ARP不同,这里的目标MAC地址的网关的MAC地址,但是目标IP地址是主机E的IP地址!
数据报文进入路由器的端口2之后,路由器发现报文内的目标MAC地址为本地端口2的MAC地址,而目标IP地址为192.168.2.1,所以会根据本地路由表查询192.168.2.1的下一跳。
路由器的寻址协议尚未研究,姑且认为路由器直接找到下一跳为192.168.2.254,出口为端口3~
路由器在寻址的过程中,也会发送ARP广播,从而获得主机E的MAC地址~
于是路由器将修改原始报文,将源MAC地址修改为端口3的MAC地址,将目标MAC地址修改为主机E的MAC地址:
源MAC | 目标MAC | 源IP | 目标IP |
---|---|---|---|
xx…xx:33 | xx…xx:ee(下一跳) | 192.168.1.1 | 192.168.2.1 |
路由器在修改报文的过程中,源IP和目标IP是不会变的~
接下来,路由器将修改过的数据报文发往主机E,发送过程与二层子网内数据报文发送过程相同。这样就实现了跨网络的数据报文转发。
随着云计算时代的来临,为了提高计算资源的利用率,虚拟化技术被广泛应用。同时,为了保证服务的稳定性,虚拟机需要能够在网络中不受限制的迁移。这里就面临着两个问题:
为了解决这两个问题,出现了很多值得一提的技术:堆叠、SVF、TRILL,可以从物理上增加二层网络的容量,也就是大二层的概念。和这些大二层技术一样,VXLAN也是为了解决二层网络容量不够的问题而生的。只不过前者需要对物理网络结构做巨大调整,而VXLAN是构建在三层网络之上的,可以对现有网络资源加以利用。
此外,为了避免大量广播在局域网内大肆传播,消耗网络资源,通常使用VLAN技术来划分广播域。但是VLAN仅允许划分4000个左右的广播域,对于公有云或其它大型虚拟化云计算服务这种动辄上万甚至更多租户的场景而言,VLAN的隔离能力显然已经力不从心。
VXLAN全称Virtual eXtensible Local Area Network——虚拟扩展局域网,采用L2 over L4(MAC-in-UDP)的报文封装模式,将二层报文用三层协议进行封装,可实现二层网络在三层范围内进行扩展,同时满足数据中心大二层虚拟迁移和多租户的需求。
简单点说:VXLAN就是使用UDP连接多个二层网络,使之成为一个更大的二层网络的技术。
核心概念如下:
先来看一下VXLAN的报文格式:
前面说过,VXLAN是在二层外面包三层,从报文内容也可以看出来:首先,是二层网络的实际报文,经过VTEP之后,现在前面增加VXLAN头;然后,VTEP使用UDP协议在外面的三层网络上传输,将VXLAN报文当作UDP报文的原始数据;最后,UDP就像正常的三层网络报文一样传递到目的地;
在同一个物理网络环境中会有很多的VTEP设备,隧道连接的VETP构成VXLAN网络。在VXLAN中,VM之间是在一个大二层使用MAC地址进行通讯,VETP需要将MAC包装到UDP中发送到目的地。那么源端VM就需要知道目标端VM的IP地址和MAC地址,远端VTEP也需要知道目标端VTEP的IP地址和MAC地址。VM的MAC地址可以通过ARP协议获得,关键问题在于,如何让大二层的ARP协议传播到目标端。也就是如何让ARP借助UDP在三层网络中传播。
为了让物理网络中的VTEP设备可以相互访问,正确的找到彼此,需要为每个VTEP设备配置对端的IP地址列表,配置VTEP的IP地址列表也称之为建立隧道,建立隧道有两种方式:手动、组播、自动。
对于手动和组播,会在下文中演示操作步骤,自动配置暂且虐过~
和前菜一样,我们先来个完整的网络拓扑图,然后谈一下同广播域和跨广播域的报文传递流程。拓扑图如下:
这张图是根据上文中的A、C、E、G四台服务器加一个VXLAN三层网关构成,然后在A、C、E、G四台服务器上分别创建虚拟机、网桥和VTEP等虚拟设备。上文中的网关、路由器和其他服务器简单的用L3 Network代替。
上图中的VTEP设备未必会有独立的IP地址,可能直接使用宿主机的IP地址,这样画便于理解,VETP连接的物理网络~
对上图简单说明一下:
- 在A服务器上创建了两个VTEP设备,分别配置不同的VNI,然后使用虚拟网桥为每个VTEP连接三台虚拟机。
- 在C服务器上创建一个VTEP设备,配置与A服务器上VTEP-A-2相同的VNI,然后使用虚拟网桥为其连接三个虚拟机。
- 在E服务器上创建一个VTEP设备,配置与A服务器上VTEP-A-1相同的VNI,然后使用虚拟网桥为其连接三个虚拟机。
- 在G服务器上创建一个VTEP设备,配置与A服务器上VTEP-A-1相同的VNI,因此,VTEP-A-1、VTEP-E-1和VTEP-G-1将处于同一个VXLAN广播域内。
- 在L3 Network增加一个VXLAN三层网关设备,用于VXLAN不同VNI的子网之间相互访问,以及VXLAN访问非VXLAN。
- VTEP隧道配置信息如下(笛卡尔积):
源端IP 源端MAC 远端IP 远端MAC VNI 192.168.1.101 xx…xx:v1 192.168.1.102 xx…xx:v2 vni-1 192.168.1.101 xx…xx:v1 192.168.1.103 xx…xx:vc vni-1 192.168.1.101 xx…xx:v1 192.168.2.101 xx…xx:ve vni-1 192.168.1.101 xx…xx:v1 192.168.2.102 xx…xx:vg vni-1 192.168.1.101 xx…xx:v1 192.168.3.254 xx…xx:00 vni-1 192.168.1.102 xx…xx:v2 192.168.1.101 xx…xx:v1 vni-2 192.168.1.102 xx…xx:v2 192.168.1.103 xx…xx:vc vni-2 192.168.1.102 xx…xx:v2 192.168.2.101 xx…xx:ve vni-2 192.168.1.102 xx…xx:v2 192.168.2.102 xx…xx:vg vni-2 192.168.1.102 xx…xx:v2 192.168.3.254 xx…xx:00 vni-2 192.168.1.103 xx…xx:vc 192.168.1.101 xx…xx:v1 vni-2 192.168.1.103 xx…xx:vc 192.168.1.102 xx…xx:v2 vni-2 192.168.1.103 xx…xx:vc 192.168.2.101 xx…xx:ve vni-2 192.168.1.103 xx…xx:vc 192.168.2.102 xx…xx:vg vni-2 192.168.1.103 xx…xx:vc 192.168.3.254 xx…xx:00 vni-2 192.168.2.101 xx…xx:ve 192.168.1.101 xx…xx:v1 vni-1 192.168.2.101 xx…xx:ve 192.168.1.102 xx…xx:v2 vni-1 192.168.2.101 xx…xx:ve 192.168.1.103 xx…xx:vc vni-1 192.168.2.101 xx…xx:ve 192.168.2.102 xx…xx:vg vni-1 192.168.2.101 xx…xx:ve 192.168.3.254 xx…xx:00 vni-1 192.168.2.102 xx…xx:vg 192.168.1.101 xx…xx:v1 vni-1 192.168.2.102 xx…xx:vg 192.168.1.102 xx…xx:v2 vni-1 192.168.2.102 xx…xx:vg 192.168.1.103 xx…xx:vc vni-1 192.168.2.102 xx…xx:vg 192.168.2.101 xx…xx:ve vni-1 192.168.1.102 xx…xx:vg 192.168.3.254 xx…xx:00 vni-1
- VXLAN三层网关配置信息
远端IP 下一跳IP 下一跳MAC VNI 逻辑接口 10.1.1.0/24 10.1.1.254 xx…xx:b1 vni-1 BDIF-1 10.1.2.0/24 10.1.2.254 xx…xx:b2 vni-2 BDIF-2
接下来,利用上图推演一些同子网数据报文转发和不同子网数据报文转发到过程:
####2.4.1、同子网互通
假设VA-1发送数据报文到VE-1,流程如下:
VA-1根据IP地址10.1.1.4向VE-1发送报文。VA-1发现VE-1的IP与本地IP地址10.1.1.1处于同一网段,但是初始状态下,VA-1上没有VE-1的MAC地址,所以VA-1发起ARP,企图通过广播获得VE-1的MAC地址,ARP报文如下:
源端IP | 源端MAC | 远端IP | 远端MAC |
---|---|---|---|
10.1.1.1 | xx…xx:a1 | 10.1.1.4 | ff:ff:ff:ff:ff:ff |
ARP报文通过网桥传递给VTEP-A-1,VTEP-A-1收到报文后,首先学习VA-1的MAC地址、VNI和接入端口三者的对应关系,然后VTEP-A-1根据头端复制列表对报文进行复制,并分别进行封装,封装后的UDP报文如下:
源端IP | 源端MAC | 远端IP | 远端MAC | VNI | 数据报文 |
---|---|---|---|---|---|
192.168.1.101 | xx…xx:v1 | 192.168.2.1 | xx…xx:ee(下一跳) | vni-1 | 原始ARP报文 |
192.168.1.101 | xx…xx:v1 | 192.168.2.3 | xx…xx:gg(下一跳) | vni-1 | 原始ARP报文 |
192.168.1.101 | xx…xx:v1 | 192.168.3.254 | xx…xx:00(下一跳) | vni-1 | 原始ARP报文 |
- VTEP 会根据VNI对原始ARP报文进行复制,添加VXLAN头,然后分别封装到UDP报文中进行传输
UDP报文到达VTEP-E-1、VTEP-G-1和VTEP-0之后,将UDP报文拆包,获得原始ARP报文,学习VA-1的MAC地址、VTEP-A-1的IP地址和VNI三者的对应关系。然后VTEP将拆包得到的ARP报文在本地广播域内广播。
VE-1、VE-2、VE-3和VG-1、VG-2、VG-3五台虚拟机以及VXLAN三层网关会收到ARP广播,然后与本地IP进行比对。VE-1与ARP报文中的目标IP地址匹配,学习VA-1的IP地址和MAC地址,作出ARP响应。其他VM与三层网关丢弃ARP报文。
由于VE-1已经缓存VA-1的IP地址与MAC地址,所以ARP响应以单播形式发出,报文如下:
源端IP | 源端MAC | 远端IP | 远端MAC |
---|---|---|---|
10.1.1.4 | xx…xx:e1 | 10.1.1.1 | xx…xx:a1 |
ARP响应报文通过网桥传递给VTEP-E-1,VTEP-E-1学习VE-1的MAC地址、VNI和接入端口三者的对应关系,然后在ARP响应报文头部添加VXLAN头,包装到UDP报文内转发,UDP报文如下:
源端IP | 源端MAC | 远端IP | 远端MAC | VNI | 数据报文 |
---|---|---|---|---|---|
192.168.2.101 | xx…xx:ve | 192.168.1.101 | xx…xx:v1(下一跳) | vni-1 | 原始ARP响应报文 |
UDP报文根据远端IP地址192.168.1.101到达VTEP-A-1之后,被拆包,得到原始ARP响应报文,然后学习VE-1的MAC地址、VETP-E-1的IP地址和VNI三者的对应关系。之后根据原始报文内的目标MAC地址,将原始ARP报文发送给VA-1。
之后VA-1与VE-1都通过ARP请求获得了对方的MAC地址,之后的数据报文将通过单播进行传递,传递流程与ARP类似~
####2.4.2、不同子网互通
假设VA-1发送数据报文到VC-1,流程如下:
VA-1根据IP地址10.1.2.1向VC-1发送数据报文。VA-1发现VC-1的IP地址与本地IP地址不在同一个网段内,所以查询路由表,找到与之对应的网关,没有与之匹配的网关信息,获得默认网关:10.1.1.254。
由于是初始状态,VA-1本地没有默认网关的MAC地址,所以发起ARP广播,试图获得默认网关的MAC地址,ARP报文如下:
源端IP | 源端MAC | 远端IP | 远端MAC |
---|---|---|---|
10.1.1.1 | xx…xx:a1 | 10.1.1.254 | ff:ff:ff:ff:ff:ff |
ARP报文通过网桥传递给VTEP-A-1,然后VTEP-A-1根据头端复制列表对报文进行负责,并分别进行封装,封装后的UDP报文如下:
源端IP | 源端MAC | 远端IP | 远端MAC | VNI | 数据报文 |
---|---|---|---|---|---|
192.168.1.101 | xx…xx:v1 | 192.168.2.1 | xx…xx:ee(下一跳) | vni-1 | 原始ARP报文 |
192.168.1.101 | xx…xx:v1 | 192.168.2.3 | xx…xx:gg(下一跳) | vni-1 | 原始ARP报文 |
192.168.1.101 | xx…xx:v1 | 192.168.3.254 | xx…xx:00(下一跳) | vni-1 | 原始ARP报文 |
UDP报文到达VTEP-E-1、VTEP-G-1和VTEP-0之后,将UDP报文拆包,获得原始ARP报文,然后VTEP将拆包得到的ARP报文在本地广播域内广播。五台虚拟机收到原始ARP报文之后,经过比对,直接丢弃。VXLAN三层网关收到ARP报文,比对发现目标IP与本地BDIF-1的IP地址匹配,学习VA-1的MAC地址、VTEP-A-1IP和VNI的三者的对应关系之后,以单播响应ARP请求,VA-1因此获得三层网关接口BDIF-1的MAC地址。
VA-1获得网关的MAC地址之后,将数据报文以单播形式发给默认网关,数据报文如下:
源端IP | 源端MAC | 远端IP | 远端MAC |
---|---|---|---|
10.1.1.1 | xx…xx:a1 | 10.1.2.1 | xx…xx:b1 |
VTEP-A-1收到原始数据报文后,添加VXLAN头,包装到UDP报文内,UDP报文如下:
源端IP | 源端MAC | 远端IP | 远端MAC | VNI | 数据报文 |
---|---|---|---|---|---|
192.168.1.101 | xx…xx:v1 | 192.168.3.254 | xx…xx:00(下一跳) | vni-1 | 原始数据报文 |
VTEP-0收到原始数据报文之后,对比发现,原始报文内的远端MAC地址为本地BDIF-1端口的MAC地址,远端IP地址为VC-1的IP地址10.1.2.1。所以根据路由表,决定下一跳为BDIF-2端口;通过ARP广播,获得远端IP地址10.1.2.1对应的MAC地址。VTEP-0将修改原始数据报文:
源端IP | 源端MAC | 远端IP | 远端MAC |
---|---|---|---|
10.1.1.1 | xx…xx:b2 | 10.1.2.1 | xx…xx:c1 |
VTEP-0修改后的原始数据报文从BDIF-2端口流出前,VTEP-0根据ARP广播,得知目的IP地址为VTEP-C-1的IP地址,BDIF-2将为其配置VXLAN头并包装为UDP报文,格式如下:
源端IP | 源端MAC | 远端IP | 远端MAC | VNI | 数据报文 |
---|---|---|---|---|---|
192.168.3.254 | xx…xx:00 | 192.168.1.103 | xx…xx:vc(下一跳) | vni-2 | VTEP-0修改后的报文 |
VTEP-C-1收到数据报文之后,拆包,获得原始数据报文。然后,根据原始数据报文中的远端MAC地址,将数据报文抓发给VC-1。
到此,完成VXLAN跨域转发~
在之前关于Linux namespace的文章中,利用bridge和veth pair实现了单机环境下不同namespace之间相互通讯。接下来的内容将尝试在不同节点上创建network namespace,利用VXLAN实现跨节点的network namespace之间相互通讯。
操作系统 | IP | hostname |
---|---|---|
CentOS Linux release 7.5.1804 (Core) | 172.16.7.100 | node-0 |
CentOS Linux release 7.5.1804 (Core) | 172.16.7.101 | node-1 |
### 创建三个network namespace ###
[root@node-0 ~]# ip netns add container-0
[root@node-0 ~]# ip netns add container-1
[root@node-0 ~]# ip netns add container-2
[root@node-0 ~]# ip netns list
container-2
container-1
container-0
### 创建brodge设备 ###
[root@node-0 ~]# ip link add type bridge
### 创建三对veth pair ###
[root@node-0 ~]# ip link add type veth
[root@node-0 ~]# ip link add type veth
[root@node-0 ~]# ip link add type veth
### 检查创建结果 ###
[root@node-0 ~]# ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
link/ether 00:50:56:2d:4b:f6 brd ff:ff:ff:ff:ff:ff
3: bridge0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether 82:76:89:91:df:3e brd ff:ff:ff:ff:ff:ff
4: veth0@veth1: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether e2:fe:90:f7:70:c0 brd ff:ff:ff:ff:ff:ff
5: veth1@veth0: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether de:15:00:f8:6c:ac brd ff:ff:ff:ff:ff:ff
6: veth2@veth3: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether ba:c4:88:b8:ef:f5 brd ff:ff:ff:ff:ff:ff
7: veth3@veth2: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether 5a:7e:f1:9b:ff:17 brd ff:ff:ff:ff:ff:ff
8: veth4@veth5: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether 9e:bf:09:a8:6c:0c brd ff:ff:ff:ff:ff:ff
9: veth5@veth4: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether da:12:08:18:f3:be brd ff:ff:ff:ff:ff:ff
### 使用veth pair将network namespace与bridge连接起来 ###
[root@node-0 ~]# ip link set dev veth0 netns container-0
[root@node-0 ~]# ip link set dev veth2 netns container-1
[root@node-0 ~]# ip link set dev veth4 netns container-2
[root@node-0 ~]# ip link set dev veth1 master bridge0
[root@node-0 ~]# ip link set dev veth3 master bridge0
[root@node-0 ~]# ip link set dev veth5 master bridge0
### 为各个network namespace下的veth设备配置IP地址,启动lo和veth设备 ###
[root@node-0 ~]# ip netns exec container-0 ip addr add 10.1.1.1/24 dev veth0
[root@node-0 ~]# ip netns exec container-0 ip link set dev lo up
[root@node-0 ~]# ip netns exec container-0 ip link set dev veth0 up
[root@node-0 ~]# ip link set dev veth1 up
[root@node-0 ~]# ip netns exec container-1 ip addr add 10.1.1.2/24 dev veth2
[root@node-0 ~]# ip netns exec container-1 ip link set dev lo up
[root@node-0 ~]# ip netns exec container-1 ip link set dev veth2 up
[root@node-0 ~]# ip link set dev veth3 up
[root@node-0 ~]# ip netns exec container-2 ip addr add 10.1.1.3/24 dev veth4
[root@node-0 ~]# ip netns exec container-2 ip link set dev lo up
[root@node-0 ~]# ip netns exec container-2 ip link set dev veth4 up
[root@node-0 ~]# ip link set dev veth5 up
### 启动网桥 ###
[root@node-0 ~]# ip link set dev bridge0 up
### 查看设备信息 ###
[root@node-0 ~]# ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
link/ether 00:50:56:2d:4b:f6 brd ff:ff:ff:ff:ff:ff
3: bridge0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
link/ether 5a:7e:f1:9b:ff:17 brd ff:ff:ff:ff:ff:ff
5: veth1@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master bridge0 state UP mode DEFAULT group default qlen 1000
link/ether de:15:00:f8:6c:ac brd ff:ff:ff:ff:ff:ff link-netnsid 0
7: veth3@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master bridge0 state UP mode DEFAULT group default qlen 1000
link/ether 5a:7e:f1:9b:ff:17 brd ff:ff:ff:ff:ff:ff link-netnsid 1
9: veth5@if8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master bridge0 state UP mode DEFAULT group default qlen 1000
link/ether da:12:08:18:f3:be brd ff:ff:ff:ff:ff:ff link-netnsid 2
### 测试单节点上network namespace之间的联通性 ###
[root@node-0 ~]# ip netns exec container-0 ping -c 3 10.1.1.2
PING 10.1.1.2 (10.1.1.2) 56(84) bytes of data.
64 bytes from 10.1.1.2: icmp_seq=1 ttl=64 time=0.047 ms
64 bytes from 10.1.1.2: icmp_seq=2 ttl=64 time=0.078 ms
64 bytes from 10.1.1.2: icmp_seq=3 ttl=64 time=0.070 ms
--- 10.1.1.2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2002ms
rtt min/avg/max/mdev = 0.047/0.065/0.078/0.013 ms
接下来在node-1上进行同样的操作,设置network namespace对应的IP地址为4、5、6。
### 创建点对点的vxlan网络,VNI:1000、对端IP:172.16.7.101、本地ID:ens33的IP、对端UDP监听端口:4789 ###
[root@node-0 ~]# ip link add type vxlan id 1000 remote 172.16.7.101 dev ens33 dstport 4789
### 查看vxlan设备详细信息 ###
[root@node-0 ~]# ip -d link show dev vxlan0
10: vxlan0: <BROADCAST,MULTICAST> mtu 1450 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether 7a:00:03:80:12:a6 brd ff:ff:ff:ff:ff:ff promiscuity 0
vxlan id 1000 remote 172.16.7.101 dev ens33 srcport 0 0 dstport 4789 ageing 300 noudpcsum noudp6zerocsumtx noudp6zerocsumrx addrgenmode eui64 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535
### 连接vxlan设备与网桥 ###
[root@node-0 ~]# ip link set dev vxlan0 master bridge0
### 启动vxlan设备 ###
[root@node-0 ~]# ip link set dev vxlan0 up
[root@node-0 ~]# ip link show dev vxlan0
10: vxlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue master bridge0 state UNKNOWN mode DEFAULT group default qlen 1000
link/ether 7a:00:03:80:12:a6 brd ff:ff:ff:ff:ff:ff
在node-1上进行同样的操作,node-1上创建vxlan时,对端设备IP为node-0的IP地址:172.16.7.100。
### 测试:尝试在node-0上ping node-1上的network namespace内的IP ###
[root@node-0 ~]# ip netns exec container-0 ping -c 3 10.1.1.4
PING 10.1.1.4 (10.1.1.4) 56(84) bytes of data.
From 10.1.1.1 icmp_seq=1 Destination Host Unreachable
From 10.1.1.1 icmp_seq=2 Destination Host Unreachable
From 10.1.1.1 icmp_seq=3 Destination Host Unreachable
--- 10.1.1.4 ping statistics ---
3 packets transmitted, 0 received, +3 errors, 100% packet loss, time 2002ms
pipe 3
### 测试失败,尝试排查一下问题,首先查看iptables规则 ###
[root@node-0 ~]# iptables -L -v --line-numbers
[root@node-0 ~]# iptables -L -v --line-numbers
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
1 2542 181K ACCEPT all -- any any anywhere anywhere ctstate RELATED,ESTABLISHED
2 2 142 ACCEPT all -- lo any anywhere anywhere
3 17 2160 INPUT_direct all -- any any anywhere anywhere
4 17 2160 INPUT_ZONES_SOURCE all -- any any anywhere anywhere
5 17 2160 INPUT_ZONES all -- any any anywhere anywhere
6 0 0 DROP all -- any any anywhere anywhere ctstate INVALID
7 8 936 REJECT all -- any any anywhere anywhere reject-with icmp-host-prohibited
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
1 0 0 ACCEPT all -- any any anywhere anywhere ctstate RELATED,ESTABLISHED
2 0 0 ACCEPT all -- lo any anywhere anywhere
3 0 0 FORWARD_direct all -- any any anywhere anywhere
4 0 0 FORWARD_IN_ZONES_SOURCE all -- any any anywhere anywhere
5 0 0 FORWARD_IN_ZONES all -- any any anywhere anywhere
6 0 0 FORWARD_OUT_ZONES_SOURCE all -- any any anywhere anywhere
7 0 0 FORWARD_OUT_ZONES all -- any any anywhere anywhere
8 0 0 DROP all -- any any anywhere anywhere ctstate INVALID
9 0 0 REJECT all -- any any anywhere anywhere reject-with icmp-host-prohibited
<snip>
### 尝试删除INPUT和FORWARD中的最后两行DROP和REJECT,在两个节点上操作 ###
[root@node-0 ~]# iptables -D INPUT 6
[root@node-0 ~]# iptables -D INPUT 6
[root@node-0 ~]# iptables -D FORWARD 8
[root@node-0 ~]# iptables -D FORWARD 8
### 再次测试 ###
[root@node-0 ~]# ip netns exec container-0 ping -c 3 10.1.1.4
PING 10.1.1.4 (10.1.1.4) 56(84) bytes of data.
64 bytes from 10.1.1.4: icmp_seq=1 ttl=64 time=0.918 ms
64 bytes from 10.1.1.4: icmp_seq=2 ttl=64 time=0.877 ms
64 bytes from 10.1.1.4: icmp_seq=3 ttl=64 time=0.921 ms
--- 10.1.1.4 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2004ms
rtt min/avg/max/mdev = 0.877/0.905/0.921/0.031 ms
这里测试的时候需要主要,有些操作系统默认的iptables规则会阻止某些流量的转发~
设置组播后,添加vxlan设备时,不需要再通过remote参数来指定对端IP来建立隧道,而是通过group参数来指定组播地址,操作方式与上面点对点的差别不大,不在继续演示。
##4、参考资料
https://blog.csdn.net/duhf_think/article/details/41483153
https://zhuanlan.zhihu.com/p/35616289
https://forum.huawei.com/enterprise/zh/thread-334207.html
https://zh.wikipedia.org/wiki/地址解析协议
https://blog.51cto.com/13770206/2122411
http://cizixs.com/2017/09/25/vxlan-protocol-introduction/
http://cizixs.com/2017/09/28/linux-vxlan/
https://www.zhihu.com/question/63497028
https://www.zhihu.com/question/58187639/answer/155994550
https://www.cnblogs.com/wipan/p/9220615.html