欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

VXLAN网络应用

程序员文章站 2022-07-07 14:02:04
...

1. 为什么需要Vxlan

  普通的VLAN数量只有4096个,无法满足大规模云计算IDC的需求,而IDC为何需求那么多VLAN呢,因为目前大部分IDC内部结构主要分为两种L2,L3。L2结构里面,所有的服务器都在一个大的局域网里面,TOR透明L2,不同交换机上的服务器互通靠MAC地址,通信隔离和广播隔离靠的vlan,网关在内网核心上。而L3结构这是从TOR级别上就开始用协议进行互联,网关在TOR上,不同交换机之间的互通靠IP地址。

  在云计算IDC里,要求服务器做到虚拟化,原来这个服务器挂在TOR A上,我可以随意把它迁移到TOR B上,而不需要改变IP地址,这个有点就是L2网路的特长,因为我这个虚拟服务器和外界(网关之外)通信还靠L3,但是我网关内部互访是走L2的,这个在L3里是无法做到的。因为L3里每个IP都是唯一的,地址也是固定位置的,除非你整网段物理搬迁。因此如何在L3网络里传输L2数据呢,这就是overlay技术。

  因此VXLAN(Virtual eXtensible LAN可扩展虚拟局域网)诞生了,基于IP网络之上,采用的是MAC in UDP技术,本来OSI7层模型里就是一层叠一层的,这种和GRE/IPSEC等tunnel技术是不是很像,这种封装技术对中间网络没有特殊要求,只要你能识别IP报文即可进行传送。

好了,解释清楚了,那么现在总结为何需要Vxlan:

1,虚拟机规模受到网络规格的限制,大L2网络里,报文通过查询MAC地址转发,MAC表容量限制了虚拟机的数量。

2,网络隔离的限制,普通的vlan和VPN配置无法满足动态网络调整的需求,同时配置复杂

3,虚拟器搬迁受到限制,虚拟机启动后假如在业务不中断基础上将该虚拟机迁移到另外一台物理机上去,需要保持虚拟机的IP地址和MAC地址等参数保持不变,这就要求业务网络是一个二层的网络。

2. Vxlan报文格式

VXLAN网络应用

Outer UDP端口使用4798,但可以修改

Outer IP头封装:源IP为发送报文的虚拟机所属的VTEP的IP地址,目的IP为目的虚拟机所属的VTEP IP地址。

Outer的目的IP地址可以是单播和组播地址,单播的情况下,目的IP为VTEP(Vxlan Tunnel End Point)的IP地址,在多播的情况下引入VXLAN的管理层,利用VNI和IP多播组的映射来确定VTEP。

当目的IP为接收端的VTEP的IP时,假如不知道这个IP地址,则需要执行ARP请求来获取,步骤如下:

1.目标IP被替换成与源虚拟机具有相同VNI的多播组IP地址;

2.所有VTEP端都接收该多播报文,VTEP查找所在主机上的全部虚拟机来匹配源虚拟机的Inner 目的MAC。

3.目标VTEP的虚拟机会回应该多播包,从而获得目标VTEP的IP地址。

4.发送端VTEP添加VNI-VTEP-虚拟机MAC的映射关系到自己的VXLAN表中,以避免再次组播学习。

Outer 以太封装:SA为发送报文的虚拟机所属的VTEP MAC地址,DA为目的虚拟机所属的VTEP上路由表中下一跳MAC地址。

3. VXLAN网络应用

下图为VXLAN的一种简单应用组网,VXLAN端口创建在br-tun上,配置VXLAN隧道的local ip在网桥br-1的同名端口上。

VXLAN网络应用

sed -i "/evs_gsogro_enable=/c evs_gsogro_enable=true" /opt/uvp/evs/user_evs_config

localip="10.12.0.26"
remoteip="10.12.0.28"
vni="5000"
service openvswitch restart

ovs-vsctl add-br br-tap0 -- set bridge br-tap0 datapath_type=dpdk other_config:fwd_mode=openflow
ovs-vsctl add-br br-int -- set bridge br-int datapath_type=dpdk other_config:fwd_mode=openflow
ovs-vsctl add-br br-tun -- set bridge br-tun datapath_type=dpdk other_config:fwd_mode=openflow
ovs-vsctl add-br br-1 -- set bridge br-1 datapath_type=dpdk other_config:fwd_mode=openflow

