VXLAN协议

VXLAN是Virtual eXtensible Local Area Network的缩写,RFC 7348的标题“A Framework for Overlaying Virtualized Layer 2 Networks over Layer 3 Networks”,说明了VXLAN是一个在传统Layer 3网络上架设出来的Layer 2 overlay网络。RFC Abstract如下:

This document describes Virtual eXtensible Local Area Network (VXLAN), which is used to address the need for overlay networks within virtualized data centers accommodating multiple tenants.  The scheme and the related protocols can be used in networks for cloud service providers and enterprise data centers.  This memo documents the deployed VXLAN protocol for the benefit of the Internet community.

在下面的场景中有两服务器,由三层物理网络连接。这两台服务器可能在同一个机架上,或者在不同的机架上,亦或在物理距离相距甚远的不同数据中心里。有4个VxLAN overlay网络,标识分别为VNI 22, 34, 74, 98。来看看Server 1上的虚拟机VM1-1和Server 2上的虚拟机VM2-4,它们属于相同的标识为VNI 22的VXLAN overlay网络。虚拟机并不知道overlay网络,也不知道VxLAN报文的封装和解封过程,因为这些过程都由物理服务器上的VTEP完成。看到这里,即使你没听说过VTEP这个概念,也大概知道它的作用了吧,VTEP (VXLAN Tunnel End Point), An entity that originates and/or terminates VXLAN tunnels,VTEP负责VxLAN的封装和解封装。

这种部署方法是基于物理机能够感知VXLAN协议,从而可以作为VxLAN的封装和解封点(VTEP) 。另外一种部署方法是把VTEP设备的位置放在网络设备中,比如交换机,可以作为一个VXLAN网络来负责VxLAN报文的封装和解封。在数据中心的部署中,物理机作为VTEP的部署方式能更好地和物理网络设备解耦,并且更加方便运维。

Linux上对VXLAN的支持

快速搭建和理解VXLAN的方法之一就是利用Linux。从内核3.7版本开始,Linux就开始支持VXLAN。到了内核3.12版本,Linux对VXLAN的支持已经完备,支持单播和组播,IPv4和IPv6。利用man查看ip的link子命令,可以查看是否有vxlan type,如下:

$ man ip-link

搜索vxlan,可以看到如下描述,可以利用ip link add增加类型为VXLAN的link。

VXLAN Type Support

For a link of type VXLAN the following additional arguments are supported:

ip link add DEVICE type vxlan id VNI [ dev PHYS_DEV ] [ { group | remote } IPADDR ] [ local { IPADDR | any } ] [ ttl TTL ] [ tos TOS ] [ dstport PORT ] [ srcport MIN

MAX ] [ [no]learning ] [ [no]proxy ] [ [no]rsc ] [ [no]l2miss ] [ [no]l3miss ] [ [no]udpcsum ] [ [no]udp6zerocsumtx ] [ [no]udp6zerocsumrx ] [ ageing SECONDS ] [ maxad‐

dress NUMBER ] [ gbp ]

下面的实验在如下环境中完成:

操作系统版本:CentOS Linux release 7.4.1708 (Core)

内核版本:3.10.0-693.2.2.el7.x86_64

云虚机vm1 eth0网络接口IP 172.31.0.106,云虚机vm2 eth0网络接口IP 172.31.0.107

场景1: 最简单的点对点VXLAN

创建简单的点对点VXLAN环境非常简单。如下图所示,只需要在两个机器(物理机或者虚拟机都可以,本实验中是云上的虚拟机环境)中各创建一个vxlan类型的网络接口即可,vxlan类型的接口vxlan1可以作为上文中提到的VTEP。

在上面的环境中,注意我们将vxlan网络接口配置上IP地址,在10.0.0.0/24网段内。在IP地址分配后,Linux系统的路由表就会创建一条路由,去往10.0.0.0/24网段的报文走网络接口vxlan1出去。vm1上去往10.0.0.0/24的报文,在vxlan1上会做VXLAN封装,内层地址是10.0.0.106,外层地址是172.31.0.106。VXLAN报文通过物理网络达到对端vm2上的VETP vxlan1,在vm2的vxlan1接口上做VXLAN协议的解封装,从而结束整个过程。

