第 24 章。虚拟化

24.1. 概述

虚拟化软件允许在同一台计算机上同时运行多个操作系统。此类用于 PC 的软件系统通常涉及一个主机操作系统,该操作系统运行虚拟化软件并支持任意数量的客户操作系统。

阅读完本章后,您将了解

  • 主机操作系统和客户操作系统的区别。

  • 如何在以下虚拟化平台上安装 FreeBSD

    • Parallels Desktop(Apple® macOS®)

    • VMware Fusion(Apple® macOS®)

    • VirtualBox™(Microsoft® Windows®, Intel®-based Apple® macOS®, Linux)

    • QEMU(FreeBSD)

    • bhyve(FreeBSD)

  • 如何调整 FreeBSD 系统以在虚拟化下获得最佳性能。

阅读本章前,您应

24.2. FreeBSD 作为 macOS® 上 Parallels Desktop 的客户机

Parallels Desktop for Mac® 是一款商业软件产品,适用于运行 macOS® 10.14.6 或更高版本的 Apple® Mac® 计算机。FreeBSD 是一个完全支持的客户操作系统。在 macOS® 上安装 Parallels 后,用户必须配置虚拟机,然后安装所需的客户操作系统。

24.2.1. 在 Mac® 上的 Parallels Desktop 上安装 FreeBSD

在 Parallels 上安装 FreeBSD 的第一步是创建一个新的虚拟机以安装 FreeBSD。

选择 从 DVD 或映像文件安装 Windows 或其他操作系统,然后继续。

Parallels setup wizard showing Install Windows or another OS from a DVD or image file chosen

选择 FreeBSD 映像文件。

Parallels setup wizard showing FreeBSD image file selected

选择 其他作为操作系统

选择 FreeBSD 将导致启动时出现引导错误。

Parallels setup wizard showing Other selected as operating system

命名虚拟机并选中 在安装前自定义设置

Parallels setup wizard showing the checkbox checked for customizing settings before installation

当配置窗口弹出时,转到 硬件 选项卡,选择 引导顺序,然后单击 高级。然后,选择 EFI 64 位 作为 BIOS

Parallels setup wizard showing EFI 64-bit chosen as BIOS

单击 确定,关闭配置窗口,然后单击 继续

Parallels setup wizard showing the summary of the new virtual machine

虚拟机将自动引导。按照一般步骤安装 FreeBSD。

FreeBSD booted on Parallels

24.2.2. 在 Parallels 上配置 FreeBSD

在 FreeBSD 成功安装在 macOS® X 上的 Parallels 上后,可以采取一些配置步骤来优化系统以进行虚拟化操作。

  1. 设置引导加载程序变量

    最重要的步骤是将 kern.hz 可调参数降低,以减少 Parallels 环境下 FreeBSD 的 CPU 使用率。这是通过在 /boot/loader.conf 中添加以下行来实现的

    kern.hz=100

    如果没有此设置,处于空闲状态的 FreeBSD Parallels 客户机将使用单处理器 iMac® 的大约 15% 的 CPU。更改后,使用率将接近 5%。

    如果安装的是 FreeBSD 14.0 或更高版本,并且 CPU 使用率仍然很高,请在 /boot/loader.conf 中添加以下附加行

    debug.acpi.disabled="ged"
  2. 创建新的内核配置文件

    所有 SCSI、FireWire 和 USB 设备驱动程序都可以从自定义内核配置文件中删除。Parallels 提供一个由 ed(4) 驱动程序使用的虚拟网络适配器,因此除了 ed(4)miibus(4) 之外的所有网络设备都可以从内核中删除。

  3. 配置网络

    最基本的网络设置使用 DHCP 将虚拟机连接到与主机 Mac® 相同的局域网。这可以通过将 ifconfig_ed0="DHCP" 添加到 /etc/rc.conf 来实现。更高级的网络设置在 高级网络 中有描述。

24.3. FreeBSD 作为 macOS® 上 VMware Fusion 的客户机

VMware Fusion for Mac® 是一款商业软件产品,适用于运行 macOS® 12 或更高版本的 Apple® Mac® 计算机。FreeBSD 是一个完全支持的客户操作系统。在 macOS® 上安装 VMware Fusion 后,用户可以配置虚拟机,然后安装所需的客户操作系统。

24.3.1. 在 VMware Fusion 上安装 FreeBSD

第一步是启动 VMware Fusion,它将加载虚拟机库。单击 +→新建 以创建虚拟机

vmware freebsd01

这将加载新建虚拟机助手。选择 创建自定义虚拟机,然后单击 继续 继续。

vmware freebsd02

选择 其他 作为 操作系统,选择 FreeBSD XFreeBSD X 64 位 作为 版本(出现提示时)。

vmware freebsd03

选择固件(推荐 UEFI)

vmware freebsd04

选择 创建新的虚拟磁盘,然后单击 继续

vmware freebsd05

检查配置,然后单击 完成

vmware freebsd06

选择虚拟机的名称以及应保存它的目录。

vmware freebsd07

按 command+E 打开虚拟机设置,然后单击 CD/DVD

vmware freebsd08

选择 FreeBSD ISO 映像或来自 CD/DVD。

vmware freebsd09

启动虚拟机

vmware freebsd10

像往常一样安装 FreeBSD

vmware freebsd11

安装完成后,可以修改虚拟机的设置,例如内存使用量以及虚拟机将访问的 CPU 数量

虚拟机的系统硬件设置无法在虚拟机运行时修改。

vmware freebsd12

CD-ROM 设备的状态。通常,当不再需要 CD/DVD/ISO 时,它会从虚拟机断开连接。

vmware freebsd09

最后要更改的是虚拟机连接到网络的方式。要允许来自主机以外的其他计算机连接到虚拟机,请选择 直接连接到物理网络(桥接)。否则,最好选择 共享主机的互联网连接 (NAT),以便虚拟机可以访问 Internet,但网络无法访问虚拟机。

vmware freebsd13

修改设置后,引导新安装的 FreeBSD 虚拟机。

24.3.2. 在 VMware Fusion 上配置 FreeBSD

在 FreeBSD 成功安装在 macOS® X 上的 VMware Fusion 上后,可以采取一些配置步骤来优化系统以进行虚拟化操作。

  1. 设置引导加载程序变量

    最重要的步骤是将 kern.hz 可调参数降低,以减少 VMware Fusion 环境下 FreeBSD 的 CPU 使用率。这是通过在 /boot/loader.conf 中添加以下行来实现的

    kern.hz=100

    如果没有此设置,处于空闲状态的 FreeBSD VMware Fusion 客户机将使用单处理器 iMac® 的大约 15% 的 CPU。更改后,使用率将接近 5%。

  2. 创建新的内核配置文件

    所有 FireWire 和 USB 设备驱动程序都可以从自定义内核配置文件中删除。VMware Fusion 提供一个由 em(4) 驱动程序使用的虚拟网络适配器,因此除了 em(4) 之外的所有网络设备都可以从内核中删除。

  3. 配置网络

    最基本的网络设置使用 DHCP 将虚拟机连接到与主机 Mac® 相同的局域网。这可以通过将 ifconfig_em0="DHCP" 添加到 /etc/rc.conf 来实现。更高级的网络设置在 高级网络 中有描述。

  4. 安装驱动程序和 open-vm-tools

    要在 VMWare 上流畅运行 FreeBSD,应安装驱动程序

    # pkg install xf86-video-vmware xf86-input-vmmouse open-vm-tools

24.4. FreeBSD 作为 VirtualBox™ 的客户机

FreeBSD 在 VirtualBox™ 中作为客户机运行效果很好。虚拟化软件适用于大多数常见操作系统,包括 FreeBSD 本身。

VirtualBox™ 客户机增强功能提供以下支持

  • 剪贴板共享。

  • 鼠标指针集成。

  • 主机时间同步。

  • 窗口缩放。

  • 无缝模式。

这些命令在 FreeBSD 客户机中运行。

首先,在 FreeBSD 客户机中安装 emulators/virtualbox-ose-additions 软件包或端口。这将安装端口

# cd /usr/ports/emulators/virtualbox-ose-additions && make install clean

将以下行添加到 /etc/rc.conf

vboxguest_enable="YES"
vboxservice_enable="YES"

如果使用 ntpd(8)ntpdate(8),请禁用主机时间同步

vboxservice_flags="--disable-timesync"

Xorg 将自动识别 vboxvideo 驱动程序。它也可以在 /etc/X11/xorg.conf 中手动输入

Section "Device"
	Identifier "Card0"
	Driver "vboxvideo"
	VendorName "InnoTek Systemberatung GmbH"
	BoardName "VirtualBox Graphics Adapter"
EndSection

要使用 vboxmouse 驱动程序,请调整 /etc/X11/xorg.conf 中的鼠标部分

Section "InputDevice"
	Identifier "Mouse0"
	Driver "vboxmouse"
EndSection

用于在主机和虚拟机之间进行文件传输的共享文件夹可以通过使用 mount_vboxvfs 将其挂载来访问。可以使用 VirtualBox GUI 或通过 vboxmanage 在主机上创建共享文件夹。例如,要在名为 BSDBox 的虚拟机中为 /mnt/bsdboxshare 下创建一个名为 myshare 的共享文件夹,请运行

# vboxmanage sharedfolder add 'BSDBox' --name myshare --hostpath /mnt/bsdboxshare

请注意,共享文件夹名称中不能包含空格。像这样从客户机系统中挂载共享文件夹

# mount_vboxvfs -w myshare /mnt

24.5. FreeBSD 作为 VirtualBox™ 的主机

VirtualBox™ 是一个积极开发的完整虚拟化软件包,适用于大多数操作系统,包括 Windows®、macOS®、Linux® 和 FreeBSD。它同样能够运行 Windows® 或类似 UNIX® 的客户机。它作为开源软件发布,但闭源组件在单独的扩展包中提供。这些组件包括对 USB 2.0 设备的支持。可以在 VirtualBox™ wiki 的下载页面 上找到更多信息。目前,这些扩展程序不适用于 FreeBSD。

24.5.1. 安装 VirtualBox™

VirtualBox™ 可在 FreeBSD 包或端口中获取,位于 emulators/virtualbox-ose。可以使用以下命令安装端口

# cd /usr/ports/emulators/virtualbox-ose
# make install clean

端口配置菜单中一个有用的选项是 GuestAdditions 程序套件。这些程序在客户机操作系统中提供了许多有用的功能,例如鼠标指针集成(允许在主机和客户机之间共享鼠标,无需按下特殊的键盘快捷键来切换)以及更快的视频渲染,尤其是在 Windows® 客户机中。在完成客户机安装后,可以通过 设备 菜单访问客户机扩展功能。

在首次启动 VirtualBox™ 之前,需要进行一些配置更改。该端口在 /boot/modules 中安装一个内核模块,该模块必须加载到正在运行的内核中

# kldload vboxdrv

为了确保模块在每次重启后始终加载,请将以下行添加到 /boot/loader.conf

vboxdrv_load="YES"

要使用允许桥接或主机专用网络的内核模块,请将以下行添加到 /etc/rc.conf 并重启计算机

vboxnet_enable="YES"