ovs-vsctl add-port br-tap0 tap0 -- set interface tap0 type=virtio
ovs-vsctl add-port br-tap0 p-tap0-int -- set interface p-tap0-int type=patch options:peer=p-tap0
ovs-vsctl add-port br-int p-tap0 -- set interface p-tap0 type=patch options:peer=p-tap0-int
ovs-vsctl add-port br-int p-tun -- set interface p-tun type=patch options:peer=p-tun-int
ovs-vsctl add-port br-tun p-tun-int -- set interface p-tun-int type=patch options:peer=p-tun
ovs-vsctl add-port br-tun vxlan -- set interface vxlan type=vxlan options:df_default="true" options:key="$vni" options:remote_ip="$remoteip"

ifconfig eth1 up
ovs-vsctl add-port br-1 eth1 -- set interface eth1 type=dpdkphy
#ovs-vsctl add-port br-1 bond0 -- set interface bond0 type=dpdkbond options:slaves=$slave1,$slave2 options:bond_mode=lacp options:xmit_hash_policy=l34
ovs-vsctl set interface br-1 options:cpu_id=1
ifconfig br-1 $localip/16

ovs-vsctl set port p-tap0 tag=2
ovs-vsctl set port br-1 tag=200

在OVS 2.5以后,OVS增加了ct action,该动作将报文送至conntrack模块处理。
连接跟踪通过对流的源IP、目的IP、IP协议类型、TCP/UDP源端口号、TCP/UDP目的端口号、ICMP类型、ICMP ID等信息进行匹配,创建连接跟踪表项,对流的状态进行跟踪。目前只有openflow模式才能使用连接跟踪。

VXLAN网络应用

首包会通过hnic端口发送到内核的Linux bridge,进行安全组过滤,然后从内核态返回到用户态EVS的hnic端口,在此处进行连接跟踪,创建连接跟踪表项,后续报文将匹配连接跟踪,直接从vm端口发送到对应端口,不需要进入内核走安全组,这样大大提高了转发性能。

ovs-vsctl add-port br-tap0 hnic0 -- set interface hnic0 type=internal
ovs-vsctl add-port br-tap0 hnic1 -- set interface hnic1 type=internal

brctl addbr br-linux1
brctl addif br-linux1 hnic0
brctl addif br-linux1 hnic1
ifconfig br-linux1 up
ovs-vsctl set port p-tap0-int tag=30
ovs-vsctl set port tap0 tag=20
ovs-vsctl set port hnic0 tag=20
ovs-vsctl set port hnic1 tag=30

ovs-ofctl add-flows br-tap0 $PWD/flow0.txt

实现原理

用户态EVS openflow转发模式采用开源流表方案,连接跟踪与流表相结合,当用户配置ct actions的流表时,就会执行连接跟踪动作,首先对报文进行L3、L4解析,提取出匹配的相关元组,然后计算hash,在根据hash查找ct表项,根据查找到的ct表项的流状态再进行一次转发,匹配对应状态的模糊匹配流表,最终发送到对应端口,达到了根据状态控制流走向的目的。

注意事项

  • Linux bridge需要UP才能做转发。
  • ply桥的两个hnic端口要配置不同的vlan,避免环回。
  • 端口删除时连接跟踪并不会清除,依赖自然老化,建议调用接口(ovs-appctl dpctl/flush-conntrack [dp] [zone=N])清除
  • 每个虚拟机的端口应该用zone或其它匹配项作区分,避免互相影响
  • 连接跟踪查询命令使用时,如果当前连接数较多,查询时间比较长、消耗内存比较多,会导致主线程卡住和内存陡增,所以请谨慎查询,切勿直接回显在屏幕

添加CT流表:

用户态链接跟踪流表信息配置在br-tap0网桥上。端口拓扑信息:

