1. 概述
网络虚拟化是云平台的核心组件之一,本文简单介绍了常见kvm虚拟网卡、网桥技术,自建私有云网络演化过程以及兼顾性能和性价比的SR-IOV技术实践。
2. 认识KVM网卡和网桥
首先我们先一起理解KVM里发送一个数据包从虚拟机到物理机的完整过程。
数据包从虚拟机中出来后,进入virtio的虚拟网卡,然后再进入kvm的虚拟层,最后通过网桥把数据包传入内核,最后到达物理网卡。上面一个流程跑下来,你一定会想能否跳过其中一个步骤或是多个步骤,简化架构提升性能。
2.1 KVM网络接口简介
KVM网络接口(虚拟网卡)一般有四种,分别是 virtio 、vhost-net 、 PCI Path-through 、 SR-IOV,模型如下:
1. Virtio纯虚拟化网卡,性能最弱。(这种即上图所说的完整流程,一般不使用)
2. Vhost-net半虚拟化网卡,跳过虚拟层直接跳转到内核网桥。
可以看到虚拟机的数据包直接跳过了虚拟网卡直接和kvm的虚拟层交换数据,减少一层损耗。这种架构只是解决了从虚拟机发包出去时候跳过虚拟网卡,但并没有在接收数据时候也跳过虚拟网卡。所以当你用发包工具测试的时候会发现虚拟机内部往外发包和外面往内发包的结果不一样,会有15%-20%的差距。
3. Pci Path-through独占网卡,这种就是虚拟机的收发直接和物理网卡数据交换,去掉中间的部分,所以性能最好。
4. SR-IOV 将原来vswitch的活儿直接集成到了网卡芯片中,硬件化虚拟网卡VF,一般能达到原生网卡的一半性能。这种架构和Pci Path-through区别在于,一个是独享,另外一个就是共享,架构几乎是一样的。
而KVM网桥承担着路由交换功能,常见的有linux-bridge 和 openvswitch(相比前者、性能更好),openstack M版及以后默认采用openvswitch。
2.2 KVM网络接口性能测试
对比测试不同架构和网桥技术的pps的数据,同时也比较了包的大小对pps的影响。 包大小分别采用了:64 bytes(小包),1518 bytes(大包)。
3. 了解openvswitch L2 L3层
Openvswitch是一个虚拟交换软件,功能强大,可支持L2和L3两种软交换机功能。
L2层支持local gre vlan xvlan协议。
L3层支持flat vlan协议。
下面分别简介各协议:
3.1 GRE
GRE:General Routing Encapsulation,一种通过封装来实现隧道的方式,其拥有以下特点:
-
跨不同网络实现二次IP通信。
-
L3上面包装L3。
-
封装在IP报文中。
-
点对点隧道。
GRE缺点:
-
增加了GRE表头会导致本应由交换机硬件来分片的变成由软件来分片(STT技术可以弥补这一点),所以一般我们会关闭网卡的GRO,以及改小MTU。
-
GRE广播,且遂道将虚拟二层打通了,广播风暴更厉害。但对于虚机来说,因为虚拟交换机是完全能够知道虚机的IP和MAC地址的映射关系的,根本不需要通过ARP广播来根据IP找MAC地址。
3.2 VLAN
VLAN: Virtual Local Area Network, VLAN是一种将局域网(LAN)设备从逻辑上划分(注意,不是从物理上划分)成一个个网段(或者 说是更小的局域网LAN),从而实现虚拟工作组(单元)的数据交换技术。
VLAN的优点:
-
端口的分隔。即便在同一个交换机上,处于不同VLAN的端口也是不能通信的。这样一个物理的交换机可以当作多个逻辑的交换机使用。
-
网络的安全。不同VLAN不能直接通信,杜绝了广播信息的不安全性。
-
灵活的管理。更改用户所属的网络不必换端口和连线,只更改软件配置就可以了。
3.3 VXLAN
VXLAN: Virtual eXtensible LAN,是一种覆盖网络技术或隧道技术。VXLAN将虚拟机发出的数据包封装在UDP中,并使用物理网络的IP/MAC作为outer-header进行封装,然后在物理IP网上传输,到达目的地后由隧道终结点解封并将数据发送给目标虚拟机。
VXLAN的优点
-
VLAN的数量限制4096个vlan远不能满足大规模云计算数据中心的需求,所以需要用到VXLAN。
-
物理网络基础设施的限制,基于IP子网的区域划分限制了需要二层网络连通性的应用负载的部署。
-
TOR交换机MAC表耗尽,VLAN虚拟化以及二层流量导致更多的MAC表耗尽,VXLAN就是要解决这个问题的。
-
解决多租户场景,如IP地址重叠比如多个私有网络的情况。
4. 自建私有云网络演化过程
自建私有云过程中,网络虚拟化方案也几经迭代:
4.1 第一版方案
openstack原生方案,统一出口网关
最初自建云主要用于部署测试机和功能机,网络要求不高,架构上采用了全部虚拟机一个二层平面的,全部流量通过网络节点进出。全部的二层跨宿主机流量都通过网络节点传递。
这种架构的优点在于架构与维护简单,缺点就是一旦网络节点崩溃就无法访问,虽然可以用LVS负载均衡,但我们实践测试过程中出现过因为LVS相互抢vip导致网络故障的问题。
4.2 第二版方案
openstack DVR方案,分布式出口网关
经过上一版方案的实际运行后,发现网络节点容易堵塞,另外我们对内网流量的需求开始上升。我们在新集群采用了新的网络架构方案DVR。
DVR的优点在于分布式,去中心化。以前内网流量都必须经过网络节点,现在使用了DVR架构后,跨宿主机的内网流量可以直接两台宿主机之间通讯,无需经过网络节点。外网也不再集中从网络节点NAT出外网,而是从各自宿主机的L3-agent服务桥接的本地外网网卡出去。这样只有没有配置浮动外网ip的虚拟机需要访问外网时候才会用到网络节点。如果不想没浮动ip的机器访问外网可以使用防火墙或是直接不使用网络节点的外网桥接口就可以了。
这种架构也完美的解决第一种架构ping延迟突然变高的问题,相当的稳定。因为虚拟机出外网无需再通过GRE网络的转发,而是直接从本机的网桥进入宿主机的另外一张网卡出去,几乎没延迟波动。
第二版方案我们同时启用了l2_population和arp_responder这两项优化
有和没有 l2_population的效果:
如果没有开启l2_population,宿主机要找到非宿主机的虚拟机就要在二层全广播的找,这样宿主机越多,网络请求越大广播风暴越可怕。开启l2_population后,系统就会自动记录全部VM的ARP表,这样只需要把包直接发给目标宿主机就可以了,减少了广播风暴。
第二版方案中我们还是发现有一些异常
出现过2-3例虚拟机已经删除,但旧宿主机上还有路由信息残留,导致新虚拟机使用该ip时候,会出现无法连通的情况。需要手动删除旧的路由信息。
#找到旧的路由信息删除即可(旧vm所在的宿主机)
ip netns exec ${NET} route -n | grep ' 169.254.31.28'
如果同一内网的虚拟机在使用公网ip进行互访时候,网络性能有所下降,根据路由图信息看到公网ip还是通过L3-agent服务绕出外网再回来。而内网就直接在内网处理了。所以在网络包量较大时候会出现很明显的性能损耗,但吞吐并没损耗。
4.3 第三版方案
SR-IOV网络优化方案
我们开始迁移游戏服业务到自建私有云,发现一些实时性较高的手游出现网络包量不足的情况,根据这种情况我们修改了架构,引入了SR-IOV。把虚拟机的虚拟网卡流量直接发送给网卡的VF,减去中间的桥接网卡和Openvswitch这种软交换机,减少网卡包量的损耗。但这种方案架构特性使得内网的网络隔离方案无法实施,只能通过vlan的划分来隔离网络,无法做到防火墙的端口隔离或是快速隔离和融合。
这里先简单介绍下SR-IOV的情况:
SR-IOV全称Single-Root I/O Virtualization。
它本身是一种技术实现方式,简单的说,它就是通过的硬件的方式,将个物理的网卡(PF),虚拟出多个虚拟机网卡(VF),虚拟出来的网卡可以直接分配的虚拟机使用。在传统的虚拟化中,虚拟机的网卡通常是通过桥接(Bridge或OVS)的方式,因为这种方式最方便,也最简单。但是这样做最大的问题在于性能。
SR-IOV并不是一个新技术,在2010年左右,Intel就已经提出来了,但因为如下技术点并没得到大规模应用和推广。
-
SR-IOV需要特定的网卡支持,支持清单:http://www.intel.cn/content/www/cn/zh/support/network-and-i-o/ethernet-products/000005722.html
-
SR-IOV在KVM应用中不支持在线迁移的功能。
-
大部分上云的服务器,对网卡的性能要求传统的网桥即可满足,所以动力不足。
KVM虚拟机在传统网桥模式下,网络稳定是没有问题的。特别是只需要跑带宽的网页服务,但它和SR-IOV一个本质的区别是,网桥模式本身会消耗宿主机的CPU,在实际场景下,当宿主机的CPU压力(>60%)比较大时,虚拟机内部网卡的发包率(PPS)性能会下降,极端情况会出现丢包。这点对于游戏业务来说,最直观的感受是游戏卡顿、玩家掉线,这在游戏业务中是绝对不允许的。
考虑到我们业务的需求情况,我们采取保留原来的二层架构。但外网部分我们使用VLAN模式取代flat平面桥接。然后使用SR-IOV技术直接桥接到外网网卡的VF上。这样我们的虚拟机就会看到两个网卡,一个内网一个外网,网关默认是走外网。这样我们既能保证二层内网的灵活性,也能提升游戏服外网的包转发能力。
包转发性能测试
SR-IOV允许虚拟机同时绑定网卡多个VF,这样网卡性能会进一步提高。目前我们采用Intel 82765千兆网卡,单网口只支持7个VF,如果宿主机性能强大可以采购4口的网卡。条件允许也可以考虑用万兆网卡,支持的VF达到64个。
SR-IOV的缺点:
-
无法灵活管理网络,只能用vlan划分网络。
-
无法软件限速,只能考虑路由或是三层交换机进行限速
-
需要一定的CPU性能,最好能独立出几个CPU来给SR-IOV和网卡软中断使用。
SR-IOV开启需要的支持内容:
-
物理主机必须支持并开启I/O内存管理单元(IOMMU)功能。
-
物理主机必须支持SR-IOV,并且在BIOS中启用了SR-IOV。
-
SR-IOV只有部分网卡支持如Intel 82765
-
支持SR-IOV的网卡必须插在总线带宽X8以上的扩展槽中。
下一个版本规划:
10W的外网包量在将来未必能满足我们的业务需求,我们将考虑DPDK技术和SR-IOV结合提高虚拟网卡和物理网卡间的数据包转发。另外我们也会上内存巨大页优化内存减少一次虚拟机数据和物理机之间的数据转发需求。
5. SR-IOV技术实践
KVM网络优化的最终方向,是减少虚拟机访问物理网卡的层数,甚至独占物理网卡。SR-IOV技术兼顾性能与性价比,在中小规模私有云中较为常见,我们也做了如下实践。
SR-IOV部署步骤如下:
1. Openstack环境部署参考官方文档,这里不再赘述。
2. 必须使用支持SR-IOV的网卡,千兆推荐Intel82576 单网口只支持7个VF。这个型号官网有完整的测试流程和数据,万兆用 intel 82599ES。也可以用intel i310这种但价格会更贵,贵200%,但性能好。
3. 开机进入bios开启SR-IOV,默认没开启。
4. vi /etc/default/grub
GRUB_CMDLINE_LINUX_DEFAULT="rootdelay=90 quiet splash intel_pstate=disable intel_iommu=on igb.max_vfs=7"# update-grub# reboot
5. 查看网卡是否开启了VF。(请注意红色标记字段,后续配置需要用上)
# lspci -nn | grep Eth02:00.0 Ethernet controller [0200]: Broadcom Corporation NetXtreme BCM5720 Gigabit Ethernet PCIe [14e4:165f]02:00.1 Ethernet controller [0200]: Broadcom Corporation NetXtreme BCM5720 Gigabit Ethernet PCIe [14e4:165f]08:00.0 Ethernet controller [0200]: Intel Corporation 82576 Gigabit Network Connection [8086:10c9] (rev 01)08:00.1 Ethernet controller [0200]: Intel Corporation 82576 Gigabit Network Connection [8086:10c9] (rev 01)08:10.0 Ethernet controller [0200]: Intel Corporation 82576 Virtual Function [8086:10ca] (rev 01)08:10.1 Ethernet controller [0200]: Intel Corporation 82576 Virtual Function [8086:10ca] (rev 01)08:10.2 Ethernet controller [0200]: Intel Corporation 82576 Virtual Function [8086:10ca] (rev 01)08:10.3 Ethernet controller [0200]: Intel Corporation 82576 Virtual Function [8086:10ca] (rev 01)08:10.4 Ethernet controller [0200]: Intel Corporation 82576 Virtual Function [8086:10ca] (rev 01)08:10.5 Ethernet controller [0200]: Intel Corporation 82576 Virtual Function [8086:10ca] (rev 01)
看到多个网卡队列就是Vf了。
6. 主控机vi /etc/neutron/plugins/ml2/ml2_conf.ini
#开启vlan
tenant_network_types= gre,vlanextension_drivers= port_security
#开启sriovnicswitch服务
mechanism_drivers= openvswitch,l2population,sriovnicswitch [ml2_type_vlan]
#这个名字必须和后台创建vlan时候一样
network_vlan_ranges= physnet2 # serviceneutron-server restart
7. 计算节点vi /etc/neutron/plugins/ml2/ml2_conf.ini
#开启vlan
tenant_network_types = gre,vlan extension_drivers = port_security
#开启sriovnicswitch服务
mechanism_drivers = openvswitch,l2population,sriovnicswitch [ml2_type_vlan]
#这个名字必须和后台创建vlan时候一样
network_vlan_ranges = physnet2 # service neutron-plugin-openvswitch-agent restart
#安装SRIOV支持模块
# apt-get install neutron-plugin-sriov-agent # vi /etc/neutron/plugins/ml2/ml2_conf_sriov.ini[ml2_sriov]
#上面lscpi(即第五步)红色标记的字段
supported_pci_vendor_devs = 8086:10ca [sriov_nic]
#网卡和vlan模块物理的名称
physical_device_mappings = physnet2:p2p1 exclude_devices =[securitygroup]
#因为不支持防火墙隔离所以要屏蔽掉
firewall_driver = neutron.agent.firewall.NoopFirewallDriver #service neutron-plugin-sriov-agent restart#vi /etc/nova/nova.confpci_passthrough_whitelist = {"devname":"p2p1","physical_network":"physnet2"}#service nova-compute restart
8. 创建方法
Kilo版本不支持页面创建,后面的版本可能支持但没测试
主控机下执行
#运行处理权限相关的脚本,装openstack是会要求配置这个文件
#source /root/admin-openrc.sh
#lan为后台网络的名称,direct为直连网卡的意思,用SR-IOV的端口
#neutron port-create lan--binding:vnic-type direct
#下面命令几个红色标注的分别为,主机类型、镜像id、上面创建的端口id(可只用一个端口,两个端口就是代表虚拟机有两个网卡)
#nova boot --flavor 12CPU-32GMEN--image e29eea41-40ed-44da-9059-dd1879feddb7 --nic port-id=446120fc-753f-45ba-a7dd-1bea20550140--nic port-id=6a78021a-21f5-44bd-ab19-33f4e3292e93TEST
然后我们需要登录虚拟机手动配置IP,接着查看SR-IOV网卡是否有VF的mac非00:00:00:00:00:00 ,如果有说明已经桥接好了,可以使用了。
ip link show dev p2p1 4: p2p1:
另外有个不清楚的地方就是需要手动把网卡的vlanid去掉,否则无法ping通外部网络。
ip link set p2p1 vf 6 vlan 0
6. SR-IOV虚拟机网卡性能测试
用hping3 从内部测试外部IP的80端口
包量能到44w,后面因为包量过大导致测试机器的博通网卡挂了。
用游戏机器人测试
能达到10w的稳定包量值。
7. 结语
中小规模的私有云,虚拟机可基于SR-IOV技术部署双网卡,既能内网隔离又能加速外网。通过kvm自带的限速功能,也能方便地限速外网流量。
大数据处理、高速存储的需求推动了网络带宽的发展,部分公有云厂商已支持450w pps、25Gbps吞吐能力的单虚拟机实例。从行业趋势看,实时对战型游戏对网络包转发、瞬间吞吐能力、延迟稳定性上要求更高。