vboxusers 组在安装 VirtualBox™ 时创建。所有需要访问 VirtualBox™ 的用户都必须被添加为该组的成员。可以使用 pw 添加新成员

# pw groupmod vboxusers -m yourusername

/dev/vboxnetctl 的默认权限非常严格,需要更改才能进行桥接网络

# chown root:vboxusers /dev/vboxnetctl
# chmod 0660 /dev/vboxnetctl

要使此权限更改永久生效,请将以下行添加到 /etc/devfs.conf

own     vboxnetctl root:vboxusers
perm    vboxnetctl 0660

要启动 VirtualBox™,请从 Xorg 会话中输入以下命令

% VirtualBox

有关配置和使用 VirtualBox™ 的更多信息,请参阅 官方网站。有关 FreeBSD 特定信息和故障排除说明,请参阅 FreeBSD wiki 中的相关页面

24.5.2. VirtualBox™ USB 支持

VirtualBox™ 可以配置为将 USB 设备传递给客户机操作系统。OSE 版本的主机控制器仅限于模拟 USB 1.1 设备,直到支持 USB 2.0 和 3.0 设备的扩展包在 FreeBSD 上可用。

要使 VirtualBox™ 能够识别连接到机器的 USB 设备,用户需要成为 operator 组的成员。

# pw groupmod operator -m yourusername

然后,将以下内容添加到 /etc/devfs.rules 中,如果该文件尚不存在,则创建该文件

[system=10]
add path 'usb/*' mode 0660 group operator

要加载这些新规则,请将以下内容添加到 /etc/rc.conf

devfs_system_ruleset="system"

然后,重新启动 devfs

# service devfs restart

重新启动登录会话和 VirtualBox™ 以使这些更改生效,并根据需要创建 USB 过滤器。

24.5.3. VirtualBox™ 主机 DVD/CD 访问

通过共享物理驱动器来实现从客户机访问主机 DVD/CD 驱动器。在 VirtualBox™ 中,可以通过虚拟机设置中的存储窗口进行设置。如果需要,首先创建一个空的 IDECD/DVD 设备。然后,从虚拟 CD/DVD 驱动器选择弹出菜单中选择主机驱动器。将出现一个标记为 Passthrough 的复选框。这允许虚拟机直接使用硬件。例如,只有选择此选项时,音频 CD 或刻录机才会起作用。

为了让用户能够使用 VirtualBox™DVD/CD 功能,他们需要访问 /dev/xpt0/dev/cdN/dev/passN。这通常通过将用户设为 operator 的成员来实现。通过将以下行添加到 /etc/devfs.conf 来更正对这些设备的权限

perm cd* 0660
perm xpt0 0660
perm pass* 0660
# service devfs restart

24.6. 在 FreeBSD 上使用 QEMU 进行虚拟化

QEMU 是一种通用的机器模拟器和虚拟化器,是完全开源的软件。它由一个庞大而活跃的社区开发,并为 FreeBSD、OpenBSD 和 NetBSD 以及其他操作系统提供支持。

  • QEMU 可以通过多种不同的方式使用。最常见的是系统模拟,它提供整个机器(CPU、内存和模拟设备)的虚拟模型以运行客户机操作系统。在这种模式下,CPU 可以完全模拟,也可以与 KVMXenHypervisor.Framework 等虚拟机管理程序一起工作,以允许客户机直接在主机 CPU 上运行。

  • QEMU 支持的第二种使用方式是用户模式模拟,QEMU 可以启动为一个 CPU 编译的进程在另一个 CPU 上运行。在这种模式下,CPU 始终被模拟。

  • QEMU 还提供了一些独立的命令行实用程序,例如 qemu-img(1) 磁盘镜像实用程序,允许用户创建、转换和修改磁盘镜像。

QEMU 可以模拟大量体系结构,包括 Arm™i386x86_64MIPS™s390XSPARC™(Sparc™ 和 Sparc64™)等。QEMU 系统模拟器目标 列表定期更新。

本节介绍如何在 FreeBSD 上使用 QEMU 进行系统模拟和用户模式模拟,并提供使用 QMEU 命令和命令行实用程序的示例。

24.6.1. 安装 QEMU 软件

QEMU 可作为 FreeBSD 包或端口获取,位于 emulators/qemu。包构建包括大多数用户的合理选项和默认值,是推荐的安装方法。

# pkg install qemu

包安装包括多个依赖项。安装完成后,创建一个指向最常使用的 QEMU 主机版本的链接。如果主机是将要使用的 Intel™ 或 AMD™ 64 位系统

# ln -s /usr/local/bin/qemu-system-x86_64 /usr/local/bin/qemu

通过运行以下命令作为非 root 用户来测试安装

% qemu

这将弹出一个窗口,其中 QEMU 正在积极尝试从硬盘、软盘、DVD/CD 和 PXE 启动。尚未设置任何内容,因此该命令将产生多个错误并以“无可引导设备”结束,如 图 1 所示。但是,它确实表明 QEMU 软件已正确安装。

QEMU with no bootable image
图 1. QEMU 没有可引导映像

24.6.2. 虚拟机安装

QEMU 处于非常活跃的开发阶段。功能和命令选项可能在不同版本之间有所不同。本节提供使用 QEMU 9.0.1 版本(2024 年夏季)开发的示例。如有疑问,请始终参考 QEMU 文档,尤其是 关于 QEMU 页面,其中包含指向支持的构建平台、模拟、弃用功能和已删除功能的链接。

按照以下步骤创建两个名为“left”和“right”的虚拟机。大多数命令可以在没有 root 权限的情况下执行。

  1. 创建一个用于与 QEMU 协作的测试环境

    % mkdir -p ~/QEMU  ~/QEMU/SCRIPTS  ~/QEMU/ISO  ~/QEMU/VM

    SCRIPTS 目录用于启动脚本和实用程序。ISO 目录用于客户机 ISO 启动映像。VM 目录是虚拟机映像 (VMs) 的存放位置。

  2. 将 FreeBSD 的最新版本下载到 ~/QEMU/ISO

    % cd ~/QEMU/ISO
    % fetch https://download.freebsd.org/releases/ISO-IMAGES/14.1/FreeBSD-14.1-RELEASE-amd64-bootonly.iso

    下载完成后,创建一个简写链接。此简写链接在下面的启动脚本中使用。

    % ln -s FreeBSD-14.1-RELEASE-amd64-bootonly.iso  fbsd.iso
  3. 将目录更改到虚拟机的位置 (~/QEMU/VM)。运行 qemu-img(1) 为“left”VM 创建磁盘映像

    % cd ~/QEMU/VM
    % qemu-img create -f raw  left.img   15G

    QEMU raw 格式专为性能而设计。该格式简单直观,没有开销,这使其更快,尤其是在高性能或高吞吐量的情况下。用例是最大限度地提高性能,其中不需要其他功能,例如快照。此格式在下面的“left”VM 的脚本中使用。

    另一种格式是 qcow2,它使用 QEMU 的“写时复制”技术来管理磁盘空间。此技术不需要完整的 15G 磁盘,只需要一个由 VM 直接管理的存根版本。磁盘会随着 VM 写入而动态增长。此格式支持快照、压缩和加密。此格式的用例是开发、测试和需要这些高级功能的情况。此格式在下面的“right”VM 的脚本中使用。

    再次运行 qemu-img(1) 使用 qcow2 为“right”VM 创建磁盘映像

    % qemu-img create -f qcow2 -o preallocation=full,cluster_size=512K,lazy_refcounts=on right.qcow2 20G

    要查看文件的实际大小,请使用

    % du -Ah right.qcow2
  4. 使用以下命令为两个虚拟机设置网络。在此示例中,主机网络接口是 em0。如果需要,请将其更改为适合主机系统的接口。必须在每次主机机器重启后执行此操作,才能启用 QEMU 客户机 VM 与网络通信。

    # ifconfig tap0 create
    # ifconfig tap1 create
    # sysctl net.link.tap.up_on_open=1
    net.link.tap.up_on_open: 0 -> 1
    # sysctl net.link.tap.user_open=1
    net.link.tap.user_open: 0 -> 1
    # ifconfig bridge0 create
    # ifconfig bridge0 addm tap0 addm tap1 addm em0
    # ifconfig bridge0 up

    上面的命令创建了两个 tap(4) 设备 (tap0tap1) 和一个 if_bridge(4) 设备 (bridge0)。然后,它们将 tap 设备和本地主机接口 (em0) 添加到 bridge,并设置两个 sysctl(8) 条目以允许普通用户打开 tap 设备。这些命令将允许虚拟机与主机上的网络堆栈进行通信。

  5. 更改到 ~/QEMU/SCRIPTS,使用以下脚本启动第一个虚拟机“left”。此脚本使用 QEMU raw 磁盘格式。

    /usr/local/bin/qemu-system-x86_64  -monitor none \
      -cpu qemu64 \
      -vga std \
      -m 4096 \
      -smp 4   \
      -cdrom ../ISO/fbsd.iso \
      -boot order=cd,menu=on \
      -blockdev driver=file,aio=threads,node-name=imgleft,filename=../VM/left.img \
      -blockdev driver=raw,node-name=drive0,file=imgleft \
      -device virtio-blk-pci,drive=drive0,bootindex=1  \
      -netdev tap,id=nd0,ifname=tap0,script=no,downscript=no,br=bridge0 \
      -device e1000,netdev=nd0,mac=02:20:6c:65:66:74 \
      -name \"left\"

将上述内容保存到一个文件中(例如 left.sh),然后简单地运行:% /bin/sh left.sh

QEMU 将在单独的窗口中启动一个虚拟机并启动 FreeBSD iso,如 图 2 所示。所有命令选项(例如 -cpu-boot)都在 QEMU 手册页 qemu(1) 中进行了详细说明。

The FreeBSD loader menu.
图 2. FreeBSD 启动加载程序菜单

如果在 QEMU 控制台窗口中单击鼠标,QEMU 将“捕获”鼠标,如 图 3 所示。键入 Ctl+Alt+G”以释放鼠标。

When QEMU has grabbed the mouse
图 3. QEMU 捕获鼠标时

在 FreeBSD 上,初始 QEMU 安装可能比较慢。这是因为模拟器在首次使用磁盘时会写入文件系统格式和元数据。后续操作通常要快得多。

在安装过程中,需要注意以下几点

  • 选择使用 UFS 作为文件系统。ZFS 在内存较小的情况下性能不佳。

  • 对于网络,请使用 DHCP。如果需要,请配置 IPv6(如果本地 LAN 支持)。

  • 添加默认用户时,确保他们属于 wheel 组。

安装完成后,虚拟机将重新启动到新安装的 FreeBSD 映像中。

root 身份登录,并按如下方式更新系统

# freebsd-update fetch install
# reboot

安装成功后,QEMU 将启动磁盘上安装的操作系统,而不是安装程序。

QEMU 支持一个 -runas 选项。为了增加安全性,请在上面的脚本列表中包含选项“ -runas your_user_name”。有关详细信息,请参阅 qemu(1)

再次以 root 用户身份登录,并添加所需的任何软件包。要在客户机中使用 X Window 系统,请参阅下面的“使用 X Window 系统”部分。