上图是一个物理上的示意图,在逻辑上形成的VXLAN overlay网络环境如下图,虚线部分示意出来的Overlay Network和VXLAN Tunnel都是逻辑上的概念。如果有容器和虚机被接入逻辑上的Overlay网络10.0.0.0/24,它们完全不用感知底层物理网络,看起来对端是和自己在同一个二层环境里,就是像是在VTEP设备的上面直接构建了一条VXLAN Tunnel,把Overlay网络里的网络接口直接在二层打通。

具体的配置只需要3条命令。如下,在vm1上执行如下命令:

# ip link add vxlan1 type vxlan id 1 remote 172.31.0.107 dstport 4789dev eth0

# ip link set vxlan1 up

# ip addr add10.0.0.106/24 dev vxlan1

上面的第一条命令创建了一个Linux上类型为vxlan的网络接口,名为vxlan1。

id: VNI标识是1。

remote: 作为一个VTEP设备来封装和解封VXLAN报文,需要知道将封装好的VXLAN报文发送到哪个对端VTEP。Linux上可以利用group指定组播组地址,或者利用remote指定对端单播地址。在实验的云环境中默认不支持组播,这里利用remote指定点对点的对端IP地址为172.31.0.107。

dstport: 指定目的端口为4789。因为当Linux内核3.7版本首次实现VXLAN时,UDP端口还并没有规定下来。很多厂商利用了8472这个端口,Linux也采用了相同的端口。后来IANA分配了4789作为VXLAN的目的UDP端口。如果你需要使用IANA端口,需要用dstport指定。

dev: 指定VTEP通过哪个物理device来通信,这里是使用eth0。

第二条命令让vxlan1接口up起来。第三条命令给设备分配IP地址10.0.0.106, 子网掩码为24 (255.255.255.0)。

在vm2上,利用类似方法创建名为vxlan1的网络接口。

# ip link add vxlan1 type vxlan id 1 remote 172.31.0.106 dstport 4789dev eth0

# ip link set vxlan1 up

# ip addr add10.0.0.107/24 dev vxlan1

以上简单的命令就完成了所有配置。用ifconfig可以看到vxlan1网络接口,如下:

# ifconfigvxlan1

vxlan1: flags=4163 mtu 1450inet10.0.0.106 netmask 255.255.255.0 broadcast 0.0.0.0ether22:2d:c4:f0:c7:29 txqueuelen 1000(Ethernet)

RX packets0 bytes 0 (0.0B)

RX errors0 dropped 0 overruns 0 frame 0TX packets0 bytes 0 (0.0B)

TX errors0 dropped 0 overruns 0 carrier 0 collisions 0

看下vm1的如下路由表,去往目的网段10.0.0.0/24的报文将走vxlan1接口。

# route -n

Kernel IP routing table

Destination Gateway Genmask Flags Metric Ref Use Iface0.0.0.0 172.31.0.253 0.0.0.0 UG 0 0 0eth010.0.0.0 0.0.0.0 255.255.255.0 U 0 0 0vxlan1169.254.0.0 0.0.0.0 255.255.0.0 U 1002 0 0eth0172.31.0.0 0.0.0.0 255.255.255.0 U 0 0 0eth0

在vm1上ping overlay网络的对端IP地址10.0.0.107,可以ping通。

# ping 10.0.0.107 -c 3PING10.0.0.107 (10.0.0.107) 56(84) bytes of data.64 bytes from 10.0.0.107: icmp_seq=1 ttl=64 time=0.447ms64 bytes from 10.0.0.107: icmp_seq=2 ttl=64 time=0.361ms64 bytes from 10.0.0.107: icmp_seq=3 ttl=64 time=0.394ms--- 10.0.0.107 ping statistics ---

3 packets transmitted, 3 received, 0% packet loss, time2000ms

rtt min/avg/max/mdev = 0.361/0.400/0.447/0.042 ms

在ping包的同时,用tcpdump抓vm1 eth0网卡的包。因为报文到达eth0前经过了网络接口vxlan1, 完成了VXLAN的封装,所以在抓包结果里应该能看到完整的VXLAN报文。

抓包时可以只抓和对端172.31.0.107通信的报文,如下:

