# 24.8.基于 FreeBSD 的 Xen™ 虚拟机

Xen 是一款 GPLv2 许可的 [类型 1 虚拟机监控程序](https://en.wikipedia.org/wiki/Hypervisor#Classification)，适用于 Intel® 和 ARM® 架构。FreeBSD 自 8.0 版本起支持 i386™ 和 AMD® 64 位 [DomU](https://wiki.xenproject.org/wiki/DomU) 和 [Amazon EC2](https://en.wikipedia.org/wiki/Amazon_Elastic_Compute_Cloud) 非特权域（虚拟机），并在 FreeBSD 11.0 中引入了 Dom0 控制域（主机）支持。FreeBSD 11 中已移除对 para-virtualized (PV) 域的支持，转而采用硬件虚拟化 (HVM) 域，这提供了更好的性能。

Xen™ 是一种裸金属虚拟机监控程序，意味着它是 BIOS 启动后加载的第一个程序。然后，启动一个特殊的特权虚拟机，称为 Domain-0（简称 Dom0）。Dom0 使用其特殊权限直接访问底层物理硬件，使其成为一种高性能解决方案。它能够直接访问磁盘控制器和网络适配器。Xen™ 管理工具由 Dom0 用来创建、列出和销毁虚拟机。Dom0 为非特权域提供虚拟磁盘和网络，通常称为 `DomU`。Xen™ Dom0 可以与其他虚拟化解决方案的服务控制台进行比较，而 DomU 是运行个别虚拟机的地方。

Xen™ 可以在不同的 Xen™ 服务器之间迁移虚拟机。当两个 Xen 主机共享相同的底层存储时，可以在不关闭虚拟机的情况下进行迁移。相反，迁移在 DomU 正常运行时进行，且无需重新启动或规划停机时间。这在维护或升级窗口中非常有用，确保 DomU 提供的服务仍然在运行。更多的 Xen™ 功能可以在 [Xen Wiki 概述页面](https://wiki.xenproject.org/wiki/Category:Overview) 上找到。请注意，并非所有功能在 FreeBSD 上都得到支持。

## 24.8.1. Xen™ Dom0 硬件要求

要在主机上运行 Xen™ 虚拟机监控程序，需要特定的硬件功能。将 FreeBSD 作为 Xen 主机（Dom0）运行时，主机处理器需要支持 Intel 扩展页表（[EPT](https://en.wikipedia.org/wiki/Extended_Page_Table)）或 AMD 嵌套页表（[NPT](https://en.wikipedia.org/wiki/Rapid_Virtualization_Indexing)）以及输入/输出内存管理单元（[IOMMU](https://en.wikipedia.org/wiki/List_of_IOMMU-supporting_hardware)）功能。

> **注意**
>
> 为了运行 FreeBSD 13 Xen™ Dom0，系统必须使用传统引导（BIOS）启动。FreeBSD 14 及更高版本支持在 BIOS 和 UEFI 模式下作为 Xen™ Dom0 启动。

## 24.8.2. Xen™ Dom0 控制域设置

用户应安装 [emulators/xen-kernel](https://cgit.freebsd.org/ports/tree/emulators/xen-kernel/) 和 [sysutils/xen-tools](https://cgit.freebsd.org/ports/tree/sysutils/xen-tools/) 包，这些包基于 Xen™ 4.18。

在安装 Xen 包之后，必须编辑配置文件，以准备主机进行 Dom0 集成。**/etc/sysctl.conf** 文件中的一个条目将禁用内存页数限制。否则，具有更高内存需求的 DomU 虚拟机将无法运行。

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

另一个与内存相关的设置是更改 **/etc/login.conf**，将 `memorylocked` 选项设置为 `unlimited`。否则，创建 DomU 域时可能会失败，出现 `Cannot allocate memory` 错误。更改 **/etc/login.conf** 后，运行 `cap_mkdb` 更新能力数据库。有关详细信息，请参阅 [资源限制](https://docs.freebsd.org/en/books/handbook/security/#security-resourcelimits)。

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

在 **/etc/ttys** 文件中添加一个 Xen™ 控制台条目：

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

在 **/boot/loader.conf** 文件中选择一个 Xen™ 内核来激活 Dom0。Xen™ 还需要主机机器的 CPU 和内存资源供自己和其他 DomU 域使用。具体需要多少 CPU 和内存取决于个别需求和硬件能力。在此示例中，为 Dom0 分配了 8GB 内存和 4 个虚拟 CPU。还激活了串口控制台，并定义了日志选项。

对于 Xen 4.7 包，使用以下命令：

```sh
# 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 及更高版本，应该使用以下命令：

```sh
# 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 虚拟机创建的日志文件存储在 **/var/log/xen** 中。如果遇到问题，请务必检查该目录的内容。

在系统启动时启用 xencommons 服务：

```sh
# sysrc xencommons_enable=yes
```

这些设置足以启动一个启用 Dom0 的系统。但是，它缺少为 DomU 虚拟机提供网络功能。为了解决这个问题，定义一个桥接接口与主机系统的 NIC 连接，供 DomU 虚拟机使用。将 *em0* 替换为主机网络接口的名称。

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

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

```sh
# reboot
```

在成功启动 Xen™ 内核并再次登录系统后，使用 Xen™ 管理工具 `xl` 查看域的信息。

```sh
# 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™ 文档](https://www.xenproject.org/help/documentation.html)。现在可以创建 DomU 虚拟机。

## 24.8.3. Xen™ DomU 虚拟机配置

无特权域由配置文件和虚拟或物理硬盘组成。DomU 的虚拟磁盘存储可以是通过 [truncate(1)](https://man.freebsd.org/cgi/man.cgi?query=truncate\&sektion=1\&format=html) 创建的文件，也可以是如在 [“创建和销毁卷”](https://docs.freebsd.org/en/books/handbook/zfs/#zfs-zfs-volume) 中所描述的 ZFS 卷。在这个例子中，使用了一个 20 GB 的卷。创建一个虚拟机，使用 ZFS 卷、FreeBSD ISO 镜像、1 GB 的内存和两个虚拟 CPU。ISO 安装文件通过 [fetch(1)](https://man.freebsd.org/cgi/man.cgi?query=fetch\&sektion=1\&format=html) 下载并保存在名为 **freebsd.iso** 的本地文件中。

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

创建一个名为 **xendisk0** 的 20 GB ZFS 卷，用作虚拟机的磁盘空间。

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

新的 DomU 虚拟机在一个文件中定义。也定义了一些特定的设置，如名称、键盘映射和 VNC 连接细节。以下 **freebsd.cfg** 包含了此示例的最小 DomU 配置：

```ini
# cat freebsd.cfg 
builder = "hvm" ①
name = "freebsd" ②
memory = 1024 ③
vcpus = 2 ④
vif = [ 'mac=00:16:3E:74:34:32,bridge=bridge0' ] ⑤
disk = [
'/dev/zvol/tank/xendisk0,raw,hda,rw', ⑥
'/root/freebsd.iso,raw,hdc:cdrom,r' ⑦
  ]
vnc = 1 ⑧
vnclisten = "0.0.0.0"
serial = "pty"
usbdevice = "tablet"
```

这些行的详细解释：

* ① 这定义了使用何种虚拟化方式。`hvm` 表示硬件辅助虚拟化或硬件虚拟机。具有虚拟化扩展的 CPU 上，来宾操作系统可以不加修改地运行，提供几乎与运行在物理硬件上一样的性能。`generic` 是默认值，创建 PV 域。
* ② 用于区分其他正在同一个 Dom0 上运行的虚拟机的名称。是必需的。
* ③ 为虚拟机分配的内存量（以兆字节为单位）。该内存量从虚拟化管理程序的总可用内存中减去，而不是从 Dom0 的内存中减去。
* ④ 分配给虚拟机的虚拟 CPU 数量。为了获得最佳性能，不要为来宾创建比物理 CPU 更多的虚拟 CPU。
* ⑤ 虚拟网络适配器。这是连接到主机网络接口的桥接。`mac` 参数设置虚拟网络接口的 MAC 地址。此参数是可选的，如果没有提供 MAC，Xen™ 会生成一个随机的。
* ⑥ 磁盘的完整路径、文件或 ZFS 卷，作为该虚拟机的磁盘存储。选项和多个磁盘定义之间由逗号分隔。
* ⑦ 定义引导介质，用于安装初始操作系统。在此示例中，是之前下载的 ISO 镜像。请参考 Xen™ 文档了解其他类型的设备和选项设置。
* ⑧ 控制 VNC 连接到 DomU 的串行控制台的选项。依次是：启用 VNC 支持，定义监听的 IP 地址，串行控制台的设备节点，以及输入方法（用于精确定位鼠标和其他输入方式）。`keymap` 定义使用的键盘映射，默认为 `english`。

创建好包含所有必要选项的文件后，可以通过将其作为参数传递给 `xl create` 来创建 DomU。

```sh
# xl create freebsd.cfg
```

> **注意**
>
> 每次重启 Dom0 后，必须将配置文件传递给 `xl create` 以重新创建 DomU。默认情况下，重启后只会创建 Dom0，而不会创建单独的虚拟机。虚拟机可以继续运行，因为它们的操作系统存储在虚拟磁盘上。虚拟机配置可能会随着时间的推移而变化（例如，添加更多内存）。虚拟机配置文件必须妥善备份并保留，以便在需要时重新创建虚拟机。

执行 `xl list` 命令的输出确认已创建 DomU。

```sh
# 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.cfg** 中定义的 `vnclisten` 行的 IP 地址。操作系统安装完成后，关闭 DomU 并断开 VNC 查看器。编辑 **freebsd.cfg**，删除或注释掉 `cdrom` 定义的行（在行首插入 `#` 字符）。要加载新的配置，需要先使用 `xl destroy` 销毁旧的 DomU，传递虚拟机名称或 ID 作为参数。然后，使用修改后的 **freebsd.cfg** 重新创建虚拟机。

```sh
# 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™ 启动输出。以下是一些相关的调试选项：

* `iommu=debug`：可以用来打印关于 IOMMU 的额外诊断信息。
* `dom0=verbose`：可以用来打印关于 Dom0 构建过程的额外诊断信息。
* `sync_console`：强制同步控制台输出的标志。对于调试非常有用，可以避免因限速而丢失消息。切勿在生产环境中使用此选项，因为它可能允许恶意的虚拟机通过控制台对 Xen™ 发起拒绝服务攻击。

FreeBSD 还应该以详细模式启动，以便识别任何问题。要激活详细启动模式，可以运行以下命令：

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

如果这些选项都无法帮助解决问题，请将串行启动日志发送到 <freebsd-xen@FreeBSD.org> 和 <xen-devel@lists.xenproject.org> 以便进一步分析。

### 24.8.4.2. 虚拟机创建故障排除

在创建虚拟机时也可能会遇到问题，以下提供了一些帮助，帮助诊断虚拟机创建问题。

虚拟机创建失败的最常见原因是 `xl` 命令输出某些错误，并以非 0 的返回码退出。如果提供的错误信息不足以帮助识别问题，可以通过多次使用 `v` 选项从 `xl` 获取更详细的输出。

```sh
# 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**。这两个日志文件中可能包含有用的调试信息。如果这些都没有帮助解决问题，请将你遇到的问题描述和尽可能多的信息发送到 <freebsd-xen@FreeBSD.org> 和 <xen-devel@lists.xenproject.org> 以获得帮助。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://book.bsdcn.org/hanbook/di-24-zhang-xu-ni-hua/24.8.-shi-yong-freebsd-shang-de-xen-xu-ni-ji.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
