24.7.使用 FreeBSD 上的 Xen™ 虚拟机

Xen 是一个 GPLv2 许可的第 1 类虚拟机管理器open in new window,适用于 Intel® 和 ARM® 架构。FreeBSD 从 FreeBSD 8.0 开始就包含了对 i386™,AMD® 64-Bit DomUopen in new windowAmazon EC2open in new window 非特权域(虚拟机)的支持,并在 FreeBSD 11.0 中包含了对 Dom0 控制域(宿主机)的支持。在 FreeBSD 11 中,取消了对准虚拟化(PV)域的支持,转而支持硬件虚拟化(HVM)域,这提供了更好的性能。

Xen™ 是一个裸虚拟机管理器,这意味着它是在 BIOS 之后加载的第一个程序。然后会启动一个称为 Domain-0(简称 Dom0)的特殊权限客户机。Dom0 利用其特殊权限直接访问底层物理硬件,使其成为一个高性能的解决方案。它能够直接访问磁盘控制器和网络适配器。用于管理和控制 Xen™ 虚拟机管理器的 Xen™ 管理工具也被 Dom0 用来创建、列出和销毁虚拟机。Dom0 为非特权域提供虚拟磁盘和网络,通常称为 DomU。Xen™ Dom0 可以比作其他虚拟机管理器解决方案的服务控制台,而 DomU 是运行单个客户虚拟机的地方。

Xen™ 可以在不同的 Xen™ 服务器之间迁移虚拟机。当两台 xen 主机共享相同的底层存储时,迁移过程可以不必先关闭虚拟机。取而代之的是,迁移是在 DomU 运行过程中实时进行的,不需要重新启动或计划停机。这在维护场景或升级窗口中非常有用,可以确保 DomU 提供的服务持续在线。Xen™ 的许多其他功能都罗列在 Xen Wiki 概述页面open in new window上。请注意,FreeBSD 还不支持其全部功能。

24.7.1.Xen™ Dom0 的硬件要求

要在宿主机上运行 Xen™ hypervisor,需要特定的硬件功能。硬件虚拟化域需要宿主机的处理器支持扩展页表(EPTopen in new window)和输入输出内存管理单元(IOMMUopen in new window)。

注意

要运行 FreeBSD Xen™ Dom0,这个容器必须使用 legacy boot(BIOS)引导。

24.7.2.设置 Xen™ Dom0 控制域

FreeBSD 11 用户应该安装基于 Xen 4.7 的软件包 emulators/xen-kernel47open in new windowsysutils/xen-tools47open in new window。FreeBSD-12.0 及更新版本的用户可以使用基于 Xen 4.11 的 emulators/xen-kernel411open in new windowsysutils/xen-tools411open in new window

在安装 Xen 软件包后,必须编辑配置文件来为宿主机整合 Dom0 做准备。在 /etc/sysctl.conf 中加入一个条目,禁用对 wired 内存页数的限制。否则,对内存要求较高的 DomU 虚拟机将无法运行:

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

另一个内存相关的设置需要修改 /etc/login.conf,将 memorylocked 选项设置为 unlimited。否则,创建 DomU 时可能遇到错误 Cannot allocate memory 而失败。在修改 /etc/login.conf 后,运行 cap_mkdb 来更新功能数据库。参阅资源限制open in new window获得更多信息。

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

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

# 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 虚拟机创建的日志存储在 /var/log/xen。如果遇到问题,请记得查看该目录中的内容。

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

# sysrc xencommons_enable=yes

进行这些设置便可以启动 Dom-0 系统了,然而我们还没有为 DomU 虚拟机提供网络功能。为了修复这一点,请在系统的主网络接口控制器定义一个桥接网络接口,以供 DomU 虚拟机连接到网络。请用你的主网络接口名称替换 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™ 文档open in new window 中找到更多信息。现在就可以创建 DomU 客户虚拟机了。

24.7.3.Xen™ DomU 客户虚拟机配置

非特权域由一个配置文件和虚拟或物理磁盘组成。如创建和销毁卷open in new window所述,DomU 的虚拟磁盘可以是由 truncate(1)open in new window 创建的文件或者 ZFS 卷。在这个例子中,我们使用一个 20 GB 的卷。该虚拟机由这个 ZFS 卷、FreeBSD ISO 镜像、1GB 内存和两颗虚拟的 CPU 组成。使用 fetch(1)open in new window 获取 ISO 安装文件,文件在本地储存为 freebsd.iso

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

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

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

