hbyve简介
自 FreeBSD 10.0-RELEASE 起,BSD 许可的 bhyve 虚拟机管理器已成为底层系统不可或缺的一部分。bhyve 强大而灵活,支持多种客户机操作系统,涵盖 FreeBSD、OpenBSD 以及多个 Linux® 发行版。在默认配置下,bhyve 提供对串行控制台的直接访问,无需模拟图形化界面,从而为用户提供了简洁而高效的交互方式。
安装使用bhyve
官网文档:Chapter 24. Virtualization | FreeBSD Documentation Portal
中文文档:24.6.使用 FreeBSD 上的 bhyve 虚拟机 — FreeBSD Handbook 2023.09.08 documentation (fiercex.github.io)
FreeBSD准备工作
若要支持bhyve,需要cpu支持,可以通过 /var/run/dmesg.boot 文件来查看,比如对AMD芯片需要支持POPCNT ,Inter芯片需要支持 EPT
和 UG
cat /var/run/dmesg.boot
显示如下:
Features2=0x7dfafbbf<SSE3,PCLMULQDQ,DTES64,MON,DS_CPL,VMX,EST,TM2,SSSE3,SDBG,F
MA,CX16,xTPR,PDCM,PCID,SSE4.1,SSE4.2,x2APIC,MOVBE,POPCNT,TSCDLT,XSAVE,OSXSAVE,AV
X,F16C,RDRAND>
AMD Features=0x2c100800<SYSCALL,NX,Page1GB,RDTSCP,LM>
AMD Features2=0x121<LAHF,ABM,Prefetch>
Structured Extended Features=0x21c27ab<FSGSBASE,TSCADJ,BMI1,AVX2,SMEP,BMI2,ERM
S,INVPCID,NFPUSG,RDSEED,ADX,SMAP,PROCTRACE>
XSAVE Features=0x1<XSAVEOPT>
VT-x: PAT,HLT,MTF,PAUSE,EPT,UG,VPID
可以看到cpu是支持POPCNT和EPT,UG
准备工作:加载 bhyve 内核模块
配置宿主机,首先,加载 bhyve 内核模块:
# kldload vmm
kldload vmm
kldstat
Id Refs Address Size Name
1 27 0xffffffff80200000 1f370e8 kernel
2 1 0xffffffff82138000 77d8 cryptodev.ko
3 1 0xffffffff82140000 5cd4d8 zfs.ko
4 1 0xffffffff831e5000 3250 ichsmb.ko
5 1 0xffffffff831e9000 2178 smbus.ko
6 1 0xffffffff83200000 33e438 vmm.ko
创建网络接口
然后,创建 tap
接口以供虚拟机中的网络设备进行连接。为了让该网络设备加入网络,另外创建一个桥接接口,其中包含 tap
接口和物理网络接口作为成员。在下面的例子中,物理网络接口为 igb0
:
# ifconfig tap0 create
# sysctl net.link.tap.up_on_open=1
net.link.tap.up_on_open: 0 -> 1
# ifconfig bridge0 create
# ifconfig bridge0 addm igb0 addm tap0
# ifconfig bridge0 up
一共5条指令:
ifconfig tap0 create
sysctl net.link.tap.up_on_open=1
ifconfig bridge0 create
ifconfig bridge0 addm igb0 addm tap0
ifconfig bridge0 up
做好这些准备工作,就可以开始配置客户机了。
创建一个FreeBSD客户机
可以创建一个单独的目录,比如~/bhyve ,将所有文件都放在这个目录里。
文档讲创建一个文件guest.img用作客户机的虚拟磁盘。指定这个虚拟磁盘的大小
truncate -s 16G guest.img
我们这里创建一个较小的客户机,名字也改成freebsd.img
truncate -s 10G freebsd.img
下载 FreeBSD 的安装镜像:
到中科大FreeBSD镜像站下载iso安装盘
wget https://mirrors.ustc.edu.cn/freebsd/releases/ISO-IMAGES/14.1/FreeBSD-14.1-BETA3-amd64-bootonly.iso
启动脚本
下面是一个启动 bhyve 虚拟机的示例命令,vmrun.sh是一个脚本,这个脚本将会启动虚拟机并循环执行,所以可在其崩溃时自动重新启动。这个脚本可接受数个选项来配置虚拟机:-c
控制虚拟 CPU 的数量,-m
限制客户机的可用内存,-t
定义使用的 tap 设备,-d
指定其使用的磁盘镜像,-i
控制 bhyve 从 CD 镜像引导,而非从磁盘引导,-I
指定要使用的 CD 镜像。最后一个参数是虚拟机的名称,该名称将被用来追踪运行中的虚拟机。这个例子将在安装模式下启动虚拟机:
sh /usr/share/examples/bhyve/vmrun.sh -c 1 -m 1024M -t tap0 -d guest.img -i -I FreeBSD-13.1-RELEASE-amd64-bootonly.iso guestname
具体我们的命令是: sh /usr/share/examples/bhyve/vmrun.sh -c 4 -m 1024M -t tap0 -d freebsd.img -i -I FreeBSD-14.1-BETA3-amd64-bootonly.iso testfreebsd
然后命令行下面,就看到FreeBSD启动的画面了
好久没有用无头机(没有安装显示器)安装系统了,vt100真亲切啊:
Console type [vt100]
虚拟硬盘是:vtbd0 VirtIO Block Device
后面就是按部就班的安装FreeBSD。安装好后,重启,结果还是从光盘启动。
只好kill掉,当然bhyve还有专门的指令:
bhyvectl --destroy --vm=testfreebsd
装机完成后再次开机
再次进入虚拟系统,这回就不挂载光盘了,手册命令:
sh /usr/share/examples/bhyve/vmrun.sh -c 4 -m 1024M -t tap0 -d guest.img guestname
实际执行命令:
sh /usr/share/examples/bhyve/vmrun.sh -c 4 -m 1024M -t tap0 -d freebsd.img testfreebsd
启动后进入了该服务器看一下:
uname -a
FreeBSD fb_bhyve 14.1-BETA3 FreeBSD 14.1-BETA3 releng/14.1-n267636-2a964a7fc34e GENERIC amd64
果然FreeBSD下用原生bhyve虚拟主机系统真的是简单又方便啊!
创建一个Linux虚拟机
要引导进入 FreeBSD 以外的系统,必须先安装 sysutils/grub2-bhyve。
pkg install grub2-bhyve
接下来,创建一个文件用作客户机的虚拟磁盘:
truncate -s 16G linux.img
手册里讲创建 device.map 文件,让 grub 将虚拟设备映射到宿主机上的镜像文件,文件内容:
(hd0) ./linux.img
(cd0) ./ubuntu-18.04.6-server-amd64.iso
当然实际上为了简单方便,device.map文件内容如下:
(hd0) ./linux.img
(cd0) ./debian.iso
下载linux安装盘
可以选择自己喜欢的linux发行版,比如可以选择ubuntu和dibian。
下载linux ubuntu安装盘:
wget https://mirrors.ustc.edu.cn/ubuntu-cdimage/releases/18.04.6/release/ubuntu-18.04.6-server-amd64.iso
下载linux debian安装盘:
wget https://mirrors.tuna.tsinghua.edu.cn/debian-cd/current/amd64/iso-cd/debian-12.5.0-amd64-netinst.iso
为了方便建立一个文件链接:
ln -s debian-12.5.0-amd64-netinst.iso debian.iso
这样不管是device.map文件里面,还是后面命令行里面,都不需要使用那么长的文件名了。
加载linux内核
使用 sysutils/grub2-bhyve 从 ISO 文件中加载 Linux® 内核,如果没有可以pkg安装:
pkg install grub2-bhyve
从 ISO 文件中加载 Linux® 内核
grub-bhyve -m device.map -r cd0 -M 1024M linuxguest
执行后进入光盘安装debian的选择界面,但是选了之后回车就退出了。刚开始不知道为什么会退出,还以为出问题了,其实就应该是这样。
如果没有进入光盘启动界面,就需要自己手工在grub里面输入boot:
grub> ls
(hd0) (cd0) (cd0,msdos1) (host)
grub> ls (cd0)/isolinux
boot.cat boot.msg grub.conf initrd.img isolinux.bin isolinux.cfg memtest
splash.jpg TRANS.TBL vesamenu.c32 vmlinuz
grub> linux (cd0)/isolinux/vmlinuz
grub> initrd (cd0)/isolinux/initrd.img
grub> boot
安装ubuntu linux
现在 Linux® 内核就加载完毕了,可以启动客户机,启动ubuntu安装:
bhyve -A -H -P -s 0:0,hostbridge -s 1:0,lpc -s 2:0,virtio-net,tap0 -s 3:0,virtio-blk,./linux.img -s 4:0,ahci-cd,./ubuntu-18.04.6-server-amd64.iso -l com1,stdio -c 4 -m 1024M linuxguest
当然最终我们是选择了安装dibian:
安装debian linux
bhyve -A -H -P -s 0:0,hostbridge -s 1:0,lpc -s 2:0,virtio-net,tap0 -s 3:0,virtio-blk,./linux.img -s 4:0,ahci-cd,./debian.iso -l com1,stdio -c 2 -m 1024M linuxguest
后面就是按部就班的安装过程了。
安装的时候可以设置软件包下载镜像,镜像源选了华为云。
mirrors.huaweicloud.com
安装debian完成后,选择重启机器,就会退出虚拟系统。
启动debian linux
每次启动之前,都要先加载内核:
grub-bhyve -m device.map -r hd0,msdos1 -M 1024M linuxguest
然后引导进入虚拟机:
bhyve -A -H -P -s 0:0,hostbridge -s 1:0,lpc -s 2:0,virtio-net,tap0 -s 3:0,virtio-blk,./linux.img -l com1,stdio -c 4 -m 1024M linuxguest
启动真是简洁明快啊,也就1-2秒就进入登录界面了:
rdmsr to register 0xcd on vcpu 0
wrmsr to register 0x140(0) on vcpu 0
wrmsr to register 0x140(0) on vcpu 1
wrmsr to register 0x140(0) on vcpu 2
wrmsr to register 0x140(0) on vcpu 3
rdmsr to register 0x34 on vcpu 1
rdmsr to register 0xc0011029 on vcpu 3
Unhandled ps2 mouse command 0xe1
/dev/vda1: clean, 36301/987360 files, 505236/3943936 blocks
Unhandled ps2 mouse command 0x88
rdmsr to register 0x64d on vcpu 0
Debian GNU/Linux 12 debian ttyS0
debian login: xxxx
Password:
Linux debian 6.1.0-21-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.90-1 (2024-05-03) x86_64
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
这样就可以进入debian愉快的玩耍拉!
持久化配置¶
要配置系统在启动时运行 bhyve 虚拟机,请对相应文件进行如下配置:
/etc/sysctl.conf
net.link.tap.up_on_open=1/etc/rc.conf
cloned_interfaces="bridge0 tap0" ifconfig_bridge0="addm igb0 addm tap0" kld_list="nmdm vmm"
安装bvm管理bhyve
为了更好的管理hbyve,我们可以安装bvm管理软件。bvm,是FreeBSD下的一个开源的虚拟机监控器(hypervisor),它使用FreeBSD的Capsicum沙箱框架提供安全性。
pkg install bvm
在第一次运行bvm --ls 的时候,会提示做哪些操作:
# bvm can't run, you need to add the following lines to /boot/loader.conf
vmm_load="YES"
if_bridge_load="YES"
if_tap_load="YES"
# In order to help you solve the NAT reflow problem,
# you need to add the following line to /boot/loader.conf
ipfw_load="YES"
ipfw_nat_load="YES"
libalias_load="YES"
net.inet.ip.fw.default_to_accept=1
# please edit '/usr/local/etc/bvm/bvm.conf' first
vmdir=/your/vm/dir/path/
也就是最主要的是先编辑/usr/local/etc/bvm/bvm.conf文件,加入vmdir目录配置。然后再将上面配置语句写入/boot/loader.conf文件中。
使用bvm创建虚拟机
bvm --create Node-1
会问很多问题,就用数字回答就行
Welcome to Bhyve Vm Manager
---------------------------
Enter os type:
[0]. FreeBSD
[1]. OpenBSD
[2]. NetBSD
[3]. Debian
[4]. Debian_LVM
[5]. Ubuntu
[6]. Kali
[7]. CentOS
[8]. openSUSE
[9]. openSUSE_LVM
[a]. Gentoo
[b]. Fedora
[c]. TrueOS
[d]. Windows10
[e]. WinServer2016
[f]. pfSense
[g]. OPNsense
[h]. Other
Enter os type: 5
Enter vm CPUs: 2
Enter vm RAM (e.g. 512m): 512M
Enter cd status:
[0]. on
[1]. off
Enter cd status: 0
Enter iso path for CD-ROM: /root/bhyve
Enter a iso file:
[0]. debian.iso
[1]. ubuntu.iso
[2]. FreeBSD-14.1-BETA3-amd64-bootonly.iso
[3]. ubuntu-18.04.6-server-amd64.iso
[4]. debian-12.5.0-amd64-netinst.iso
Enter a iso file: 1
Enter boot from:
[0]. cd0
[1]. hd0
Enter boot from: 0
Enter uefi type:
[0]. none
[1]. uefi
[2]. uefi_csm
Enter uefi type: 0
Enter hostbridge:
[0]. hostbridge
[1]. amd_hostbridge
Enter hostbridge: 0
Enter auto booting:
[0]. no
[1]. yes
Enter auto booting: yes
input invalid
[0]. no
[1]. yes
Enter auto booting: 1
Enter booting sequence index (1~1000): 10
Enter booting estimate time (1~1000 secs.): 10
[0]. name : Node-1
[1]. os : Ubuntu
[2]. cpus : 2
[3]. ram : 512m
[4]. CD : on
[5]. iso path : /root/bhyve/ubuntu.iso
[6]. boot from : cd0
[7]. uefi type : none
[8]. hostbridge : hostbridge
[9]. auto boot : yes
[a]. boot index : 10
[b]. boot time : 10
[c]. disk config
[d]. network config
[e]. cancel
Enter an number to edit or 'ok' to complet: c
Enter vm number of disks: 1
Enter vm disk(0) size (e.g. 5g): 10g
Enter ZFS support:
[0]. on
[1]. off
Enter ZFS support: on
input invalid
[0]. on
[1]. off
Enter ZFS support: 0
Enter zpool:
[0]. zroot/ROOT/default
[1]. zroot/tmp
[2]. zroot/home
[3]. zroot/usr/src
[4]. zroot/usr/ports
[5]. zroot/var/log
[6]. zroot
[7]. zroot/var/audit
[8]. zroot/var/crash
[9]. zroot/home/skywalk
[a]. zroot/var/mail
[b]. zroot/var/tmp
Enter zpool: 0
Enter storage interface:
[0]. SATA hard-drive [ahci-hd]
[1]. Virtio block storage interface [virtio-blk]
Enter storage interface: 1
[0]. disk number : 1
[1]. disk(0) size : 10g
[2]. ZFS support : on
[3]. ZFS pool : zroot/ROOT/default
[4]. interface : virtio-blk
[5]. go back
Enter an number: 5
---------------------------
[0]. name : Node-1
[1]. os : Ubuntu
[2]. cpus : 2
[3]. ram : 512m
[4]. CD : on
[5]. iso path : /root/bhyve/ubuntu.iso
[6]. boot from : cd0
[7]. uefi type : none
[8]. hostbridge : hostbridge
[9]. auto boot : yes
[a]. boot index : 10
[b]. boot time : 10
[c]. disk config
[d]. network config
[e]. cancel
Enter an number to edit or 'ok' to complet: d
Enter vm number of nics: 1
Enter nic-0 network mode:
[0]. Bridged
[1]. NAT
Enter nic-0 network mode: 0
Select the binding device:
[0]. igb0
[1]. switch0 10.0.1.0/24
[2]. switch1 10.0.2.0/24
[3]. switch2 10.0.3.0/24
[4]. switch3
[5]. switch4
[6]. switch5
[7]. switch6
[8]. switch7
Select the binding device: 0
Enter IP-Address:
[0]. none
[1]. dhcp
[2]. static
Enter IP-Address: 1
Enter network interface:
[0]. Intel e82545 network interface [e1000]
[1]. Virtio network interface [virtio-net]
Enter network interface: 1
[0]. NIC numbers : 1
[1]. nic-0 mode : Bridged
[2]. nic-0 bind : igb0
[3]. nic-0 ip : dhcp
[4]. interface : virtio-net
[5]. add a nic
[6]. go back
Enter an number: 6
---------------------------
[0]. name : Node-1
[1]. os : Ubuntu
[2]. cpus : 2
[3]. ram : 512m
[4]. CD : on
[5]. iso path : /root/bhyve/ubuntu.iso
[6]. boot from : cd0
[7]. uefi type : none
[8]. hostbridge : hostbridge
[9]. auto boot : yes
[a]. boot index : 10
[b]. boot time : 10
[c]. disk config
[d]. network config
[e]. cancel
Enter an number to edit or 'ok' to complet: ok
创建好就可以启动了
开始启动bvm虚拟机
bvm --start Node-1
启动之后,可以用bvm --ls 看到状态信息:
bvm --ls
NAME GUEST CPU MEMORY DISK STATE
Node-1 Ubuntu 2 512M [1]10G on
可以使用bvm --login 登录虚拟机
bvm --login Node-1
然后就可以在命令行下开始装机拉!
其它bvm指令
关机命令:
bvm --poweroff Node-1
复制虚拟机,使用
bvm --clone Node-1 Node-2
如果虚拟机被关机挂住,可以ps找到进程kill掉
ps -aux |grep bvm
root 8525 0.0 0.0 13184 2696 0 I+ 09:48 0:00.00 bvm --login Node-1
root 9117 0.0 0.0 12808 2384 1 S+ 10:09 0:00.00 grep bvm
root 8430 0.0 0.0 13184 2700 2 Is+ 09:47 0:00.01 bvmb Node-1
root 9020 0.0 0.0 13184 2708 3 Ss+ 10:08 0:00.01 bvmb Node-2
root@fbhost:~/bhyve # kill 8430
总结
FreeBSD原生的bhyve虚拟机管理系统兼容性好、高效稳定、自动化程度高,全部操作都可以在命令行下搞定,非常适合大规模云计算环境使用。同时也非常适合配置较低的机器使用。比如这台服务器是j9000芯片+8G内存+32G Mini 硬盘,却可以同时开3个虚拟机,如果用ESxi虚拟的话,这个配置可能都达不到ESXi的安装需求,更不要说开虚拟机了。
bvm拥有直观的交互界面,即使完全不懂bhyve的初学者也能轻松上手,很快就创建出虚拟机子系统。bvm还有克隆功能,可以快速创建多个虚拟机系统。
调试
linux ubuntu客户端grub-bhyve启动安装之后退出
使用 sysutils/grub2-bhyve 从 ISO 文件中加载 Linux® 内核:
grub-bhyve -m device.map -r cd0 -M 1024M linuxguest
可以看到出来选择界面了:
+--------------------------------------------------------------------+
|Install Ubuntu Server |
|OEM install (for manufacturers) |
|Install MAAS Region Controller |
|Install MAAS Rack Controller |
|Check disc for defects |
|Rescue a broken system |
|Boot and Install with the HWE kernel |
但是选了选项之后就会退出。
想明白了,这里就应该退出啊,退出之后就可以下一步启动虚拟机了啊
有的设备grub-bhyve启动后进入grub没有光盘
grub> ls
(hd0) (host)
原来是device.map文件里面的光盘路径写错了
设置grub-bhyve启动设置更多内存报错
grub-bhyve -m device.map -r cd0 -M 2024M linuxguest
Could not setup memory for VM
Error in initializing VM
发现只能设为1024,设为其它值就报错。
原来是grub-bhyve设置一次后,后面再设为其它数值就会报错。要启动一次虚拟机之后,才能重新设置。
bhyve启动linux虚拟报错No such file or directory
bhyve -A -H -P -s 0:0,hostbridge -s 1:0,lpc -s 2:0,virtio-net,tap0 -s 3:0,virtio-blk,./linux.img \ > -s 4:0,ahci-cd,./debian-12.5.0-amd64-netinst.iso -l com1,stdio -c 4 -m 1024M linuxguest bhyve: Could not open backing file: ./debian-12.5.0-amd64-netinst.iso : No such file or directory Device emulation initialization error: No such file or directory root@fbhost:~/bhyve # sh: turning off NDELAY mode
问题是文件在的啊
把命令里面的空格以及不该有的字符都重新处理一下,问题解决
原来/debian-12.5.0-amd64-netinst.iso后面多了一些字符导致的,从手册cp过来的时候有个 \ 换行符,在删掉换行符的时候留多了空格或tab等其它字符(试了空格不会影响,应该是手册里命令带的tab符号的干扰)。
bhyve启动linux虚拟报错could not activate CPU 0: Device busy
执行命令:
bhyve -A -H -P -s 0:0,hostbridge -s 1:0,lpc -s 2:0,virtio-net,tap0 -s 3:0,virtio-blk,./linux.img -s 4:0,ahci-cd,./ubuntu-18.04.6-server-amd64.iso -l com1,stdio -c 4 -m 1024M linuxguest
报错改了,变成:bhyve: could not activate CPU 0: Device busy
从网上搜索,没有搜到类似的问题。cpu0被占用,真的找不到解决方法,曾一度怀疑是j1900cpu的问题。后来才知道,可能是前面实验的时候占用了cpu,用命令清一下即可:
bhyvectl --destroy --vm=linuxguest
加载linux内核报错Could not reinit VM linuxguest
grub-bhyve -m devicedebian.map -r cd0 -M 1024M linuxguest
Could not reinit VM linuxguest
Error in initializing VM
这就证明加载成功了,不能再重复加载了。
报错linux虚拟机报Abort trap
~/bhyve # bhyve -A -H -P -s 0:0,hostbridge -s 1:0,lpc -s 2:0,virtio-net,tap0 -s 3:0,virtio-blk,./linux.img -s 4:0,ahci-cd,./debian.iso -l com1,stdio -c 2 -m 1024M linuxguest
vm exit[0]
reason VMX
rip 0x0000000000000000
inst_length 0
status 0
exit_reason 33 (VM-entry failure due to invalid guest state)
qualification 0x0000000000000000
inst_type 0
inst_error 0
Abort trap
不明白什么原因,反正只要前面步骤对,bhyve就不会出这些乱七八糟的报错。
bvm启动报错can't create Bridged
bvm --start Node-1
can't create Bridged
原来是创建Bridge的时候,错选了实体0号网卡。需要选择虚拟的1-3号网卡。
bvm --config Node-1 进入配置后,重新设置使用1号网卡,在启动,就正常了
bvm启动报错duplicate session: Node-1
bvm --start Node-1
duplicate session: Node-1
ps发现有个bvm的进程,kill掉就好了
root@fbhost:~/bhyve # ps -aux |grep bvm
root 8381 0.0 0.0 12808 2372 0 S+ 09:47 0:00.00 grep bvm
root 5625 0.0 0.0 13184 2692 3 Is+ 23:20 0:00.01 bvmb Node-1
kill 5625