# tcpdump -i eth0 host 172.31.0.107 -s0 -v -w vxlan_vni_1.pcap

抓包结果如下,wireshark自动将UDP目的端口为4789的报文识别成VXLAN报文,直接显示内层的报文,protocol为ICMP协议。如果使用Linux默认接口8472,显示的应该是UDP协议,还需要修改wireshark的协议设置,让其识别成VXLAN。

场景2: 容器跨主机通信

上面最简单的点对点VXLAN实验只是个简答的演示,没有太多实际工程意义,本节用容器通信来演示一个更加完整的场景。

场景描述:在vm1和vm2上各部署一个docker容器,默认情况下,一个容器宿主机上的容器能够直接用私网IP地址通信,因为它们利用一个网桥接在一起。而不同宿主机上的容器无法直接用私网IP地址通信。k8s等docker部署软件中的网络组建实际上完成了这部分工作,让不同宿主机的容器能够直接通信。本节使用原生docker,以及在宿主机上自建的vxlan网络接口,来打通不同宿主机上容器,让它们可以直接利用内网IP通信。

注意:因为实验在云上的虚拟机上完成,上面提到的容器宿主机,用的是云上的虚拟机。容器宿主机也可以是物理机,实验效果不变。

准备docker容器

安装docker的过程不展开了,docker官方文档有详细的描述。在Linux安装了docker后,可以看到多了一个docker0的网络接口,默认在172.17.0.0/16网段。这个是连接本地多个容器的网桥。

# ifconfigdocker0

docker0: flags=4163 mtu 1450inet172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255ether02:42:44:e8:74:e8 txqueuelen 0(Ethernet)

RX packets6548 bytes 360176 (351.7KiB)

RX errors0 dropped 0 overruns 0 frame 0TX packets7489 bytes 40249455 (38.3MiB)

TX errors0 dropped 0 overruns 0 carrier 0 collisions 0

使用默认172.17.0.0/16网段,docker容器的IP地址都会从172.17.0.2开始分配。为了能使vm1和vm2上的容器使用不同的IP地址,在利用docker run启动容器的时候需要能自定义IP地址,而利用--ip参数自定义IP地址的功能只能在自定网络中支持,所以先创建一个自定义网络,指定网段172.18.0.0/16。

# docker network create --subnet 172.18.0.0/16mynetwork

3231f89d69f6b3fbe2550392ebe4d00daa3d19e251f66ed2d81f61f2b9184362

# docker networklsNETWORK ID NAME DRIVER SCOPE

1cb284a6cb33 bridge bridge local

069538be0246 host host local

3231f89d69f6 mynetwork bridge local

0b7934996485 nonenull local

利用docker network ls查看,可以看到一个新的bridge网络被创建,名称为我指定的mynetwork。利用ifconfig可以看到多了一个网络接口,名字不是dockerXX,而直接以br开头,是一个网桥。

br-3231f89d69f6: flags=4099 mtu 1500inet172.18.0.1 netmask 255.255.0.0 broadcast 172.18.255.255ether02:42:97:22:a5:f9 txqueuelen 0(Ethernet)

RX packets0 bytes 0 (0.0B)

RX errors0 dropped 0 overruns 0 frame 0TX packets0 bytes 0 (0.0B)

TX errors0 dropped 0 overruns 0 carrier 0 collisions 0

创建一个新的容器,如下:

# docker run -itd --net mynetwork --ip 172.18.0.2centos

16bbaeaaebfccd2a497e3284600f5c0ce230e89678e0ff92f6f4b738c6349f8d

--net指定自定义网络

--ip指定IP地址

centos指定image

查看容器ID和状态,并且登录SHELL,如下:

# docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

16bbaeaaebfc centos"/bin/bash" 2 minutes ago Up 2minutes condescending_swartz

# docker exec-it 16bbaeaaebfc /bin/bash

[root@16bbaeaaebfc/]# ifconfigbash:ifconfig: command not found

注意:docker为了创建容器的效率,通常都用了size很小的image,意味着很多常用工具需要安装,比如centos image里面的ifconfig。可以利用yum whatprovides ifconfig命令查看ifconfig输入哪个包,查到属于net-tools-2.0-0.22.20131004git.el7.x86_64包,直接用yum install net-tools -y安装即可。再执行ifconfig命令,可以看到容器eth0网卡的IP地址为172.18.0.2。

