1. 构建 KVM 环境
KVM 从诞生开始就需要硬件虚拟化的支持,KVM 必需的硬件虚拟化扩展分别是:Intel 的虚拟化技术(Intel VT)和 AMD 的 AMD-V 技术。首先处理器(CPU)要在硬件上支持VT 技术,还要在BIOS 中将其功能打开,KVM才能使用到。目前,多数流行的服务器和部分桌面处理器的 BIOS 都默认将 VT 打开了。
1.1 初始化操作系统
本次安装系统为: CentOS 7 x64
查看 CPU 是否支持虚拟化:
[[email protected] ~]#lscpu Architecture: x86_64 CPU op-mode(s): 32-bit, 64-bit Byte Order: Little Endian CPU(s): 4 On-line CPU(s) list: 0-3 Thread(s) per core: 1 Core(s) per socket: 1 Socket(s): 4 NUMA node(s): 1 Vendor ID: GenuineIntel CPU family: 6 Model: 60 Model name: Intel Core Processor (Haswell) Stepping: 1 CPU MHz: 2397.222 BogoMIPS: 4794.44 Virtualization: VT-x Hypervisor vendor: KVM Virtualization type: full L1d cache: 32K L1i cache: 32K L2 cache: 4096K NUMA node0 CPU(s): 0-3
lscpu 能够查看当前主机是否开启虚拟化功能,通过上面信息得知:
CPU 型号:英特尔核心处理器
核心:4
虚拟化技术:VT-x
由于上面是通过 KVM 虚拟机,可以看到 Hypervisor vendor: KVM
确认模块是否加载
[[email protected] ~]#lsmod | egrep kvm kvm_intel 162153 0 kvm 525259 1 kvm_intel [[email protected] ~]#ls /dev/kvm /dev/kvm
/dev/kvm 是 kvm 内核模块提供给用户空间 qemu-kvm 程序使用的一个控制接口,它提供了客户机(Guest)操作系统运行所需要的模拟和实际的硬件设备环境。
1.2 安装 qemu-kvm
CentOS 7 本地yum 就直接对 qemu-kvm 提供支持。
[[email protected] ~]#yum list all | egrep qemu-kvm qemu-kvm.x86_64 10:1.5.3-105.el7 @yum qemu-kvm-common.x86_64 10:1.5.3-105.el7 @yum qemu-kvm-tools.x86_64 10:1.5.3-105.el7 yum [[email protected] ~]#yum install qemu-kvm -y [[email protected] ~]#ln -vs /usr/libexec/qemu-kvm /usr/bin/ ‘/usr/bin/qemu-kvm’ -> ‘/usr/libexec/qemu-kvm’
1.3 启动一个 kvm 虚拟机
这里使用 cirros 系统作为镜像文件直接启动,下载地址:http://download.cirros-cloud.net/
[[email protected] ~]#qemu-kvm -smp 1 -m 512m /images/cirros-0.3.5-i386-disk.img VNC server running on `::1:5900' -smp 指定cpu的核心数 -m 指定内存的大小
启动完成,默认是以 VNC 的方式可以连接到控制台
通过 “Ctrl + Alt + 2” 切换到 QEMU 监视器窗口,在监视器窗口中可以执行一些命令,比如:info kvm 查看当前 QEMU 是否使用 KVM
通过 “Ctrl + Alt + 1” 切换到普通的客户机命令行模式。
这样一个普通的虚拟机就创建完毕,但是这依然无法正常提供服务。
2. KVM 核心基础功能
KVM 采用完全虚拟化(Full Virtualization)技术,在KVM环境中运行的客户机(Guest)操作系统是未经过修改的普通操作系统。在硬件虚拟化技术的支持下,内核的KVM模块和 QEMU 的设备模拟协同工作,就构成了一整套与物理计算机系统完全一致的虚拟化的计算软硬件系统。要运行一个完整的计算机系统,必要的子系统:处理器、内存、存储、网络、显示等。
通过 qemu-kvm 可以创建一个基础的虚拟机,在使用 qemu-kvm 时,不一定需要超级用户(root)来操作,但是需要让当前用户对 /dev/kvm 这个接口具有可读可写的权限。另外,在涉及网络配置、设备分配时,仍然需要 root 权限。如果使用 qemu-kvm 命令行创建虚拟机,默认是开启了对 KVM 的支持,可以通过在 QEMU monitor(Ctrl+Alt+2)中执行 info kvm 命令查看是否显示 "kvm support: enabled" ,如果没有开启,则在创建时,需要使用: qemu-kvm -enable-kvm
2.1 CPU 配置
在 QEMU-KVM中,QEMU 提供对 CPU 的模拟,展现给客户机一定 CPU 数目和 CPU 的特性;在kvm开启的情况下,客户机中 CPU 指令的执行由硬件处理器的虚拟化功能来辅助执行,具有非常高的执行效率。
2.1.1 Vcpu 概念
QEMU/KVM 为客户机提供了一整套的硬件系统环境,在客户机看来其所拥有的 CPU 即是 vCPU(Virtual cpu)。在 KVM 环境中,每个客户机都是一个标准的 Linux 进程(QEMU 进程),而每一个 vCPU 在宿主机中是 QEMU 进程派生的一个普通线程。在 虚拟化基础 里已经提出过这个概念。
在普通的 Linux 系统中,进程一般有两种执行模式:内核模式和用户模式。而在 kvm 环境中,增加了第三种模式:客户模式。vCPU 在三种执行模式下的不同分工:
(1)用户模式(User mode)
主要处理 I/O 的模拟和管理,由 QEMU 的代码实现;
(2)内核模式(Kernel mode)
这里的 内核模式 是 GuestOS 内核模式,主要处理特别需要高性能和安全相关的指令,如处理客户模式到内核模式的转换,处理客户模式下 I/O 指令或其他特权指令引起的退出(VM-Exit),处理影子内存管理(shadow MMU);
(3)客户模式(Guest mode)
主要执行 Guest 中的大部分指令, I/O 和一些特权指令除外。
在系统的底层 CPU 硬件中需要有硬件辅助虚拟化技术的支持(Intel VT 或 AMD-V),宿主机就运行在硬件之上,KVM 的内核部分是作为可动态加载内核模块运行在宿主机中的,其中一个模块是和硬件无关的实现虚拟化核心基础架构的kvm模块,另一个是硬件平台相关的 kvm_intel(或 kvm_amd)模块。而 KVM 中的一个客户机是作为一个用户空间进程(qemu-kvm)运行的,它和其他普通的用户空间进程一样由内核来调度使其运行在物理 cpu 上,不过它由 KVM 模块的控制,可以在前面介绍的三种模式下运行。
2.1.2 kvm 支持的 CPU 模型
通过如下命令可以查看 qemu-kvm 支持的 CPU 类型:
[[email protected] ~]#qemu-kvm -cpu ?
当不加 "-cpu" 参数启动时,采用 "qemu64" 作为默认的 CPU 模型,演示如下:
[[email protected] ~]#qemu-kvm /images/cirros-0.3.5-i386-disk.img -nographic ... ... # cat /proc/cpuinfo processor : 0 vendor_id : AuthenticAMD cpu family : 6 model : 13 model name : QEMU Virtual CPU version 1.5.3 stepping : 3 microcode : 0x1000065 cpu MHz : 3400.000 cache size : 512 KB fdiv_bug : no hlt_bug : no f00f_bug : no coma_bug : no fpu : yes fpu_exception : yes cpuid level : 4 wp : yes flags : fpu de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 syscall nx lm up pni cx16 hypervisor lahf_lm abm sse4a vmmcall bogomips : 6800.00 clflush size : 64 cache_alignment : 64 address sizes : 43 bits physical, 48 bits virtual
客户机中的 cpu mode: QEMU Virtual CPU version 1.5.3 这就是当前版本 QEMU 的 qemu64 cpu模型的名称。在 QEMU 命令行,可以用 "-cpu mode" 来指定 客户机中 cpu 模型,一般使用 "-cpu host"来指定客户机中的cpu,表示将宿主机cpu的所有功能映射到客户机中。
[[email protected] ~]#egrep "model name" /proc/cpuinfo # 宿主机中cpu类型 model name : AMD Ryzen 5 2600 Six-Core Processor model name : AMD Ryzen 5 2600 Six-Core Processor model name : AMD Ryzen 5 2600 Six-Core Processor model name : AMD Ryzen 5 2600 Six-Core Processor [[email protected] ~]#qemu-kvm -cpu host /images/cirros-0.3.5-i386-disk.img -nographic ... ... # egrep "model name" /proc/cpuinfo # 客户机中 cpu 类型 model name : AMD Ryzen 5 2600 Six-Core Processor
2.1.3 进程的 cpu 亲和性和 vcpu 绑定
通常在 smp 系统中, Linux 内核的进程调度器根据自有的调度策略将系统中的一个进程调度到某个 CPU 上执行。一个进程在前一个执行时间是在 cpuM(M为系统中的某 CPU 的 ID)上运行,而在后一个执行时间是在 cpuN上运行。这样的情况在 Linux 中是很常见的,因为 Linux 对进程执行的调度采用时间片法则(即用完自己时间片立即暂停执行),而在默认情况下,一个普通进程或线程的处理器亲和性体现在所有可用的 cpu 上,进程或线程有可能在这些 CPU 之中的任何一个上执行。
cpu 亲和性的设置,是指将进程绑定到特定的一个或多个 CPU 上去执行,而不允许将进程调度到其他的 cpu 上。Linux 内核对进程的调度算法也是遵守进程的处理器亲和性设置的。
设置亲和性带来的好处是:可以减少进程在多个 cpu 之间切换运行带来的缓存命中失效(cache missing),从该进程运行的角度来看,可能性能得到了一定程度上的提升。
设置亲和性带来的坏处是:破坏了原有 SMP 系统中各个 cpu 的负载均衡(load balance),可能会导致整个系统的进程调度变得低效。
每个vcpu都是宿主机中一个普通的qemu线程,可以使用 taskset 工具对其设置处理器亲和性,使其绑定到某一个或几个固定的 CPU 上去调度。尽管 Linux 内核的进程调度算法已经很高效,在多数情况下不需要手工干预,不过,在虚拟化环境中有时必要将客户机的 QEMU 进程或线程绑定到固定的逻辑 cpu 上。
第一步,隔离宿主机的两个逻辑 CPU 专门供一个客户机使用
1. 修改 grub.cfg 配置并重启系统 [[email protected] ~]#vim /etc/default/grub ... GRUB_CMDLINE_LINUX="isolcpus=2,3 crashkernel=auto rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet" ... [[email protected] ~]#grub2-mkconfig -o /boot/grub2/grub.cfg Generating grub configuration file ... Found linux image: /boot/vmlinuz-3.10.0-327.el7.x86_64 Found initrd image: /boot/initramfs-3.10.0-327.el7.x86_64.img Found linux image: /boot/vmlinuz-0-rescue-c0b3d6ef598f4904bb1c5a67fbc8640d Found initrd image: /boot/initramfs-0-rescue-c0b3d6ef598f4904bb1c5a67fbc8640d.img done [[email protected] ~]#reboot 2. 检查是否生效 [[email protected] ~]#ps -eLo psr | egrep 0 | wc -l 259 [[email protected] ~]#ps -eLo psr | egrep 1 | wc -l 124 [[email protected] ~]#ps -eLo psr | egrep 2 | wc -l 5 [[email protected] ~]#ps -eLo psr | egrep 3 | wc -l 5 [[email protected] ~]#ps -eLo ruser,pid,ppid,lwp,psr,args | awk '{if($5==2){print $0}}' root 272 2 272 2 [watchdog/2] root 273 2 273 2 [migration/2] root 274 2 274 2 [ksoftirqd/2] root 275 2 275 2 [kworker/2:0] root 276 2 276 2 [kworker/2:0H] [[email protected] ~]#ps -eLo ruser,pid,ppid,lwp,psr,args | awk '{if($5==3){print $0}}' root 277 2 277 3 [watchdog/3] root 278 2 278 3 [migration/3] root 279 2 279 3 [ksoftirqd/3] root 280 2 280 3 [kworker/3:0] root 281 2 281 3 [kworker/3:0H]
通过上面配置,cpu0 和 cpu1 上分别有 259 和 124 个线程在运行,而 cpu2和cpu3上分别运行了5个线程:
(1)watchdog 监控系统运行状况,出现死锁,死机情况,能及时处理
(2)migration 用于进程在不同 CPU 间迁移
(3)两个 kworker 用于处理 workqueues
(4)ksoftirqd 进程 用于调度 CPU 软中断的进程
这些进程都是内核对各个 cpu 的一些守护进程,没有其他的普通进程运行在 cpu2 和 cpu3 上。
第二步,启动一个拥有两个 vcpu 的客户机并将其 vcpu 绑定到宿主机的两个 cpu 上。
# 启动一个客户机 [[email protected] ~]#qemu-kvm -smp 2 -m 512m /images/cirros-0.3.5-i386-disk.img -daemonize VNC server running on `::1:5900' [[email protected] ~]# # 查看代表 vcpu 的线程 [[email protected] ~]#ps -ef | egrep qemu-kvm root 2569 1 22 23:47 ? 00:00:06 qemu-kvm -smp 2 -m 512m /images/cirros-0.3.5-i386-disk.img -daemonize root 2587 1544 0 23:48 pts/0 00:00:00 grep -E --color=auto qemu-kvm [[email protected] ~]#ps -Tp 2569 PID SPID TTY TIME CMD 2569 2569 ? 00:00:00 qemu-kvm 2569 2573 ? 00:00:04 qemu-kvm 2569 2574 ? 00:00:00 qemu-kvm 2569 2576 ? 00:00:00 qemu-kvm
开启一个 2 cpu 的客户机,查看线程发现有 4 个线程,其中 一个主线程,2个vcpu线程,一个是I/O操作线程(参考:虚拟化基础部分)
通过 qemu monitor (Ctrl+Alt+2)可以查看 vcpu 是哪两个线程ID
# 绑定代表整个客户机的 QEMU 进程,使其运行在 CPU2 上 [[email protected] ~]#taskset -cp 2 2569 pid 2569's current affinity list: 0,1 pid 2569's new affinity list: 2 # 绑定 vcpu0 到 cpu2 [[email protected] ~]#taskset -cp 3 2573 pid 2573's current affinity list: 0,1 pid 2573's new affinity list: 3 # 绑定 vcpu1 到 cpu3 [[email protected] ~]#taskset -cp 3 2574 pid 2574's current affinity list: 0,1 pid 2574's new affinity list: 3 [[email protected] ~]#ps -eLo ruser,pid,ppid,lwp,psr,args | awk '{if($5==2){print $0}}' root 272 2 272 2 [watchdog/2] root 273 2 273 2 [migration/2] root 274 2 274 2 [ksoftirqd/2] root 275 2 275 2 [kworker/2:0] root 276 2 276 2 [kworker/2:0H] root 2569 1 2569 2 qemu-kvm -smp 2 -m 512m /images/cirros-0.3.5-i386-disk.img -daemonize root 2569 1 2573 2 qemu-kvm -smp 2 -m 512m /images/cirros-0.3.5-i386-disk.img -daemonize root 2795 2 2795 2 [kworker/2:1] [[email protected] ~]#ps -eLo ruser,pid,ppid,lwp,psr,args | awk '{if($5==3){print $0}}' root 277 2 277 3 [watchdog/3] root 278 2 278 3 [migration/3] root 279 2 279 3 [ksoftirqd/3] root 280 2 280 3 [kworker/3:0] root 281 2 281 3 [kworker/3:0H] root 2569 1 2574 3 qemu-kvm -smp 2 -m 512m /images/cirros-0.3.5-i386-disk.img -daemonize
总的来说,在KVM环境中,一般并不推荐手动设置 QEMU 进程的亲和性来绑定vcpu,但是,在非常了解系统硬件架构的基础上,根据实际应用的需求,可以将其绑定到特定的 cpu 上,从而提高客户机中的 CPU 执行效率或 cpu 资源独享的隔离性。
3. 内存配置
在通过 qemu 命令行启动客户机时设置内存大小的参数如下:
-m megs 设置客户机的内存大小为 megs 默认单位:MB 可以通过显式加单位如: 512m 1G
3.1 大页(Huge Page)
x86 架构的 cpu 默认使用 4KB大小的内存页面,但是它们也支持较大的内存页。Linux 2.6 及以上的内核都支持 huge page。如果在系统中使用 huge page,则内存页的数量会减少,从而需要更少的页表(page table),节约了页表所占用的内存数量,并且所需的地址转换也减少了,TLB缓存失效的次数也减少了,从而提高了内存访问的性能。另外,由于地址转换所需的信息一般保存在 CPU 的缓存中,huge page 的使用让地址转换信息减少,从而减少了CPU缓存的使用,减轻了cpu缓存的压力,让cpu缓存能更多的用于应用程序的数据缓存,也能够在整体上提升系统的性能。
在KVM中,也可以将 huge page 的特性应用到客户机中,qemu-kvm 就提供了 "-mem-path FILE" 参数选项用于使用 huge page。另外,还有一个参数 "-mem-prealloc" 可以让宿主机在启动客户机时就全部分配好客户机的内存,而不是在客户机实际用到更多内存时才按需分配。-mem-prealloc 必须在有 "-mem-path" 参数时才能使用。
提前分配好内存的好处:客户机的内存访问速度更快
提前分配好内存的缺点:客户机启动就得到了所有的内存,从而让宿主机的内存很快减少了。
为宿主机添加 huge page 支持:
(1)检查宿主机目前状态,检查了默认的内存大小和内存使用情况,如下: [[email protected] ~]#getconf PAGESIZE 4096 [[email protected] ~]#egrep -i hugepages /proc/meminfo AnonHugePages: 67584 kB HugePages_Total: 0 HugePages_Free: 0 HugePages_Rsvd: 0 HugePages_Surp: 0 Hugepagesize: 2048 kB 关于 huge page 几个参数的说明: HugePages_Total: Hugepage的页面数量 HugePages_Free: 剩余的页面数量 HugePages_Rsvd: 被分配预留但是还没有使用的page数目 HugePages_Surp:HugePages_Total减去/proc/sys/vm/nr_hugepages中的值(我对这个理解也不很清楚) Hugepagesize: 每单位数量大小 (2)挂载 hugetlbfs 文件系统,命令为 "mount -t hugetlbfs hugetlbfs /dev/hugepages",如下: [[email protected] ~]#mount -t hugetlbfs hugetlbfs /dev/hugepages (3)设置 huge page 的数量,命令为“sysctl vm.nr_hugepages=num”,如下: [[email protected] ~]#sysctl -w vm.nr_hugepages=1024 vm.nr_hugepages = 1024 [[email protected] ~]#egrep -i hugepages /proc/meminfo AnonHugePages: 67584 kB HugePages_Total: 1024 HugePages_Free: 1024 HugePages_Rsvd: 0 HugePages_Surp: 0 Hugepagesize: 2048 kB (4)启动客户机让其使用 hugepage 的内存,使用 "--mem-path" 参数,如下: [[email protected] ~]#qemu-kvm -smp 2 -m 1024m --mem-path /dev/hugepages/ --mem-prealloc /images/cirros-0.3.5-i386-disk.img VNC server running on `::1:5900' [[email protected] ~]#egrep -i hugepages /proc/meminfo AnonHugePages: 10240 kB HugePages_Total: 1024 HugePages_Free: 504 HugePages_Rsvd: 0 HugePages_Surp: 0 Hugepagesize: 2048 kB
查看宿主机中 huge page 的使用情况,可以看到 "HugePages_Free" 数量减少,因为客户机使用了一定数量的 hugepage,在创建中使用 "--mem-prealloc" 选项,因此大概上是 (512*2048) 刚好1G内存
至此,如果在客户机中运行的应用程序具备使用 huge page 的能力,那么就可以在客户机中使用 huge page 带来性能的提升。
总的来说,对于内存访问密集型的应用,在KVM客户机中使用 huge page 是可以较明显的提高客户机性能的,不过,它也有一个缺点,使用 huge page 的内存不能被换出(swap out),也不能使用 ballooning 方式自动增长。
4. 存储配置
QEMU 提供了对多种块存储设备的模拟,包括 IDE设备、SCSI设备、软盘、U盘、virtio磁盘等,而且对设备的启动顺序提供了灵活的配置。
(1)-had file
将file 镜像文件作为客户机中的第一个IDE设备(序号0),在客户机中表现为 /dev/hda 设备或者 /dev/sda 设备。
(2)详细配置存储驱动器的 -driver 参数来详细定义一个存储驱动器,该参数的具体形式如下:
file=file 使用file文件作为镜像文件加载到客户机的驱动器中。
if=interface 可用的类型有:ide、scsi、virtio 等等
cache=cache 设置宿主机对块设备数据(包括文件或一个磁盘)访问中的cache 情况,可以设置为 "none","writeback","writethrough" 等。 其默认值为 "writethrough",即“直写模式”,它是在调用 write写入数据的同时将数据写入磁盘缓存(disk cache)和后端块设备(block device)中,其优点是操作简单,其缺点是写入数据速度慢。而 "writeback" 即“回写模式”,在调用 write 写入数据时只将数据写入到磁盘缓存中即返回,只有在数据被换出缓存时才将修改的数据写到后端存储中,其优 点是写入数据速度较快,其缺点是一旦更新数据在写入后端存储之前遇到系统掉电,数据会无法恢复。
这两种方式在读取数据时尽量使用缓存,若设置了 "cache=none",关闭缓存。
aio=aio 选择异步 IO(Asynchronous IO)的方式,有 "threads" 和 "native" 两个值可选。其默认值为 "threads",即让一个线程池去处理异步IO;而 "native" 只适用于 "cache=none" 的情况,就是使用Linux 原生的 AIO
示例:使用qemu-kvm 创建虚拟机(磁盘部分)
qemu-kvm -cpu host -m 512m -drive file=/images/rhel6.img,if=virtio,cache=writeback -daemoize
4.1 qemu-img 命令的使用
qemu-img 是 QEMU 的磁盘管理工具,qemu-img 支持命令分为以下几种:
(1)check [-f fmt] filename
对磁盘镜像文件进行一致性检查,查找镜像文件的错误,目前仅支持"qcow2"、"qed"、"vdi" 格式文件检查。
(2)create [-f fmt][-o options] filename [size]
创建一个格式为 fmt,大小为size,文件名为 filename 的镜像文件。在使用 create 创建时,-f 选项指定要创建的格式(比如:qcow2), -o 选项可以指定大小,类型等。
[[email protected] ~]#qemu-img create -f qcow2 -o size=20G,preallocation=metadata cirros.qcow2 Formatting 'cirros.qcow2', fmt=qcow2 size=21474836480 encryption=off cluster_size=65536 preallocation='metadata' lazy_refcounts=off [[email protected] ~]#ll -tsh cirros.qcow2 4.1M -rw-r--r-- 1 root root 21G Jul 8 04:25 cirros.qcow2 preallocation='metadata' 支持稀疏文件格式,创建的文件时没有占用很多的块存储。
(3)info [-f fmt] filename
展示 filename 镜像文件信息。如果文件使用的是稀疏文件的存储方式,会显示出它本来分配的大小及实际占用的磁盘大小。如果文件中存放有客户机快照,快照信息也会被显示出来。
[[email protected] ~]#qemu-img info cirros.qcow2 image: cirros.qcow2 file format: qcow2 virtual size: 20G (21474836480 bytes) disk size: 4.1M cluster_size: 65536 Format specific information: compat: 1.1 lazy refcounts: false
(4)resize filename [+|-] size
改变镜像文件的大小,使其不同于创建之时的大小。缩小镜像的大小前,需要在客户机中保证其中的文件系统有空闲空间,否则会数据丢失,另外,qcow2 格式文件不支持缩小操作。
[[email protected] ~]#qemu-img info cirros.qcow2 image: cirros.qcow2 file format: qcow2 virtual size: 20G (21474836480 bytes) disk size: 4.1M cluster_size: 65536 Format specific information: compat: 1.1 lazy refcounts: false [[email protected] ~]#qemu-img resize +5G cirros.qcow2 qemu-img: Parameter 'size' expects a size [[email protected] ~]#qemu-img resize cirros.qcow2 +5G Image resized. [[email protected] ~]#qemu-img info cirros.qcow2 image: cirros.qcow2 file format: qcow2 virtual size: 25G (26843545600 bytes) disk size: 4.2M cluster_size: 65536 Format specific information: compat: 1.1 lazy refcounts: false
5. 网络配置
qemu-kvm 主要向客户机提供了 4 种不同模式的网络:
(1)基于网桥(bridge)的虚拟网卡;
(2)基于 NAT 的虚拟网络;
(3)QEMU 内置的用户模式网络(user mode networking);
(4)直接分配网络设备的网络(包括 VT-d 和 SR-IOV)
网络四种模式的实现请参考:四种简单的网络模型