VxLAN原理

VxLAN
 背景介绍:
  从上个世纪虚拟化技术就被提出,但由于硬件技术达不到,而没能被重视,自本世纪初硬件制造技术越来越来强,导致很多单台物理机只跑一个应用或几个应用根本无法完全使用硬件的全部性能,导致大量资源浪费,虚拟化也在这个时候被推到了风口浪尖上,最先使用虚拟化技术的当属数据中心,但马上人们就发现了问题:
  1. VLAN数量和困境
    VLAN数量严重不足,导致超过4096个租户后,就无法再划分VLAN了,那该如何隔离每个租户的虚拟机那?
   事实上传统通过VLAN隔离的网络,存在诸多不便,比如无法动态调整,网络扩容困难,更要命的是当物理机出现
   故障或负载过重时对VM做迁移十分不便,这要如何解决?

  2. 二层网络边界限制
    在虚拟化之下为了让VM迁移方便二层网络不断扩展,这带来了二层接入设备越来越多,STP问题越来越突出,
   最直接的就是大量端口因为防环被阻塞,出现了接入到汇聚间带宽下降了1/4,汇聚到核心间带宽下降了1/8,
      越接近树根的交换机,端口阻塞越严重,导致整体带宽资源浪费严重,效率低下且成本增加,这还是问题中
   的一部分!【STP(生成树协议)主要在二层交换网络中避免交换机出现环路导致"网络风暴";】
      紧接着二层交换机的MAC地址缓存表告急,但物理机上的VM还在不断增加,新MAC由于无法缓存,导致
      交换机只能在所有接口上泛洪广播,导致全网被大量广播充斥,严重影响业务流量,该怎么办?

  3. 管理困境
   大二层之下如何有效管理物理,提高网络的利用率,同时又能兼顾上层虚拟化应用?

  在这样的背景之下,VMware和思科就提出VxLAN(Virtual eXtensible LAN)技术,随后HP和微软也提出了NVGRE(Network Virtual GRE),这两种技术的主要特点是隧道的起点和终点主要在vSwitch上,而非物理交换机上,隧道的封装在服务器内部的vSwitch上就已经打好,所以进入物理网络时, 数据包的外层IP都是物理接口上的IP,这就将原本二层帧变成了三层IP报文,直接进行路由转发即可,这样就实现了大二层透传,甚至可跨DC(数据中心)。这两种技术都各有优劣,VxLAN由于使用了很成熟了四层UDP来承载VxLAN数据体,使得数据包头变的更大了,而相应的数据区就只能继续减小,而NVGRE则是对GRE(Generic Routing Encapsulation,通用路由协议封装)做了升级版,将原GRE协议中低24位用作租户网络标识符(TNI),来扩展VLAN,它和VxLAN的VNI一样,都将VLAN扩展到2的24次方个,但NVGRE最大缺点就是不能支持传统的复制均衡,因为四层负载均衡需要基于IP和端口来调动,而GRE头部在四层之前这导致四层负载均衡无法解析GRE头,也就无法获取四层端口信息,导致无法对其做负载均衡。这就是"Overlay"网络诞生的原因,Overlay可翻译为叠加,即叠加网络。注: Overlay网络,不止这些,还有VMware私有的STT,GRE等。


传统VxLAN
  VxLAN本质上是一种隧道协议的实现,它不依赖于云,当两个物理上只能通过三层互通的网络,若想实现二层互联时,VxLAN就是一种可选的解决方案,它就类似于VPN(虚拟专用网),只是VPN是为了数据安全而做了安全加密,VxLAN不需要这些,它仅是通过VxLAN协议驱动将原本的以太网帧封装到VxLAN中,然后在从四层(UDP)开始重新封装,发送到网络中后,外面看这个包就是一个普通的IP包,可直接进行直连或路由转发,所谓直连,就是目标是LAN中的主机,而路由则是需要路由器转发到报文。

