Centos7使用SR-IOV创建KVM虚拟机方法
一、SR-IOV介绍1、传统方式的瓶颈:qemu的网卡,传统方式是使用tap网卡,桥接到宿主的bridge上,但性能很差,尤其是包转发率很低,难以满足对性能要求比较高的场景。性能差的主要原因是路径太长,经过的内核设备太多,即使是使用万兆VIRTIO虚拟网卡,TAP作为字符设备也会成为性能瓶颈,根本原因在于linux/unix内核本身就不是为高性能而设计的,linux/unix更适合做控制平面,而不
一、SR-IOV介绍
1、传统方式的瓶颈:
qemu的网卡,传统方式是使用tap网卡,桥接到宿主的bridge上,但性能很差,尤其是包转发率很低,难以满足对性能要求比较高的场景。性能差的主要原因是路径太长,经过的内核设备太多,即使是使用万兆VIRTIO虚拟网卡,TAP作为字符设备也会成为性能瓶颈,根本原因在于linux/unix内核本身就不是为高性能而设计的,linux/unix更适合做控制平面,而不是转发平面。
传统使用TAP创建KVM虚拟机方法(启用virtio,使能多队列支持):
qemu-system-x86_64 \
-name vfw10G \
-m 16384 \
-smp 12 \
-cpu host \
-hda /gao/vit_tool/store/vfw10G.qcow2 \
-cdrom /gao/vit_tool/iso/virtual_install_12171620.iso \
-boot c \
-enable-kvm \
-netdev type=tap,ifname=vfw10G_eth0,script=no,downscript=no,id=net0 \
-device e1000,netdev=net0,mac=70:D0:81:3B:1F:5C,bus=pci.0,addr=0x3 \
-netdev type=tap,ifname=vfw10G_eth1,script=no,downscript=no,id=net1,queues=8 \
-device virtio-net-pci,mq=on,vectors=5,netdev=net1,mac=70:D0:81:C7:7A:08,bus=pci.0,addr=0x4 \
-netdev type=tap,ifname=vfw10G_eth2,script=no,downscript=no,id=net2,queues=8 \
-device virtio-net-pci,mq=on,vectors=5,netdev=net2,mac=70:D0:81:E6:B4:36,bus=pci.0,addr=0x5 \
-daemonize \
-vnc :12 \
2、解决思路:
减少中间路径,最简单有效的方法就是bypass内核。SRIOV(Single-Root I/O Virtualization)的作用就是bypass宿主内核,实现宿主机物理网卡与VM虚拟网卡passthrough直通。
3、PF和VF:
物理功能(PF):PF是全功能的PCIE,可以像其他任何PCIE设备一样进行发现、管理、和处理。PF拥有完全配置和控制PCIE设备资源的能力。
虚拟功能(VF):VF是一种轻量级的PCIE功能,VF可以与PF以及与同一PF相关联的其他VF共享一个或多个物理资源。VF仅允许拥有用于其自身行为的配置资源。
每个物理网卡就是一个PF,在开启SRIOV后,每个PF可以生成固定数量的VF,每个VF都可以在宿主上作为一张网卡直接使用,或者直通到QEMU虚拟机里作为虚拟机里的网卡使用,这就实现了bypass宿主内核。
不同网卡方案对比图如下:
二、 开启SR-IOV支持
1、在BIOS里开启网卡SR-IOV
注:即使BIOS里开启全局SRIOV,网卡也依然可以当作普通网卡使用
2、在BIOS里开启VT-d支持
3、在grub配置iommu支持
修改/boot/grub2/grub.cfg或 /etc/grub2.cfg文件(软链接),在linux16加载内核镜像一行追加“intel_iommu=on iommu=pt”,“iommu.passthrough=1”不加也可,包含在“intel_iommu=on”
[root@localhost ~]# ls -l /etc/grub2.cfg
lrwxrwxrwx. 1 root root 22 Nov 19 17:54 /etc/grub2.cfg -> …/boot/grub2/grub.cfg
linux16 /vmlinuz-3.10.0-514.el7.x86_64 root=/dev/mapper/cl-root ro crashkernel=auto rd.lvm.lv=cl/root rd.lvm.lv=cl/swap rhgb quiet intel_iommu=on iommu=pt
也可修改/etc/default/grub文件,在GRUB_CMDLINE_LINUX最后追加“intel_iommu=on iommu=pt”参数,然后执行grub2-mkconfig -o /boot/grub2/grub.cfg刷新 grub.cfg 文件;
[root@localhost ~]# cat /etc/default/grub
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR=" ( s e d ′ s , r e l e a s e . ∗ (sed 's, release .* (sed′s,release.∗,g’ /etc/system-release)"
GRUB_DEFAULT=saved
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT=“console”
GRUB_CMDLINE_LINUX=“crashkernel=auto rd.lvm.lv=cl/root rd.lvm.lv=cl/swap rhgb quiet intel_iommu=on iommu=pt iommu.passthrough=1”
GRUB_DISABLE_RECOVERY=“true”
[root@localhost ~]# grub2-mkconfig -o /boot/grub2/grub.cfg
Generating grub configuration file … Found linux image:
/boot/vmlinuz-3.10.0-514.el7.x86_64 Found initrd image:
/boot/initramfs-3.10.0-514.el7.x86_64.img Found linux image:
/boot/vmlinuz-0-rescue-e5ec5990f1e548bea132e3458196c892 Found initrd
image: /boot/initramfs-0-rescue-e5ec5990f1e548bea132e3458196c892.img
done
注:额外追加“console=ttyS0,115200”参数可支持串口显示;
4、虚拟化支持及开启成功验证
1)验证CPU是否支持虚拟化方法如下:
grep -E “vmx|svm” /proc/cpuinfo
如果输出内容中有 vmx,说明CPU支持 VT。
2)验证KVM加载成功方法:
[root@localhost ~]# lsmod |grep kvm
kvm_intel 170181 14
kvm 554609 1 kvm_intel
irqbypass 13503 4 kvm,vfio_pci
3)验证BIOS里开启SR-IOV和Intel VT-d,Grub开启IOMMU生效方法如下:
[root@localhost ~]# cat /proc/cmdline | grep intel_iommu
BOOT_IMAGE=/vmlinuz-3.10.0-514.el7.x86_64 root=/dev/mapper/cl-root ro crashkernel=auto rd.lvm.lv=cl/root rd.lvm.lv=cl/swap rhgb quiet intel_iommu=on iommu=pt iommu.passthrough=1
[root@localhost ~]# dmesg | grep -e IOMMU
[ 0.000000] DMAR: IOMMU enabled
[ 0.064288] DMAR-IR: IOAPIC id 3 under DRHD base 0xfbffc000 IOMMU 0
[ 0.064289] DMAR-IR: IOAPIC id 1 under DRHD base 0xc7ffc000 IOMMU 1
[ 0.064290] DMAR-IR: IOAPIC id 2 under DRHD base 0xc7ffc000 IOMMU 1
BIOS里只开启SR-IOV,忘记开启Intel VT-d时只会打印:
[root@localhost ~]# dmesg | grep -e IOMMU
[ 0.000000] DMAR: IOMMU enabled
并且创建虚拟机添加“–hostdev=xxxx”参数,创建SR-IOV虚拟网卡时会报错如下:
ERROR unsupported configuration: host doesn’t support passthrough of host PCI devices
4)验证vfio加载正常:
[root@localhost ~]# lsmod | grep vfio
vfio_iommu_type1 17632 1
vfio_pci 36948 1
vfio 26136 5 vfio_iommu_type1,vfio_pci
irqbypass 13503 4 kvm,vfio_pci
注意:重启后“lsmod | grep vfio”并不会有显示,只有虚拟机创建后才会加载启动vfio,看到显示。
三、生成VF虚拟网卡
1、查看并启动网卡
[root@localhost ~]# lspci | grep net
07:00.0 Ethernet controller: Intel Corporation I210 Gigabit Network Connection (rev 03)
08:00.0 Ethernet controller: Intel Corporation I210 Gigabit Network Connection (rev 03)
83:00.0 Ethernet controller: Intel Corporation I350 Gigabit Network Connection (rev 01)
83:00.1 Ethernet controller: Intel Corporation I350 Gigabit Network Connection (rev 01)
88:00.0 Ethernet controller: Intel Corporation 82599ES 10-Gigabit SFI/SFP+ Network Connection (rev 01)
88:00.1 Ethernet controller: Intel Corporation 82599ES 10-Gigabit SFI/SFP+ Network Connection (rev 01)
注:I210不支持SR-IOV,I350千兆、82599万兆支持SR-IOV。
2、查看网卡所支持分配的VF数量(将接口名称改为自己机器上的网卡)
[root@localhost ~]# cat /sys/class/net/enp7s0/device/sriov_totalvfs
cat: /sys/class/net/enp7s0/device/sriov_totalvfs: No such file or directory
[root@localhost ~]#
[root@localhost ~]# cat /sys/class/net/enp133s0f0/device/sriov_totalvfs
7
[root@localhost ~]# cat /sys/class/net/ens14f0/device/sriov_totalvfs
63
3、创建VF虚拟网卡
[root@localhost ~]# echo 2 > /sys/class/net/ens14f0/device/sriov_numvfs
[root@localhost ~]# echo 2 > /sys/class/net/ens14f1/device/sriov_numvfs
[root@localhost ~]#
[root@localhost ~]# lspci | grep net
88:00.0 Ethernet controller: Intel Corporation 82599ES 10-Gigabit SFI/SFP+ Network Connection (rev 01)
88:00.1 Ethernet controller: Intel Corporation 82599ES 10-Gigabit SFI/SFP+ Network Connection (rev 01)
88:10.0 Ethernet controller: Intel Corporation 82599 Ethernet Controller Virtual Function (rev 01)
88:10.1 Ethernet controller: Intel Corporation 82599 Ethernet Controller Virtual Function (rev 01)
88:10.2 Ethernet controller: Intel Corporation 82599 Ethernet Controller Virtual Function (rev 01)
88:10.3 Ethernet controller: Intel Corporation 82599 Ethernet Controller Virtual Function (rev 01)
注:带Virtual Function的就是创建出的虚拟VF网卡,前面是其总线信息。
4、使用IP工具给创建好的VF配置MAC地址
[root@localhost ~]# ip link set ens14f0 vf 0 mac e4:11:22:33:44:50
[root@localhost ~]# ip link set ens14f0 vf 1 mac e4:11:22:33:44:51
[root@localhost ~]#
[root@localhost ~]# ip link set ens14f1 vf 0 mac e4:11:22:33:44:60
[root@localhost ~]# ip link set ens14f1 vf 1 mac e4:11:22:33:44:61
5、查看虚拟接口VF及配置MAC
[root@localhost ~]# ip link show ens14f0
12: ens14f0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
link/ether 00:90:0b:45:ee:a2 brd ff:ff:ff:ff:ff:ff
vf 0 MAC e4:11:22:33:44:50, spoof checking on, link-state auto, trust off
vf 1 MAC e4:11:22:33:44:51, spoof checking on, link-state auto, trust off
[root@localhost ~]#
[root@localhost ~]# ip link show ens14f1
13: ens14f1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
link/ether 00:90:0b:45:ee:a3 brd ff:ff:ff:ff:ff:ff
vf 0 MAC e4:11:22:33:44:60, spoof checking on, link-state auto, trust off
vf 1 MAC e4:11:22:33:44:61, spoof checking on, link-state auto, trust off
6、查看PF与VF对应关系
脚本内容如下:
[root@localhost gao]# cat pf-vf
echo "physfn is $1"
echo "pf info:"
ls /sys/class/net/$1 -l
echo "vf info:"
eth_dev=`ls /sys/class/net/$1/device/virtfn* -l | cut -d ">" -f 2 |cut -d "/" -f 2`
for i in $eth_dev; do echo "`ls /sys/bus/pci/devices/$i/net` --> $i"; done
执行结果如下:
[root@localhost gao]# ./pf-vf enp133s0f1
physfn is enp133s0f1
pf info:
lrwxrwxrwx. 1 root root 0 Mar 8 14:06 /sys/class/net/enp133s0f1 -> …/…/devices/pci0000:80/0000:80:02.1/0000:85:00.1/net/enp133s0f1
vf info:
ls: cannot access /sys/bus/pci/devices/0000:85:10.1/net: No such file or directory
–> 0000:85:10.1
enp133s16f5 --> 0000:85:10.5
enp133s17f1 --> 0000:85:11.1
enp133s17f5 --> 0000:85:11.5
enp133s18f1 --> 0000:85:12.1
enp133s18f5 --> 0000:85:12.5
enp133s19f1 --> 0000:85:13.1
注:千兆卡I350执行结果正常,万兆82599执行报错,原因是万兆/sys/bus/pci/devices/$i/下没有net目录,无法打印出接口名称,且ifconfig能看到千兆注册的VF接口名,万兆看不到;
[root@localhost gao]# ./pf-vf ens14f0
physfn is ens14f0
pf info:
lrwxrwxrwx. 1 root root 0 Mar 8 14:06 /sys/class/net/ens14f0 -> …/…/devices/pci0000:80/0000:80:03.0/0000:88:00.0/net/ens14f0
vf info:
ls: cannot access /sys/bus/pci/devices/0000:88:10.0/net: No such file or directory
–> 0000:88:10.0
ls: cannot access /sys/bus/pci/devices/0000:88:10.2/net: No such file or directory
–> 0000:88:10.2
7、查看VF与PF对应关系
脚本内容如下:
[root@localhost gao]# cat vf-pf
$ cat vf-pf
echo "vf info:"
ls /sys/class/net/$1 -l
NAME=`ls /sys/class/net/$1/device/physfn/net/`
echo "pf info:"
echo "physfn is $NAME"
ls /sys/class/net/$NAME -l
执行结果如下:
[root@localhost gao]# ./vf-pf enp133s16f5
vf info:
lrwxrwxrwx. 1 root root 0 Mar 9 10:43 /sys/class/net/enp133s16f5 -> …/…/devices/pci0000:80/0000:80:02.1/0000:85:10.5/net/enp133s16f5
pf info:
physfn is enp133s0f1
lrwxrwxrwx. 1 root root 0 Mar 8 14:06 /sys/class/net/enp133s0f1 -> …/…/devices/pci0000:80/0000:80:02.1/0000:85:00.1/net/enp133s0f1
注:千兆卡I350执行结果正常,万兆82599无接口名无法执行,原因是万兆/sys/bus/pci/devices/$i/下没有net目录,无法ifconfig查看接口名称;
以上两个脚本在千兆和万兆上没有区分,需要修改优化。
四、使用SR-IOV虚拟网卡创建KVM虚拟机
1、创建磁盘镜像
qemu-img create /gao/vfw1.qcow2 20G
2、创建hostdev虚拟机
virt-install --virt-type kvm --name vfw1 --ram 10240 --vcpus 12 --cdrom=/gao/vfw-r.iso --disk /gao/vfw1.qcow2,format=qcow2 --network network=default --hostdev=88:10.1 --hostdev=88:10.2 --graphics vnc,listen=1.2.3.4,port=5911 --noautoconsole --os-type=linux --os-variant=rhel7
注:其中–hostdev指定为“lspci | grep net”显示带Virtual Function的创建出的虚拟VF网卡的总线信息,就是将VF分配给VM虚拟机使用了。
最终下发的device 参数如下:
[root@localhost ~]# ps -ax | grep qemu
/usr/libexec/qemu-kvm …
-device virtio-net-pci,netdev=hostnet0,id=net0,mac=52:54:00:0e:34:9d,bus=pci.0,addr=0x3
-device vfio-pci,host=88:10.1,id=hostdev0,bus=pci.0,addr=0x7
-device vfio-pci,host=88:10.2,id=hostdev0,bus=pci.0,addr=0x8
对应VM虚拟机配置文件如下:
cat /etc/libvirt/qemu/vfw1.xml
<interface type='network'>
<mac address='52:54:00:0e:34:9d'/>
<source network='default'/>
<model type='virtio'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
</interface>
......
<hostdev mode='subsystem' type='pci' managed='yes'>
<source>
<address domain='0x0000' bus='0x88' slot='0x10' function='0x1'/>
</source>
<address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x0'/>
</hostdev>
<hostdev mode='subsystem' type='pci' managed='yes'>
<source>
<address domain='0x0000' bus='0x88' slot='0x10' function='0x2'/>
</source>
<address type='pci' domain='0x0000' bus='0x00' slot='0x09' function='0x0'/>
</hostdev>
如上所示:管理口使用“network=default”默认网络,使用的是“‘virtio’”注册出来的是万兆口,并且默认创建桥virbr0并绑定对应宿主机虚拟口vnet0,可以新增绑定管理物理口也到virbr0,实现同网段管理虚拟机VM;–hostdev指定虚拟网卡VF总线信息为“lspci | grep net”显示带Virtual Function的创建出的虚拟VF网卡的总线信息,“address type”的总线信息为VM内部显示的PCI总线信息,如下:
[shell /root]$lspci | grep 0200
00:03.0 Class 0200: Device 8086:100e (rev 03)
00:07.0 Class 0200: Device 8086:10ed (rev 01)
00:08.0 Class 0200: Device 8086:10ed (rev 01)
00:09.0 Class 0200: Device 8086:10ed (rev 01)
00:0a.0 Class 0200: Device 8086:10ed (rev 01)
最终,运行虚拟机时/run/libvirt/qemu/vfw1.xml会根据/etc/libvirt/qemu/vfw1.xml生成。
五、修改KVM虚拟机配置
1、查看虚拟机配置文件
virsh list --all 查看所有虚拟机的名称,运行或未运行的;
virsh dumpxml name Name是虚拟机的名称;
2、编辑虚拟机配置文件(编辑之后需要重启虚拟机才会生效)
virsh edit name
SR-IOV的虚拟网卡 VF绑定到VM虚拟机的方法也可以直接修改XML文件,虚拟网卡VF总线信息指定为“lspci | grep net”显示带Virtual Function的创建出的虚拟VF网卡的总线信息,“address type”的总线信息为VM内部显示的总线信息,按照前后顺序指定排序即可,修改“/etc/libvirt/qemu/xxx.xml”增加如下内容:
<hostdev mode='subsystem' type='pci' managed='yes'>
<source>
<address domain='0x0000' bus='0x85' slot='0x10' function='0x0'/>
</source>
<address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/>
</hostdev>
修改管理口默认网络绑定桥的方法如下:
<interface type='bridge'> 修改接口类型为桥
<mac address='52:54:00:0e:34:9d'/>
<source bridge='br0'/> 修改绑定到哪个桥口
<model type='e1000'/> 修改注册的虚接口类型
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
</interface>
注:XML配置文件编辑之后必须先virsh define后再重启虚拟机才会按新配置启动生效,否则还是按照/run/libvirt/qemu/下的旧配置启动。
3、根据配置文件定义虚拟机
virsh define /etc/libvirt/qemu/xxx.xml
注:此处必须带XML配置文件的全路径才可以成功,Libvirsh虚拟机的配置文件默认路径为/etc/libvirt/qemu/,virsh define执行后/run/libvirt/qemu/xxx.xml会根据/etc/libvirt/qemu/xxx.xml重新生成。
4、先正常关机
virsh shutdown name
注:无法正常关机就后台kill掉。
5、再按修改后配置启动kvm虚拟机生效
virsh start name
六、virsh 操作虚拟机常用命令
命令含义
virsh dumpxml name 查看虚拟机配置文件
virsh start name 启动kvm虚拟机
virsh console name 连接到虚拟机终端
virsh shutdown name 正常关机
virsh destroy name 非正常关机,相当于物理机直接拔掉电源
virsh undefine name 彻底删除,无法找回,如果想找回来,需要备份/etc/libvirt/qemu的xml文件
virsh define xx.xml 根据配置文件定义虚拟机
virsh suspend name 挂起,终止
virsh resume name 恢复挂起状态
virsh edit name 编辑虚拟机配置文件(编辑之后需要重启虚拟机才会生效)
virsh list 查看正在运行的虚拟机(在root账号或加sudo运行才能看到)
virsh list --all 查看所有虚拟机(在root账号或加sudo运行才能看到)
更多推荐
所有评论(0)