这完成了“左侧”VM 的设置。

要安装“右侧”VM,请运行以下脚本。此脚本包含对 tap1、format=qcow2、映像文件名、MAC 地址和终端窗口名称的修改。如果需要,请包括如上所述的“-runas”参数。

/usr/local/bin/qemu-system-x86_64  -monitor none \
  -cpu qemu64 \
  -vga cirrus \
  -m 4096  -smp 4   \
  -cdrom ../ISO/fbsd.iso \
  -boot order=cd,menu=on \
  -drive if=none,id=drive0,cache=writeback,aio=threads,format=qcow2,discard=unmap,file=../VM/right.qcow2 \
  -device virtio-blk-pci,drive=drive0,bootindex=1  \
  -netdev tap,id=nd0,ifname=tap1,script=no,downscript=no,br=bridge0 \
  -device e1000,netdev=nd0,mac=02:72:69:67:68:74 \
  -name \"right\"

安装完成后,“左侧”和“右侧”机器可以相互通信,也可以与主机通信。如果主机上有严格的防火墙规则,请考虑添加或修改规则以允许桥接设备和 tap 设备相互通信。

24.6.3. 使用技巧

24.6.3.1. 使用 X Window 系统

安装 Xorg 描述了如何设置 X Window 系统。请参考该指南进行初始 X Window 设置,然后查阅 桌面环境 以了解如何设置完整的桌面。

本节演示了 XFCE 桌面的使用。

安装完成后,以普通用户身份登录,然后键入

% startx

XFCE4 窗口管理器应该启动并显示一个正常工作的图形桌面,如 图 4 所示。在初始启动时,显示桌面可能需要长达一分钟的时间。有关使用详情,请参阅 XFCE 网站 上的文档。

Both QEMU VMs
图 4. 两个 QEMU VM

为客户机系统添加更多内存可能会加快图形用户界面的速度。

这里,“左侧”VM 已安装 X Window 系统,而“右侧”VM 仍处于文本模式。

24.6.3.2. 使用 QEMU 窗口

QEMU 窗口充当完整的 FreeBSD 控制台,能够运行多个虚拟终端,就像裸机系统一样。

要切换到另一个虚拟控制台,请单击 QEMU 窗口并键入 Alt+F2Alt+F3。FreeBSD 应该切换到另一个虚拟控制台。 图 5 显示了“左侧”VM 在 ttyv3 上显示虚拟控制台。

Switching to Another Virtual Console in the QEMU Window
图 5. 在 QEMU 窗口中切换到另一个虚拟控制台

主机当前的桌面管理器或窗口管理器可能已经为 Alt+F1Alt+F2 键序列设置了另一个功能。如果是这样,请尝试键入 Ctl+Alt+F1Ctl+Alt+F2 或其他类似的键组合。有关详细信息,请查看窗口管理器或桌面管理器文档。

24.6.3.3. 使用 QEMU 窗口菜单

QEMU 窗口的另一个功能是 查看 菜单和缩放控件。最有用的是 适合缩放。单击此菜单选项后,就可以通过单击窗口角控件并调整窗口大小来调整 QEMU 窗口的大小。 图 6 显示了在图形模式下调整“左侧”窗口大小的效果。

Using the View Menu `Zoom to Fit` Option
图 6. 使用“查看”菜单的 适合缩放 选项

24.6.3.4. 其他 QEMU 窗口菜单选项

查看 菜单中还显示了

  • cirrus-vgaserial0parallel0 选项。这些选项允许将输入/输出切换到选定的设备。

QEMU 窗口的 机器 菜单允许对客户机 VM 进行四种类型的控制

  • 暂停 允许暂停 QEMU 虚拟机。这可能有助于冻结快速滚动的窗口。

  • 重置 立即将虚拟机重置为冷“开机”状态。与真实机器一样,除非绝对必要,否则不建议这样做。

  • 关机 模拟 ACPI 关机信号,操作系统将进行正常关机。

  • 退出 立即关闭虚拟机 - 除非必要,否则也不建议这样做。

24.6.4. 向客户机 VM 添加串行端口接口

要实现串行控制台,运行 FreeBSD 的客户机 VM 需要插入

console="comconsole"

/boot/loader.conf 中,以允许使用 FreeBSD 串行控制台。

以下更新的配置显示了如何在客户机 VM 上实现串行控制台。运行脚本以启动 VM。

# left+serial.sh
echo
echo "NOTE: telnet startup server running on guest VM!"
echo "To start QEMU, start another session and telnet to localhost port 4410"
echo

/usr/local/bin/qemu-system-x86_64  -monitor none \
  -serial telnet:localhost:4410,server=on,wait=on\
  -cpu qemu64 \
  -vga std \
  -m 4096 \
  -smp 4   \
  -cdrom ../ISO/fbsd.iso \
  -boot order=cd,menu=on \
  -blockdev driver=file,aio=threads,node-name=imgleft,filename=../VM/left.img \
  -blockdev driver=raw,node-name=drive0,file=imgleft \
  -device virtio-blk-pci,drive=drive0,bootindex=1  \
  -netdev tap,id=nd0,ifname=tap0,script=no,downscript=no,br=bridge0 \
  -device e1000,netdev=nd0,mac=02:20:6c:65:66:74 \
  -name \"left\"
qemu freebsd07
图 7. 通过 TCP 启用串行端口

图 7 中,串行端口在 VM 启动时重定向到主机系统上的 TCP 端口,QEMU 监视器等待 (wait=on) 激活客户机 VM,直到 telnet(1) 连接到指定的本地主机端口。在收到来自独立会话的连接后,FreeBSD 系统开始启动并查找 /boot/loader.conf 中的控制台指令。使用指令“console=comconsole”,FreeBSD 在串行端口上启动控制台会话。QEMU 监视器检测到这一点,并将该串行端口上的必要字符 I/O 指向主机上的 telnet 会话。系统启动并完成启动后,登录提示在串行端口 (ttyu0) 和控制台 (ttyv0) 上启用。

重要的是要注意,这种通过 TCP 的串行重定向发生在虚拟机之外。它与虚拟机上的任何网络都没有交互,因此不受任何防火墙规则的影响。把它想象成一个连接到真实机器上 RS-232 或 USB 端口上的哑终端。

24.6.4.1. 有关使用串行控制台的注意事项

在串行控制台上,如果调整窗口大小,请执行 resizewin(1) 以更新终端大小。

可能需要(甚至必须)阻止将 syslog 消息发送到控制台(QEMU 控制台和串行端口)。有关重定向控制台消息的详细信息,请参阅 syslog.conf(5)

更新 /boot.loader.conf 以允许串行控制台后,客户机 VM 每次都会尝试从串行端口启动。确保串行端口已启用,如上面的列表所示,或者更新 /boot/loader.conf 文件以不要求串行控制台。

24.6.5. QEMU 用户模式仿真

QEMU 还支持运行在与主机 CPU 不同的架构上预编译的应用程序。例如,可以在 x86_64 主机上运行 Sparc64 架构的操作系统。这将在下一节中演示。

24.6.5.1. 在 x86_64 主机上设置 SPARC64 客户机 VM

使用与主机不同的架构设置新的 VM 包括以下几个步骤

  • 获取将在客户机 VM 上运行的软件

  • 为客户机 VM 创建新的磁盘映像

  • 使用新架构设置新的 QEMU 脚本

  • 执行安装

在以下过程中,使用 OpenBSD 6.8 SPARC64 软件的副本进行此 QEMU 用户模式仿真练习。

并非所有版本的 OpenBSD Sparc64 都可以在 QEMU 上运行。已知 OpenBSD 版本 6.8 可以运行,并被选为本节的示例。

  1. 从 OpenBSD 档案下载 OpenBSD 6.8 Sparc64。

    在 OpenBSD 下载站点上,只维护最新的版本。需要搜索档案才能获取过去的版本。

    % cd ~/QEMU/ISO
    % fetch https://mirror.planetunix.net/pub/OpenBSD-archive/6.8/sparc64/install68.iso
  2. 为 Sparc64 VM 创建新的磁盘映像类似于上面的“右侧”VM。本例使用 QEMU qcow2 格式作为磁盘

    % cd ~/QEMU/VM
    qemu-img create -f qcow2 -o preallocation=full,lazy_refcounts=on sparc64.qcow2 16G
  3. 使用以下脚本作为新的 Sparc64 架构。与上面的示例一样,运行脚本,然后启动新的会话并 telnet 到指定的端口上的本地主机

    echo
    echo "NOTE: telnet startup server running on guest VM!"
    echo "To start QEMU, start another session and telnet to localhost port 4410"
    echo
    
    /usr/local/bin/qemu-system-sparc64 \
      -serial telnet:localhost:4410,server=on,wait=on \
      -machine sun4u,usb=off \
      -smp 1,sockets=1,cores=1,threads=1 \
      -rtc base=utc \
      -m 1024 \
      -boot d \
      -drive file=../VM/sparc64.qcow2,if=none,id=drive-ide0-0-1,format=qcow2,cache=none \
      -cdrom ../ISO/install68.iso \
      -device ide-hd,bus=ide.0,unit=0,drive=drive-ide0-0-1,id=ide0-0-1 \
      -msg timestamp=on \
      -net nic,model=sunhme -net user \
      -nographic \
      -name \"sparc64\"

请注意以下几点

  • -boot d 选项从 QEMU CDROM 设备启动,该设备设置为 -cdrom ../ISO/install68.iso

  • 与以前一样,telnet 服务器选项设置为在端口 4410 上等待独立连接。启动另一个会话并使用 telnet(1) 连接到端口 4410 上的本地主机。

  • 脚本设置了 -nographic 选项,这意味着只有串行端口 I/O。没有图形界面。

  • 网络不是通过 tap(4) / if_bridge(4) 组合设置的。本例使用 QEMU 网络的另一种方法,称为“串行线互联网协议”(SLIRP),有时也称为“用户模式网络”。有关此方法和其他 QEMU 网络方法的文档,请参阅:QEMU 网络文档

如果一切都设置正确,系统将按 图 8 所示启动。

qemu freebsd08
图 8. QEMU 在用户模式仿真期间从 CDROM 启动 OpenBSD 6.8 Sparc64

系统安装完成后,修改脚本并将启动参数更改为 -boot c。这将指示 QEMU 从提供的硬盘启动,而不是从 CDROM 启动。

已安装的系统可以使用起来与其他客户机虚拟机一样。但是,客户机的底层架构是 Sparc64,而不是 x86_64。

如果系统在 OpenBios 控制台提示符 0 > 处停止,请输入 power-off 以退出系统。

图 9 显示了已安装系统的 root 登录并运行 uname(1)

qemu freebsd09
图 9. QEMU 在用户模式仿真期间从 CDROM 启动

24.6.6. 使用 QEMU 监视器

QEMU 监视器 控制正在运行的 QEMU 模拟器(客户机 VM)。

使用监视器,可以

  • 动态添加或删除设备,包括磁盘、网络接口、CD-ROM 或软盘。

  • 冻结/解冻来宾 VM,并从磁盘文件保存或恢复其状态。

  • 收集有关 VM 和设备状态的信息。

  • 动态更改设备设置。

