24.7.使用 FreeBSD 上的 bhyve 虚拟机
bhyve 是一款 BSD 授权的虚拟化管理程序,已在 FreeBSD 10.0-RELEASE 中成为基本系统的一部分。该虚拟化管理程序支持多个操作系统,包括 FreeBSD、OpenBSD、许多 Linux® 发行版以及 Microsoft Windows®。默认情况下,bhyve 提供对串行控制台的访问,而不模拟图形控制台。通过使用新处理器的虚拟化卸载功能,避免了翻译指令和手动管理内存映射的传统方法。
bhyve 的设计要求:
支持 Intel® 处理器的 Intel 扩展页表(EPT),
或支持 AMD® 处理器的 AMD 快速虚拟化索引(RVI)或嵌套页表(NPT),
或 ARM® aarch64 CPU。
在 ARM 上,仅支持纯 ARMv8.0 虚拟化,目前不使用虚拟化主机扩展。托管 Linux® 或 FreeBSD 虚拟机时,如果有多个 vCPU,则需要 VMX 非限制模式支持(UG)。
判断 Intel 或 AMD 处理器是否支持 bhyve 的最简单方法是运行 dmesg 或查看 /var/run/dmesg.boot 文件中的 POPCNT 处理器特征标志(对于 AMD® 处理器)或 EPT 和 UG(对于 Intel® 处理器)的 VT-x 行。
24.7.1. 准备宿主机
创建虚拟机的第一步是配置宿主系统。首先,加载 bhyve 内核模块:
# kldload vmm将虚拟机与宿主的网络连接有几种方法;一种简单的方式是为虚拟机中的网络设备创建一个 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 up24.7.2. 创建 FreeBSD 虚拟机
创建一个文件作为虚拟机的虚拟磁盘。指定虚拟磁盘的大小和名称:
下载 FreeBSD 安装镜像:
FreeBSD 附带了示例脚本 vmrun.sh,用于在 bhyve 中运行虚拟机。该脚本将启动虚拟机并在一个循环中运行,这样如果虚拟机崩溃,它会自动重新启动。vmrun.sh 接受多个选项来控制虚拟机的配置,包括:
-c控制虚拟 CPU 的数量,-m限制分配给虚拟机的内存,-t定义使用的 tap 设备,-d指定使用的磁盘镜像,-i告诉 bhyve 从 CD 镜像而非磁盘启动,-I定义使用的 CD 镜像。
最后一个参数是虚拟机的名称,用于跟踪正在运行的虚拟机。以下命令列出了所有可用的程序参数选项:
此示例以安装模式启动虚拟机:
虚拟机将启动并开始安装。当系统在安装结束时询问是否进入 shell 时,选择 Yes。
重启虚拟机。重启虚拟机会导致 bhyve 退出,但 vmrun.sh 脚本会在循环中运行 bhyve 并自动重新启动。当发生这种情况时,选择启动菜单中的重启选项以跳出循环。现在可以从虚拟磁盘启动虚拟机系统:
24.7.3. 创建 Linux® 虚拟机
Linux 虚拟机可以像其他常规 基于 UEFI 的虚拟机 虚拟机一样启动,或者可以使用 Port sysutils/grub2-bhyve 。
为此,首先确保已安装该 Port,然后创建一个文件作为虚拟机的虚拟磁盘:
使用 grub2-bhyve 启动 Linux 虚拟机是一个两步过程。
首先加载内核,然后启动虚拟机。
使用 sysutils/grub2-bhyve 加载 Linux® 内核。
创建一个 device.map 文件,grub 将用它来将虚拟设备映射到宿主系统上的文件:
使用 sysutils/grub2-bhyve 从 ISO 镜像加载 Linux® 内核:
这将启动 grub。如果安装 CD 包含 grub.cfg 文件,将显示一个菜单。如果没有,则必须手动定位并加载 vmlinuz 和 initrd 文件:
现在内核已加载,可以启动虚拟机系统:
系统将启动并开始安装。在虚拟机中安装系统后,重启虚拟机。重启虚拟机会导致 bhyve 退出。虚拟机实例需要被销毁才能重新启动:
现在,可以直接从虚拟磁盘启动虚拟机。加载内核:
启动虚拟机:
Linux® 将在虚拟机中启动并最终显示登录提示。登录后使用虚拟机。完成后,重启虚拟机以退出 bhyve。销毁虚拟机实例:
24.7.4. 使用 UEFI 固件启动 bhyve 虚拟机
除了 bhyveload 和 grub-bhyve,bhyve 超级虚拟机还可以使用 UEFI 固件启动虚拟机。这种选项可能支持其他加载器不支持的客操作系统。
要使用 bhyve 中的 UEFI 支持,首先需要获取 UEFI 固件镜像。可以通过安装 Port 或包sysutils/bhyve-firmware 来完成。
将固件安装好后,在 bhyve 命令行中添加 -l bootrom,/path/to/firmware 标志。实际的 bhyve 命令可能如下所示:
为了允许虚拟机存储 UEFI 变量,可以将变量文件附加到 -l 标志中。请注意,bhyve 将会将对虚拟机变量的修改写入指定的变量文件。因此,请确保首先为每个虚拟机创建一个变量模板文件的副本:
然后,在 bhyve 参数中添加该变量文件:
注意
某些 Linux 发行版要求使用 UEFI 变量存储其 UEFI 启动文件的路径(例如,使用
linux64.efi或grubx64.efi,而不是bootx64.efi)。因此,建议使用变量文件来避免手动修改启动分区文件。
要查看或修改变量文件的内容,可以使用 efivar(8) 从主机进行操作。
sysutils/bhyve-firmware 还包含支持 CSM 的固件,用于以传统 BIOS 模式启动没有 UEFI 支持的虚拟机:
24.7.5. 为 bhyve 虚拟机启用图形 UEFI 帧缓存
UEFI 固件支持对于主要以图形为主的操作系统(如 Microsoft Windows®)特别有用。
可以通过添加 -s 29,fbuf,tcp=0.0.0.0:5900 标志启用 UEFI-GOP 帧缓存。可以使用 w=800 和 h=600 配置帧缓存分辨率,并且可以通过添加 wait 指示 bhyve 在启动虚拟机之前等待 VNC 连接。帧缓存可以从主机或通过网络通过 VNC 协议进行访问。此外,可以添加 -s 30,xhci,tablet 以实现与主机的精确鼠标光标同步。
最终的 bhyve 命令将如下所示:
请注意,在 BIOS 模拟模式下,若控制从固件传递给客操作系统,帧缓存将停止更新。
24.7.6. 创建 Microsoft Windows® 虚拟机
为 Windows 10 或更早版本的操作系统设置虚拟机,可以直接使用原始安装媒体,过程相对简单。除了最低资源要求,运行 Windows 作为虚拟机还需要:
配置虚拟机内存(使用
-w标志)使用 UEFI 启动固件启动。
以下是使用 Windows 安装 ISO 启动虚拟机虚拟机的示例:
在安装过程中,建议只使用一个或两个 VCPU,但安装完成后可以增加此数量。
必须安装 VirtIO 驱动,以使用定义的 virtio-net 网络接口。另一种选择是通过将 virtio-net 更改为 e1000(Intel E82545)模拟来切换到 E1000 模式,但性能会受到影响。
24.7.6.1. 创建 Windows 11 虚拟机
从 Windows 11 开始,Microsoft 引入了 TPM 2 模块的硬件要求。bhyve 支持将硬件 TPM 传递到虚拟机。可以修改安装媒体以禁用相关的硬件检查。有关此过程的详细说明,请参见 FreeBSD Wiki。
警告
制造商并不支持修改 Windows 安装媒体以在没有 TPM 模块的情况下运行 Windows 虚拟机。实施此类方法前,请考虑你的应用程序和使用案例。
24.7.7. 在 bhyve 虚拟机中使用 ZFS
如果主机上可用 ZFS,使用 ZFS 卷而不是磁盘镜像文件可以为虚拟机提供显著的性能提升。可以通过以下方式创建 ZFS 卷:
启动虚拟机时,指定 ZFS 卷作为磁盘驱动器:
如果你在主机和虚拟机中都使用 ZFS,请记住两者都会缓存虚拟机的内容,可能会造成内存竞争压力。为缓解此问题,考虑将主机的 ZFS 文件系统设置为仅缓存元数据。为此,请对主机上的 ZFS 文件系统应用以下设置,将 <name> 替换为特定虚拟机 zvol 数据集的名称:
24.7.8. 创建虚拟机快照
现代超级虚拟机允许用户创建“快照”,该快照包括虚拟机的磁盘、CPU 和内存内容。快照通常可以在虚拟机运行或关闭的情况下创建。然后,可以将虚拟机恢复到快照拍摄时的精确状态。
24.7.8.1. ZFS 快照
使用 ZFS 卷作为虚拟机的后端存储可以进行虚拟机磁盘的快照。例如:
虽然可以在虚拟机运行时对 ZFS 卷进行快照,但请注意,在虚拟机活跃时,虚拟磁盘的内容可能处于不一致的状态。因此,建议在执行此命令之前,先关闭或暂停虚拟机。默认情况下,不支持暂停虚拟机,需要先启用(参见 内存和 CPU 快照)
警告
在虚拟机使用 ZFS zvol 时回滚到快照可能会破坏文件系统内容并导致虚拟机崩溃。所有未保存的数据将丢失,且自上次快照以来的修改可能会被销毁。
若虚拟机关闭,可能需要第二次回滚以恢复文件系统的可用状态。这最终会摧毁自快照以来所做的所有更改。
24.7.8.2. 内存和 CPU 快照(实验性功能)
从 FreeBSD 13 开始,bhyve 具有一个实验性的“快照”功能,可以将虚拟机的内存和 CPU 状态转储到文件中,然后暂停虚拟机。稍后可以从快照文件恢复虚拟机。
然而,此功能默认情况下未启用,并且需要从源代码重新编译系统。有关编译内核和自定义选项的详细描述,请参见 从源代码构建。
警告
此功能尚不适合生产环境使用,并且仅适用于特定的虚拟机配置。存在多个限制:
nvme和virtio-blk存储后端目前无法工作快照仅在虚拟机使用每种设备的一种类型时支持,即如果附加了多个
ahci-hd磁盘,快照创建将失败此功能在 Intel 系统上可能较为稳定,但可能在 AMD CPU 上无法工作。
注意
在执行以下步骤之前,请确保 /usr/src 目录是最新的。请参见 更新源代码 以了解如何操作的详细步骤。
首先,在 /etc/src.conf 文件中添加以下内容:
注意
如果系统进行了部分或完全重建,建议在继续操作前运行
然后按照 从源代码更新 FreeBSD 快速入门部分 中的步骤构建并安装世界和内核。
要验证快照功能是否成功启用,可以输入:
并检查输出中是否列出了 --suspend 标志。如果没有该标志,说明该功能未正确激活。
然后,你可以快照并暂停你选择的运行中的虚拟机:
注意
提供绝对路径和文件名给
--suspend。否则,bhyve 将把快照数据写入启动 bhyve 时所在的目录。确保将快照数据写入安全目录。生成的输出包含虚拟机的完整内存转储,因此可能包含敏感数据(例如密码)!
此操作会生成三个文件:
内存快照 - 文件名与
--suspend输入相同内核文件 - 文件名与
--suspend输入相同,后缀为 .kern元数据 - 包含系统状态的元数据,后缀为 .meta
要从快照恢复虚拟机,可以使用 -r 标志与 bhyve:
在不同 CPU 架构上恢复虚拟机快照将无法工作。通常,尝试在与创建快照的系统不同的系统上恢复将会失败。
24.7.9. 在 Jail 中运行 bhyve
为了提高安全性并将虚拟机与主机操作系统隔离,可以将 bhyve 运行在 jail 中。有关 jail 及其安全性好处的详细描述,请参见 Jails。
24.7.9.1. 为 bhyve 创建 Jail
首先,创建一个 jail 环境。如果使用 UFS 文件系统,直接运行:
如果使用 ZFS 文件系统,请使用以下命令:
然后为虚拟机 bhyvevm0 创建一个 ZFS zvol:
如果不使用 ZFS,使用以下命令直接在 jail 目录结构中创建一个磁盘映像文件:
下载一个 FreeBSD 镜像,最好是与主机版本相同或更旧的版本,并将其解压到 jail 目录中:
注意
在 jail 中运行高版本的 FreeBSD(例如,在 13.2-RELEASE 主机中运行 14.0-RELEASE)是不支持的。
接下来,向 /etc/devfs.rules 添加 devfs 规则集:
注意
如果 /etc/devfs.rules 文件中已有其他编号为 100 的 devfs 规则,请将列表中的 ID 替换为另一个尚未使用的 ID 号码。
注意
如果不使用 ZFS 文件系统,请跳过 /etc/devfs.rules 中与 zvol 相关的规则:
这些规则将导致 bhyve
创建名为
bhyvevm0和bhyvevm1的虚拟机磁盘卷,使用名为
tap10的 tap 网络接口。即有效的接口名称将是tap10、tap100、tap101、…tap109、tap1000等。限制对可能的 tap 接口名称的访问将防止 jail(从而 bhyve)看到主机和其他 jails 的 tap 接口。使用以“bhyve”开头的 nmdm 设备,即 /dev/nmdmbhyve0。
可以根据需要扩展和更改这些规则,以适应不同的虚拟机和接口名称。
注意
如果你打算在主机和一个或多个 jails 中使用 bhyve,请记住,tap 和 nmdm 接口名称将在共享环境中操作。例如,你只能将 /dev/nmdmbhyve0 用于主机或 jail 中的 bhyve。
重新启动 devfs 以加载更改:
然后,在 /etc/jail.conf 或 /etc/jail.conf.d 中为新的 jail 添加定义。将接口编号 $if 和 IP 地址替换为你的个人变体。
示例 1. 使用 NAT 或路由流量与防火墙
此示例假设使用类似 pf 或 ipfw 的防火墙来 NAT 你的 jail 流量。有关实现此功能的更多详细信息,请参见 防火墙 章节。
示例 2. 使用桥接网络连接
注意
如果你之前将 /etc/devfs.rules 中的 devfs 规则集 ID 100 替换为你自己的唯一数字,请记得在 jails.conf 中也替换相应的数字 ID。
24.7.9.2. 配置 Jail
首次启动 Jail 并进行一些额外的配置工作时,输入以下命令:
重启并启用 Jail:
之后,你可以在 Jail 内创建虚拟机。首先,下载 FreeBSD 虚拟机操作系统的安装 ISO 文件:
24.7.9.3. 在 Jail 内创建虚拟机
使用 bhyvectl 初始化虚拟机:
注意
在 Jail 中启动虚拟机时,可能需要使用
bhyvectl创建虚拟机。跳过此步骤可能会导致启动bhyve时出现以下错误信息:
最后,使用你喜欢的方式启动虚拟机。
示例 3. 使用 vmrun.sh 和 ZFS 启动
在 ZFS 文件系统上使用 vmrun.sh:
示例 4. 使用 vmrun.sh 和 UFS 启动
在 UFS 文件系统上使用 vmrun.sh:
示例 5. 使用 ZFS 启动 UEFI 虚拟机操作系统
如果你希望使用 UEFI 虚拟机操作系统,请首先在 Jail 内安装所需的固件包 sysutils/bhyve-firmware:
然后直接使用 bhyve 启动:
这能让你通过 VNC 连接到虚拟机 bhyvevm0,并通过 /dev/nmdbbhyve0B 使用串行控制台。
24.7.10. 虚拟机控制台
将 bhyve 控制台包裹在一个会话管理工具中,如 sysutils/tmux 或 sysutils/screen,是非常有利的,这样可以断开并重新连接到控制台。也可以将 bhyve 的控制台设置为一个 null modem 设备,并通过 cu 访问。要实现这一点,请加载 nmdm 内核模块,并将 -l com1,stdio 替换为 -l com1,/dev/nmdm0A。/dev/nmdm 设备会根据需要自动创建,每对设备对应于 null modem 电缆的两端(/dev/nmdm0A 和 /dev/nmdm0B)。更多信息请参见 nmdm(4)。
要从控制台断开连接,输入换行符(即按 RETURN),然后是波浪符(~),最后是点符号(.)。请记住,只有连接会被断开,而登录会话仍然保持活动状态。因此,其他用户连接到同一控制台时,可以在无需重新认证的情况下继续使用任何活动会话。出于安全考虑,建议在断开连接前注销。
nmdm 设备路径中的编号必须对每个虚拟机唯一,并且在 bhyve 启动之前,不能被任何其他进程使用。编号可以随意选择,无需来自连续的数字序列。设备节点对(即 /dev/nmdm0a 和 /dev/nmdm0b)是在 bhyve 连接其控制台时动态创建的,并在 bhyve 关闭时销毁。在创建启动虚拟机的脚本时,请牢记这一点:你需要确保所有虚拟机都分配有唯一的 nmdm 设备。
24.7.11. 管理虚拟机
每个虚拟机都会在 /dev/vmm 中创建一个设备节点。这使得管理员可以轻松查看正在运行的虚拟机列表:
可以使用 bhyvectl 销毁指定的虚拟机:
以这种方式销毁虚拟机会立即将其杀死。任何未保存的数据将丢失,打开的文件和文件系统可能会被损坏。要优雅地关闭虚拟机,请向其 bhyve 进程发送 TERM 信号。这会触发虚拟机的 ACPI 关机事件:
24.7.12. 工具和实用程序
有许多工具和应用程序可在 ports 中找到,帮助简化设置和管理 bhyve 虚拟机:
表 1. bhyve 管理工具
24.7.13. 持久化配置
为了在启动时自动启动 bhyve 虚拟机,需要进行一些配置文件的修改。
/etc/sysctl.conf 当使用 tap 接口作为网络后端时,你需要手动将每个使用的 tap 接口设置为 UP,或者仅需设置以下 sysctl 参数:
/etc/rc.conf 要通过 桥接 将虚拟机的 tap 设备连接到网络,你需要在 /etc/rc.conf 中持久化设备设置。此外,你可以通过
kld_list配置变量加载必要的内核模块vmm用于 bhyve 和nmdm用于 nmdm 设备。在配置ifconfig_bridge0时,确保将<ipaddr>/<netmask>替换为物理接口(在此示例中为 igb0)的实际 IP 地址,并从物理设备中移除 IP 设置。
示例 6. 设置桥接设备的 IP 地址
对于一个与网络连接的 igb0 接口,其 IP 为 10.10.10.1,子网掩码为 255.255.255.0,你将使用以下命令:
警告
修改系统的 IP 地址配置可能会导致远程连接中断(例如通过 SSH 连接)!在执行这些命令时,请确保采取必要的预防措施以保持系统访问,或在本地终端会话中进行这些修改。
最后更新于