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

Xen 是一个 GPLv2 许可的第一类虚拟机管理器,适用于 Intel® 和 ARM® 架构。FreeBSD 从 FreeBSD 8.0 开始就包含了对 i386™,AMD® 64-Bit DomUAmazon EC2 非特权域(虚拟机)的支持,并在 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 概述页面上。请注意,FreeBSD 还不支持其全部功能。

22.7.1. Xen™ Dom0 的硬件要求

要在宿主机上运行 Xen™ hypervisor,需要特定的硬件功能。硬件虚拟化域需要宿主机的处理器支持 Extended Page Table(EPT)和输入输出内存管理单元(IOMMU)。

提示:

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

22.7.2. 设置 Xen™ Dom0 控制域

FreeBSD 11 用户应该安装基于 Xen 4.7 的 emulators/xen-kernel47sysutils/xen-tools47 软件包。FreeBSD-12.0 或更新版本的用户可以使用基于 Xen 4.11 的 emulators/xen-kernel411sysutils/xen-tools411

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

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

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

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

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

  1. # 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:

  1. # echo 'hw.pci.mcfg=0' >> /boot/loader.conf
  2. # echo 'if_tap_load="YES"' >> /boot/loader.conf
  3. # echo 'xen_kernel="/boot/xen"' >> /boot/loader.conf
  4. # 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 或更高版本中,应使用:

  1. # echo 'if_tap_load="YES"' >> /boot/loader.conf
  2. # echo 'xen_kernel="/boot/xen"' >> /boot/loader.conf
  3. # 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 服务:

  1. # sysrc xencommons_enable=yes

进行这些设置便可以启动 Dom-0 系统了,然而我们还没有为 DomU 虚拟机提供网络功能。为了修复这一点,请在系统的主网络介面控制器定义一个桥接网络介面,以供 DomU 虚拟机连接到网络。请用你的主网络介面名称替换 em0

  1. # sysrc cloned_interfaces="bridge0"
  2. # sysrc ifconfig_bridge0="addm em0 SYNCDHCP"
  3. # sysrc ifconfig_em0="up"

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

  1. # reboot

成功引导 Xen™ 内核并再次登录进入系统后,使用 Xen™ 管理工具 xl 显示域的信息:

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

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

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

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

  1. # fetch ftp://ftp.freebsd.org/pub/FreeBSD/releases/ISO-IMAGES/12.0/FreeBSD-12.0-RELEASE-amd64-bootonly.iso -o freebsd.iso

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

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

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

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

这些命令的详细解释:

  1. builder = "hvm"

定义使用的虚拟化类型。hvm 表示硬件辅助的虚拟化或者硬件虚拟机。客户机操作系统可以通过虚拟化插件运行在未经修改的 CPU 上,提供近乎在物理硬件上运行的性能。而 generic 是默认值,将会创建一个 PV 域。

  1. name = "freebsd"

指定虚拟机名称,以便和其他同样运行在 Dom0 的虚拟机区分开来。这是必需项:

  1. memory = 1024

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

  1. vcpus = 2

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

  1. vif = [ 'mac=00:16:3E:74:34:32,bridge=bridge0' ]

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

  1. '/dev/zvol/tank/xendisk0,raw,hda,rw',

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

  1. '/root/freebsd.iso,raw,hdc:cdrom,r'

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

  1. vnc = 1
  2. vnclisten = "0.0.0.0"
  3. serial = "pty"
  4. usbdevice = "tablet"

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

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

  1. # xl create freebsd.cfg

提示:

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

xl list 的输出结果确认 DomU 已被创建:

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

开始安装基本操作系统,启动 VNC 客户端,将其指向主机的主网络地址或 freebsd.cfgvnclisten 一行定义的 IP 地址。操作系统安装完毕后,关闭 DomU 并断开与 VNC 查看器的连接。编辑 freebsd.cfg,删除带有 cdrom 定义的一行,或者在该行的开头插入一个 # 字符,将其注释出来。要加载这个新的配置,必须将其名称或 id 作为参数,用 xl destroy 删除旧的 DomU。然后用修改过的 freebsd.cfg 重新创建它:

  1. # xl destroy freebsd
  2. # xl create freebsd.cfg

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

22.7.4. 疑难解答

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

22.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 也应该在详细输出模式中启动。要激活详细输出启动,请运行:

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

如果上述的选项都没有帮助你解决问题,请将串口启动日志发送到 freebsd-xen@FreeBSD.org 和 xen-devel@lists.xenproject.org 以供进一步分析。

22.7.4.2. 客户机创建疑难解答

在创建客户机时也可能出现问题,下面将尝试为那些试图诊断客户机创建问题的人提供一些帮助。

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

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

如果这些详细的输出不能帮助你诊断问题,在 /var/log/xen 中还有 QEMU 和 Xen™ toolstack 日志。请注意,域的名称会被附加到日志名称中,所以如果域名为 freebsd,你应该找到 /var/log/xen/xl-freebsd.log,并可能找到 /var/log/xen/qemu-dm-freebsd.log。这两个日志文件都可能包含用于调试的有用信息。如果这些都不能帮助你解决问题,请将你所面临的问题的描述和尽可能多的信息发送到 freebsd-xen@FreeBSD.org 和 xen-devel@lists.xenproject.org,以便获得帮助。