这个 DomU 客户虚拟机定义在一个文件中。诸如主机名、键盘布局和 VNC 连接的细节定义也在其中。如下的例子中,freebsd.cfg 包含了一个最简单化的 DomU 配置:

# 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 的虚拟机区分开来。这是必需项。

③ 分配给虚拟机的内存容量(用 MB 表示)。这个容量是从虚拟机管理器的总可用内存中分配的,而不是 Dom0 的内存。

④ 分配给虚拟机的虚拟 CPU 数量。为了实现最佳性能,请不要为创建的虚拟机分配多于宿主机物理 CPU 数量的虚拟 CPU。

⑤ 设定虚拟网络适配器。这个网桥将网络适配器连接到宿主机上的网络接口。mac 参数是为虚拟网络接口设定的 MAC 地址,为可选项;如果没有提供,Xen™ 将会随机生成一个。

⑥ 用作虚拟机磁盘空间的磁盘、文件或 ZFS 卷的完整路径。选项和多个磁盘定义之间用逗号隔开。

⑦ 定义初始化系统安装的启动介质。在这个例子中为先前下载的 ISO 镜像。关于其他类型的设备和选项设置请参阅 Xen™ 文档。

⑧ 设定 DomU 控制台连接 VNC。按照顺序为:激活 VNC 支持,定义监听的 IP 地址,串行控制台的设备节点,精确鼠标指针定位和其他输入设备的输入方式。keymap 定义使用何种键位,默认为 english

设定所有这些必要参数并创建文件之后,将它作为参数输入 xl create 来创建 DomU:

# xl create freebsd.cfg

提示

每次 Dom0 重启后,必须将这个配置文件再次传递到 xl create 来重新创建 DomU。默认状态下,重启后只会创建 Dom0 而不会创建虚拟机。这些虚拟机可以从在虚拟磁盘中存储的操作系统中恢复之前的状态。你可以修改虚拟机配置文件(比如增加内存)。虚拟机配置文件应该得到妥当备份,并在需要重新创建虚拟机时保证可用。

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 定义的一行,或者在该行的开头插入一个 # 字符,将其注释出来。要加载这个新的配置,必须将其名称或 id 作为参数,用 xl destroy 删除旧的 DomU。然后用修改过的 freebsd.cfg 重新创建它:

# xl destroy freebsd
# xl create freebsd.cfg

之后,这个虚拟机可以通过 VNC 查看器再次访问。这次,它会从安装操作系统的虚拟磁盘中引导,并可以作为虚拟机使用了。

24.7.4.疑难解答

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

24.7.4.1.宿主机引导疑难解答

请注意,接下来的疑难解答适用于 Xen™ 4.11 或更新版本。如果你还在使用 Xen™ 4.7 并遇到问题,请考虑迁移到更新版本的 Xen™。

为了排查宿主机启动问题,你可能需要一根串口线或 USB 调试线。通过在 loader.conf 中添加 xen_cmdline 选项,可以获得详细的 Xen™ 启动输出。几个相关的调试选项是:

  • iommu=debug:可用于输出关于 IOMMU 的额外诊断信息。
  • dom0=verbose:可用于输出关于 Dom0 构建过程的额外诊断信息。
  • sync_console:强制同步控制台输出。有助于在调试过程中避免由于更新频率限制导致丢失消息。请不要在生产环境中使用这个选项,因为它可能使恶意客户机使用控制台对 Xen™ 进行 DoS 攻击。

为了识别任何可能存在的问题,FreeBSD 也应该在详细输出模式中启动。要激活详细的引导输出,请运行:

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

如果上述的选项都没有帮助你解决问题,请将串口启动日志发送到 f[email protected][email protected] 以供进一步分析。

24.7.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™ toolstack 日志。请注意,域的名称会被附加到日志名称中,所以如果域名为 freebsd,你应该会找到 /var/log/xen/xl-freebsd.log,并可能找到 /var/log/xen/qemu-dm-freebsd.log。这两个日志文件都可能包含用于调试的有用信息。如果这些都不能帮助你解决问题,请将你所面临的问题的描述和尽可能多的信息发送到 [email protected][email protected],以便获得帮助。