[root@16bbaeaaebfc /]# ifconfigeth0

eth0: flags=4163 mtu 1500inet172.18.0.2 netmask 255.255.0.0 broadcast 172.18.255.255ether02:42:ac:12:00:02 txqueuelen 0(Ethernet)

RX packets3319 bytes 19221325 (18.3MiB)

RX errors0 dropped 0 overruns 0 frame 0TX packets2015 bytes 132903 (129.7KiB)

TX errors0 dropped 0 overruns 0 carrier 0 collisions 0

在vm2上执行同样的操作,在创建新容器的时候,指定IP地址为172.18.0.3,容器的环境即准备完毕。在vm1上的centos 容器中ping 172.18.0.3,和预期一致,是无法ping通的。

[root@16bbaeaaebfc /]# ping 172.18.0.3 -c 2PING172.18.0.3 (172.18.0.3) 56(84) bytes of data.

From172.18.0.2 icmp_seq=1Destination Host Unreachable

From172.18.0.2 icmp_seq=2Destination Host Unreachable--- 172.18.0.3 ping statistics ---

2 packets transmitted, 0 received, +2 errors, 100% packet loss, time1000ms

pipe2[root@16bbaeaaebfc/]# ping 172.18.0.1 -c 2PING172.18.0.1 (172.18.0.1) 56(84) bytes of data.64 bytes from 172.18.0.1: icmp_seq=1 ttl=64 time=0.060ms64 bytes from 172.18.0.1: icmp_seq=2 ttl=64 time=0.079ms--- 172.18.0.1 ping statistics ---

2 packets transmitted, 2 received, 0% packet loss, time999ms

rtt min/avg/max/mdev = 0.060/0.069/0.079/0.012 ms

创建VXLAN接口接入docker网桥

先来梳理下docker及docker容器在Linux宿主机网络模块中做的操作,梳理清楚之后会发现打通不同宿主机上docker容器的方法非常简单。从宿主Linux系统的视角看操作系统中的网络设备,总结如下:

docker0接口:网桥,在安装完docker后默认被创建,网段是172.17.0.0/16,网桥的默认IP地址为172.17.0.1。

br-xxxx接口:网桥,在创建完自定义docker网络完被创建,网段是被用户指定的172.18.0.0/16,网桥的默认IP地址为172.18.0.1。

vethxxxx接口:veth网络接口,在创建一个具体的docker容器后被创建,如果有N个运行的容器,就会有N个veth网络接口。容器中的eth0接口和宿主机的veth网络接口是一个veth网络对,Linux上的veth接口作为一个端口连接入docker网桥,如docker0或其他自定义网桥。这也是为什么一个宿主机上的docker容器能够默认通信的原因,因为它们创建后就被接入到了同一个网桥上。

为了方便理解,在默认网段172.17.0.0/16中创建2个容器,在自定义网段中上文已经创建了1个docker容器,利用btctl查看网桥及其接口,如下:

# brctl show

bridge name bridgeidSTP enabled interfaces

br-3231f89d69f6 8000.02429722a5f9 no veth2fa4c50

docker08000.024244e874e8 no vethc7cd982

vethd3d0c18

从上面的输出结果可以看到,默认网桥docker0上,有vethc7cd982和vethd3d0c18两个网络接口接入。在定义网络网桥br-3231f89d69f6一个端口上,veth2fa4c50网络接口接入。这三个veth网络接口分别连接着一个docker容器的eth0网络接口,连接着同一个网桥的veth网络接口vethc7cd982和vethd3d0c18默认二层能通。

有了上面的梳理和本文第一节VXLAN网络接口的基础知识,想必打通不同宿主机上docker容器的方法也比较清晰了。思路就是在两个容器宿主机上各创建一个VXLAN接口,并且将VXLAN接口接入docker网桥的端口上,如下图:

有了VXLAN接口的连接后,从vm1上docker容器发出的包到达docker网桥后,可以从网桥的VXLAN接口出去,从而报文在VETP(VXLAN接口)处被封装成VXLAN报文,再从物理网络上到达对端VETP所在的主机vm2。对端VTEP能正确解包VXLAN报文的话,随后即可将报文通过vm2上的docker网桥送到上层的docker容器中。