VTEP(VXLAN Tunnel End Point):
  网上经常将其解释为VxLAN的封装和解封装的组件,但我觉得这样说明容易混淆协议驱动和用户看到的VxLAN接口,所以在此说明,VTEP可理解为一个虚拟VxLAN隧道接口,当我们想让自己的应用数据包走VxLAN隧道时,便于我们操作和控制VxLAN隧道的对端是谁。而真正将应用数据封装到VxLAN是操作系统调用VxLAN协议驱动实现的。

  

     在这个图中,vxlan0接口就可认为是一个VTEP,当vm1要访问vm2它俩是要通信,就必须依靠VxLAN-Tunnel来实现。那vm1和vm2如何配置使用vxlan0那?
  事实上这是不需要考虑到,因为p0和vxlan0都是Ovs-vSwitch上的虚拟二层接口,可理解为它们就是普通的交换机接口,交换机接口是二层的,当交换机要将一个数据包发送到网络上时,它要广播获取对方的MAC,然后直接二层转发即可,vm1要访问vm2,当vm1发起访问时,数据包到达vSwitch时,vSwitch查询MAC地址表,没有10.0.0.2的MAC,于是在所有端口上泛洪ARP广播,vxlan0就收到了这个ARP广播报文,vxlan0接口会将收到的数据发送给VxLAN驱动,VxLAN驱动根据vxlan0即可的配置信息,指定vxlan隧道的对端是192.168.10.23,于是VxLAN驱动开始对整个ARP二层帧作为其传输的数据封装到VxLAN报文中,然后调用TCP/IP协议栈,将VxLAN报文封装到UDP中,接着继续封装IP,链路层完成后,报文被写入发送缓冲区中,内核最终通过DMA芯片将发生缓冲区中的数据发送到网卡,接着数据包就进入物理网络,在物理网络中的数据包就是这个样子的:

  

  可以看到,物理网络中看到的数据包的源IP:192.168.10.15,目标IP:192.168.10.23,这就是二层直接转发,或叫大二层的扩展,这种方式也被称为三层网关方式,当vm1访问vm2时, 对于vm2来说,它的VxLAN网关就是Server1上vxlan0 。那我们在来看看,VxLAN对VLAN的扩展,这也被称为二层VxLAN网关,实际和三层一样,都是相对的。

  

  我们很清楚,VLAN之间是互相隔离的,p0被分到VLAN101了,vxlan0接口在默认VLAN0中,它俩如何通信,但是事实上vxlan0接口会被自动配置为tunck口,所以vxlan0接口依然可以收到vm1发的二层广播报文,下图就是VxLAN承载二层VLAN的包结构,也就是所谓的VLAN扩展。

  

   以上拓扑结构若你想测试,可参考下面的OpenVSwitch的配置,这是VMware环境下测试:

  1. 安装OpenVSwitch
    yum install openvswitch

  2. 启动OpenVSwitch服务
    systemctl start openvswitch

  3. 创建vSwtich
    ovs-vsctl add-br br-vxlan #br-vxlan就是vSwitch的名字.此名可任意.

  4. 创建VxLAN虚拟网口vxlan0
    #在Server0上配置vxlan0时这样写:
      ovs-vsctl add-port br-vxlan tun0 -- set interface tun0 type=vxlan options:remote_ip=192.168.10.23
    #创建了一个VxLAN类型的接口tun0
    #set interface实际上修改了vSwitch配置数据库中的interface表.
    #OpenVSwitch2.0.0时只能这样看:
      ovsdb-client dump Open_vSwitch #将默认Open_vSwitch数据库中的所有数据都dump出来看.

    #OpenVSwitch2.5.x后可这样单独看Interface表
      ovsdb-client dump Open_vSwitch Interface

    #在Server1上配置vxlan0是这样写:
      ovs-vsctl add-port br-vxlan tun0 -- set interface tun0 type=vxlan options:remote_ip=192.168.10.15

    #若想测试gre,可修改type=gre,或使用下ip link来创建gre隧道.


  查看配置信息:
    ovs-vsctl show

  5. 创建虚拟网口p0
    ovs-vsctl add-port br-vxlan p0 -- set interface p0 type=internal

  6. 创建一个网络名称空间,来充当一个简单的虚拟机
    ip netns add vm1

  #接着将拉一根虚拟网线将vm1与vSwitch br-vxlan的p0口连接起来.
  #但要注意: p0实际上是被关联到vm1中了,vm1内部默认只有一个lo0接口,
  # 我们需要将一个宿主机上可见的网口摘掉,安装到vm1中。
  # 关于网络名称空间,可参考: 容器原理
    ip link set p0 netns vm1

  #接着对安装到vm1中的p0网口,配置IP地址
    ip netns exec vm1 ifconfig p0 10.0.0.1/24 up

  #查看配置信息:
    ip netns exec vm1 ifconfig

  7. 接着就可以在VMware Network Adapter VMnet1上抓包来看了。
   #这时在Server0上的vm1中:
    ip netns exec vm1 ping 10.0.0.2

   #在VMnet1上抓包,此时就可以查看VxLAN三层网关的效果了。

  8. 接着来看看二层网关的效果:
    ovs-ofctl show br-vxlan

    

    #在流表中创建一个Action Set(动作集):【注意: 可先在Server0或Server1上配置,然后ping,在抓包看】
    ovs-ofctl add-flow br-vxlan "priority=10,in_port=2,dl_vlan=0xffff,actions=mod_vlan_vid:101,normal"
  #简单说明:
  # priority:指定规则优先级,数字越大越优先,默认为32768,范围:0~65535, 建议设置,避免出现违背我们意愿的行为发生。
     in_port: 指定对从那个接口进入vSwitch上的流量做匹配.
     vlan: 0xffff 表示匹配所有vlan号,若需精确匹配vlan号,只需指定具有的VLAN号即可,如: vlan=101
     actions: 指定匹配前面两个条件后,执行的动作集合。
   mod_vlan_vid:101 这是修改VLANID为101
     normal 使数据包服从设备正常的L2/L3处理。(并非所有OpenFlow开关都实现此操作。)

  ovs-ofctl add-flow br-vxlan "priority=8,in_port=3,dl_vlan=101,actions=strip_vlan,output:3"
    #dl_vlan: 指定匹配所有数据包的VLAN ID
    #strip_vlan: 去掉VLAN层
    #output:3 将匹配的流量从编号为2的接口上送出。

 以上两条流规则就实现对vm1或vm2上出来的流量添加VLAN ID101,并且当收到对方回应时,将VLAN ID 101的VLAN层去掉,还原为正常IP包,发给vm1或vm2.

  下图就是VxLAN所监听的端口:

    

   #另外,若你想看看,vxlan0上的数据包是什么样的,可这样做:
  OpenVSwitch2.0.0以后这样配置:
  [root@s23 ~]# ovs-vsctl -- set Bridge br-vxlan mirrors=@my1 \
            -- --id=@m1 get port tun0 -- --id=@a1 get port p1 \
            -- --id=@my1 create mirror name=t1 select-dst-port=@m1 select-src-port=@m1 output-port=@a1
    #说明:
    # 上面实际是配置了一个端口SPAN.
    # SPAN:Switched Port Analyzer(交换端口分析器),这是一种交换机端口镜像技术,
        目的是将某些端口进入和出去的流量都,复制一份到指定端口 做协议分析.
        注:端口监控分为两种:本地SPAN 和 远程SPAN(RSPAN),
       RSPAN:通常采用VLAN来实现将跨交换机的复制端口流量.
    #上面配置的是本地SPAN.
    # OVS2.0.0以后,修改了配置方式
    # 1. 先在指定vSwitch上创建一个镜像ID
        2. 将想监控 或 监控口的流量复制到那个接口 都定义一个引用ID
        3. 创建镜像,需要使用name定义镜像名, select-dst-port和select-src-port
        设置要监控那些接口,需要指定引用ID,可指定多个,用逗号分隔。
        若只需要进入此接口的流量就指定dst,若只需要出去的流量就指定src
        4. output-port设置将监控口的流量复制到那个接口上.
      【注意: p1是又添加到端口,可自行参考前面创建】

  [root@s23 ~]# ovs-vsctl list mirror
    _uuid : 85df4437-c903-4110-9061-1d54d36c0427
    external_ids : {}
    name : "t1"
    output_port : 206ace18-b3e6-4423-9216-5088a60b82c1
    output_vlan : []
    select_all : false
    select_dst_port : [8e1dd937-dd97-4446-89c8-af304ff960a5]
    select_src_port : [8e1dd937-dd97-4446-89c8-af304ff960a5]
    select_vlan : []
    statistics : {tx_bytes=0, tx_packets=0}


