Vxlan学习笔记---概念与实践
先导---Overlay网络
Overlay网络是一种灵活的叠加虚拟网络。
为什么需要Overlay网络?

- 移动性 - 跟踪边缘设备连接的主机
- 伸缩性 - 减少核心网络状态,网络边缘分布式和分区处理
- 多租户 - 共享网络资源
- 灵活性/可编程 - 减少维护节点数量
使用Overlay网络可按需在底层承载网络上快速部署虚拟业务网络。
Overlay术语
(本文中大部分都原图在参考资料10中的PPT)

Overlay分类
服务:
- 二层服务
- 三层服务
边缘设备:
- 网络式Overlay
- 主机式Overlay(如VXLAN)
- 混合式Overlay(如使用OVS实现的VXLAN)
信令:
- 数据平面学习
- 控制平面学习


简介
VXLAN全名为Virtual eXtensible Local Area Network,即虚拟可扩展局域网。它基于UDP,是一种虚拟化隧道通信技术。它是一种建立在三层网络之上的一种Overlay网络。
工作原理
术语
-
VTEP(VXLAN Tunnel Endpoints, VXLAN隧道端点)
VXLAN网络的边缘设备,用来进行封包和解包。VTEP可以是网络设备或端节点。项目里就使用OVS来作为VTEP。
-
VNI(VXLAN Network Identifier,VXLAN网络标识符)
是每个VXLAN段的标识,长24位。
-
Tunnel(VXLAN隧道)
是个逻辑上的概念,像是为通信的双方搭建了一个单独的通信通道。
物理网络上可以创建多个VXLAN网络,通过VNI来标识不通的VXLAN网络,使之可以互相隔离。
报文格式
VXLAN的报文格式如下:
由内到外分别为:
-
VXLAN Header
在原始的二层帧前,长度为8字节。大部分都是保留位,最重要的是VNI,占24位。
-
UDP Header
将原始二层帧和VXLAN头用UDP头进行封装,目的端口号(=VXLAN端口)默认使用4789,源端口通过内层数据包的哈希得出,这样更方便在VXLAN的Overlay网络上做负载均衡。
-
IP Header
源ip为源VTEP的IP地址,目的Ip为目的VTEP的IP地址。
-
MAC Header
源MAC为源VTEP的MAC地址,目的MAC为到达目的VTEP的路径中下一跳设备的MAC地址。
注意到在原始的二层帧前面又加了50个字节的报头,因此需要设置VM/容器中网卡的mtu为1450。
VXLAN的转发过程
VXLAN的转发过程为:原始报文从源VM出发,经过源VTEP,被VTEP加上VXLAN头部及UDP头部,根据VXLAN头部的VNI将封装后的报文(通过底层物理网络)递送至所有拥有此VNI的VTEP,目的VTEP再递交给对应的VM。
这里的VM泛指虚拟机和docker等虚拟网络设备
这里就产生了一个问题:
- 源VTEP如何知道该递交给哪个VTEP,即如何获取目的VTEP的ip地址?
其实,VTEP内部会有一张转发表,该表是通过学习机制来维护的。转发表长这样:
| VTEP IP | VTAP MAC | VNI |
|---|---|---|
根据这张表,就可以解决上面的问题,完成VXLAN报文的转发。
下图展示了VTAP发现和学习地址的过程。

下图展示了VXLAN单播数据流的转发过程

跨宿主机docker搭建vxlan过程
linu环境下常用的vxlan实现方式有Linux内核实现和OVS实现,这里使用OVS实现。
-
在两端创建容器,取名为test1
sudo docker run -itd --name test1 --net=none --privileged=true router/quagga -
在两端的OVS上添加网桥,取名为test_br
sudo ovs-vsctl add-br testbr -
连接网桥和容器,容器中的网卡取名为tap1,设置mtu=1450
sudo ovs-docker add-port testbr tap1 test1 --mtu=1450 -
为网桥添加一个vxlan类型的端口vxlan_port,
remote_ip为对端地址(粘贴时注意更换)。vni标识为24位。sudo ovs-vsctl add-port testbr vxlan_port \ -- set Interface vxlan_port \ type=vxlan options:remote_ip=10.1.1.122 \ options:key=123456 options:dst_port=8472 -
为两端的容器配置ip地址,其中一端为10.0.0.1/24,另一端为10.0.0.2/24(这里容器里没有ifconfig这个命令,为方便,使用了nsenter进入容器进行操作)
sudo nsenter -t $(sudo docker inspect -f {{.State.Pid}} test1) -n ifconfig tap1 10.0.0.1/24 -
ping另一端
sudo nsenter -t $(sudo docker inspect -f {{.State.Pid}} test1) -n ping 10.0.0.2 -
实验后清理环境
sudo docker rm -f test1 && sudo ovs-vsctl del-br testbr