bhyve 存储
在 vm-bhyve 中,我使用了自定义模版来使用 sparse-zvol ,这样在ZFS vol卷块存储上构建的 bhyve虚拟化运行Ubuntu 可以用来实现FreeBSD不支持的功能。
我计划使用 FreeBSD Linux Jail 来作为基础OS,构建一个 LFS(Linux from scratch) ,但是如何创建一个Linux文件系统是一个问题: FreeBSD只支持对Linux文件系统的读写,但不能创建,所以我需要先在 bhyve虚拟化运行Ubuntu 中对 gpart实践(linux分区及zfs分区) 创建的 linux-data 分区进行文件系统构建。
bhyve 支持存储类型
bhyve 支持3种存储类型:
功能 |
|
|
|
|---|---|---|---|
技术 |
完全模拟标准SATA控制器,最古老和缓慢的虚拟磁盘类型 |
完全模拟通过PCIe连接的现代NVMe控制器 |
为虚拟环境设计的paravirtualized块设备驱动 |
性能 |
最慢,但是兼容性最好 |
对于 |
中间性能的存储类型,在高负载下性能不如 |
Guest系统支持 |
支持所有操作系统的古老且遗留标准存储 |
被Windows10+及大多数现代linux支持,是现代OS的最佳选择 |
需要Guest系统安装VirtIO驱动,Linux默认支持但Windows需要安装驱动 |
分区
在 gpart实践(linux分区及zfs分区) 创建的分区如下( gpart show nda0 ):
gpart 检查磁盘分区可以看到添加的2个分区...
=> 40 3907029088 diskid/DISK-Y39B70RTK7AS GPT (1.8T)
40 532480 1 efi (260M)
532520 2008 - free - (1.0M)
534528 4194304 2 freebsd-swap (2.0G)
4728832 536870912 3 freebsd-zfs (256G)
541599744 536870912 4 linux-data (256G)
1078470656 2828558336 5 freebsd-zfs (1.3T)
3907028992 136 - free - (68K)
分区4 linux-data ( /dev/diskid/DISK-Y39B70RTK7ASp4 )将连接到 bhyve虚拟化运行Ubuntu 创建需要的Linux文件系统
vm-bhyve 配置
备注
这里记录了我最终实践正确的配置,实际上我走了一点弯路,见下文 "异常排查"
修订 FreeBSD 15环境bhyve中实现NVIDIA GPU passthrough 的虚拟机配置
/zdata/vms/xdev/xdev.conf:
xdev.conf 添加第二个 disk1 配置loader="uefi"
cpu=4
memory=16G
wired_memory="yes"
network0_type="virtio-net"
network0_switch="igc0bridge"
network0_device="tap0"
disk0_name="disk0"
disk0_dev="sparse-zvol"
disk0_type="virtio-blk"
disk1_name="/dev/diskid/DISK-Y39B70RTK7ASp4"
disk1_dev="custom"
disk1_type="nvme"
#passthru0="1/0/0=2:0"
#passthru0="1/0/0"
graphics="yes"
graphics_listen="0.0.0.0"
graphics_port="5900"
uuid="513d828a-9172-11f0-9751-0003ee002989"
network0_mac="58:9c:fc:03:19:32"
debug="yes"
启动虚拟机:
vm start xdev
此时在Host主机上检查 vm-bhyve.log 可以看到使用了如下参数来启动和使用设备:
vm-bhyve.log 可以观察到bhyve的参数使用情况Sep 17 20:34:21: [bhyve options: -c 4 -m 16G -AHPw -l bootrom,/usr/local/share/uefi-firmware/BHYVE_UEFI.fd -S -U 513d828a-9172-11f0-9751-0003ee002989 -u]
Sep 17 20:34:21: [bhyve devices: -s 0,hostbridge -s 31,lpc -s 4:0,virtio-blk,/dev/zvol/zdata/vms/xdev/disk0 -s 5:0,nvme,/dev/diskid/DISK-Y39B70RTK7ASp4 -s 6:0,virtio-net,tap0,mac=58:9c:fc:03:19:32 -s 7:0,fbuf,tcp=0.0.0.0:5900]
Sep 17 20:34:21: [bhyve console: -l com1,/dev/nmdm-xdev.1A]
备注
这里还有一点波折,我发现添加了第二块虚拟磁盘之后,虚拟机识别的虚拟网卡命名从 enp0s5 变成了 enp0s6 ,所以还需要通过VNC登陆终端修订一下 /etc/netplan/50-cloud-init.yaml 的网卡名字
虚拟机内部使用Host透传的物理磁盘分区
需要注意,Host主机的物理磁盘分区是作为块设备透传进虚拟机的,对于虚拟机来说,视为一个完整的磁盘。这样,使用上有一些需要注意点:
因为我的目标是通过虚拟机对Host主机的物理磁盘分区创建文件系统(因为Host主机FreeBSD系统没有这个能力),所以不能在虚拟机内部使用这个映射块文件创建分区表,而是将整个磁盘直接创建文件系统
只有VM内部使用映射的块文件作为的虚拟磁盘不创建分区表,直接创建文件系统,那么回到Host主机上,就能正常看到分区上的Linux文件系统,也就能被Host主机的FreeBSD系统读写
后续也能在Host主机上对这个物理磁盘分区(文件系统)构建 LFS(Linux from scratch)
登陆到bhyve虚拟机内部检查
fdisk -l可以看到一块NVMe设备:
fdisk -l 可以看到透传的分区现在是一个NVMe设备Disk /dev/nvme0n1: 256 GiB, 274877906944 bytes, 536870912 sectors
Disk model: bhyve-NVMe
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
现在可以在虚拟机内部(我的
xdev使用了 Ubuntu Linux 24.04.3)虚拟磁盘上创建EXT4文件系统:
mkfs.ext4 /dev/nvme0n1
然后就可以在Host物理主机上实践:
也可以在虚拟机内部(我的
xdev使用了 Ubuntu Linux 24.04.3)虚拟磁盘上创建XFS文件系统:
mkfs.xfs /dev/nvme0n1
然后就可以在Host物理主机上实践:
异常排查
备注
我最初的配置是参考了Google AI的回答( freebsd vm-bhyve use disk partition ),但是Google AI的答案实际上似是而非,特别是提供的配置案例搞错了 disk1_dev (该配置是指Host主机的设备类型,但是Google AI误配置为Host主机设备)。以下是Google AI提供的错误配置:
# This is an example, your configuration will differ.
# disk0_dev="zvol/zroot/vm/guestname/disk0"
disk1_dev="/dev/ada1p2"
disk1_type="ahci-hd"
最初的错误配置
我最初在 xdev.conf 自作聪明添加了一行 disk1_name="disk1" :
...
disk1_name="disk1"
disk1_dev="/dev/diskid/DISK-Y39B70RTK7ASp4"
disk1_type="nvme"
...
没想到这个 disk1_name 会引导 vm-bhyve 去 /zdata/vms/xdev/ 目录下找名为 disk1 的设备文件,日志 /zdata/vms/xdev/bhyve.log 报错:
disk1 块文件不存在bhyve: Could not open backing file: /zdata/vms/xdev/disk1: No such file or directory
nvme: Could not open backing file: No such file or directory
Device emulation initialization error: No such file or directory
去除掉这行错误配置, vm-bhyve 才能启动,那么现在的配置正确了么?
...
disk1_dev="/dev/diskid/DISK-Y39B70RTK7ASp4"
disk1_type="nvme"
...
虚拟机启动了,但是我登陆 xdev 虚拟机,发现并没有第2块虚拟磁盘( fdisk -l )
这是为什么?我明明已经配置了 disk1_dev="/dev/diskid/DISK-Y39B70RTK7ASp4" ,难道不是指定了虚拟机的磁盘设备对应的物理Host的设备文件么?
最终的正确配置
经过一番搜索,我发现 bhyve HDD passthrough 的案例虽然不是Host主机物理分区传递给VM,但是提供了物理主机完整磁盘设备透传给VM的配置案例:
loader="grub"
cpu=1
memory=512M
ahci_device_limit="8"
network0_type="virtio-net"
network0_switch="public"
disk0_type="ahci-hd"
disk0_name="disk0.img"
disk1_dev="custom"
disk1_opts="sectorsize=512"
disk1_type="ahci-hd"
disk1_name="/dev/ada0"
disk2_dev="custom"
disk2_opts="sectorsize=512"
disk2_type="ahci-hd"
disk2_name="/dev/ada1"
disk3_dev="custom"
disk3_opts="sectorsize=512"
disk3_type="ahci-hd"
disk3_name="/dev/ada2"
...
原来:
disk1_name指的是物理主机设备名,也就是要透传给bhyve虚拟机的Host主机设备
如果是相对名,例如
disk0就会在虚拟机目录/zdata/vms/xdev下找设备文件名disk0如果是绝对名,例如
/dev/diskid/DISK-Y39B70RTK7ASp4就会把Host主机物理磁盘分区(p4)透传给bhyve虚拟机
disk1_dev不是设备名,而是设备类型,通常有如下类型:
sparse-zolv: 稀疏类型的ZFS volume块文件,这是我之前构建虚拟机使用的
sparse-disk: 稀疏类型的磁盘镜像文件(disk image file)
disk: 磁盘镜像文件
custom: 自定义实际上就是物理设备? (目前我的实践是这样理解的)
disk1_type不是Host主机的设备类型,而是bhyve使用的存储驱动类型,通常有如下类型(见上文对比表)
ahci-hd: 模拟标准SATA控制器
nvme: 模拟PCIe连接的NVMe控制器
virtio-blk: paravirtualized块设备
所以,我最终实践验证正确的将Host主机物理磁盘分区透传给bhyve虚拟机的配置是:
loader="uefi"
cpu=4
memory=16G
wired_memory="yes"
network0_type="virtio-net"
network0_switch="igc0bridge"
network0_device="tap0"
disk0_name="disk0"
disk0_dev="sparse-zvol"
disk0_type="virtio-blk"
disk1_name="/dev/diskid/DISK-Y39B70RTK7ASp4"
disk1_dev="custom"
disk1_type="nvme"
#passthru0="1/0/0=2:0"
#passthru0="1/0/0"
graphics="yes"
graphics_listen="0.0.0.0"
graphics_port="5900"
uuid="513d828a-9172-11f0-9751-0003ee002989"
network0_mac="58:9c:fc:03:19:32"
debug="yes"
参考
bhyve HDD passthrough 这个案例启发了我修订了正确的配置