具体的配置如下,在vm1上:

# ip link add vxlan_docker type vxlan id 200 remote 172.31.0.107 dstport 4789dev eth0

# ip link set vxlan_docker up

# brctl addif br-3231f89d69f6 vxlan_docker

第一条命令创建VNI为200的VXLAN网络接口,名称为vxlan_docker,参数设置和场景1中的各个参数类似。

第三条命令把新创建的VXLAN接口vxlan_docker接入到docker网桥br-3231f89d69f6中。

在vm2上,输入如下命令:

# ip link add vxlan_docker type vxlan id 200 remote 172.31.0.106 dstport 4789dev eth0

# ip link set vxlan_docker up

# brctl addif br-f4b35af34313 vxlan_docker

在vm1的docker容器上再ping 172.18.0.3,结果如下,ping可以通。注意RTT的时间,ping 172.18.0.3的RTT在10^(-1)毫秒级别,ping 172.18.0.1的RTT在10^(-2)毫秒级别,前者是走物理网络的延迟,后者是协议栈的延迟,两者有量级上的差别。

# docker exec -it 16bbaeaaebfc ifconfigeth0

eth0: flags=4163 mtu 1500inet172.18.0.2 netmask 255.255.0.0 broadcast 172.18.255.255ether02:42:ac:12:00:02 txqueuelen 0(Ethernet)

RX packets3431 bytes 19230266 (18.3MiB)

RX errors0 dropped 0 overruns 0 frame 0TX packets2132 bytes 141908 (138.5KiB)

TX errors0 dropped 0 overruns 0 carrier 0 collisions 0# docker exec-it 16bbaeaaebfc ping 172.18.0.3 -c 2PING172.18.0.3 (172.18.0.3) 56(84) bytes of data.64 bytes from 172.18.0.3: icmp_seq=1 ttl=64 time=0.544ms64 bytes from 172.18.0.3: icmp_seq=2 ttl=64 time=0.396ms--- 172.18.0.3 ping statistics ---

2 packets transmitted, 2 received, 0% packet loss, time1001ms

rtt min/avg/max/mdev = 0.396/0.470/0.544/0.074ms

#

# docker exec-it 16bbaeaaebfc ping 172.18.0.1 -c 2PING172.18.0.1 (172.18.0.1) 56(84) bytes of data.64 bytes from 172.18.0.1: icmp_seq=1 ttl=64 time=0.072ms64 bytes from 172.18.0.1: icmp_seq=2 ttl=64 time=0.072ms--- 172.18.0.1 ping statistics ---

2 packets transmitted, 2 received, 0% packet loss, time999ms

rtt min/avg/max/mdev = 0.072/0.072/0.072/0.000 ms

最后说明,本节只是为了演示Linux VXLAN的用于而构造了这个简单但没有实际用处的场景,在跨主机环境的容器之间利用VXLAN从二层打通。在工程中做容器跨主机通信时有很多方面需要考虑,也有很多项目在致力于这方面的研究。比如Flannel,通过给每台宿主机分配一个子网的方式为容器提供虚拟网络,它基于Linux TUN/TAP,使用UDP封装IP包来实现L3 overlay网络,并借助etcd维护网络的分配情况。Github上有项目的文档,另外文章做了不错的基本介绍。