以及许多其他操作。

监控器的最常见用途是检查 VM 的状态,以及添加、删除或更改设备。一些操作(例如迁移)仅在 KVM、Xen 等虚拟机管理程序加速器下可用,并且在 FreeBSD 主机上不支持。

在使用图形桌面环境时,使用 QEMU 监控器最简单的方法是在从终端会话启动 QEMU 时使用 -monitor stdio 选项。

# /usr/local/bin/qemu-system-x86_64  -monitor stdio \
  -cpu qemu64 \
  -vga cirrus \
  -m 4096  -smp 4   \
  ...

这将在终端窗口中生成一个新的提示 (qemu),如 图 10 所示。

qemu freebsd13
图 10. QEMU 监控器提示和 "stop" 命令

该图还显示了 stop 命令在 FreeBSD 启动序列期间冻结系统。系统将保持冻结状态,直到在监控器中输入 cont 命令。

24.6.6.1. 向 VM 添加新磁盘

要向正在运行的 VM 添加新磁盘,需要按照上述步骤准备磁盘。

% cd ~/QEMU/VM
% qemu-img create -f raw  new10G.img  10G

图 11 显示了在 VM 中添加新磁盘所需的监控器命令序列。一旦在监控器中使用 device_add 命令添加了设备,它就会显示在图的下部所示的 FreeBSD 系统控制台上。可以根据需要配置磁盘。

请注意,如果要在 VM 重启后使用新磁盘,则必须将其添加到启动脚本中。

qemu freebsd14
图 11. 添加新磁盘的 QEMU 监控器命令

24.6.6.2. 使用 QEMU 监控器管理快照

QEMU 的文档在使用术语 快照 时描述了几个类似的概念。命令行上有一个 -snapshot 选项,它指的是使用驱动器或驱动器的一部分来包含设备副本。然后是监控器命令 snapshot_blkdevsnapshot_blkdev_internal,它们描述了实际复制 blockdev 设备的行为。最后,有监控器命令 savevmloadvmdelvm 命令,它们指的是创建和保存、加载或删除整个虚拟机的副本。除最后者外,监控器 info snapshots 命令还列出了最近快照的详细信息。

本节将重点介绍创建、保存和加载完整的 VM 映像,并将为此目的使用术语 快照

首先,从头开始重新创建 "left" VM,这次使用 qcow2 格式。

% cd ~/QEMU/VM
% rm left.img
% qemu-img create -f qcow2 left.qcow2 16G  # Clean file for a new FreeBSD installation.
% cd ../SCRIPTS
# /bin/sh left.sh                     # See the below program listing.

安装完成后,重启,这次使用 -monitor stdio 选项以允许使用监控器。

# left VM script.
/usr/local/bin/qemu-system-x86_64  -monitor stdio \
  -cpu qemu64 \
  -vga std \
  -m 4096 \
  -smp 4   \
  -cdrom ../ISO/fbsd.iso \
  -boot order=cd,menu=on \
  -blockdev driver=file,aio=threads,node-name=imgleft,filename=../VM/left.qcow2 \
  -blockdev driver=qcow2,node-name=drive0,file=imgleft \
  -device virtio-blk-pci,drive=drive0,bootindex=1  \
  -netdev tap,id=nd0,ifname=tap0,script=no,downscript=no,br=bridge0 \
  -device e1000,netdev=nd0,mac=02:20:6c:65:66:74 \
  -name \"left\"

为了演示快照,可以使用以下步骤。

  1. 从头开始安装 FreeBSD。

  2. 准备环境并使用 savevm 监控器命令创建快照。

  3. 安装多个软件包。

  4. 关闭系统。

  5. 重新启动一个裸 QEMU 实例并利用监控器命令 loadvm 来恢复 VM。

  6. 观察到恢复的 VM 没有任何软件包。

在 "准备环境" 步骤中,在单独的虚拟控制台 (ttyv1) 上,使用 vi(1) 启动一个编辑会话,模拟用户活动。如果需要,可以启动其他程序。快照应考虑快照创建时所有正在运行的应用程序的状态。

图 12 显示了新安装的 FreeBSD 系统,没有软件包,以及 ttyv1 上的编辑会话。此时 vi(1) 编辑器处于 插入 模式,输入者正在键入单词 "broadcast"。

qemu freebsd15
图 12. 首次快照之前的 QEMU VM

要生成快照,在监控器中输入 savevm。确保为其提供一个标签(例如 original_install)。

QEMU 9.0.1 monitor - type 'help' for more information
(qemu)
(qemu) savevm original_install

接下来,在主控制台窗口中,安装一个软件包,例如 zip(1),它没有依赖项。完成后,重新进入监控器并创建另一个快照 (snap1_pkg+zip)。

图 13 显示了上述命令的结果以及 info shapshots 命令的输出。

qemu freebsd16
图 13. 使用监控器命令创建快照的 QEMU

重启系统,并在 FreeBSD 启动之前,切换到监控器并输入 stop。VM 将停止。

输入 loadvm,并使用上面使用的标签(这里为 original_install)。

QEMU 9.0.1 monitor - type 'help' for more information
(qemu) stop
(qemu) loadvm original_install
(qemu) cont

VM 屏幕将立即切换到上面输入 savevm 命令的确切时刻。请注意,VM 仍然处于停止状态。

输入 cont 启动 VM,切换到 ttyv1 上的编辑会话,并在键盘上键入一个字母。编辑器仍然处于插入模式,应该做出相应的响应。快照创建时运行的任何其他程序都应该不受影响。

上述步骤展示了如何创建快照、修改系统,然后通过恢复先前的快照来 "回滚" 系统。

默认情况下,QEMU 将快照数据存储在与映像相同的文件中。使用 qemu-img(1) 查看快照列表,如下面的 图 14 所示。

qemu freebsd17
图 14. 使用 qemu-img(1) 检查快照的 QEMU

24.6.7. 使用 QEMU USB 设备

QEMU 支持创建由映像文件支持的虚拟 USB 设备。这些是虚拟 USB 设备,可以像真实的 USB 设备一样进行分区、格式化、挂载和使用。

/usr/local/bin/qemu-system-x86_64  -monitor stdio \
  -cpu qemu64 \
  -vga cirrus \
  -m 4096  -smp 4   \
  -cdrom ../ISO/fbsd.iso \
  -boot order=cd,menu=on \
  -drive if=none,id=usbstick,format=raw,file=../VM/foo.img \
  -usb \
  -device usb-ehci,id=ehci \
  -device usb-storage,bus=ehci.0,drive=usbstick \
  -device usb-mouse \
  -blockdev driver=file,node-name=img1,filename=../VM/right.qcow2 \
  -blockdev driver=qcow2,node-name=drive0,file=img1 \
  -device virtio-blk-pci,drive=drive0,bootindex=1  \
  -netdev tap,id=nd0,ifname=tap1,script=no,downscript=no,br=bridge0 \
  -device e1000,netdev=nd0,mac=02:72:69:67:68:74 \
  -name \"right\"

此配置包括一个 -drive 规范,它具有 id=usbstick、raw 格式和一个映像文件(必须由 qemu-img(1) 创建)。下一行包含一个 -device usb-ehci 规范,用于 USB EHCI 控制器,其 id=ehci。最后,一个 -device usb-storage 规范将上述驱动器连接到 EHCI USB 总线。

当系统启动时,FreeBSD 将识别一个 USB 集线器,添加连接的 USB 设备,并将其分配给 da0,如 图 15 所示。

qemu freebsd12
图 15. QEMU 创建的 USB 集线器和大容量存储设备

该设备已准备好使用 gpart(8) 进行分区,并使用 newfs(8) 进行格式化。因为 USB 设备由 qemu-img(1) 创建的文件支持,所以写入设备的数据将在重启后保留。

24.6.8. 通过直通使用主机 USB 设备

QEMU USB 直通支持在 9.0.1 版(2024 年夏季)中被列为实验性功能。但是,以下步骤展示了如何将挂载在主机上的 USB 闪存盘供来宾 VM 使用。

有关更多信息和示例,请参见

图 16 的上半部分显示了 QEMU 监控器命令。

  • info usbhost 显示有关主机系统上所有 USB 设备的信息。在主机系统上找到所需的 USB 设备,并记下该行上的两个十六进制值。(在下面的示例中,主机 USB 设备是 Memorex Mini,其供应商 ID 为 0718,产品 ID 为 0619。)在下面的 device_add 步骤中使用 info usbhost 命令显示的两个值。

  • device_add 将 USB 设备添加到来宾 VM。

qemu freebsd18
图 16. 访问主机上 USB 设备的 QEMU 监控器命令

如前所述,一旦 device_add 完成,FreeBSD 内核就会识别一个新的 USB 设备,如 . 的下半部分所示。

使用新设备的步骤如 图 17 所示。

qemu freebsd19
图 17. 通过直通使用主机 USB 设备

如果 USB 设备格式化为 FAT16 或 FAT32 文件系统,则可以使用 mount_msdosfs(8) 将其作为 MS-DOS™ 文件系统挂载,如所示示例。/etc/hosts 文件被复制到新挂载的驱动器,并进行校验和以验证 USB 设备上文件的完整性。然后使用 umount(8) 将设备卸载。

如果 USB 设备使用 NTFS 格式化,则需要安装 fusefs-ntfs 软件包并使用 ntfs-3g(8) 访问设备。

# pkg install fusefs-ntfs
# kldload fusefs
# gpart show da1
# ntfs-3g /dev/da1s1 /mnt

Access the drive as needed.  When finished:

# umount /mnt

更改上面的设备标识符以匹配已安装的硬件。有关使用 NTFS 文件系统的更多信息,请咨询 ntfs-3g(8)

24.6.9. FreeBSD 上的 QEMU 总结

如上所述,QEMU 与几种不同的虚拟机管理程序加速器配合使用。

QEMU 支持的 虚拟化加速器 列表包括

  • KVM 在 Linux 上支持 64 位 Arm、MIPS、PPC、RISC-V、s390x 和 x86

  • Xen 在 Linux 上作为 dom0 支持 Arm、x86

  • Hypervisor Framework (hvf) 在 MacOS 上支持 x86 和 Arm(仅限 64 位)

  • Windows Hypervisor Platform (whpx) 在 Windows 上支持 x86

  • NetBSD Virtual Machine Monitor (nvmm) 在 NetBSD 上支持 x86

  • Tiny Code Generator (tcg) 在 Linux 和其他 POSIX、Windows、MacOS 上支持 Arm、x86、Loongarch64、MIPS、PPC、s390x 和 Sparc64。

本节中的所有示例都使用了 Tiny Code Generator (tcg) 加速器,因为这是目前 FreeBSD 上唯一支持的加速器。

24.7. 使用 bhyve 的 FreeBSD 作为主机

bhyve 是一款基于 BSD 许可证的虚拟机管理程序,从 FreeBSD 10.0-RELEASE 开始成为系统基础的一部分。该虚拟机管理程序支持多种虚拟机,包括 FreeBSD、OpenBSD、许多 Linux® 发行版和 Microsoft Windows®。默认情况下,bhyve 提供对串行控制台的访问,但不会模拟图形控制台。它利用了较新 CPU 的虚拟化卸载功能,以避免使用指令转换和手动管理内存映射等传统方法。

