一 QEMU介绍
QEMU是一套由法布里斯·贝拉(Fabrice Bellard)所编写的以GPL许可证分发源码的模拟处理器,在GNU/Linux平台上使用广泛。0.9.1及之前版本的qemu通过使用kqemu加速器能模拟至接近真实电脑的速度,在qemu1.0之后的版本,都无法使用kqemu,主要利用qemu-kvm加速模块,并且加速效果以及稳定性明显好于kqemu。
QEMU有两种主要运作模式:
* User mode模拟模式,亦即是用户模式。QEMU能启动那些为不同中央处理器编译的Linux程序。
* System mode模拟模式,亦即是系统模式。QEMU能模拟整个电脑系统,包括中央处理器及其他周边设备。它使得为跨平台编写的程序进行测试及除错工作变得容易。其亦能用来在一部主机上虚拟数部不同虚拟电脑。
更详细介绍请前往官方网址:QEMU
二 QEMU使用
针对QEMU的两种运作模式,分别介绍两种模式下的QEMU使用方法。
- 用户模式(User-mode emulation)
借助docker容器技术,这种方式的模拟器安装运行方便快捷,具体步骤如下:
- 下载qemu-$arch-static文件(下载地址 Releases · multiarch/qemu-user-static · GitHub),选择对应平台文件下载,如qemu-aarch64-static.tar.gz;
- 将文件解压,拷贝到目录 /usr/bin/ 下;
tar –zvxf qemu-aarch64-static.tar.gz
sudo cp qemu-aarch64-static /usr/bin/
chmod +x /usr/bin/qemu-aarch64-static
- 确定内核开启binfmt_misc,添加binfmt_misc文件;
docker run --rm --privileged multiarch/qemu-user-static:register –reset
- 运行模拟器
docker run -it -v /usr/bin/qemu-aarch64-static:/usr/bin/qemu-aarch64-static arm64v8/centos
- 系统模式 (System-mode emulation)
如果在宿主机上只安装了qemu-kvm的话,宿主机上只能运行X86构架的虚拟机,并能够利用kvm加速,并不能将arm指令翻译成X86指令运行。所有还需要安装qemu-system-aarch64,它提供了aarch64架构虚拟机在x86架构上的运行支持。
- 安装qemu
wget https://download.qemu.org/qemu-4.1.0.tar.xz
tar xvJf qemu-4.1.0.tar.xz
cd qemu-4.1.0
./configure
make
make install
- 固件下载
以前系统的启动过程可以简化为 BIOS固件—->引导程序—->操作系统,但是由于传统的BIOS启动方式存在许多问题,如bios运行在16位模式,寻址空间小,运行慢等,所以现在X86、ARM架构等架构都采用了改进的 UEFI 启动方式(当然会有兼容传统BIOS启动方式的考虑)。
- 用qemu命令创建虚拟硬盘
qemu-img create -f qcow2 arm-64.qcow2 50G
- qemu-system-aarch64命令光盘安装操作系统
qemu-system-aarch64 -m 2048 -cpu cortex-a72 -smp 8 -M virt -nographic -drive if=none,file=CentOS-7-aarch64-Everything-1810.iso,id=cdrom,media=cdrom -device virtio-scsi-device -device scsi-cd,drive=cdrom -drive if=none,file=arm-64.qcow2,id=hd0 -device virtio-blk-device,drive=hd0 -kernel ./vmlinuz -initrd ./initrd.img -bios QEMU_EFI.fd
- 安装过程
过程中按照提示选择安装即可。Qemu的详细使用方法参考官方说明文档:https://qemu.weilnetz.de/doc/qemu-doc.html。
Note:
安装过程中磁盘配置选择如下配置项 “1) Standard Partition”
- 虚拟机网络配置
首先提一个概念"桥接",网上各种说法,但自己的理解是:以一个物理网卡为基本硬件,创建一个虚拟的路由器(路由器的概念不用说了吧)。当虚拟机需分配IP地址时,创建一个临时的虚拟网卡,并将这个网卡连接到虚拟路由器上,虚拟网卡通过虚拟路由器从真实的DHCP端得到IP地址。
- 安装桥接软件
查看桥接软件是否安装 ,没有安装则安装
[root@HikvisionOS ~]# rpm -q bridge-utils
bridge-utils-1.5-9.el7.x86_64
- 配置桥接
- 添加一个桥设备br0
方法一:
# vi /etc/sysconfig/network-scripts/ifcfg-br0
DEVICE=br0
TYPE=Bridge
ONBOOT=yes
BOOTPROTO=dhcp //可根据实际情况设置静态IP也可
方法二:
brctl addbr br0
- 将br0与 enp65s0f1桥接
方法一:
# vi /etc/sysconfig/network-scripts/ifcfg-enp65s0f1
DEVICE="enp65s0f1"
BOOTPROTO="dhcp"
HWADDR="00:22:19:63:A7:F6"
IPV6INIT="no"
ONBOOT="yes"
BRIDGE=br0
方法二:
brctl addif br0 enp65s0f1
做完以上内容,重启网络服务
# service network restart
- 将br0与 tap0桥接
方法一:
在/etc目录下创建qemu-ifup文件:
# vim /etc/qemu-ifup
添加如下内容:
#!/bin/sh
set -x
switch=br0
if [ -n "$1" ];then
/usr/bin/sudo /usr/sbin/tunctl -u `whoami` -t $1
/usr/bin/sudo /sbin/ip link set $1 up
sleep 0.5s
/usr/bin/sudo /usr/sbin/brctl addif $switch $1
exit 0
else
echo "Error: no interface specified"
exit 1
fi
为了简单直接给予任何人对该文件的所有权限,否则虚拟机将还是无法分配到ip地址
#chmod 777 /etc/qemu-ifup
该文件的主要作用就是在启动虚拟机时,创建一个虚拟网络设备(tapN,N=0、1、2...可理解为一个网卡或者是路由器上的一个插口),并将该设备使用桥接控制工具brctl添加到switch(桥br0)上,可理解为在一个路由器上开了一个新的网线插口。
方法二:
dhclient br0
tunctl -b -u root –t tap0 // 虚拟机启动后会自动生成tap0,如果没有则用tunctl命令生成
ifconfig tap0 up
brctl addif br0 tap0
- 最后重启一下虚拟机的网络服务
# service network restart
- 启动虚拟机
qemu-system-aarch64 -m 2048 -cpu cortex-a72 -smp 8 -M virt -nographic -kernel ./vmlinuz -initrd ./initrd.img -hda arm-64.qcow2 -append "root=/dev/vda4" -bios QEMU_EFI.fd -netdev type=tap,ifname=tap0,id=net0,script=no,downscript=no -device virtio-net-device,netdev=net0,mac=52:54:00:12:34:56
注意,如果存在多台虚拟机,多台虚拟机的MAC地址不能相同,否则IP地址相同产生冲突,启动虚拟机时指定MAC地址即可。
三 性能参数
- CPU性能测试
采用sysbench对两种模式的虚拟机进行CPU的性能测试 (sysbench的安装和用法请阅读地址:GitHub - akopytov/sysbench: Scriptable database and system performance benchmark)。
测试命令:sysbench cpu --cpu-max-prime=20000 --threads=2 run。两种模式下的测试结果如下。
虚拟模式 CPU性能参数 | User-mode emulation | System-mode emulation |
CPU参数 | Architecture: aarch64 Byte Order: Little Endian CPU(s): 2 On-line CPU(s) list: 0,1 Thread(s) per core: 1 Core(s) per socket: 2 Socket(s): 1 NUMA node(s): 1 Vendor ID: GenuineIntel CPU family: 6 Model: 158 Model name: Intel(R) Core(TM) i5-7500 CPU @ 3.40GHz Stepping: 9 CPU MHz: 3408.149 NUMA node0 CPU(s): 0,1 | Architecture: aarch64 Byte Order: Little Endian CPU(s): 2 On-line CPU(s) list: 0,1 Thread(s) per core: 1 Core(s) per socket: 2 Socket(s): 1 NUMA node(s): 1 Vendor ID: ARM Model: 0 Model name: Cortex-A57 Stepping: r1p0 BogoMIPS: 125.00 NUMA node0 CPU(s): 0,1 Flags: fp asimd evtstrm aes pmull sha1 sha2 crc32 cpuid |
线程数 | 2 | 2 |
每个线程产生的素数上线 | 20000 | 20000 |
所有线程每秒完成的event | 138.14 | 220.52 |
共耗时时间(s) | 10.0115 | 10.0040 |
10秒内所有线程完成的event | 1383 | 2208 |
完成1次event最小耗时(ms) | 13.36 | 7.21 |
所有event平均耗时(ms) | 14.46 | 8.94 |
完成1次event最多耗时(ms) | 35.35 | 51.45 |
95%的event耗时时间(ms) | 15.00 | 15.55 |
平均每个线程完成的event/标准差 | 691.5000/4.50 | 1104.0000/10.00 |
每个线程平均耗时/标准差 | 9.9987/0.00 | 9.8696/0.03 |
3.2 系统资源消耗
3.2.1 用户模式
top - 18:30:57 up 20 min, 3 users, load average: 0.21, 0.55, 0.55
Tasks: 218 total, 1 running, 217 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 0.2 sy, 0.0 ni, 99.8 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 1863100 total, 141524 free, 925784 used, 795792 buff/cache
KiB Swap: 2097148 total, 2097140 free, 8 used. 756064 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
806 root 20 0 324492 6768 5276 S 0.3 0.4 0:11.18 vmtoolsd
1281 root 20 0 735548 80952 28140 S 0.3 4.3 0:06.44 dockerd
11831 root 20 0 0 0 0 S 0.3 0.0 0:00.03 kworker/0:0
11997 root 20 0 162152 2400 1580 R 0.3 0.1 0:00.13 top
1 root 20 0 128272 7004 4224 S 0.0 0.4 0:03.98 systemd
2 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kthreadd
4 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 kworker/0:0H
5 root 20 0 0 0 0 S 0.0 0.0 0:01.61 kworker/u256:0
6 root 20 0 0 0 0 S 0.0 0.0 0:03.42 ksoftirqd/0
3.2.2 系统模式
top - 18:35:54 up 14:03, 4 users, load average: 0.13, 0.16, 0.28
Tasks: 220 total, 2 running, 218 sleeping, 0 stopped, 0 zombie
%Cpu(s): 3.9 us, 7.6 sy, 0.0 ni, 88.6 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 3861360 total, 115616 free, 3179044 used, 566700 buff/cache
KiB Swap: 4064252 total, 3917052 free, 147200 used. 389400 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
36 root 25 5 0 0 0 R 14.3 0.0 94:17.52 ksmd
5795 root 20 0 4094532 2.6g 2640 S 9.0 71.4 138:59.87 qemu-system-aar
1368 root 20 0 727304 32060 3932 S 0.7 0.8 2:48.93 dockerd
363 root 20 0 0 0 0 S 0.3 0.0 0:11.80 xfsaild/sda3
1535 root 20 0 416108 97560 51836 S 0.3 2.5 0:52.66 X
2752 jersonb+ 20 0 3654128 395792 45704 S 0.3 10.3 1:50.12 gnome-shell
四 总结
从上面CPU的性能测试来看,系统模式下的CPU性能相比用户模式下的CPU性能稍好一些。但是从虚拟机的安装难度和学习成本方面来看,基于docker的用户模式则要方便快捷很多,同时模拟整机的系统模式虚拟机对主机的资源消耗太大,而用户模式下对主机的资源消耗则要小很多。
一方面从软件的安装部署上来看,基于docker的虚拟机模式有着先天的优势,DevOps和k8s等自动化运维工具不仅有助于开发人员部署维护各种软件应用,甚至还可以优化软件架构(如比较流行的微服务)。另一方面,有着强大功能和生态社区的docker跟被各种商业云系统所青睐(如容器云),借助云系统和docker有利于后续软件业务的拓展。
因此选择docker模式的虚拟机应成为我们国产化方向和开发模式的首选。