# ovs-appctl dpif/show
br-tap0:
        br-tap0 65534/4: (hnic)
        hnic0 1/7: (hnic)
        hnic1 1/78: (hnic)
        p-tap0-int 4/none: (patch: peer=p-tap0)
        tap0 3/13: (virtio)

其中“/”左边是datapath端口号,右边是openflow端口号

# 获取相应的端口号

VM=$(get_ofport_by_name "tap0" "virtio")
LINUX_BR_IN=$(get_ofport_by_name "hnic0")
LINUX_BR_OUT=$(get_ofport_by_name "hnic1")
PATCH_TAP_INT=$(get_ofport_by_name "p-tap0-int" "(patch: peer=p-tap0)")
echo "setup_ct_1: VM=$VM, LINUX_BR_IN=$LINUX_BR_IN, LINUX_BR_OUT=$LINUX_BR_OUT, PATCH_TAP_INT=$PATCH_TAP_INT"

# 添加ct流表,相关端口变量均用上述值替换

# 确保ARP报文能正常通过
ovs-ofctl add-flow br-tap0 "arp,actions=normal"

# 添加流表。网桥上的ip报文,进行连接跟踪操作,跳转到table1表
ovs-ofctl add-flow br-tap0 "ip,action=ct(table=1,zone=1)"

# 添加流表,从vm过来的ip报文,zone=1的,并且连接跟踪状态是new的,发送到Linux bridge IN端口
ovs-ofctl add-flow br-tap0 "table=1,in_port=$VM,ip,ct_state=+new,ct_zone=1,actions=output:$LINUX_BR_IN"

# 添加流表,从br-int过来的ip报文,zone=1的,并且连接跟踪状态是new的,发送到Linux bridge OUT端口
ovs-ofctl add-flow br-tap0 "table=1,in_port=$PATCH_TAP_INT,ip,ct_state=+new,ct_zone=1,actions=output:$LINUX_BR_OUT"

# 添加流表,从linux bridge IN过来的ip报文,zone=1的,并且连接跟踪状态是new的,进行连接跟踪commit(代表已经建立了连接跟踪),然后发送到vm端口
ovs-ofctl add-flow br-tap0 "table=1,in_port=$LINUX_BR_IN,ip,ct_state=+new,ct_zone=1,actions=ct(zone=1,commit)$VM"

# 添加流表,从linux bridge OUT过来的ip报文,zone=1的,并且连接跟踪状态是new的,进行连接跟踪commit(代表已经建立了连接跟踪),然后发送到br-int-patch端口
ovs-ofctl add-flow br-tap0 "table=1,in_port=$LINUX_BR_OUT,ip,ct_state=+new,ct_zone=1,actions=ct(zone=1,commit)$PATCH_TAP_INT"

# 添加流表,从vm过来的ip报文,zone=1的,并且连接跟踪状态是est的,发送到br-int-patch端口
ovs-ofctl add-flow br-tap0 "table=1,in_port=$VM,ip,ct_state=+est,ct_zone=1,actions=output:$PATCH_TAP_INT"

# 添加流表,从patch-br-int过来的ip报文,zone=1的,并且连接跟踪状态是est的,发送到vm端口
ovs-ofctl add-flow br-tap0 "table=1,in_port=$PATCH_TAP_INT,ip,ct_state=+est,ct_zone=1,actions=output:$VM"

通过配置上述流表,可以实现从虚拟机过来的流,如果是新流,会匹配new状态的流表,将报文送到内核进行安全组匹配,如果能通过安全组,会重新回到ply桥,建立连接跟踪并发送出去,这条流后续的报文就会匹配到est状态的流表,直接发送出去,不会再送到内核进行安全组匹配,达到了加速的目的。

打流,查看CT状态:

linux-PqrxkK:~ # ovs-appctl dpctl/dump-conntrack netdev@ovs-netdev
udp,orig=(src=192.168.100.2,dst=192.168.100.3,sport=46139,dport=5001),reply=(src=192.168.100.3,dst=192.168.100.2,sport=5001,dport=46139),zone=1

设置连接跟踪数上限为300万,有效值为1-3000万 
linux-PqrxkK:~ # ovs-vsctl set br-tap0 other_config:conntrack-limit=3000000
相关标签: ovs ct