bhyve 的设计要求:

  • 支持 Intel® 扩展页表 (EPT) 的 Intel® 处理器,

  • 或支持 AMD® 快速虚拟化索引 (RVI) 或嵌套页表 (NPT) 的 AMD® 处理器,

  • 或支持 ARM® aarch64 CPU 的 ARM® 处理器。

在 ARM 上,仅支持纯 ARMv8.0 虚拟化,目前不使用虚拟化主机扩展。托管 Linux® 虚拟机或具有多个 vCPU 的 FreeBSD 虚拟机需要 VMX 无限制模式支持 (UG)。

要确定 Intel 或 AMD 处理器是否支持 bhyve,最简单的方法是运行 dmesg 命令或查看 /var/run/dmesg.boot 文件。对于 AMD® 处理器,请在 Features2 行查找 POPCNT 处理器功能标志;对于 Intel® 处理器,请在 VT-x 行查找 EPTUG 标志。

24.7.1. 准备主机

在 bhyve 中创建虚拟机的第一步是配置主机系统。首先,加载 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 up

24.7.2. 创建 FreeBSD 虚拟机

创建一个文件作为虚拟机的虚拟磁盘。指定虚拟磁盘的大小和名称

# truncate -s 16G guest.img

下载 FreeBSD 安装镜像以进行安装

# fetch https://download.freebsd.org/releases/ISO-IMAGES/14.0/FreeBSD-14.0-RELEASE-amd64-bootonly.iso
FreeBSD-14.0-RELEASE-amd64-bootonly.iso                426 MB   16 MBps    22s

FreeBSD 附带了一个名为 vmrun.sh 的示例脚本,用于在 bhyve 中运行虚拟机。它将启动虚拟机并在循环中运行,因此如果虚拟机崩溃,它会自动重启。vmrun.sh 接受多个选项来控制虚拟机的配置,包括:

  • -c 控制虚拟 CPU 的数量,

  • -m 限制虚拟机可用的内存量,

  • -t 定义要使用的 tap 设备,

  • -d 指示要使用的磁盘镜像,

  • -i 告诉 bhyve 从 CD 镜像启动而不是从磁盘启动,以及

  • -I 定义要使用的 CD 镜像。

最后一个参数是虚拟机的名称,用于跟踪正在运行的虚拟机。以下命令列出所有可用的程序参数选项

# sh /usr/share/examples/bhyve/vmrun.sh -h

此示例在安装模式下启动虚拟机

# sh /usr/share/examples/bhyve/vmrun.sh -c 1 -m 1024M -t tap0 -d guest.img \
     -i -I FreeBSD-14.0-RELEASE-amd64-bootonly.iso guestname

虚拟机将启动并开始安装程序。在虚拟机中安装系统后,当系统在安装结束时询问是否要进入 Shell 时,请选择

重新启动虚拟机。重新启动虚拟机会导致 bhyve 退出,但 vmrun.sh 脚本会在循环中运行 bhyve,并会自动重新启动它。发生这种情况时,从引导加载程序菜单中选择重新启动选项以退出循环。现在可以从虚拟磁盘启动虚拟机

# sh /usr/share/examples/bhyve/vmrun.sh -c 4 -m 1024M -t tap0 -d guest.img guestname

24.7.3. 创建 Linux® 虚拟机

Linux 虚拟机可以像任何其他常规的 基于 UEFI 的虚拟机 一样启动,或者也可以使用 sysutils/grub2-bhyve 端口。

为此,首先确保安装了该端口,然后创建一个文件作为虚拟机的虚拟磁盘

# truncate -s 16G linux.img

使用 grub2-bhyve 启动 Linux 虚拟机是一个两步过程。

  1. 首先,必须加载内核,然后才能启动虚拟机。

  2. Linux® 内核使用 sysutils/grub2-bhyve 加载。

创建一个 device.map 文件,供 grub 用于将虚拟设备映射到主机系统上的文件

(hd0) ./linux.img
(cd0) ./somelinux.iso

使用 sysutils/grub2-bhyve 从 ISO 镜像加载 Linux® 内核

# grub-bhyve -m device.map -r cd0 -M 1024M linuxguest

这将启动 grub。如果安装 CD 包含 grub.cfg 文件,则会显示一个菜单。如果没有,则必须手动找到并加载 vmlinuzinitrd 文件

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

现在,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,./somelinux.iso \
    -l com1,stdio -c 4 -m 1024M linuxguest

系统将启动并开始安装程序。在虚拟机中安装系统后,重新启动虚拟机。这将导致 bhyve 退出。在重新启动虚拟机之前,需要销毁虚拟机实例

# bhyvectl --destroy --vm=linuxguest

现在,可以从虚拟磁盘直接启动虚拟机。加载内核

# grub-bhyve -m device.map -r hd0,msdos1 -M 1024M linuxguest
grub> ls
(hd0) (hd0,msdos2) (hd0,msdos1) (cd0) (cd0,msdos1) (host)
(lvm/VolGroup-lv_swap) (lvm/VolGroup-lv_root)
grub> ls (hd0,msdos1)/
lost+found/ grub/ efi/ System.map-2.6.32-431.el6.x86_64 config-2.6.32-431.el6.x
86_64 symvers-2.6.32-431.el6.x86_64.gz vmlinuz-2.6.32-431.el6.x86_64
initramfs-2.6.32-431.el6.x86_64.img
grub> linux (hd0,msdos1)/vmlinuz-2.6.32-431.el6.x86_64 root=/dev/mapper/VolGroup-lv_root
grub> initrd (hd0,msdos1)/initramfs-2.6.32-431.el6.x86_64.img
grub> boot

启动虚拟机

# 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

Linux® 现在将在虚拟机中启动,最终会显示登录提示。登录并使用虚拟机。完成后,重新启动虚拟机以退出 bhyve。销毁虚拟机实例

# bhyvectl --destroy --vm=linuxguest

24.7.4. 使用 UEFI 固件启动 bhyve 虚拟机

除了 bhyveloadgrub-bhyve,bhyve 虚拟机管理程序还可以使用 UEFI 固件启动虚拟机。此选项可能支持其他加载程序不支持的客户操作系统。

要使用 bhyve 中的 UEFI 支持,首先需要获取 UEFI 固件镜像。这可以通过安装 sysutils/bhyve-firmware 端口或软件包来完成。

固件就位后,将 -l bootrom,/path/to/firmware 标志添加到 bhyve 命令行中。实际的 bhyve 命令可能如下所示

# bhyve -AHP -s 0:0,hostbridge -s 1:0,lpc \
  	-s 2:0,virtio-net,tap1 -s 3:0,virtio-blk,./disk.img \
	-s 4:0,ahci-cd,./install.iso -c 4 -m 1024M \
	-l bootrom,/usr/local/share/uefi-firmware/BHYVE_UEFI.fd \
	guest

要允许虚拟机存储 UEFI 变量,可以使用追加到 -l 标志的变量文件。请注意,bhyve 会将虚拟机的修改写入指定的变量文件。因此,请务必先创建每个虚拟机的变量模板文件副本

# cp /usr/local/share/uefi-firmware/BHYVE_UEFI_VARS.fd /path/to/vm-image/BHYVE_UEFI_VARS.fd

然后,将该变量文件添加到 bhyve 参数中

# bhyve -AHP -s 0:0,hostbridge -s 1:0,lpc \
  	-s 2:0,virtio-net,tap1 -s 3:0,virtio-blk,./disk.img \
	-s 4:0,ahci-cd,./install.iso -c 4 -m 1024M \
	-l bootrom,/usr/local/share/uefi-firmware/BHYVE_UEFI.fd,/path/to/vm-image/BHYVE_UEFI_VARS.fd \
	guest

某些 Linux 发行版需要使用 UEFI 变量来存储 UEFI 启动文件的路径(例如,使用 linux64.efigrubx64.efi 而不是 bootx64.efi)。因此,建议为 Linux 虚拟机使用变量文件,以避免手动更改启动分区文件。

要查看或修改变量文件内容,请使用主机上的 efivar(8) 命令。

sysutils/bhyve-firmware 还包含一个支持 CSM 的固件,用于以传统 BIOS 模式启动不支持 UEFI 的虚拟机

# bhyve -AHP -s 0:0,hostbridge -s 1:0,lpc \
  	-s 2:0,virtio-net,tap1 -s 3:0,virtio-blk,./disk.img \
	-s 4:0,ahci-cd,./install.iso -c 4 -m 1024M \
	-l bootrom,/usr/local/share/uefi-firmware/BHYVE_UEFI_CSM.fd \
	guest

24.7.5. bhyve 虚拟机的图形 UEFI 帧缓冲区

UEFI 固件支持对于 Microsoft Windows® 等以图形为主的客户操作系统特别有用。

UEFI-GOP 帧缓冲区支持也可以使用 -s 29,fbuf,tcp=0.0.0.0:5900 标志启用。可以使用 w=800h=600 配置帧缓冲区分辨率,还可以通过添加 wait 标志指示 bhyve 在启动虚拟机之前等待 VNC 连接。可以通过主机或通过网络使用 VNC 协议访问帧缓冲区。此外,可以添加 -s 30,xhci,tablet 标志以实现与主机的精确鼠标光标同步。

生成的 bhyve 命令如下所示

# bhyve -AHP -s 0:0,hostbridge -s 31:0,lpc \
  	-s 2:0,virtio-net,tap1 -s 3:0,virtio-blk,./disk.img \
	-s 4:0,ahci-cd,./install.iso -c 4 -m 1024M \
	-s 29,fbuf,tcp=0.0.0.0:5900,w=800,h=600,wait \
	-s 30,xhci,tablet \
	-l bootrom,/usr/local/share/uefi-firmware/BHYVE_UEFI.fd \
	guest

请注意,在 BIOS 模拟模式下,一旦从固件将控制权传递到客户操作系统,帧缓冲区将停止接收更新。

24.7.6. 创建 Microsoft Windows® 虚拟机

可以直接从原始安装介质设置 Windows 10 或更早版本的虚拟机,这是一个相对简单的过程。除了最低资源要求外,运行 Windows 作为虚拟机还需要:

  • 连接虚拟机内存(标志 -w),以及

  • 使用 UEFI 引导程序启动。

使用 Windows 安装 ISO 启动虚拟机的示例

bhyve \
      -c 2 \
      -s 0,hostbridge \
      -s 3,nvme,windows2016.img \
      -s 4,ahci-cd,install.iso \
      -s 10,virtio-net,tap0 \
      -s 31,lpc \
      -s 30,xhci,tablet \
      -l bootrom,/usr/local/share/uefi-firmware/BHYVE_UEFI.fd \
      -m 8G -H -w \
      windows2016

在安装期间应只使用一个或两个 VCPU,但安装 Windows 后可以增加这个数量。

必须安装 VirtIO 驱动程序 才能使用定义的 virtio-net 网络接口。另一种选择是通过将上述命令行中的 virtio-net 更改为 e1000 来切换到 E1000(Intel E82545)仿真。但是,性能会受到影响。

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 create -V16G -o volmode=dev zroot/linuxdisk0

