随着云计算与大数据的快速发展,其对数据中心网络的性能和管理提出了更高的要求,但传统云计算架构存在多个I/O瓶颈,由于云平台基本上是采用传统的X86服务器加上虚拟化方式组建,随着40G、100G高速网卡的出现,如何在通用的X86平台上实现网络的快速转发就成为关键。DPDK是INTEL推出的基于X86平台提升数据面报文快速处理速率的应用程序开发包[1],关于DPDK的资料已经比较多,本文不再做过多介绍,本文重点关注DPDK与OpenStack的结合。
目前在OpenStack中使用DPDK实现数据平面用户态转发的项目有两个networking-ovs-dpdk 和networking-vpp,networking-vpp[2]项目还在功能完善阶段,而Open vSwitch+DPDK的实现已经全部合入主干,因此本文主要介绍Open vSwitch+DPDK的实现原理、如何配置使用以及该特性目前在社区的完善度。
Open vSwitch with DPDK
Open vSwitch在2.2版本开始支持DPDK,从2.4开始可以使用DPDK优化的vHost路径[3],其架构如下图所示[4]:
Open vSwith使用DPDK在用户态实现了netdev datapath:使用轮询driver绕过内核协议栈来直接处理物理网卡上的数据包,使用vHost and IVSHEM库作为宿主机到guest OS的控制和数据通道。当使用IVSHEM时,可以在guest OS中运行DPDK应用,这种场景下DPDK中的应用必使用宿主机上的共享内存大页。对于vHost的实现,Open vSwith通过socket实现控制消息的处理,通过共享的内存大页实现真正数据包的处理。
Open vSwitch中vHost-user类型
vHost-user介绍
vhost-user是利用现有的vhost提供的机制(共享内存,ioeventfd和irqfd),针对virito设备实现的一种交换的传输方式。vhost-user通过UNIX socket在两个进程之间设置Vrings和共享内存。当virtio设备发出kick信息时,也通过UNIX socket和进程进行交互,想了解关于vhost、vhost-user更多细节可参考我同事写的一篇文章[14]。
结合Open vSwitch和QEMU使用时,在Open vSwitch的vhost-user模式下,Open vSwitch作为backend,QEMU作为client,在vhost-user-client模式下,QEMU作为backend,Open vSwitch作为client,下一节会有详细说明。
Open vSwitch支持的vHost-user类型
在Open vSwitch中vHost User通过socket进行通信,模式为client-server,其中server端负责创建/管理/销毁所需socket连接,客户端只需要通过socket连接到server端,Open vSwitch支持两种类型的vHost User端口[5]:
VHOST-USER
vhost-user在Open vSwitch中的端口类型为dpdkvhostuser,该模式下Open vSwitch作为server端,QEMU作为client端,使用该类型端口时,要求QEMU版本必须>=2.2。
该模式下vHost端口不具备‘reconnect’能力。当Open vSwitch服务异常后,QEMU作为client端能感知到该异常并将端口状态置为down,但当Open vSwitch服务恢复后,QEMU作为client端不会自动重新连接server,导致虚拟机网络无法自动恢复。
VHOST-USER-CLIENT
vhost-user-client在Open vSwitch中的端口类型dpdkvhostuserclient,该模式下Open vSwitch作为client端,QEMU作为server端,使用该类型端口时,要求QEMU版本必须>=2.7。
该模式下vHost端口具备‘reconnect’能力。使用该类型端口创建虚拟机时,QEMU会等端口创建成功,client连接上后启动虚拟机,在Open vSwitch服务出现异常或被停止后,QEMU会将端口状态置为down,当Open vSwitch服务恢复正常后,client会重新连接server,触发QEMU重新将端口状态置为up。
Open vSwitch with DPDK在OpenStack中的实现
OpenStack对Open vSwitch with DPDK的支持是在Kilo版本,这是一个跨Nova和Neutron两个模块的特性,Nova中需要在libvirt 的vif driver中新增一个vhost user driver,具体实现可参考[6],Neutron侧的代码放在一个独立的子项目networking-ovs-dpdk[7],在Mitaka版本,Neutron侧的代码全部合入主干[8],但该特性的CI仍然保留在networking-ovs-dpdk子项目。
本文以OpenStack最新发行版Ocata介绍该特性的实现,OS选用Ubuntu 16.04,由于该特性需要使用内存大页,服务器推荐至少8G内存,2块物理网卡,本实验使用的是Intel 82567网卡。
配置内存大页
传统的X86平台默认内存页大小为4K,可配置2MB,1GB 的内存大页,可参考[9]中相关说明,生产环境中需要根据实际需求来选择大页内存类型,例如在NFV场景,对虚拟机的性能有较高要求,宿主机的CPU和内存不开启复用,那么配置1GB的内存大页更合理,本实验使用2MB的内存大页。
挂载内存大页,并设置OS启动时自动挂在大页
1 2 3 4 | # mkdir -p /dev/hugepages # mount -t hugetlbfs none /dev/hugepages -o pagesize=2MB # vi /etc/fstab nodev /dev/hugepages hugetlbfs pagesize=2MB 0 0 |
重启OS
1 | $ sudo reboot |
验证大页是否挂载成功
绑定使用DPDK的网卡
安装DPDK
推荐使用源码编译安装DPDK[9],DPDK最新开发版本为17.02,最新稳定版本为16.11.1:
1 2 3 4 5 6 7 8 | $ cd /opt/dpdk $ wget http://fast.dpdk.org/rel/dpdk-16.07.tar.xz $ tar xf dpdk-16.07.tar.xz $ export DPDK_DIR="/opt/dpdk" $ export DPDK_TARGET="x86_64-native-linuxapp-gcc" $ export DPDK_BUILD="$DPDK_DIR/dpdk-16.07/$DPDK_TARGET" $ cd $DPDK_DIR/dpdk-16.07 $ sudo make install T=$DPDK_TARGET DESTDIR=install |
加载IGB_UIO驱动
编译好的DPDK中包括该驱动:
1 2 | # modprobe uio # insmod $DPDK_DIR/dpdk-16.07/x86_64-native-linuxapp-gcc/kmod/igb_uio.ko |
绑定网卡
查询网卡的PCI号:
1 | ethtool -i eth1 | grep bus-info |
使用DPDK源码中提供的绑定脚本绑定网卡
1 | python dpdk-devbind.py --bind=igb_uio 网卡PCI号 |
网卡绑定成功后如下图所示:
NEUTRON中相关配置
OPENVSWITCH-AGENT安装配置
openvswitch-agent安装时只会自动安装openvswitch,需要手动安装openvswitch-dpdk,推荐使用openvswitch的源码编译、安装,安装之前需要先停掉openvswitch服务。
1 | # service openvswitch-switch stop |
编译安装OPENVSWITCH
从官方下载openvswitch:http://openvswitch.org/download,本实验使用ovs 2.6.1版本
1 2 3 4 5 6 7 8 9 | $ export OVS_DIR="/opt/ovs" $ export OVS_DB_PATH="/usr/local/etc/openvswitch" $ export OVS_DB_SOCK="/usr/local/var/run/openvswitch/db.sock" $ tar xvf openvswitch-2.6.1.tar.gz $ cd $OVS_DIR/openvswitch-2.6.1 $ ./boot.sh $ ./configure --with-dpdk=$DPDK_BUILD $ make $ sudo make install |
创建OVS 数据库
1 2 3 | $ sudo mkdir -p $OVS_DB_PATH $ sudo ovsdb-tool create $OVS_DB_PATH/conf.db \ /usr/local/share/openvswitch/vswitch.ovsschema |
设置OVS使用的内存大页
可先查询各NUMA node上内存大页的使用情况,
1 2 | $ cat /sys/devices/system/node/node*/meminfo|grep Huge $ sudo ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-socket-mem="512,1" |
启动OVS DB服务
1 2 3 4 | $ sudo ovsdb-server --remote=punix:$OVS_DB_SOCK \ --remote=db:Open_vSwitch,Open_vSwitch,manager_options \ --pidfile –detach sudo ovs-vsctl --db=unix:$OVS_DB_SOCK --no-wait init |
设置ovs以DPDK的方式启动:
1 | $ sudo ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-init=true |
添加物理网卡
物理网卡绑定DPDK驱动后才能被ovs-vswitchd发现:
在openvswitch2.7之前,物理网卡在openvswitch中的命名以dpdk开头:
1 | $ sudo ovs-vsctl add-port br-eth1 dpdk0 -- set Interface dpdk0 type=dpdk |
启动OVS-VSWITCHD
1 2 | $ sudo ovs-vswitchd unix:$OVS_DB_SOCK \ --pidfile --detach --log-file=/var/log/openvswitch/ovs-vswitchd.log |
创建DATAPATH类型为NETDEV的网桥
1 2 | $ sudo ovs-vsctl add-br br-int -- set bridge br-int datapath_type=netdev $ sudo ovs-vsctl add-br br-eth1 -- set bridge br-eth1 datapath_type=netdev |
修改OPENVSWITCH-AGENT配置文件
在ovs标签下修改下面3个配置项:
1 2 3 4 | [ovs] datapath_type=netdev vhostuser_socket_dir=/usr/local/var/run/openvswitch bridge_mappings=dpdk:br-eth1(使用vlan类型网络配置该项) |
重启openvswitch-agent服务
Nova中相关配置
创建带内存大页的flavor:
1 2 | $ sudo openstack flavor create --id 3 --ram 64 --vcpus 1 hugepage $ sudo openstack flavor set --property hw:mem_page_size=large hugepage |
基本功能验证
创建虚拟机
在Ocata版本之前,Neutron只支持vhost-user类型的port,Ocata实现了对vhost-user-client类型的port的支持[11]。
创虚拟机时,Neutron会根据openvswitch-agent上报openvswitch支持的interface type作端口绑定,在vhost-user-client和vhost-user都支持的情况下优先使用vhost-user-client。
虚拟机使用vhost-user port如下图所示:
虚拟机使用vhost-user-client port如下图所示:
可以通过查看端口的状态来检查虚拟机的网卡是否被Open vSwitch和QEMU正确处理:
虚拟机热迁移
经验证在Ocata版本Nova支持对带vhostuser类型网卡的虚拟机进行在线迁移。
支持的网络类型
经验证在Ocata 版本,Neutron中flat、vlan、vxlan类型的网络均支持vhostuser类型的port,如何配置使用vxlan网络可参考[12]。
安全组功能
当Open vSwitch使用DPDK后,使用iptables实现的安全组driver已经无法使用,但完全基于OpenFlow流表实现的安全组driver在Newton版本已经实现[13],修改openvswitch-agent的配置文件:
1 2 | [securitygroup] firewall_driver = openvswitch |
经验证vhostuser类型port的安全组功能在Ocata版本基本可用,但还存在一些问题,例如计算节点上port较多时,Open vSwitch流表数量过多(社区已在做相关优化[15]),链接跟踪无法自动清除问题。
总结
通过上述实验可以看出,OpenStack的发展速度确实比较快,对Open vSwitch with DPDK的基本功能已经全部支持。本文只是验证了一下该特性的基本功能,后续会再做一下稳定性和性能相关测试,如何将该特性应用到生产环境会是我接下来研究的重点。