下图是网上找到,画的非常好的VxLAN通信流程:
  需要注意:
  第二步:当配置了多条VxLAN隧道时,因为初始化时,没有对方的MAC, VNI,和IP的对应表。因此VxLAN会使用默认的239.1.1.1这个组播地址,对所有VxLAN 隧道接口发送这个报文。
  第三步:VxLAN收到组播包后,VTEP-3 和 VTEP-2都会收到,它们都会先学习一个MAC,VNI,IP到对应条目。接着它俩将VxLAN头部去掉,还原为原始ARP广播报文后,转发到自己所在的LAN中.

  

最后来说说云之下的VxLAN
  VxLAN本身仅是一个隧道协议,只是因为它能够解决叠加网络的问题,所以就将其引入到网络虚拟化中,成为SDN(软件定义网络)中的一种功能实现。SDN是一种网络虚拟化的整体概念框架,它不是具体的技术,它是一种理念,一种指定如何使用软件来完成对物理网络的虚拟化的理论。
  在SDN这种理念下,目前比较知名的API实现是OpenFlow,我在OpenFlow和SDN原理中有较为详细的说明,由于本人能力有限也无法深入刨析,只能尽可能让每位认真学习的道友能明白其中大概的原理。由于SDN理念之巨大,OpenFlow也并非是完整的将整个TCP/IP协议栈都抽象化成API的,这点需要知道。在OpenFlow的流行之下,目前已经有很多基于OpenFlow协议实现的软件:OpenVSwitch就是其中之一。
  下面两种图是摘自: https://www.cnblogs.com/sammyliu/p/4627230.html
  它就描述了SDN的理念,下面我简单做一些说明:
    首先SDN理念是将物理网络抽象化,将其分为控制平面和数据平面
    OpenFlow将其更具体化了,它将物理网络转为了一台PC的架构,即分为硬件层,内核空间 和 用户空间
    其中对于用户空间来说,它就是控制平面,内核空间就是数据平面(数据的提供者)
    而从内核空间来看,硬件层是数据平面(实际存储策略数据,并执行动作者),而内核空间是控制平面(控制策略下发者)

  有了以上概念,就可以继续说明下图了
  对于Service Node来说它是实际转发策略的制定者,也就说它是控制平面,而具体的vxlan驱动是实际运行在硬件中的执行者,可将其理解为一个仅有vxlan功能的物理设备,即数据平面。当VM1发送数据到vxlan101接口上时,vxlan驱动收到了用户的数据流,但它发现自己不知道如何转发流量,因为初始化时,VNI,VTEP,MAC对应关系表没有,因此它就会将该数据包完整转发给控制器(控制平面),然后控制器负责做出转发决策,若此时控制器查询数据库发现自己也没有VNI,VTEP,MAC对应关系表的相关条目,于是下发策略让vxlan101(VTEP)将请求通过组播239.1.1.1组播出去,这样隧道接口上的加入相同组播组的接口都会收到,并作出相应动作,假如这个VxLAN包中的实际数据是ARP查询,当目标收到后,它会回应ARP响应后,当vxlan101(3.3.3.3)收到响应后,它会将其转发给控制平面,控制器将会根据响应学习一条VNI,VTEP,MAC对应关系的条目,并再次告诉数据平面要如何转发,这样一个来回后,对于vxlan101(3.3.3.3)这个实际执行者来说,它就缓存了一条转发策略,下次vm1在发来数据流,它就可以直接执行转发,而无需将数据包转发给控制器了。
  下图仅做参考.

  

  

 

posted @ 2019-08-01 12:59  张朝锋  阅读(2472)  评论(0编辑  收藏  举报