启动虚拟机时,将 ZFS 卷指定为磁盘驱动器

# bhyve -A -H -P -s 0:0,hostbridge -s 1:0,lpc -s 2:0,virtio-net,tap0 \
  	-s3:0,virtio-blk,/dev/zvol/zroot/linuxdisk0 \
	-l com1,stdio -c 4 -m 1024M linuxguest

如果对主机和虚拟机内部都使用 ZFS,请注意主机和虚拟机在缓存虚拟机内容时可能会争用内存。要缓解这种情况,请考虑将主机的 ZFS 文件系统设置为仅使用元数据缓存。为此,请将以下设置应用于主机的 ZFS 文件系统,并将 <name> 替换为虚拟机的特定 zvol 数据集名称。

# zfs set primarycache=metadata <name>

24.7.8. 创建虚拟机快照

现代虚拟机管理程序允许用户创建其状态的“快照”;此类快照包括虚拟机的磁盘、CPU 和内存内容。通常可以在虚拟机正在运行或已关闭的情况下创建快照。然后,可以重置虚拟机并将其恢复到创建快照时的精确状态。

24.7.8.1. ZFS 快照

将 ZFS 卷用作虚拟机的备份存储,可以对虚拟机的磁盘进行快照。例如

zfs snapshot zroot/path/to/zvol@snapshot_name

虽然可以在虚拟机运行时以这种方式对 ZFS 卷进行快照,但请注意,虚拟机的磁盘内容在虚拟机处于活动状态时可能处于不一致状态。因此,建议在执行此命令之前先关闭或暂停虚拟机。默认情况下不支持暂停虚拟机,需要先启用(请参阅 内存和 CPU 快照)。

在虚拟机使用 ZFS zvol 时将其回滚到快照可能会损坏文件系统内容并导致虚拟机崩溃。虚拟机中所有未保存的数据将丢失,上次快照以来的修改可能会被破坏。

关闭虚拟机后,可能需要进行第二次回滚以将文件系统恢复到可使用状态。这最终会破坏快照后所做的任何更改。

24.7.8.2. 内存和 CPU 快照(实验性功能)

从 FreeBSD 13 开始,bhyve 具有一个实验性的“快照”功能,用于将虚拟机的内存和 CPU 状态转储到文件中,然后暂停虚拟机。之后可以从快照文件内容恢复虚拟机。

但是,此功能默认情况下未启用,需要从源代码重建系统。请参阅从源代码构建,了解使用自定义选项编译内核过程的详细说明。

该功能尚未准备好用于生产环境,并且仅限于针对特定虚拟机配置工作。存在多个限制

  • nvmevirtio-blk 存储后端尚不支持

  • 快照仅在访客使用每种设备的一种类型时受支持,即如果有多个 ahci-hd 磁盘附加,快照创建将失败

  • 此外,该功能在 Intel 上可能相当稳定,但在 AMD CPU 上可能无法正常工作。

在执行以下步骤之前,请确保/usr/src 目录是最新的。请参阅更新源代码,了解执行此操作的详细步骤。

首先,将以下内容添加到/etc/src.conf

WITH_BHYVE_SNAPHOT=yes
BHYVE_SNAPSHOT=1
MK_BHYVE_SNAPSHOT=yes

如果系统已部分或全部重建,建议运行

# cd /usr/src
# make cleanworld

再继续操作。

然后按照从源代码更新 FreeBSD 的快速入门部分中概述的步骤构建和安装 world 和内核。

要验证快照功能是否已成功激活,请输入

# bhyvectl --usage

并检查输出是否列出了 --suspend 标志。如果缺少该标志,则该功能未正确激活。

然后,您可以快照并挂起您选择的正在运行的虚拟机

# bhyvectl --vm=vmname --suspend=/path/to/snapshot/filename

--suspend 提供绝对路径和文件名。否则,bhyve 将将快照数据写入 bhyve 启动所在的目录。

请确保将快照数据写入安全目录。生成的输出包含访客的完整内存转储,因此可能包含敏感数据(例如密码)!

这将创建三个文件

  • 内存快照 - 命名与 --suspend 的输入相同

  • 内核文件 - 命名与 --suspend 的输入相同,后缀为.kern

  • 元数据 - 包含有关系统状态的元数据,命名后缀为.meta

要从快照恢复访客,请使用 bhyve-r 标志

# bhyve -r /path/to/snapshot/filename

在不同的 CPU 架构上恢复访客快照将不起作用。通常,尝试在与快照创建者不完全相同的系统上恢复可能会失败。

24.7.9. 将 bhyve 设为监狱

为了提高安全性并将虚拟机与主机操作系统分离,可以将 bhyve 运行在监狱中。请参阅监狱,了解有关监狱及其安全优势的详细说明。

24.7.9.1. 为 bhyve 创建一个监狱

首先,创建一个监狱环境。如果使用 UFS 文件系统,只需运行

# mkdir -p /jails/bhyve

如果使用ZFS 文件系统,请使用以下命令

# zfs create zroot/jails
# zfs create zroot/jails/bhyve

然后为虚拟机 bhyvevm0 创建一个 ZFS zvol

# zfs create zroot/vms
# zfs create -V 20G zroot/vms/bhyvevm0

如果不使用 ZFS,请使用以下命令直接在监狱目录结构中创建磁盘映像文件

# mkdir /jails/bhyve/vms
# truncate -s 20G /jails/bhyve/vms/bhyvevm0

下载 FreeBSD 映像,最好是与主机相同或更旧的版本,并将其解压缩到监狱目录中

# cd /jails
# fetch -o base.txz http://ftp.freebsd.org/pub/FreeBSD/releases/amd64/13.2-RELEASE/base.txz
# tar -C /jails/bhyve -xvf base.txz

在监狱中运行比主机更高的 FreeBSD 版本不受支持(例如,在嵌入在 13.2-RELEASE 主机中的监狱中运行 14.0-RELEASE)。

接下来,将 devfs 规则集添加到/etc/devfs.rules

[devfsrules_jail_bhyve=100]
add include $devfsrules_hide_all
add include $devfsrules_unhide_login
add path 'urandom' unhide
add path 'random' unhide
add path 'crypto' unhide
add path 'shm' unhide
add path 'zero' unhide
add path 'null' unhide
add path 'mem' unhide
add path 'vmm' unhide
add path 'vmm/*' unhide
add path 'vmm.io' unhide
add path 'vmm.io/*' unhide
add path 'nmdmbhyve*' unhide
add path 'zvol' unhide
add path 'zvol/zroot' unhide
add path 'zvol/zroot/vms' unhide
add path 'zvol/zroot/vms/bhyvevm0' unhide
add path 'zvol/zroot/vms/bhyvevm1' unhide
add path 'tap10*' unhide

如果您的/etc/devfs.rules 文件中存在另一个具有数字 ID 100 的 devfs 规则,请用另一个尚未使用的 ID 号替换列表中的规则。

如果不使用 ZFS 文件系统,请跳过/etc/devfs.rules 中的相关 zvol 规则。

add path 'zvol' unhide
add path 'zvol/zroot' unhide
add path 'zvol/zroot/vms' unhide
add path 'zvol/zroot/vms/bhyvevm0' unhide
add path 'zvol/zroot/vms/bhyvevm1' unhide

这些规则将导致 bhyve

  • 创建一个具有名为 bhyvevm0bhyvevm1 的磁盘卷的虚拟机,

  • 使用名称前缀为 tap10tap 网络接口。这意味着,有效的接口名称将是 tap10tap100tap101、…​ tap109tap1000 等等。

    限制对可能的tap 接口名称子集的访问将阻止监狱(以及 bhyve)看到主机的tap 接口和其他监狱的tap 接口。

  • 使用前缀为“bhyve”的nmdm 设备,即/dev/nmdmbhyve0

这些规则可以根据需要进行扩展和更改,使用不同的访客和接口名称。

如果您打算在主机以及一个或多个监狱中使用 bhyve,请记住tapnmdm 接口名称将在共享环境中运行。例如,您只能使用/dev/nmdmbhyve0 用于主机上的 bhyve 或监狱中的 bhyve。

重新启动 devfs 以加载更改

# service devfs restart

然后将新监狱的定义添加到/etc/jail.conf/etc/jail.conf.d 中。将接口号$if 和 IP 地址替换为您的个人变体。

示例 1. 使用 NAT 或通过防火墙路由流量
bhyve {
        $if = 0;
        exec.prestart = "/sbin/ifconfig epair${if} create up";
        exec.prestart += "/sbin/ifconfig epair${if}a up";
        exec.prestart += "/sbin/ifconfig epair${if}a name ${name}0";
        exec.prestart += "/sbin/ifconfig epair${if}b name jail${if}";
        exec.prestart += "/sbin/ifconfig ${name}0 inet 192.168.168.1/27";
        exec.prestart += "/sbin/sysctl net.inet.ip.forwarding=1";

        exec.clean;

        host.hostname = "your-hostname-here";
        vnet;
        vnet.interface = "em${if}";
        path = "/jails/${name}";
        persist;
        securelevel = 3;
        devfs_ruleset = 100;
        mount.devfs;

        allow.vmm;

        exec.start += "/bin/sh /etc/rc";
        exec.stop = "/bin/sh /etc/rc.shutdown";

        exec.poststop += "/sbin/ifconfig ${name}0 destroy";
}

此示例假设使用 pfipfw 等防火墙来对您的监狱流量进行 NAT。请参阅防火墙 章节,了解有关实现此目的的可用选项的更多详细信息。

示例 2. 使用桥接网络连接
bhyve {
        $if = 0;
        exec.prestart = "/sbin/ifconfig epair${if} create up";
        exec.prestart += "/sbin/ifconfig epair${if}a up";
        exec.prestart += "/sbin/ifconfig epair${if}a name ${name}0";
        exec.prestart += "/sbin/ifconfig epair${if}b name jail${if}";
        exec.prestart += "/sbin/ifconfig bridge0 addm ${name}0";
        exec.prestart += "/sbin/sysctl net.inet.ip.forwarding=1";

        exec.clean;

        host.hostname = "your-hostname-here";
        vnet;
        vnet.interface = "em${if}";
        path = "/jails/${name}";
        persist;
        securelevel = 3;
        devfs_ruleset = 100;
        mount.devfs;

        allow.vmm;

        exec.start += "/bin/sh /etc/rc";
        exec.stop = "/bin/sh /etc/rc.shutdown";

        exec.poststop += "/sbin/ifconfig ${name}0 destroy";
}

如果您之前在/etc/devfs.rules 中用您自己的唯一号码替换了 devfs 规则集 ID 100,请记住在您的jails.conf 中也替换数字 ID。

24.7.9.2. 配置监狱

要首次启动监狱并执行一些额外的配置工作,请输入

# cp /etc/resolv.conf /jails/bhyve/etc
# service jail onestart bhyve
# jexec bhyve
# sysrc ifconfig_jail0="inet 192.168.168.2/27"
# sysrc defaultrouter="192.168.168.1"
# sysrc sendmail_enable=NONE
# sysrc cloned_interfaces="tap100"
# exit

重新启动并启用监狱

