github编辑

vm-bhyve Wiki

欢迎来到 vm-bhyve 的 wiki。

希望你能在这里找到有关使用 vm-bhyve 的信息、示例,以及我们当前支持和将来计划支持的详细内容。

感谢你的到访!

—— Matt

功能

Apr 22, 2016

这是一份(相当)完整的 vm-bhyve 当前支持功能清单。除非另有说明,所有功能均适用于一切类型的 guest。

  • 配置文件简单,可轻松手动编辑

  • FreeBSD guest(含基于 FreeBSD 的衍生版本,如 pfSense)

  • Linux / OpenBSD / NetBSD guest

  • Windows guest

  • SmartOS guest

  • guest 模板,可用于为新建 guest 指定配置、磁盘、网络等

  • 支持运行于 ZFS 或其他任意文件系统上

  • 多数据存储——可创建多个位置来存放虚拟机数据

  • 支持稀疏文件、zvol、sparse zvol 和自定义磁盘设备

  • nmdm 控制台和标准输入输出上运行 guest 及安装程序

  • 动态分配控制台用的 nmdm 设备

  • 动态分配网络用的 tap 设备

  • 支持任意数量的虚拟交换机,其接口可动态创建并桥接

  • 虚拟交换机的 VLAN 支持

  • 虚拟交换机的 NAT 支持

  • 能够将 guest 连接到手动配置的桥接(vm switch import myswitch bridgeX

  • guest 与虚拟交换机的详细信息输出(vm infovm switch info

  • guest 支持多块磁盘设备(UEFI guest 最多可达 3 个)

  • 多网络适配器支持

  • PCI 直通

  • 可为 guest 指定 UTC 时间

  • 可通过配置文件为 guest 启用设备 virtio-rnd

  • 所有需要 grub 命令的 grub-bhyve guest 使用自定义 grub 配置文件。这些 guest 会在控制台显示可访问的启动菜单。

  • 对基于 ZFS 的 guest 可进行快照、回滚与克隆

  • 可创建基于 ZFS 的 guest 镜像,并据此部署新 guest

  • 支持设置 rctl 限制

路线图

Aug 16, 2018

技巧

在 2025.11.9,Ports 中 sysutils/vm-bhyvearrow-up-right 的版本是 1.6.2。

1.3 版本(开发版本)

1.2 版本(当前 FreeBSD Ports 版本)

这是当前的开发版本,有以下新特性:

1.1 版本

1.0 版本

当前计划是将现有代码库(截至 0.12.5)稳定为 1.0 版本,待确认无明显错误即可发布。我对当前功能很满意。已测试了 FreeBSD / Linux / NetBSD / OpenBSD / Windows 多种 guest,运行正常。我尝试设置了在主机启动时自动启动的 guest(5 个),均无问题。

截至 4 月 15 日,当前代码已升级为 1.0-beta。我计划保留一到两周,此期间只递增修订号/构建号(现在为独立整数)。之后我将发布 1.0 并提交 Port 更新。其他功能变更将纳入 1.1,并暂时仅在 GitHub 发布。我不希望频繁提交 Port 更新到 FreeBSD;想要最新功能的用户可从 GitHub 获取,其他用户则可在 Ports 获取稳定的 1.0。

该版本已分支为 1-0.stable。待确认脱离 beta 状态,Ports 将更新此版本。版本号简化为 1.0,并附加构建号。如需修复,将在此分支完成,并在必要时以 1.0-pX 形式更新 Ports。

0.12.5 版本(已完成)

0.12 版本(已完成)

0.11 版本(已完成)

更新了 grub-bhyve 支持,现在使用主机上的自动生成 grub.cfg 文件,而不再直接向加载器传递启动命令。这带来以下好处:

0.10 版本(已完成)

完全重写了 grub-bhyve 支持。用户可通过选项 grub_installXgrub_runX 完全控制传递给加载器的启动与安装命令。

简单开始

Jul 26, 2022

安装 vm-bhyve 并启动 FreeBSD guest 所需命令的简单概览:

第 1 行

安装 vm-bhyve

如果需要支持 Linux grub,可安装软件包 grub2-bhyve;如需运行包括 Windows 在内的 UEFI 启动系统,请安装 UEFI 相关 Port。

第 2 行

为虚拟机创建数据集。若不使用 ZFS,只需创建一个普通目录即可。

第 3–4 行

/etc/rc.conf 中启用 vm-bhyve 并设置要使用的数据集。如果不使用 ZFS,只需设置 $vm_dir="/my/vm/folder"

第 5 行

运行 vm init 命令,在 $vm_dir 下创建所需目录并加载内核模块。

第 6 行

安装随 vm-bhyve 提供的示例模板。

第 7–8 行

创建虚拟交换机 “public”,并将你的网络接口附加到 “public”。将 em0 替换为实际连接网络的接口。

第 9 行

从 FTP 站点下载 FreeBSD 镜像。

第 10–12 行

使用 FreeBSD 的 default.conf 模板创建新的 guest,运行安装程序并连接到其控制台。此时可像普通系统一样进行安装。如果在安装命令前添加选项 -f,guest 将直接在你的终端上运行,因此不需要再执行 console 命令(请注意,选项 -f 仅在 vm-bhyve-0.12.5+ 中可用)。

完整示例模板

November, 2025

以下是运行 FreeBSD guest 的完整模板示例。

其他操作系统的配置示例请参见 Supported Guest Examplesarrow-up-right 页面。

所有模板均存放在目录 $vm_dir/.templates 下,文件名应为 [我的模板名].conf。你可以创建任意数量的模板,并在创建 guest 时指定,例如:

若在创建 guest 时未指定模板名称,则默认使用 default.conf

模板示例(FreeBSD guest)

第 1 行

FreeBSD guest 需要使用 bhyveload 作为加载器。

第 2-3 行

指定该 guest 的 CPU 核心数和内存大小。内存选项可以以 MG 结尾。

第 4-6 行

第一块磁盘的选项,即 guest 启动的磁盘。disk0_dev 不是必需的,默认值为 file。也可以使用 ZVOL 或自定义磁盘,详情请参考磁盘示例页面。

第 7-8 行

第一块网络适配器的选项。如果不需要网络,可以删除这些选项。目前唯一支持的接口类型是 virtio-net。该接口会自动连接到 public 虚拟交换机(若有)。

使用 tmux

Oct 3, 2022

在默认情况下,vm-bhyve 使用 cu/nmdm 作为控制台会话管理工具。如果你希望虚拟机运行在 tmux 会话中,从 v1.1+ 开始支持此功能。只需在 $vm_dir/.config/system.conf 中设置选项 console

设置完成后,启动的所有新 guest 都会关联到一个 tmux 会话。会话名称与 guest 名称相同,同时也可以使用标准命令 vm console guest 连接到该 tmux 会话。

示例:

受支持的 Guest 示例

该文件列出了已经测试过的 guest,并展示了安装器和 guest 启动时可使用的配置选项。目标是建立配置清单,供大家在自己的模板中选用。在大多数情况下,guest 都是使用其默认安装选项进行测试的。

如果你成功地使用了这里未列出的 guest 操作系统,请告知我,以便更新列表。

请注意,我在这些示例中都省略了网络和磁盘设置,因为所有 guest 的格式都是相同的。不同配置请参见网络或磁盘示例页面。

所有 guest 都需要 cpu 和内存选项,非常简单:

如果你使用的是 vm-bhyve-0.11 及更新版本,则 grub guest 不再需要 boot 命令,因此安装和运行时的 guest 配置文件中可以去掉该选项。

vm-bhyve-0.12.5 中,如果分区 1(msdos1/openbsd1)正确,任何 grub-bhyve guest 都不需要选项 grub_run_partition

完整的可用配置选项列表及说明,请参见手册页或 sample-templates 目录下的 config.sample

FreeBSD / pfSense / MidnightBSD

该配置文件应支持所有 FreeBSD 和 MidnightBSD 版本。对于 pfSense,我使用了嵌入式内核选项,效果良好。

Windows

建议至少为 Windows 准备 1G 内存,磁盘仿真需要使用 ahci-hd。

NetBSD

OpenBSD

以下示例针对 OpenBSD 6.2 amd64,因为安装命令有版本号和架构。我已成功运行 5.2,其他版本只要更新安装命令中的版本号也应可用。i386 guest 同样可用,但需更新安装命令。

resflash

resflash 是用于 U 盘的 OpenBSD 镜像,也适合作为虚拟网络设备。以下示例为 resflash 20171202_1952 amd64。

启动命令如下:

OpenBSD(UEFI)

UEFI 模式下安装 OpenBSD 并使用 VNC 的模板:

ZVOL 示例:

OpenBSD UEFI 注意事项:

  • 安装器默认会选择错误的根磁盘,请确保选择了正确的磁盘(sd1)。

  • 安装完成后,请执行 vm poweroff openbsd-vm,否则 VM 会重新启动到安装盘。

  • 对于 UEFI,安装盘需要的格式是 .img,而不能是 .iso

  • 使用命令:sudo vm iso https://cdn.openbsd.org/pub/OpenBSD/7.6/amd64/install76.img

Alpine Linux

Alpine 的特殊之处在于安装 CD 上的文件针对不同的 Alpine 版本有不同的后缀。基本文件名为 vmlinuz-[后缀]initramfs-[后缀]。请相应调整你的 vm .conf 文件:

Alpine 版本
后缀

standard

vanilla

virtual

virt

Alpine Virtual 模板:

兼容模板:

CentOS 6 (LVM)

请注意,CentOS 的 kernel 和 initramfs 文件带内核版本号,如果系统没有内核 2.6.32-573.el6,需要修改配置。

如果你熟悉 Linux,可以在 guest 中安装 grub2,并配置 vm-bhyve 使用 grub 配置文件。默认情况下,vm-bhyve 会查找 /boot/grub/grub.cfg,也可通过 grub_run_dirgrub_run_file 配置修改。(参见下文 CentOS 7 使用 guest 中 /grub2/grub.cfg 启动的示例)

CentOS 7

RHEL 6.5 (LVM)

基于内核 2.6.32-431.el6.x86_64。如果使用了其他版本内核,请相应修改配置。如果不确定内核版本,可在不指定 grub 命令的情况下启动 guest,然后使用 vm console 访问 bootloader,在 bootloader 中查找正确内核(ls (hd0,1)/)。

退出 bootloader,可手动输入正确启动命令或输入 exit。如常规操作,使用 ~ + Ctrl+D 退出控制台。

Debian & Ubuntu (Grub)

如果需要 Ubuntu 14.04,还需添加以下内容,否则会卡在 grub 提示符:

Debian UEFI

Ubuntu UEFI

类似 Debian,不使用 efivars,使用 zvol。

VyOS

需要设置磁盘扇区大小,否则安装器会报错。

RouterOS (CHR)

根据 讨论arrow-up-right,可以在 bhyve 中运行 RouterOS 6.x 的 CHR。示例配置如下:

通过对 MikroTik 官网下载的镜像进行一些修改,可以按照 教程arrow-up-right 正确运行基于 RouterOS 7.x 的 CHR。

Gentoo

使用 /boot 替代 /isolinux(参见 https://github.com/churchers/vm-bhyve/issues/186):arrow-up-right

安装模板:

安装完成后的可用配置:

OpenWRT

可以使用固件 uefi-csm 运行 OpenWRT x86/64。

下面是个配置示例。只需下载最新的磁盘镜像并放入 vm 目录。

启动 VM 后,可以通过 vm console VM 访问控制台。

OpenWRT UEFI

以下配置在 uefi 下使用 virtio 驱动,并为 LAN 创建了额外的 switch

  • 使用命令 sudo vm switch create openwrt 创建额外 switch。

配置文件中 network1 的 switch 设置为 public,因为 OpenWRT 会自动使用 eth1 作为 WAN 并通过 DHCP 获取 IP。

OpenWRT 也会自动将 LAN 子网设置为 192.168.1.0/24(eth0),如果 WAN 和 LAN 子网相同,将导致路由表冲突,因此需要修改 LAN 子网。

  • 下载 x86/64 ext4 efi 镜像,用 gzip 解压,然后复制到 VM 目录,并重命名为 disk0.img,替换已创建的 disk0.img

配置示例:

虚拟磁盘

Oct 19, 2021

当从模板创建 guest 时,会为模板中指定的每个磁盘创建一块磁盘镜像。如果希望在 guest 创建后添加磁盘,可以使用命令 vm add,或者先创建磁盘镜像,再手动更新配置文件。

下面是一些支持的磁盘配置示例:

普通稀疏文件

稀疏 ZVOL

如果不想使用稀疏 ZVOL,也可以通过指定 disk0_dev="zvol" 来支持非稀疏 ZVOL:

自定义磁盘

可自定义磁盘镜像的路径。磁盘可以是稀疏文件、ZVOL,甚至是 /dev/ 下的物理磁盘:

带选项的简单稀疏文件

自定义 ZVOL 磁盘

如果希望为已有 guest 添加额外的 ZVOL 磁盘,可按以下步骤操作:

首先为磁盘镜像创建新的 ZVOL。如果不希望 ZVOL 是稀疏的,请去掉选项 -s

然后将其作为额外磁盘添加到 guest 配置文件中:

VirtIO 9p 文件共享

以下示例展示了如何使用 VirtIO 9p 与 VM 共享文件或文件夹:

首先,将以下内容添加到 guest 配置文件中:

另外,可在 disk1_name 后追加 ,ro 来设置只读。

在 FreeBSD guest 上,可使用以下命令挂载 9p 共享:

持久化配置可通过 fstab(5) 完成:

虚拟网卡

Mar 2, 2020

一些可能的网络配置示例。

所有 guest 都支持多个网络接口。

基本示例,连接到虚拟交换机“public”

自定义 MAC 地址

请注意,首次运行时,如果网络接口没有 MAC 地址,vm-bhyve 将自动为其分配一个静态 MAC 地址,并写入配置文件。

bhyve 仅接受以 58:9c:fc 开头的自定义 MAC 地址,否则将无法启动(无论 guest OS 是什么),且不会给出有用的错误信息。

自定义网络设备

默认情况下,vm-bhyve 会为每个接口创建动态 tap 设备。如果需要进行复杂配置,需要手动设置网络,这可能会成为问题,因为设备在启动 guest 之前并不存在。

通过指定自定义设备,你可以在 rc.conf 自行配置该设备。请注意,我省略了配置选项 switch。如果指定了,tap 设备会自动附加到虚拟交换机。如果你已按需求配置了自定义设备,可以省略 switch 设置。

数据存储

Jul 16, 2016

vm-bhyve 1.1 现在支持多个数据存储(datastore),并新增了一组用于管理数据存储的命令。

基本配置与以前相同。你需要为 vm-bhyve 的配置和 guest 创建一个目录或 ZFS 数据集,并在 /etc/rc.conf 中设置:

在运行 vm-bhyve 时,该目录用于 ISO 文件和核心配置数据,同时也成为虚拟机的默认数据存储(datastore)。如果列出数据存储,将显示如下信息:

这里显示了数据存储的名称、类型和文件系统路径。对于 ZFS 存储,还会显示数据集名称。

可以使用以下命令添加新的数据存储:

  • 名称必须为 16 个字符以内的字母、数字、-.

  • 数据存储规范(spec)可以是目录路径或 zfs:pool/dataset

  • 注意:系统不会自动创建目录或数据集,需要提前创建。

示例:

要移除数据存储,可使用:

该命令只会从配置中移除数据存储,数据本身不会被删除。

创建虚拟机时,默认会使用默认数据存储。但可以通过选项 -d 指定其他数据存储:

命令 listinfo 也已更新,能显示数据存储信息:

请注意,guest 名称仍需在所有数据存储中唯一。如果有多个相同名称的 guest(例如添加一个已包含 guest 的数据存储),vm-bhyve 命令会按添加顺序搜索数据存储,仅操作找到的第一个 guest。

虚拟交换机

Jun 29, 2020

vm-bhyve 的设计理念是基于“虚拟交换机”。你可以创建任意数量的虚拟交换机,每个交换机都有一个简单的名称。

在配置 guest 时,你可以为每个网络接口指定要连接的交换机名称。当 guest 启动时,会创建一个虚拟以太网(tap)设备,并自动将其添加到指定的虚拟交换机中。

在后台,每个虚拟交换机对应系统上的一个简单 bridge 接口。vm-bhyve 会跟踪每个交换机对应的 bridge(使用 ifconfig 的 groups 功能),并利用此信息将每个 tap 接口连接到正确的 bridge。如果交换机名称少于 12 个字符,则接口命名为 vm-{name},这在配置其他工具(如 pf/dnsmasq)时非常有用。

查看虚拟交换机信息

使用 list 命令可以查看交换机列表及基本信息:

使用 info 命令可以查看更详细信息及连接的 guest:

创建一个简单的交换机 public

在示例模板中,每个 guest 都有一个接口连接到虚拟交换机 public。使用此名称并无特殊原因,你可以为交换机取任意名字:

上述命令创建了虚拟交换机,并将物理接口 em0 连接到它。如果 em0 能访问互联网,那么连接到该交换机的 guest 也能访问互联网。

分配 VLAN 号

为虚拟交换机分配 VLAN 号,会为连接的每个物理接口创建一个 vlan 接口,并将其连接到交换机,而非真实接口。这样,交换机上的 guest 可以正常通信,经过物理接口的数据包会带上指定的 VLAN 标签:

要移除 VLAN,将其设置为 0

使用自定义 bridge

有时你可能希望手动配置 bridge 接口,以使用 vm-bhyve 不直接支持的功能。在这种情况下,可以先在 /etc/rc.conf 手动创建 bridge,然后导入到 vm-bhyve

该命令假定你已手动创建了 bridge0。运行后,vm-bhyve 会为 bridge 接口分配描述。如果 guest 配置中指定 networkX_switch="customswitch",该接口将连接到你的自定义 bridge。

NAT

有关 NAT 配置详情,请参见 Wiki 页面:

https://github.com/churchers/vm-bhyve/wiki/NAT-Configurationarrow-up-right

故障排除

如果无法删除虚拟交换机,请检查该交换机是否有对应的 bridge。通常格式应为 vm-<switch_name>,或者如果名称包含 -,则为 bridge<#>。如果不符合,需要先删除相关虚拟交换机配置,再重新创建交换机。

参考解决方案:https://github.com/churchers/vm-bhyve/issues/373arrow-up-right

NAT 配置

Oct 18, 2018

不幸的是,从 v1.2 起,vm-bhyve 移除了内部 NAT 配置。作为 shell 脚本,之前依赖配置外部系统(如 pf 和 dnsmasq)来提供 NAT 功能。有些用户想使用其他工具或防火墙,并且很多用户由于已有的 pf 或 dnsmasq 配置而导致 NAT 出现问题。因此,现在可以说通过手动配置 NAT 比尝试使用 vm-bhyve 启用 NAT 并手动安装或调整生成的配置更简单且出错率更低。

下面是使用 pf 为 vm-bhyve guests 设置 NAT 主机的一些基础指南。

主机配置

在此示例中,我选择为 guest 使用 192.168.8.x 网络,网关为 192.168.8.1

我们需要启用网关功能,使主机能够在公有网络和 NAT 网络之间转发数据包。同时需要启动 pf 服务,在 /etc/rc.conf 中配置如下:

接下来在 /etc/pf.conf 中创建 NAT 规则,将私有网络的数据包进行 NAT。此示例中,em0 是主机面向公网的接口:

此时可以重启主机,或者如果愿意,也可以手动使用 sysctl 启动 pf 并启用转发:

vm-bhyve 配置

现在需要创建交换机,用于连接 guest。应为该交换机分配一个 NAT 网络范围内的 IP,用作 guest 的网关。我将其命名为 public,这是所有 vm-bhyve 示例中使用的默认交换机名称,你也可以根据环境自定义名称:

此时,你可以配置 guest 使用该虚拟交换机并启动:

Guest 配置示例:

在 guest 中测试本地和外部网络连接:

DHCP / dnsmasq

为 guest 提供 DHCP 服务可以使用 dnsmasq(需通过 Ports 安装)。基于上述虚拟交换机 public192.168.8.x 网络范围,简单配置示例如下:

这样,guest 就可以通过虚拟交换机获得 IP 并通过主机 NAT 上网。

为 Guest 配置 Grub

Jun 22, 2018

vm-bhyve 内置支持软件包 grub2-bhyve,它能够启动大多数可由 GRUB2 启动的 guest。本节介绍可在 guest 配置文件中设置的各种配置选项,以控制 grub2-bhyve 及其效果。

要让 guest 使用 grub2-bhyve 加载器,需要在 guest 配置文件中设置 loader="grub"

Grub 加载器运行在 guest 控制台上,因此当 guest 处于 Bootloader 状态时,可以使用标准命令 vm console guest 访问。如果以前台或交互模式(仅 tmux)启动 guest,一启动就会直接进入 grub 加载器。

无配置

如果完全未指定 grub 配置,grub2-bhyve 会在 guest 的 hd0 分区 1 上查找 /boot/grub/grub.cfg 文件。如果文件存在,它会被处理,大多数情况下会显示带有选项的启动菜单。

如果未找到 GRUB2 配置文件,grub2-bhyve 会直接进入 grub> 命令行界面。

guest 中 grub.cfg 文件位于非标准位置

如果 guest 有 GRUB2 配置文件,但不在 grub2-bhyve 查找的标准位置,可在 guest 配置文件中使用 grub_run_dirgrub_run_file 指定文件位置。

例如,CentOS 7 使用 /grub2/grub.cfg,文件名未变,仅需指定新目录:

若 guest 系统文件名为 /grub2/grub2.conf,则可指定:

grub.cfg 位于不同分区

在默认情况下,vm-bhyve 将 guest 磁盘分区的根指定为 hd0,1。如果启动分区不是 1,可在配置文件中指定其他分区:

此配置下,grub2-bhyve 会在 (hd0,2)/boot/grub/grub.cfg 查找 grub 配置文件。分区设置也会影响自定义命令,例如:

等同于在 grub> 命令行运行 linux (hd0,2)/vmlinuz

guest 无 GRUB2,使用自定义启动命令

如果 guest 没有 GRUB2 配置文件,启动时 grub2-bhyve 会进入 grub> 命令行。此时可连接 guest 并输入启动命令,例如启动 NetBSD:

为了避免每次启动都手动输入,可在 guest 配置文件中指定启动命令(无需 boot):

如果需要多条命令,可增加行并依次编号为 grub_run1grub_run2 等。在指定命令后,vm-bhyve 会生成自定义的 grub.cfg 文件。当启动 guest 时,将显示包含单个 guestname (bhyve run) 选项的自定义 grub 菜单,该选项默认 3 秒后选择(可用 loader_timeout="X" 配置更改超时)。

对于大多数 Linux guest,最好在 guest 内安装 GRUB2,以便 guest 自行管理配置文件。内核升级可能需要修改启动命令,如果手动写入 guest 配置文件,未更新命令将导致无法启动。

安装器命令

在正常情况下,grub2-bhyve 会在 CD 的 /boot/grub/grub.cfg 查找 grub 配置文件,如找不到,则进入 grub> CLI。我们未提供配置选项指定其他位置,但提供了自定义启动命令的功能。例如 CentOS 6 样例模板的 ISO 安装命令如下:

运行 Windows

Sep 3, 2020

如果想运行 Windows,强烈建议使用 FreeBSD 11 及以上版本,并启用 UEFI 图形支持。

首先需要确保系统已经安装 UEFI 固件(如果尚未安装):

Guest 配置

使用 Windows 模板创建 guest。默认配置为 2 个 CPU 和 2GB 内存,同时使用 Windows 原生支持的 Intel 网络适配器 e1000 。如果需要修改配置选项,可使用命令 vm configure guest

注意

如果运行的是 Windows 10 以前的版本,需要使用 disk0_opts="sectorsize=512" 将磁盘扇区大小设置为 512。安装 Microsoft SQL Server 时也必须将扇区大小设置为 512。

安装

通过指定 Windows ISO 文件正常启动安装。在安装模式下运行时,vm-bhyve 将等待 VNC 客户端,在 VNC 连接后再启动 guest,以便捕捉 Windows 的选项 “Boot from CD/DVD”(从 CD/DVD 启动)。在此期间,vm list 中显示 guest 为锁定状态。

连接 VNC 客户端后,按常规方式完成 Windows 安装。

添加 VirtIO 网络驱动

虽然网络适配器 e1000 能开箱即用,提供网络访问,但建议尽可能的使用设备 virtio-net。安装驱动的方法有几种:

  • 如果 guest 可以通过 e1000 上网,可直接在 guest 内下载并安装 VirtIO 驱动,安装完成后关闭 guest,更改 guest 配置为 VirtIO 设备并重启。

  • 在安装模式下启动 guest,并指定 VirtIO ISO 文件:

  • 也可以给 guest 添加 CD 设备,并指向 ISO 文件:

CPU 设置

部分 Windows 版本(多数桌面版)不支持一个以上的物理 CPU。在默认情况下,bhyve 会将每个虚拟 CPU 配置为一个独立 package。

可通过修改 sysctl hw.vmm.topology.cores_per_package 来创建每个 CPU 的多个核心而不是多个 package。例如,将其设置为 4,将使 8 vCPU 的 guest 配置为 2 x 4 核 package。

必须在 /boot/loader.conf 中设置该 sysctl,重启生效。

在 FreeBSD 12,使用 vm-bhyve 1.3,可通过配置文件为每个 guest 控制 CPU 拓扑:

NVMe 支持

从 FreeBSD 12.1R 起,bhyve 支持 NVMe 仿真。在 vm-bhyve 配置中,可使用以下选项:

甚至可以将 guest 安装到 NVMe 物理磁盘,无需虚拟磁盘。例如:

其中 4/0/0 为直通 NVMe SSD。

目前 NVMe 可启动 Windows 8.1 及更新版本。如果要从 NVMe 磁盘启动 Windows 7,请按以下步骤操作:

  1. 使用 ahci-hd 控制器安装 Windows 7 guest,按常规流程进行。

  2. 安装后,添加额外的 disk1.img 并使用 NVMe 控制器。

  3. 安装 Microsoft NVMe 补丁 Windows6.1-KB2990941-v3-x64.msuWindows6.1-KB3087873-v2-x64.msu,确保 Windows 7 guest 设备管理器中出现 NVMe 控制器和 disk1。

  4. 关闭 guest,在配置中交换 disk0.img 和 disk1.img,然后重启。

  5. 关闭 guest,移除 AHCI 控制器和 disk1.img,仅保留 NVMe 控制器与 disk0.img,然后再次启动。此时 Windows 7 guest 的设备管理器中将只显示 NVMe 控制器,不再有 AHCI 控制器。

运行 OmniOS

Jan 26, 2022

OmniOS 的开发已在 OmniOSce 中延续,由 OmniOS 社区和基金会提供支持。现在不再需要修改安装介质,这在旧版本的 OmniOS 中是必须的(可查看此页面的旧版本)。

下载最新版本

大约每六个月发布一个稳定版本,并享有一年的支持。建议访问官方 OmniOSce 下载页面arrow-up-right

开始安装

OmniOSce 支持 virtio-net 驱动,相比 e1000 提供的性能更佳:

启动安装,并按照安装程序或 OmniOSce 安装教程arrow-up-right 进行操作:

使用 VNC 查看器连接,跟随安装教程操作:

解决 rpool 创建失败

当选择磁盘并进入 ZFS Pool 选项时,需要将扇区大小设置为 4K。

解决 “internal error: Argument out of domain”

在使用基于文件的磁盘镜像安装 OmniOS 时可能出现如下错误(2020 年 2 月):

解决方法是使用不同的 ashift 参数创建池:

  • 选择 3 Shell (for manual rpool creation)

  • 创建池:zpool create -o ashift=12 rpool c1t0d0

  • 返回安装菜单:exit

  • 继续安装:2 Install OmniOS straight on to a preconfigured rpool

illumos bug trackerarrow-up-right 待修复提交arrow-up-right

配置 OmniOSce 串行控制台

在最新版本,不再必须使用串行控制台。你可以通过 UEFI loader 使用 VNC 查看器。不过,如果你想用串行控制台,可以按如下方式启用:

安装程序的最后一步可通过 shell 提示来自定义安装,使用菜单项:Shell (for post-install ops on /mnt)

OmniOSce 安装器 postmenu

第一行配置 loader 仅使用串行控制台,其余命令将默认 OS 控制台切换到 ttya:

运行 Linux:以 Alpine Linux 为例

Mar 27, 2021

我花了一些时间才弄明白这个过程,所以为了帮助其他人(包括未来的自己),我写了这份指南。

首先,按照 https://github.com/churchers/vm-bhyvearrow-up-right 上的说明操作。

所有命令必须以 root 身份运行,因此要么直接以 root 登录,要么先运行 su

如果你有配置 lagg(网络冗余),请使用例如 lagg0 作为接口:vm switch add public lagg0

注意,当你使用有线/无线连接的 lagg 冗余时,虚拟机只能通过有线连接访问互联网。

为了保证互联网访问正常,需要确保设置如下:

在我的情况下,前两个值是自动设置的(可能是由 vm-bhyve 完成的),所以我只需要设置后两个。

注意

如果你的防火墙是 ipfw/firewall,那么这些设置可适用;如果你使用 pf,也许需要另外的设置。

出处:FreeBSD 论坛arrow-up-right

要在开机时生效,请将所需值追加到 /etc/sysctl.conf 中,但省略 sysctl 字样。在我的例子中,我添加了:

接下来,为了能够安装和运行 Alpine Linux,先用 alpine 模板创建虚拟机:vm create -t alpine -s 5G alpine

这一步会运行失败,但能让你进入 grub 命令行。在这里你可以找到所选 Alpine ISO 中实际的 Linux 内核名称;不同发行版名称不同。vm-bhyve 提供的模板使用的是 vmlinuz-vanillainitramfs-vanilla,这是与发行版相关的部分。

接着启动安装,例如:vm install alpine alpine-virt-3.13.2-x86_64.iso

连接虚拟机:vm console alpine

启动时,它会显示:

按任意键后,在 GRUB 菜单按 c 进入 grub 命令行。输入 ls 查看可用设备,对于 alpine-virt-3.13.2-x86_64.iso,结果为:(cd0) (cd0,msdos2) (hd0) (host)

逐层查看文件树,找到位于 /boot 的内核:

继续查看 /boot

可以看到,对于这个 ISO,内核文件名是 initramfs-virtvmlinuz-virt

你可以通过输入 reboot 退出控制台,等待几秒钟,然后按 ~+Ctrl+d 返回主机终端。

接下来,编辑该虚拟机的配置文件:vm config alpine(将 alpine 替换为你的虚拟机名称),或者复制模板创建自己的模板。对于本例中的 ISO,需要将所有 vanilla 替换为 virt,即将 /boot/vmlinuz-vanilla 替换为 /boot/vmlinuz-virt/boot/initramfs-vanilla 替换为 /boot/initramfs-virt

如果使用 vm config alpine,只需重新运行:vm install alpine alpine-virt-3.13.2-x86_64.iso,然后 vm console alpine

或者如果你创建了新模板,则创建新虚拟机,再运行安装。

登录用户名为 root(无密码),此时系统消息会提示运行 setup-alpine。这个命令才是真正安装 Alpine 的步骤,在此之前网络不会工作。

UEFI 图形界面(VNC)

UEFI 图形(VNC)支持说明

从 5 月 27 日起,bhyve UEFI 现在支持帧缓冲设备(frame buffer),可通过 VNC 访问。

更新 vm-bhyve

确保使用至少 vm-bhyve 1.1 版本。

使用支持的 FreeBSD 版本

  • 如果从源码构建,图形支持目前仅在 12-CURRENT 和 11-STABLE 可用。

  • 如果使用二进制版本,可使用 11.0 RC。

  • 不支持低于 FreeBSD 11 的版本。

获取最新 UEFI 固件

可以通过 Port sysutils/uefi-edk2-bhyve 安装 UEFI 固件。依赖较多,建议使用 pkg 安装:

更新

现在 pkg install sysutils/bhyve-firmware 会自动安装 edk2-bhyveuefi-edk2-bhyve-csm。原 Port sysutils/uefi-edk2-bhyve 已删除。

对于 vm-bhyve 1.1-p3 及以后版本,安装包即可自动查找固件路径。旧版本需手动复制固件至虚拟机目录下的 .config

更新虚拟机配置

在已经使用 UEFI 的 Windows 虚拟机上,添加以下配置:

启动虚拟机时,会添加一个 800x600 的帧缓冲设备。VNC 端口会动态分配,可在 vm listvm info guest 下的 console-ports 查看。

其他配置选项

  • 默认创建 PS2 鼠标,适用于旧版本 Windows/FreeBSD。

  • 使用 XHCI 鼠标(体验更佳):

  • FreeBSD 13.0 及以后,启用 HMS 驱动:

  • FreeBSD 13.0 前,使用 misc/utouch-kmod Port。

  • 指定 VNC 监听的主机 IP:

  • 指定 VNC 端口(默认为 5900,可为每台虚拟机指定不同端口):

  • 设置分辨率(默认 800x600,可选以下分辨率):

支持的分辨率有:

  • 等待 VNC 客户端连接(可在安装过程中暂停启动,默认 auto):

输出信息说明

Aug 5, 2016

使用 vm infovm switch info 命令时显示的信息概览。请注意,这些命令可以接受指定的 guest 名称或 switch 名称,但如果未提供,则会输出所有 guest 或 switch 的详细信息。

vm info guest

主要信息

State(状态)

guest 是否正在运行,如果在本地运行,还会显示 bhyve 进程的 PID。

Datastore(数据存储)

guest 存储所在的 vm-bhyve 数据存储名称。数据存储能使用多个 ZFS 数据集或其他文件系统来存储虚拟机。

Loader(引导加载器)

非 UEFI guest 使用的内核加载器类型,为 grubbhyveload

UUID(通用唯一识别码)

guest 自动分配的 UUID。创建 guest 时会生成静态 UUID,可在配置文件中修改。

UEFI(统一可扩展固件接口)

guest 是否配置为使用 UEFI。若使用 BIOS 兼容固件,应设置为 csm

CPU(处理器)

分配给 guest 的 CPU 数量。

Memory(内存)

分配给 guest 的系统内存大小。

Memory Resident(常驻内存)

guest 当前占用的主机内存大小。

控制台端口

列出 guest 配置的各种控制台或图形端口。com 端口会显示连接的 /dev/nmdm 设备,若启用 tmux(仅 1.2 版本),会显示 tmux 会话。图形(VNC)控制台会显示 VNC 服务器监听的 IP 和端口。

网络接口

Number(数字)

接口索引,对应 networkX 配置选项。

Emulation(仿真)

网络硬件仿真类型,通常为 virtio-net,FreeBSD 12 还支持 e1000

Virtual Switch(虚拟交换机)

接口连接的虚拟交换机名称。

Fixed MAC Address(固定的 MAC 地址)

接口的 MAC 地址。所有虚拟接口在运行时分配静态 MAC,可在配置文件中修改。

Fixed Device(固定的设备)

若接口配置为使用特定 tap 设备,会显示在此。可通过手动创建接口并在 guest 配置中使用 networkX_device 指定。

Active Device(活动的设备)

当前 guest 使用的 tap 设备。如果配置了静态设备,应与 Fixed Device 相同。默认情况下,tap 设备在运行时动态创建。

Desc(设备描述)

接口描述,用作内部标识,由 vmnet + guest 名称 + 接口编号 + switch 名称组成。

MTU(最大传输单元)

接口的 MTU,vm-bhyve 会尝试与所连接的虚拟交换机 MTU 匹配。

Bridge(桥)

该虚拟交换机对应的主机 bridge 接口名称。

Bytes In / Bytes Out(已接收 / 发送的字节数)

接口已接收 / 发送的字节数。

虚拟磁盘

Number(数字)

接口内部索引,对应 guest 配置文件中的 diskX 选项。

Device Type(设备类型)

磁盘在主机上的存储类型,可能为稀疏文件(file)、ZVOL 或自定义。

Emulation(仿真)

仿真磁盘设备类型,通常为 virtio-blkahci-hd

Options(参数)

磁盘的附加配置,例如扇区大小、只读设置等。

System Path(系统路径)

磁盘镜像在主机上的路径。

Bytes Size / Bytes Used(总字节数 / 实际使用的字节数)

磁盘镜像总大小 / guest 实际使用的字节数。

vm switch info

主要信息

Type(类型)

虚拟交换机类型。auto 表示由 vm-bhyve 管理,bridge 设备自动创建;manual 表示使用自己在 rc.conf 中配置的 bridge 接口。

Ident(标识)

该交换机对应的实际 bridge 接口。

VLAN(虚拟局域网)

虚拟交换机设置的 VLAN 编号(如果有)。

NAT(网络地址转换)

虚拟交换机是否启用 NAT。

Physical Ports(物理端口)

分配给交换机的主机物理接口列表,vm-bhyve 会将这些接口添加到 bridge。

Bytes In / Bytes Out(接收 / 发送的字节数)

交换机接收 / 发送的字节数。

Virtual Port(虚拟端口)

每个连接到交换机的虚拟机都会显示一个虚拟端口条目。

Device(设备)

连接到交换机的 tap 设备。

VM(虚拟机)

使用该接口的虚拟机名称。

UEFI 引导下的串行控制台输出

Jun 29, 2025

如果你使用 loader="grub",所需的命令会自动注入,以确保串行输出正常。不幸的是,像 Ubuntu 20.20 LTS 这样的现代 Linux 发行版要求使用 UEFI 才能在不修改上游镜像的情况下正确启动。为了启用正确的输出,我们必须修改 guest 内的 grub 配置。

Ubuntu 20.20 LTS

创建文件 /etc/default/grub.d/99-bhyve.cfg,内容如下:

然后运行 update-grub 激活新设置。下次重启后,使用 vm console <guest> 应该可以输出控制台内容。

Ubuntu 22.04 LTS

创建文件 /etc/default/grub.d/99-bhyve.cfg,内容如下:

然后运行 sudo update-grub 激活新设置。下次重启后,使用 vm console <guest> 应该可以输出控制台内容。

CentOS 7

按照 示例模板arrow-up-rightRed Hat 官方文档arrow-up-right 操作,打开 /etc/default/grub 并更新为:

然后运行 grub2-mkconfig -o /boot/efi/EFI/centos/grub.cfg 激活新设置。下次重启后,使用 vm console <guest> 应该可以输出控制台内容。

AlmaLinux 8

按照 示例模板arrow-up-rightRed Hat 官方文档arrow-up-right 操作,使用 root 执行以下命令:

注意:如果你急需通过 VNC 输入管道符号 (|),可以按 Alt+124。参考这里arrow-up-right

下次重启后,使用 vm console <guest> 应该可以输出控制台内容。

迁移虚拟机

Apr 9, 2024

从本地主机迁移虚拟机到远程主机

可以使用单条命令将一个虚拟机完整地从源主机迁移到目标主机。

理想情况下应使用免密码的密钥认证,尽管不是严格必要的。

更多详情请参见手册页:

云镜像

Oct 29, 2024

使用云镜像

你可以使用云镜像来创建虚拟机。vm img 命令会将镜像下载到 datastore,并在需要时解压(支持 .xz.tar.gz.gz 文件)。镜像应为 RAW 或 QCOW2 格式。使用此功能需要安装软件包 qemuqemu-devel

使用官方云镜像启动 FreeBSD:

使用 cloud-init

vm-bhyve 支持为虚拟机提供基础的 cloud-init 配置。可通过 vm create 命令的选项 -C 启用。你还可以使用选项 -k <文件> 将公钥注入虚拟机。使用 cloud-init 需要安装软件包 cdrkit-genisoimage

示例:

Ubuntu 云镜像示例配置文件

vm-bhyve 命令行接口

October, 2025

🔧 全局与系统命令

  • vm version – 显示 vm-bhyve 的版本和修订号。

  • vm init – 初始化 vm-bhyve 目录、默认数据存储和交换机。

  • vm set [setting=value] – 设置全局 vm-bhyve 配置选项。

  • vm get [all|setting] – 显示全局配置或指定选项。

🖧 交换机管理

  • vm switch list – 列出所有定义的虚拟交换机。

  • vm switch info <名称> – 显示指定交换机的信息。

  • vm switch create <名称> – 创建新交换机(可选参数:-t type-i interface 等)。

  • vm switch vlan <名称> <vlan|0> – 为交换机分配 VLAN ID。

  • vm switch nat <名称> <on|off> – 启用或禁用 NAT。

  • vm switch private <名称> <on|off> – 切换私有模式(无外部接口)。

  • vm switch add <名称> <接口> – 为交换机添加物理接口。

  • vm switch remove <名称> <接口> – 从交换机移除接口。

  • vm switch destroy <名称> – 删除交换机。

💾 数据存储管理

  • vm datastore list – 列出所有数据存储。

  • vm datastore add <名称> <路径> – 在指定路径添加数据存储。

  • vm datastore remove <名称> – 删除数据存储。

🖥️ 虚拟机管理

  • vm list – 列出所有虚拟机。

  • vm info <名称> – 显示虚拟机详细信息。

  • vm create <名称> – 创建新虚拟机(可选模板/数据集)。

  • vm install <名称> <iso> – 使用 ISO 启动虚拟机进行安装。

  • vm start <名称> – 启动虚拟机。

  • vm stop <名称> – 优雅停止虚拟机。

  • vm restart <名称> – 重启虚拟机。

  • vm console <名称> – 连接虚拟机控制台(串口或图形界面)。

  • vm configure <名称> – 编辑虚拟机配置文件。

  • vm rename <旧> <新> – 重命名虚拟机。

  • vm add <名称> – 向虚拟机添加磁盘或网卡。

🚀 批量与电源控制

  • vm startall – 启动 /etc/rc.confvm_list=" " 列出的所有虚拟机。

  • vm stopall – 停止所有运行中的虚拟机。

  • vm reset <名称> – 强制重置虚拟机(类似按下重置键)。

  • vm poweroff <名称> – 强制关闭虚拟机。

  • vm destroy <名称> – 删除虚拟机及其资源。

🧩 高级 / 其他

  • vm passthru – 列出可用于 PCI 直通的设备。

  • vm clone <名称> <新名称> – 克隆虚拟机(可选择快照)。

  • vm snapshot <名称> – 创建虚拟机快照。

  • vm rollback <名称@快照> – 回滚虚拟机至指定快照。

💿 镜像 / ISO

  • vm iso [url] – 列出或下载 ISO 镜像。

  • vm img [url] – 列出或下载 raw 镜像文件。

  • vm image list – 列出注册的虚拟机镜像。

  • vm image create <名称> – 从虚拟机创建可复用镜像。

  • vm image destroy <uuid> – 删除镜像。

  • vm image provision <uuid> <新名称> – 从镜像创建新虚拟机。

代码布局

27, 2016

vm-bhyve 文件概览及其用途。

./vm

这是用户运行的主要命令。它几乎不包含逻辑,仅执行一些检查,确保 vm-bhyve 已启用、库文件和 $vm_dir 存在,并且操作系统和当前用户符合要求。如果运行在 ZFS 上,我们会将 $vm_dir 替换为指定数据集的挂载点。然后调用 __parse_cmd 来确定用户想执行的功能。

所有功能都存储在库文件中,通常位于 /usr/local/lib/vm-bhyve/。我们也会在 ./lib/ 中查找库文件,这能让你直接从当前目录运行 vm,便于开发。

./lib/vm-cmd

包含一些 case 语句,用于解析用户请求的命令并运行相应的函数。该文件还包含解析全局 vm 选项的函数。

./lib/vm-config

解析配置文件并返回配置变量的函数。我们有一个简单的配置加载器,它读取配置文件并存储在全局变量中。__config_get 函数在全局变量中查找所请求的设置并返回。由于此文件代码量较小,将来可能会合并到 vm-common

./lib/vm-core

处理基本命令(如 start|stop|install|iso|console 等)的所有函数。大多数命令(除 switch 和 ZFS 特定命令外)都由此文件中的函数处理。该文件以前还包含运行 bhyve 的代码,但因文件过大,已迁移到 vm-run

./lib/vm-guest

包含运行需要启动加载器(bhyveload 或 grub-bhyve)的 guest 所需的代码。以前每个操作系统都有对应函数,现在所有 guest 都由通用的 __guest_load 函数处理。由于该文件现在仅包含两个函数,将来可能会合并回 vm-run

./lib/vm-info

vm-bhyve 有两个“信息”命令(vm info [guest] & vm switch info [switch]),用于输出关于 guest 和 switch 的大量信息。代码量较大,因此单独实现于此文件。

./lib/vm-rctl

为 bhyve 进程分配 rctl 限制的代码。此函数在 bhyve 启动前调用,然后等待 bhyve 启动,因为只要 bhyve 启动,我们的代码会阻塞直到其退出。

./lib/vm-run

启动 bhyve 的主要逻辑。生成 bhyve 设备字符串、创建控制台端口、分配网络接口的代码都在此文件中。我们将 bhyve 命令拆分到不同变量(_devices, _comstring, _opts, _iso_dev),所有 guest 通过一次 bhyve 调用处理。

./lib/vm-switch

处理 vm switch ... 命令的所有代码。还包含 switch 库函数,如 __vm_switch_id,用于根据 switch 名称返回对应的桥接接口名。

./lib/vm-sysrc

处理使用 sysrc 更新配置文件的函数。有时需要在现有配置中追加或删除值,这些操作由此文件中的函数处理。与 vm-config 类似,代码量较小,日后可能合并到 vm-common

./lib/vm-util

包含各种通用工具函数。常用函数如 util::errutil::log 存放在此处。

./lib/vm-zfs

处理所有 ZFS 功能的函数。快照、克隆、回滚以及所有 vm image 命令的代码都在此文件中。

还有函数 __zfs_init,用于在 ZFS 上正确设置 vm-bhyve。在所有情况下 $vm_dir 应为 vm-bhyve 数据的文件系统路径。但在 ZFS 上,用户需提供 "zfs:pool/vm" 而非文件系统路径。__zfs_init 会确保 ZFS 正在运行,然后获取指定数据集的挂载点。如果成功,挂载点存储在 $vm_dir,数据集存储在全局 $VM_ZFS_DATASET 变量中。这样,大部分 vm-bhyve 代码可以像平常一样使用 $vm_dir,需要直接访问 ZFS 数据集的函数可使用 $VM_ZFS_DATASET

代码风格

30, 2016

变量

一般情况下,我们对变量使用以下格式:

除非变量设计为全局变量,否则应始终在当前函数顶部使用 local 声明。函数有时会修改在父函数中声明的变量,在这种情况下,应在函数说明中的 @modifies 列表中列出该变量,以明确该函数会修改其作用域之外的变量。

所有变量都使用花括号访问:${_variable}

函数

大部分函数前缀使用其所属库的名称,以便明确函数的定义来源:

大多数函数前会有简短说明,解释函数的功能,并列出参数和/或返回值,除非代码本身已经非常明显。

私有函数前缀使用 __

代码风格

注释

代码应充分注释,特别是当逻辑不易立即理解时。

缩进与行长

所有代码应正确缩进,使用 4 个空格。行长度应保持合理,如有必要,可使用 \ 将代码分行。

If 语句

If 语句的写法如下。如果有多个语句,应在语句间留空行:

在合适的情况下,可将测试简化为一行,提高简洁性和可读性:

为了简化代码并缩短行长,函数应尽量先进行检查,然后在必要时直接返回或退出,而不是在 if 语句中包含大量代码块,例如:

返回值

在合理情况下,函数成功返回 0,出错返回其他整数。对于返回值,我们更倾向于使用 setvar,而不是 $(func)echo,因为后者需要子 Shell,而不使用子 Shell 已被证明可提升性能。

Case 语句

在一般情况下,;; 应单独换行以提高可读性。唯一例外是当每个 case 仅包含一行时,换行会不必要地增加代码长度。函数调用应对齐:

最后更新于