vxlan报文 wireshark_Linux VXLAN相关推荐

  1. 【Linux4.1.12源码分析】VXLAN报文内核协议栈处理

    4.1.12内核已经支持vxlan报文的gro功能,意味着vxlan报文交给协议栈之前,已经被聚合过了,而在早期的内核中聚合逻辑是在encap_rcv函数之后实现的. 之前分析的UDP报文处理中,可以 ...

  2. VXLAN报文形式和如果通讯的

    VXLAN隧道是如何建立的 本节将为您介绍VXLAN隧道的建立过程,并在这个过程中更好地理解VXLAN的工作原理. 什么是VXLAN中的VTEP和VNI 下面让我们来进一步了解VXLAN的网络模型以及 ...

  3. vlan跨交换机 udp广播_【详解】VLAN和VXLAN有何区别?VXLAN运用场景有哪些?

    随着网络技术的发展,云计算凭借其系统利用率高.人力/管理成本低以及灵活性/扩展性方面展现的优势,已经成为目前各大行业IT建设的新趋势. 而服务器的虚拟化作为云计算的核心技术之一,也得到了越来越多的应用 ...

  4. OVS对VXLAN报文解封包

    VXLAN的全称为Virtual eXtensible LAN,从名称看,它的目标就是扩展VLAN协议.802.1Q的VLAN TAG只占12位,只能提供4096个网络标识符.而在VXLAN中,标识符 ...

  5. EVPN VXLAN报文交互

    1.BGP EVPN建立 配置MP-BGP后,激活邻居关系后,设备间互相发送交互报文.报文中会标记组建的是EVPN邻居关系 2.开始交互type 3报文,完成VXLAN隧道的建立 将本地VTEP下所配 ...

  6. vxlan报文 wireshark_配置 VXLAN

    简介 本文档简要概述虚拟可扩展局域网 (VXLAN),并提供了几个配置示例以及验证命令和输出. Cisco 建议您了解以下主题: 组播路由概念,例如交汇点 (RP) 和平台无关组播 (PIM). 虚拟 ...

  7. 总结 Underlay 和 Overlay 网络,在k8s集群实现underlay网络,网络组件flannel vxlan/ calico IPIP模式的网络通信流程,基于二进制实现高可用的K8S集群

    1.总结Underlay和Overlay网络的的区别及优缺点 Overlay网络:  Overlay 叫叠加网络也叫覆盖网络,指的是在物理网络的 基础之上叠加实现新的虚拟网络,即可使网络的中的容器可 ...

  8. VLAN vs. VXLAN:云时代下各施所长

    来源于:SDNLAB VXLAN(Virtual eXtensible Local Area Network,虚拟可扩展局域网)可以说是目前最热门的网络虚拟化技术.自2014年引入以来,VXLAN已逐 ...

  9. 做了几年的网工也未必了解VLAN和VXLAN的区别,今天我来告诉你!

    资深网络工程师对于vlan和vxlan应该能够区别开,但是刚入行.或者平时不太关注技术栈的网工们对于vlan和vxlan常常混淆,甚至都没有听过vxlan,那么今天我带着大家来剖析一下这两种技术,相信 ...

最新文章

  1. 运筹学两阶段法编程c语言,运筹学上机实验 - 单纯形方法的两阶段法
  2. 提高python执行效率_提升Python程序运行效率的6个方法
  3. Android之back键拦截处理
  4. 能帮你快速设计好APP的UI kits套装
  5. 如何设置linux端口桥接,怎么在linux下配置桥接?
  6. apache 网址重定向
  7. python所有第三方库_自动更新Python所有第三方库
  8. DataMatrix 码提取流程
  9. Linux后台运行程序
  10. 中级计算机平面设计考试题,平面设计师(中级)技能试题答案
  11. 华为云服务器价格表(CPU内存/磁盘/带宽收费标准)
  12. WinCC V7.2学习记录
  13. Scrum板与Kanban如何抉择?vfmzulfdr板与按照ftjzox
  14. 转】用Hadoop构建电影推荐系统
  15. webp格式如何转成png?
  16. BUUCTF·[AFCTF2018]Vigenère·WP
  17. jenkins中文语言设置
  18. Golang中defer的执行时机
  19. 转:医院网络营销存在的弊端
  20. 第十四章 使用SQL Shell界面(三)

热门文章

  1. 文献管理软件Mendeley使用技法
  2. 全球经济自由度指数1995-2022
  3. 图片投票小程序微信投票软件发起投票软件互动酷投票
  4. SpringBoot 区分环境dev test prod
  5. 昆明理工大学计算机学硕调剂,昆明理工大学2021考研调剂公告
  6. zed相机拆机_机器人技术:ZED 双目相机内参标定方法
  7. AR 预测模型的 Matlab 实现(超详细建模流程)
  8. Java + OpenCV 实现更换背景图片(绿色幕布切图)(JavaCV)
  9. 西门子串口通讯10-CP441-2在STEP7环境中做Modbus从站通讯
  10. vulhub漏洞复现之bash(Shellshock CVE-2014-6271)