# sysrc jail_enable=YES
# service jail restart bhyve

之后,您可以在监狱内创建一个虚拟机。对于 FreeBSD 访客,请先下载安装 ISO

# jexec bhyve
# cd /vms
# fetch -o freebsd.iso https://download.freebsd.org/releases/ISO-IMAGES/14.0/FreeBSD-14.0-RELEASE-amd64-bootonly.iso

24.7.9.3. 在监狱内创建虚拟机

要创建虚拟机,请使用 bhyvectl 先对其进行初始化

# jexec bhyve
# bhyvectl --create --vm=bhyvevm0

在从监狱启动虚拟机时,可能需要使用 bhyvectl 创建访客。跳过此步骤可能会导致启动 bhyve 时出现以下错误消息

vm_open: 无法打开 vm-name。没有此文件或目录

最后,使用您首选的方式启动访客。

示例 3. 使用 vmrun.sh 和 ZFS 启动

在 ZFS 文件系统上使用 vmrun.sh

# jexec bhyve
# sh /usr/share/examples/bhyve/vmrun.sh -c 1 -m 1024M \
     -t tap100 -d /dev/zvols/zroot/vms/bhyvevm0 -i -I /vms/FreeBSD-14.0-RELEASE-amd64-bootonly.iso bhyvevm0
示例 4. 使用 vmrun.sh 和 UFS 启动

在 UFS 文件系统上使用 vmrun.sh

# jexec bhyve
# sh /usr/share/examples/bhyve/vmrun.sh -c 1 -m 1024M \
     -t tap100 -d /vms/bhyvevm0 -i -I /vms/FreeBSD-14.0-RELEASE-amd64-bootonly.iso bhyvevm0
示例 5. 为 UEFI 访客启动 bhyve 和 ZFS

如果您想使用 UEFI 访客,请记住首先在监狱中安装所需的固件包sysutils/bhyve-firmware

# pkg -j bhyve install bhyve-firmware

然后直接使用 bhyve

# bhyve -A -c 4 -D -H -m 2G \
        -s 0,hostbridge \
        -s 1,lpc \
        -s 2,virtio-net,tap100 \
        -s 3,virtio-blk,/dev/zvol/zroot/vms/bhyvevm0 \
	-s 4,ahci-cd,/vms/FreeBSD-14.0-RELEASE-amd64-bootonly.iso \
        -s 31,fbuf,tcp=127.0.0.1:5900,w=1024,h=800,tablet \
        -l bootrom,/usr/local/share/uefi-firmware/BHYVE_UEFI.fd \
        -l com1,/dev/nmdbbhyve0A \
        bhyvevm0

这将允许您通过 VNC 连接到您的虚拟机 bhyvevm0,以及在/dev/nmdbbhyve0B 上的串行控制台。

24.7.10. 虚拟机控制台

将 bhyve 控制台包装在会话管理工具(例如sysutils/tmuxsysutils/screen)中,以便分离并重新连接到控制台是有利的。bhyve 控制台也可以是空模式设备,可以使用 cu 访问。为此,请加载nmdm 内核模块,并将 -l com1,stdio 替换为 -l com1,/dev/nmdm0A/dev/nmdm 设备将根据需要自动创建,其中每个设备都是一对,对应于空模式电缆的两端(/dev/nmdm0A/dev/nmdm0B)。请参阅nmdm(4),了解详细信息。

# kldload nmdm
# 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,/dev/nmdm0A -c 4 -m 1024M linuxguest
# cu -l /dev/nmdm0B
Connected

Ubuntu 13.10 handbook ttyS0

handbook login:

要断开控制台连接,请输入一个换行符(即按 RETURN),然后输入波浪号(~),最后输入点号(.)。请记住,只有连接被断开,而登录会话仍然处于活动状态。因此,另一个连接到相同控制台的用户可以使用任何活动会话,而无需先进行身份验证。出于安全原因,建议在断开连接之前注销。

nmdm 设备路径中的数字必须对每个虚拟机都是唯一的,并且在 bhyve 启动之前不能被任何其他进程使用。该数字可以任意选择,不需要从连续的数字序列中获取。当 bhyve 连接其控制台时,设备节点对(即/dev/nmdm0a/dev/nmdm0b)将动态创建,并在其关闭时销毁。在创建启动虚拟机的脚本时请牢记这一点:您需要确保所有虚拟机都被分配了唯一的nmdm 设备。

24.7.11. 管理虚拟机

每个虚拟机在/dev/vmm 中都会创建一个设备节点。这使管理员可以轻松地查看正在运行的虚拟机的列表

# ls -al /dev/vmm
total 1
dr-xr-xr-x   2 root  wheel    512 Mar 17 12:19 ./
dr-xr-xr-x  14 root  wheel    512 Mar 17 06:38 ../
crw-------   1 root  wheel  0x1a2 Mar 17 12:20 guestname
crw-------   1 root  wheel  0x19f Mar 17 12:19 linuxguest
crw-------   1 root  wheel  0x1a1 Mar 17 12:19 otherguest

可以使用 bhyvectl 销毁指定的虚拟机

# bhyvectl --destroy --vm=guestname

以这种方式销毁虚拟机意味着立即终止它。任何未保存的数据都将丢失,打开的文件和文件系统可能会损坏。要正常关闭虚拟机,请向其 bhyve 进程发送 TERM 信号。这将触发访客的 ACPI 关闭事件

# ps ax | grep bhyve
17424  -  SC      56:48.27 bhyve: guestvm (bhyve)
# kill 17424

24.7.12. 工具和实用程序

端口中提供了许多实用程序和应用程序,以帮助简化设置和管理 bhyve 虚拟机

表 1. bhyve 管理器
名称许可证文档

vm-bhyve

BSD-2

sysutils/vm-bhyve

文档

CBSD

BSD-2

sysutils/cbsd

文档

Virt-Manager

LGPL-3

deskutils/virt-manager

文档

Bhyve RC 脚本

未知

sysutils/bhyve-rc

文档

bmd

未知

sysutils/bmd

文档

vmstated

BSD-2

sysutils/vmstated

文档

24.7.13. 持久配置

为了配置系统在启动时启动 bhyve 虚拟机,需要对一些配置文件进行更改。

  1. /etc/sysctl.conf

    当使用 tap 接口作为网络后端时,您需要手动将每个使用的 tap 接口设置为 UP,或者简单地设置以下 sysctl

    net.link.tap.up_on_open=1
  2. /etc/rc.conf

    要通过 bridge 将虚拟机的 tap 设备连接到网络,您需要在 /etc/rc.conf 中持久保存设备设置。此外,您可以通过 kld_list 配置变量加载 bhyve 所需的内核模块 vmmnmdm 设备所需的 nmdm。配置 ifconfig_bridge0 时,请确保将 <ipaddr>/<netmask> 替换为实际的物理接口 IP 地址(本例中为 igb0),并从物理设备中删除 IP 设置。

    # sysrc cloned_interfaces+="bridge0 tap0"
    # sysrc ifconfig_bridge0="inet <ipaddr>/<netmask> addm igb0 addm tap0"
    # sysrc kld_list+="nmdm vmm"
    # sysrc ifconfig_igb0="up"
示例 6. 设置桥接设备的 IP

对于一个主机,其 igb0 接口连接到网络,IP 地址为 10.10.10.1,网络掩码为 255.255.255.0,您需要使用以下命令

# sysrc ifconfig_igb0="up"
# sysrc ifconfig_bridge0="inet 10.10.10.1/24 addm igb0 addm tap0"
# sysrc kld_list+="nmdm vmm"
# sysrc cloned_interfaces+="bridge0 tap0"

如果您在远程执行这些命令时(例如通过 SSH)修改系统的 IP 地址配置,可能会导致您被锁定!请采取预防措施以维护系统访问权限,或在本地终端会话登录时进行这些修改。

24.8. FreeBSD 作为 Xen™-主机

Xen 是一款基于 GPLv2 许可的 1 类虚拟机管理程序,适用于 Intel® 和 ARM® 架构。FreeBSD 自 FreeBSD 8.0 起就包含 i386™ 和 AMD® 64 位 DomUAmazon EC2 非特权域(虚拟机)支持,并在 FreeBSD 11.0 中包含 Dom0 控制域(主机)支持。从 FreeBSD 11 开始,对半虚拟化 (PV) 域的支持已删除,取而代之的是硬件虚拟化 (HVM) 域,这提供了更好的性能。

Xen™ 是一款裸机虚拟机管理程序,这意味着它是 BIOS 之后加载的第一个程序。然后,一个名为域 0(简称 Dom0)的特权虚拟机开始运行。Dom0 使用其特权直接访问底层物理硬件,使其成为一种高性能解决方案。它可以直接访问磁盘控制器和网络适配器。Xen™ 管理工具用于管理和控制 Xen™ 虚拟机管理程序,也由 Dom0 用于创建、列出和销毁 VM。Dom0 为非特权域提供虚拟磁盘和网络,通常称为 DomU。Xen™ Dom0 可以与其他虚拟机管理程序解决方案的服务控制台进行比较,而 DomU 是运行各个客户机 VM 的地方。

Xen™ 可以将 VM 在不同的 Xen™ 服务器之间迁移。当两个 Xen 主机共享相同的底层存储时,迁移可以在不先关闭 VM 的情况下完成。相反,迁移是在 DomU 运行时实时执行的,不需要重新启动它或计划停机时间。这在维护场景或升级窗口中很有用,以确保 DomU 提供的服务仍然可用。在 Xen Wiki 概述页面 上列出了更多 Xen™ 功能。请注意,并非所有功能都支持 FreeBSD。

24.8.1. Xen™ Dom0 的硬件要求

要在主机上运行 Xen™ 虚拟机管理程序,需要某些硬件功能。将 FreeBSD 作为 Xen 主机(Dom0)运行需要主机处理器中的 Intel 扩展页表 (EPT) 或 AMD 嵌套页表 (NPT) 和输入/输出内存管理单元 (IOMMU) 支持。

为了运行 FreeBSD 13 Xen™ Dom0,该系统必须使用传统引导(BIOS)启动。FreeBSD 14 及更高版本支持在 BIOS 和 UEFI 模式下作为 Xen™ Dom0 启动。

24.8.2. Xen™ Dom0 控制域设置

用户应安装 emulators/xen-kernelsysutils/xen-tools 软件包,基于 Xen™ 4.18。

安装 Xen 软件包后,必须编辑配置文件以准备主机进行 Dom0 集成。对 /etc/sysctl.conf 的一项更改将禁用对允许连接的内存页数的限制。否则,内存需求更高的 DomU VM 将无法运行。

# echo 'vm.max_wired=-1' >> /etc/sysctl.conf

另一个与内存相关的设置涉及更改 /etc/login.conf,将 memorylocked 选项设置为 unlimited。否则,创建 DomU 域可能会失败,并出现 无法分配内存 错误。更改 /etc/login.conf 后,运行 cap_mkdb 更新功能数据库。有关详细信息,请参见 资源限制

# sed -i '' -e 's/memorylocked=64K/memorylocked=unlimited/' /etc/login.conf
# cap_mkdb /etc/login.conf

