在部署openstack的官方文档(最近几个版本)中的neutron组件默认使用的是linux bridge来做网桥,除直接使用提供者网络(provider network)以外,网络节点的负载会比较大,所有的外部网络通信流量都要走网络节点,于是就看了看Juno版本以后增加的 DVR(分布式虚拟路由器),有了 DVR 之后,路由变成了分布式,每个计算节点上面都可以做路由,东西向流量直接通过计算节点路由而不需要经过网络节点,Floating IP 也是在计算节点上面实现的,对于有 floating IP 的 VM 访问公网,直接走计算节点上面的路由器出去,对于没有 floating IP 的 VM 访问公网才会从网络节点的路由器 SNAT 出去。
看来看去,想起来几年前,我比较熟悉的OVS(Open vSwitch),于是打开官网看了看,更新还真不少,搞出来了个OVN,OVN 是 OVS 的控制平面,它给 OVS 增加了对虚拟网络的原生支持,用在openstack上的话,相当于它干了大部分以前neutron agent干的活,计算节点不在需要部署neutron agent了,OVN全搞定,neutron只需要调用OVN的北向接口,其它的事都交给OVN来搞定,应该说是彻底解放了neutron,具体的安装配置可以参考:https://docs.openstack.org/networking-ovn/latest/。
在看OVS文档过程中,看到了一个DPDK的东东,完全不懂,于是就研究一下,在这里把整个过程记录下来,和大家分享一下。
DPDK
DPDK(Data Plane Development Kit),是一组快速处理数据包的开发平台及接口,运行于Intel X86平台上(最新版本也开始支持PowerPC和ARM)。
在X86结构中,处理数据包的传统方式是CPU中断方式,既网卡驱动接收到数据包后通过中断通知CPU处理,然后由CPU拷贝数据并交给协议栈。在数据量大时,这种方式会产生大量CPU中断,导致CPU无法运行其他程序。而DPDK则采用轮询方式实现数据包处理过程:DPDK重载了网卡驱动,该驱动在收到数据包后不中断通知CPU,而是将数据包通过零拷贝技术存入内存,这时应用层程序就可以通过DPDK提供的接口,直接从内存读取数据包。这种处理方式节省了CPU中断时间、内存拷贝时间,并向应用层提供了简单易行且高效的数据包处理方式,使得网络应用的开发更加方便。但是DPDK需要网卡支持,目前以intel的网卡为主,想要知道您的网卡是否支持,可以到DPDK的官网查询:http://dpdk.org。
怎么样,是不是很高大尚?要不要写个程序通过DPDK提供的接口来读取数据包?呵呵,说句实话,这对我来说目前还有一定难度,在这里就暂时不给大家show了,如果有兴趣的话,DPDK的源代码里有helloworld,还有一些其它的sample。
DPDK + OVS
我们再回到OVS上来,OVS是目前得到广泛认可的一个软件虚拟交换机,目前已经实现了通过DPDK的接口从内存直接读取数据包,然后在软件层再进行各种转发……,这应该是充分发挥了DPDK的优势,相信速度也会得到明显的改善(别高兴太早)。下面我就把我在Mac+virtualbox环境下的整个安装、调试过程和大家分享一下。
基础环境准备
如果您有硬件环境,那么建议您还是使用两台物理服务器来进行测试,要求是内存至少要2G以上,网卡需要支持DPDK,可以到DPDK的官网查询:http://dpdk.org查询您的网卡是否支持。
怎么样知道你的网卡型号呢? 很简单,打开机盖看,哈哈。
当然也有不打开机盖的方法,安装完操作系统(centos)后,执行lspci
,应该就能看到你的网卡的具体型号了。
如果没有硬件怎么办? 当然是万能的虚拟机了,本文中将使用virtualbox来创建两台虚拟机进行测试,为了达到相关的要求,建议你的机器内存>=8G。
网络:需要用到3个Host-Only网络,在virtualbox上提前创建好。
网络名分别为: vboxnet0、vboxnet1、vboxnet2三个,它们对应的网络为:
vboxnet0: 192.168.56.1/24
vboxnet0: 192.168.57.1/24
vboxnet0: 192.168.58.1/24
如下所示:
虚拟机配置:
cpu 2c 内存2G 硬盘8G
创建完虚拟机后,进入网络设置界面:
网卡1-3设置相同,分别选择vboxnet0、vboxnet1、vboxnet2。
特别特别要注意的是:控制芯片一定要选择82545EM,混杂模式一定要全部允许
请在看一遍上面的文字,别怪我没提醒你。
网卡4主要用于上外网,因此选择"网络地址转换(NAT)"即可,如下图所示:
最后“OK”保存,开始安装你的centos吧,安装过程中不需要创新新用户,给root设置一个密码,这些过程就不写了,如果没搞过自己琢磨吧。
至此,假设你的centos7已经安装完成。
网络配置
网卡1用于做管理使用,配置固定IP,如下:
TYPE=Ethernet
BOOTPROTO=static
IPADDR=192.168.56.160
NETMASK=255.255.255.0
GATEWAY=192.168.56.1
DEFROUTE=no
NAME=enp0s17
DEVICE=enp0s17
ONBOOT=yes
网卡2和3暂时不用动.
网卡4主要用于上外网,配置成自动获取IP、默认路由、默认启动,如下所示:
TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=dhcp
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=stable-privacy
NAME=enp0s10
UUID=2a07d19e-5811-45c9-abd0-d6134386b4b2
DEVICE=enp0s10
ONBOOT=yes
编译安装DPDK
安装前执行下面的命令将操作系统升级到最新版本:
yum update
执行下命的命令安装编译所需的依赖:
yum install rpm-build autoconf automake libtool systemd-units openssl openssl-devel python2-devel python3-devel python2 python2-twisted python2-zope-interface python2-six python2-sphinx desktop-file-utils groff graphviz procps-ng checkpolicy selinux-policy-devel kernel-devel python-sphinx python-twisted-core python-zope-interface libcap-ng-devel kernel-devel
然后下载当前稳定版本的源代码,并解压:
cd /usr/src
wget http://fast.dpdk.org/rel/dpdk-17.05.2.tar.xz
tar xf dpdk-17.05.2.tar.xz
设置环境变量,将以下内容增加到~/.bash_profile
文件:
export DPDK_DIR=/usr/src/dpdk-stable-17.05.2
export DPDK_TARGET=x86_64-native-linuxapp-gcc
export DPDK_BUILD=$DPDK_DIR/$DPDK_TARGET
执行下命的命令进行编译:
source ~/.bash_profile
cd dpdk-stable-17.05.2
make install T=x86_64-native-linuxapp-gcc
由于DPDK需要将数据包从网卡直接拷贝到内存,因此需要调整内存页大小和页数,以提高内存使用效率。
编辑/etc/default/grub
文件,将下面的内容加到引导启动项GRUB_CMDLINE_LINUX
:
default_hugepagesz=2m hugepagesz=2m hugepages=512 iommu=pt intel_iommu=on
执行如下命令写入引导项:
grub2-mkconfig -o /boot/grub2/grub.cfg
编辑/etc/fstab
,在最后增加如下内容,在系统启动时挂载大内存页。
nodev /mnt/huge hugetlbfs defaults 0 0
执行如下命令创建挂载点:
mkdir -p /mnt/huge
编译安装Open vSwitch
执行如下命令编译安装OVS:
cd /usr/src/
wget http://openvswitch.org/releases/openvswitch-2.8.1.tar.gz
tar -zxvf openvswitch-2.8.1.tar.gz
chown -R root:root openvswitch-2.8.1
cd openvswitch-2.8.1/
./boot.sh
./configure --with-dpdk=$DPDK_BUILD
make install
为了方便我们后面的配置,把主机名改为ovs1。
编辑/etc/hostname
即可。
执行reboot
重启机器。
复制虚拟机
为了我们能够测试两个虚拟机间的传输性能,我们需要使用virtualbox复制一台一样的虚拟机,复制的时候记得选择“网卡重新初始化选项”。复制完成后进行如下更改:
1、将网卡1的IP配置成192.168.56.161。
2、将hostname改为ovs2。
所有配置完成后,启动ovs1和ovs2。
创建虚拟网桥(分别在ovs1和ovs2上执行)
重启机器后执行如下命令将编译好的dpdk驱动加载到系统内核:
modprobe uio
insmod $DPDK_BUILD/kmod/igb_uio.ko
执行如下命令查看当前网卡绑定的情况:
$DPDK_DIR/usertools/dpdk-devbind.py --status
结果如下:
Network devices using DPDK-compatible driver
============================================
<none>
Network devices using kernel driver
===================================
0000:00:07.0 '82545EM Gigabit Ethernet Controller (Copper) 100f' if=enp0s7 drv=e1000 unused= *Active*
0000:00:08.0 '82545EM Gigabit Ethernet Controller (Copper) 100f' if=enp0s8 drv=e1000 unused=
0000:00:09.0 '82545EM Gigabit Ethernet Controller (Copper) 100f' if=enp0s9 drv=e1000 unused=
0000:00:0a.0 '82545EM Gigabit Ethernet Controller (Copper) 100f' if=enp0s10 drv=e1000 unused= *Active*
Other Network devices
=====================
<none>
Crypto devices using DPDK-compatible driver
===========================================
<none>
可以看到我们的4张网卡目前都是使用默认的e1000驱动。
执行如下命令,将第二张网卡绑定到dpdk驱动:
$DPDK_DIR/usertools/dpdk-devbind.py --bind=igb_uio 0000:00:08.0
再次执行$DPDK_DIR/usertools/dpdk-devbind.py --status
结果如下:
Network devices using DPDK-compatible driver
============================================
0000:00:08.0 '82545EM Gigabit Ethernet Controller (Copper) 100f' drv=igb_uio unused=
Network devices using kernel driver
===================================
0000:00:07.0 '82545EM Gigabit Ethernet Controller (Copper) 100f' if=enp0s7 drv=e1000 unused= *Active*
0000:00:09.0 '82545EM Gigabit Ethernet Controller (Copper) 100f' if=enp0s9 drv=e1000 unused=igb_uio
0000:00:0a.0 '82545EM Gigabit Ethernet Controller (Copper) 100f' if=enp0s10 drv=e1000 unused=igb_uio *Active*
Other Network devices
=====================
<none>
可以看到第二块网卡已经使用了DPDK驱动。
OK,DPDK到此大功告成。
启动OVS:
export PATH=$PATH:/usr/local/share/openvswitch/scripts
ovs-ctl start
启动过程如下:
Starting ovsdb-server [ OK ]
system ID not configured, please use --system-id ... failed!
Configuring Open vSwitch system IDs [ OK ]
Inserting openvswitch module [ OK ]
Starting ovs-vswitchd Zone 0: name:<rte_eth_dev_data>, phys:0x7f9cecc0, len:0x30100, virt:0x7f1366dcecc0, socket_id:0, flags:0
[ OK ]
Enabling remote OVSDB managers
为什么我们要4张网卡? 除了1张用于管理,1张用于上外网,另外两张主要用于对比测试,第二张192.168.57.1/24网段使用dpdk驱动,第三张192.168.58.1/24使用普通网络。现在我们就创建两个网桥br0和br1,分别将第二张网卡加入到br0、第三张网卡加入到br1。
首先对ovs进行dpdk初始化配置:
ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-init=true
创建br0,将第二张网卡以DPDK设备形式加入到br0:
ovs-vsctl add-br br0 -- set bridge br0 datapath_type=netdev
ovs-vsctl add-port br0 myportnameone -- set Interface myportnameone type=dpdk options:dpdk-devargs=0000:00:08.0
0000:00:08.0为第二张网卡的ID。
创建br1,将第三张网卡加入到br1:
ovs-vsctl add-br br1
ovs-vsctl add-port br1 enp0s9
执行ovs-vsctl show
查看网桥配置情况如下:
c81a1a9a-ebfc-4aab-a008-24697f1ff1ca
Bridge "br0"
Port myportnameone
Interface myportnameone
type: dpdk
options: {dpdk-devargs="0000:00:08.0"}
Port "br0"
Interface "br0"
type: internal
Bridge "br1"
Port "br1"
Interface "br1"
type: internal
Port "enp0s9"
Interface "enp0s9"
ovs_version: "2.8.1"
上面的过程在ovs1和ovs2上完全相同,下过分别给两个网桥配置ip。
在ovs1上,执行如下命令给br0和br1设置IP:
ifconfig br0 192.168.57.10/24 up
ifconfig br1 192.168.58.10/24 up
在ovs2上,执行如下命令给br0和br1设置IP:
ifconfig br0 192.168.57.11/24 up
ifconfig br1 192.168.58.11/24 up
配置完成后,在ovs1上应该通直接ping通 192.168.57.11 和 192.168.58.11
网速测试
我们使用iperf进行网速测试,在两台虚拟机上安装iperf:
yum install iperf
在ovs1上关闭防火墙启动服务端:
systemctl stop firewalld.service
iperf -s -i 1
在ovs2上执行如下命令分别测试两条链路的网速:
iperf -t 10 -i 1 -c 192.168.57.10
iperf -t 10 -i 1 -c 192.168.58.10
结果如下:
[root@ovs2 ~]# iperf -t 10 -i 1 -c 192.168.57.10
------------------------------------------------------------
Client connecting to 192.168.57.10, TCP port 5001
TCP window size: 85.0 KByte (default)
------------------------------------------------------------
[ 3] local 192.168.57.11 port 46748 connected with 192.168.57.10 port 5001
[ ID] Interval Transfer Bandwidth
[ 3] 0.0- 1.0 sec 16.2 MBytes 136 Mbits/sec
[ 3] 1.0- 2.0 sec 19.2 MBytes 161 Mbits/sec
[ 3] 2.0- 3.0 sec 19.2 MBytes 161 Mbits/sec
[ 3] 3.0- 4.0 sec 19.1 MBytes 160 Mbits/sec
[ 3] 4.0- 5.0 sec 17.5 MBytes 147 Mbits/sec
[ 3] 5.0- 6.0 sec 18.4 MBytes 154 Mbits/sec
[ 3] 6.0- 7.0 sec 18.6 MBytes 156 Mbits/sec
[ 3] 7.0- 8.0 sec 17.8 MBytes 149 Mbits/sec
[ 3] 8.0- 9.0 sec 17.8 MBytes 149 Mbits/sec
[ 3] 9.0-10.0 sec 17.5 MBytes 147 Mbits/sec
[ 3] 0.0-10.0 sec 181 MBytes 152 Mbits/sec
[root@ovs2 ~]# iperf -t 10 -i 1 -c 192.168.58.10
------------------------------------------------------------
Client connecting to 192.168.58.10, TCP port 5001
TCP window size: 85.0 KByte (default)
------------------------------------------------------------
[ 3] local 192.168.58.11 port 53078 connected with 192.168.58.10 port 5001
[ ID] Interval Transfer Bandwidth
[ 3] 0.0- 1.0 sec 158 MBytes 1.33 Gbits/sec
[ 3] 1.0- 2.0 sec 146 MBytes 1.23 Gbits/sec
[ 3] 2.0- 3.0 sec 147 MBytes 1.23 Gbits/sec
[ 3] 3.0- 4.0 sec 162 MBytes 1.36 Gbits/sec
[ 3] 4.0- 5.0 sec 153 MBytes 1.29 Gbits/sec
[ 3] 5.0- 6.0 sec 119 MBytes 998 Mbits/sec
[ 3] 6.0- 7.0 sec 135 MBytes 1.13 Gbits/sec
[ 3] 7.0- 8.0 sec 117 MBytes 980 Mbits/sec
[ 3] 8.0- 9.0 sec 168 MBytes 1.41 Gbits/sec
[ 3] 9.0-10.0 sec 161 MBytes 1.35 Gbits/sec
[ 3] 0.0-10.0 sec 1.43 GBytes 1.23 Gbits/sec
怎么样? 结果是不是很惊人?
总结
为什么? 为什么? 为什么?为什么使用dpdk驱动的速度会比普通网卡的速度慢那么多呢?只有普通网卡的1/10,理论和实践为什么差距辣么大?
我个人认为可能是由于我的环境所致,本身虚拟机才2G内存,数据传输完成后,OVS还要进行大量的数据包处理,虚拟机cpu性能也不是很强,才会出现这样的局面,这和我的预想完全相反,整个人感觉这几天的工夫白花了。
当然,也可能是某些地方配置不对,希望各位指正。
后续工作
现在需要在物理环境进行测试,但看了一下我手里的服务器网卡都不支持DPDK,特在此向各位征集网卡2张,要求intel的,并且支持dpdk。
如果谁有可以和我联系,微信: cj_zhao, 1周内测试完成,原样寄回,谢谢!
如果您喜欢我的作品,欢迎点赞、打赏、关注。
请我吃个雪糕……