/etc/ttys 中为 Xen™ 控制台添加一个条目

# echo 'xc0     "/usr/libexec/getty Pc"         xterm   onifconsole  secure' >> /etc/ttys

/boot/loader.conf 中选择一个 Xen™ 内核将激活 Dom0。Xen™ 还需要主机机器的资源,例如 CPU 和内存,用于自身和其他 DomU 域。所需的 CPU 和内存量取决于各个需求和硬件功能。在本例中,为 Dom0 提供了 8 GB 内存和 4 个虚拟 CPU。串行控制台也已激活,并定义了日志记录选项。

以下命令用于 Xen 4.7 软件包

# echo 'hw.pci.mcfg=0' >> /boot/loader.conf
# echo 'if_tap_load="YES"' >> /boot/loader.conf
# echo 'xen_kernel="/boot/xen"' >> /boot/loader.conf
# echo 'xen_cmdline="dom0_mem=8192M dom0_max_vcpus=4 dom0pvh=1 console=com1,vga com1=115200,8n1 guest_loglvl=all loglvl=all"' >> /boot/loader.conf

对于 Xen 4.11 及更高版本,应使用以下命令

# echo 'if_tap_load="YES"' >> /boot/loader.conf
# echo 'xen_kernel="/boot/xen"' >> /boot/loader.conf
# echo 'xen_cmdline="dom0_mem=8192M dom0_max_vcpus=4 dom0=pvh console=com1,vga com1=115200,8n1 guest_loglvl=all loglvl=all"' >> /boot/loader.conf

Xen™ 为 DomU VM 创建的日志文件存储在 /var/log/xen 中。如果遇到问题,请确保检查该目录的内容。

在系统启动期间激活 xencommons 服务

# sysrc xencommons_enable=yes

这些设置足以启动启用 Dom0 的系统。但是,它缺乏 DomU 机器用于连接到网络的网络功能。要解决此问题,请使用系统的主要 NIC 定义一个桥接接口,DomU VM 可以使用该接口连接到网络。将 em0 替换为主机网络接口名称。

# sysrc cloned_interfaces="bridge0"
# sysrc ifconfig_bridge0="addm em0 SYNCDHCP"
# sysrc ifconfig_em0="up"

重新启动主机以加载 Xen™ 内核并启动 Dom0。

# reboot

成功引导 Xen™ 内核并再次登录系统后,Xen™ 管理工具 xl 用于显示有关域的信息。

# xl list
Name                                        ID   Mem VCPUs      State   Time(s)
Domain-0                                     0  8192     4     r-----     962.0

输出确认 Dom0(称为 Domain-0)的 ID 为 0 并且正在运行。它还具有在 /boot/loader.conf 中定义的内存和虚拟 CPU。更多信息可以在 Xen™ 文档 中找到。现在可以创建 DomU 客户机 VM。

24.8.3. Xen™ DomU 客户机 VM 配置

非特权域由配置文件和虚拟或物理硬盘组成。DomU 的虚拟磁盘存储可以是 truncate(1) 创建的文件,也可以是 “创建和销毁卷” 中描述的 ZFS 卷。在本例中,使用了一个 20 GB 的卷。使用 ZFS 卷、FreeBSD ISO 映像、1 GB 内存和两个虚拟 CPU 创建一个 VM。使用 fetch(1) 获取 ISO 安装文件,并将其保存到本地名为 freebsd.iso 的文件中。

# fetch https://download.freebsd.org/releases/ISO-IMAGES/14.0/FreeBSD-14.0-RELEASE-amd64-bootonly.iso -o freebsd.iso

创建一个名为 xendisk0 的 20 GB ZFS 卷,用作 VM 的磁盘空间。

# zfs create -V20G -o volmode=dev zroot/xendisk0

新的 DomU 客户机 VM 在文件中定义。还定义了一些特定定义,例如名称、键盘映射和 VNC 连接详细信息。以下 freebsd.cfg 包含本示例的最小 DomU 配置

# cat freebsd.cfg
builder = "hvm" (1)
name = "freebsd" (2)
memory = 1024 (3)
vcpus = 2 (4)
vif = [ 'mac=00:16:3E:74:34:32,bridge=bridge0' ] (5)
disk = [
'/dev/zvol/tank/xendisk0,raw,hda,rw', (6)
'/root/freebsd.iso,raw,hdc:cdrom,r' (7)
  ]
vnc = 1 (8)
vnclisten = "0.0.0.0"
serial = "pty"
usbdevice = "tablet"

这些行解释得更详细

1这定义了要使用哪种虚拟化类型。hvm 指硬件辅助虚拟化或硬件虚拟机。客户机操作系统可以在具有虚拟化扩展的 CPU 上运行,提供与在物理硬件上运行几乎相同的性能。generic 是默认值,它创建一个 PV 域。
2此虚拟机的名称,以将其与在同一 Dom0 上运行的其他虚拟机区分开来。必需的。
3要为 VM 提供的 RAM 量,以兆字节为单位。此数量从虚拟机管理程序的总可用内存中减去,而不是 Dom0 的内存。
4客户机 VM 可用的虚拟 CPU 数量。为了获得最佳性能,请不要创建具有比主机上的物理 CPU 数量更多的虚拟 CPU 的客户机。
5虚拟网络适配器。这是连接到主机网络接口的网桥。mac 参数是在虚拟网络接口上设置的 MAC 地址。此参数是可选的,如果没有提供 MAC,Xen™ 将生成一个随机的 MAC。
6此 VM 的磁盘存储的磁盘、文件或 ZFS 卷的完整路径。选项和多个磁盘定义用逗号分隔。
7定义用于安装初始操作系统的引导介质。在本例中,它是之前下载的 ISO 映像。有关其他类型的设备和选项设置,请查阅 Xen™ 文档。
8控制与 DomU 串行控制台的 VNC 连接的选项。依次,这些是:活动的 VNC 支持,定义要监听的 IP 地址,串行控制台的设备节点,以及用于精确定位鼠标和其他输入方法的输入方法。keymap 定义要使用的键盘映射,默认值为 english

创建完包含所有必要选项的文件后,通过将文件作为参数传递给 xl create 来创建 DomU。

# xl create freebsd.cfg

每次重新启动 Dom0 时,都必须将配置文件再次传递给 xl create 以重新创建 DomU。默认情况下,重新引导后只创建 Dom0,而不是各个 VM。VM 可以从它们停止的地方继续,因为它们将操作系统存储在虚拟磁盘上。虚拟机配置可能会随着时间的推移而改变(例如,当添加更多内存时)。必须适当地备份虚拟机配置文件,并使其可供使用,以便在需要时能够重新创建客户机 VM。

xl list 的输出确认 DomU 已创建。

# xl list
Name                                        ID   Mem VCPUs      State   Time(s)
Domain-0                                     0  8192     4     r-----  1653.4
freebsd                                      1  1024     1     -b----   663.9

要开始安装基本操作系统,请启动 VNC 客户端,将其指向主机的网络地址或 freebsd.cfgvnclisten 行中定义的 IP 地址。安装完操作系统后,关闭 DomU 并断开 VNC 查看器的连接。编辑 freebsd.cfg,删除带有 cdrom 定义的行或将其注释掉,方法是在该行开头插入一个 # 字符。要加载此新配置,需要使用 xl destroy 删除旧的 DomU,并将名称或 ID 作为参数传递。之后,使用修改后的 freebsd.cfg 重新创建它。

# xl destroy freebsd
# xl create freebsd.cfg

然后,可以使用 VNC 查看器再次访问该机器。这次,它将从安装了操作系统的虚拟磁盘启动,并且可以作为虚拟机使用。

24.8.4. 故障排除

本节包含一些基本信息,用于帮助您解决在使用 FreeBSD 作为 Xen™ 主机或客户机时遇到的问题。

24.8.4.1. 主机启动故障排除

请注意,以下故障排除技巧适用于 Xen™ 4.11 或更高版本。如果您仍在使用 Xen™ 4.7 并遇到问题,请考虑迁移到更新版本的 Xen™。

为了解决主机启动问题,您可能需要一根串行电缆或一根调试 USB 电缆。可以通过在 loader.conf 中的 xen_cmdline 选项中添加选项来获取详细的 Xen™ 启动输出。一些相关的调试选项包括

  • iommu=debug: 可以用来打印有关 iommu 的更多诊断信息。

  • dom0=verbose: 可以用来打印有关 dom0 构建过程的更多诊断信息。

  • sync_console: 强制同步控制台输出的标志。在调试时非常有用,可以避免由于速率限制而丢失消息。切勿在生产环境中使用此选项,因为它可能允许恶意客户机使用控制台对 Xen™ 进行拒绝服务攻击。

FreeBSD 也应该以详细模式启动,以便识别任何问题。要激活详细启动,请运行以下命令

# echo 'boot_verbose="YES"' >> /boot/loader.conf

如果这些选项都不能解决问题,请将串行启动日志发送到 [email protected][email protected] 以进行进一步分析。

24.8.4.2. 客户机创建故障排除

在创建客户机时也可能出现问题,以下内容试图为那些试图诊断客户机创建问题的用户提供一些帮助。

客户机创建失败最常见的原因是 xl 命令输出一些错误并以非 0 的返回值退出。如果提供的错误不足以帮助识别问题,也可以通过重复使用 v 选项从 xl 获取更详细的输出。

# xl -vvv create freebsd.cfg
Parsing config from freebsd.cfg
libxl: debug: libxl_create.c:1693:do_domain_create: Domain 0:ao 0x800d750a0: create: how=0x0 callback=0x0 poller=0x800d6f0f0
libxl: debug: libxl_device.c:397:libxl__device_disk_set_backend: Disk vdev=xvda spec.backend=unknown
libxl: debug: libxl_device.c:432:libxl__device_disk_set_backend: Disk vdev=xvda, using backend phy
libxl: debug: libxl_create.c:1018:initiate_domain_create: Domain 1:running bootloader
libxl: debug: libxl_bootloader.c:328:libxl__bootloader_run: Domain 1:not a PV/PVH domain, skipping bootloader
libxl: debug: libxl_event.c:689:libxl__ev_xswatch_deregister: watch w=0x800d96b98: deregister unregistered
domainbuilder: detail: xc_dom_allocate: cmdline="", features=""
domainbuilder: detail: xc_dom_kernel_file: filename="/usr/local/lib/xen/boot/hvmloader"
domainbuilder: detail: xc_dom_malloc_filemap    : 326 kB
libxl: debug: libxl_dom.c:988:libxl__load_hvm_firmware_module: Loading BIOS: /usr/local/share/seabios/bios.bin
...

如果详细输出无法帮助诊断问题,则 /var/log/xen 中还有 QEMU 和 Xen™ 工具栈日志。请注意,域的名称会附加到日志名称,因此如果域名为 freebsd,则应找到 /var/log/xen/xl-freebsd.log,并可能还有一个 /var/log/xen/qemu-dm-freebsd.log。这两个日志文件都可能包含用于调试的有用信息。如果这些都无法解决问题,请将您遇到的问题的描述以及尽可能多的信息发送到 [email protected][email protected],以便获得帮助。


最后修改于: 2024 年 11 月 9 日 by Chris Moerz