24.6.使用 FreeBSD 上的 bhyve 虚拟机 =================================== BSD 许可的 bhyve 虚拟机管理器随着 FreeBSD 10.0-RELEASE 开始成为底层系统的一部分。这个虚拟机管理器支持数种客户机,包括 FreeBSD,OpenBSD 和数个 Linux® 发行版。默认情况下,bhyve 提供对串行控制台的访问而不模拟图形化控制台。其利用较新的 CPU 上的虚拟化 offload 功能来避免使用过时方法翻译指令和手动管理内存映射。 bhyve 在设计上需要支持 Intel® 扩展页表(EPT)或 AMD® 快速虚拟化索引(RVI)或 Nested 页表(NPT)的 CPU。以超过一枚 vCPU 运行 Linux 或者 FreeBSD 客户机需要 VMX unrestricted 模式(UG)支持。大多数新的处理器,特别是 Intel® Core™ i3/i5/i7 和 Intel® Xeon™ E3/E5/E7 都支持这些功能。对 UG 的支持是从 Intel® 的 Westmere 微架构引入的。若要查阅一份完整的支持 EPT 的 Intel® 处理器列表,请参见 https://ark.intel.com/content/www/us/en/ark/search/featurefilter.html?productType=873&0_ExtendedPageTables=True\ 。RVI 在第三代以及之后的 AMD Opteron™(Barcelona)处理器中应用。判断处理器是否支持 bhyve 的方法是运行 ``demsg``\ ,或者在 **/var/run/dmesg.boot** 中的 ``Feature2`` 一行查找 ``POPCNT`` 处理器功能标识(针对 AMD® 处理器);或者在 ``VT-x`` 一行查找 ``EPT`` 和 ``UG`` 处理器功能标识(针对 Intel® 处理器)。 24.6.1.准备宿主机 ----------------- 在 bhyve 中创建虚拟机的第一步是配置宿主操作系统。首先,加载 bhyve 内核模块: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # kldload vmm 然后,创建 ``tap`` 接口以供虚拟机中的网络设备进行连接。为了让该网络设备加入网络,另外创建一个桥接接口,其中包含 ``tap`` 接口和物理网络接口作为成员。在下面的例子中,物理网络接口为 ``igb0``\ : .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # 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.6.2.创建一个 FreeBSD 客户机 ------------------------------ 创建一个文件用作客户机的虚拟磁盘。指定这个虚拟磁盘的大小和名称: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # truncate -s 16G guest.img 下载 FreeBSD 的安装镜像: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # fetch https://download.freebsd.org/releases/ISO-IMAGES/13.1/FreeBSD-13.1-RELEASE-amd64-bootonly.iso FreeBSD-13.1-RELEASE-amd64-bootonly.iso 366 MB 16 MBps 22s FreeBSD 附带了一个在 bhyve 中运行虚拟机的示例脚本。这个脚本将会启动虚拟机并循环执行,所以可在其崩溃时自动重新启动。这个脚本可接受数个选项来配置虚拟机:\ ``-c`` 控制虚拟 CPU 的数量,\ ``-m`` 限制客户机的可用内存,\ ``-t`` 定义使用的 **tap** 设备,\ ``-d`` 指定其使用的磁盘镜像,\ ``-i`` 控制 bhyve 从 CD 镜像引导,而非从磁盘引导,\ ``-I`` 指定要使用的 CD 镜像。最后一个参数是虚拟机的名称,该名称将被用来追踪运行中的虚拟机。这个例子将在安装模式下启动虚拟机: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # sh /usr/share/examples/bhyve/vmrun.sh -c 1 -m 1024M -t tap0 -d guest.img -i -I FreeBSD-13.1-RELEASE-amd64-bootonly.iso guestname 这个虚拟机将会引导并启动安装器。在虚拟机中完成系统安装并进入最后阶段,当系统提示是否进入 shell 时,选择 **Yes**\ 。 重新启动虚拟机。重启会导致 bhyve 退出,这时循环执行 ``bhyve`` 的 **vmrun.sh** 脚本会自动重启虚拟机。这时请从引导器菜单中选择重启来跳出循环。之后,客户机就可以从虚拟磁盘中启动了: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # sh /usr/share/examples/bhyve/vmrun.sh -c 4 -m 1024M -t tap0 -d guest.img guestname 24.6.3.创建一个 Linux® 客户机 ----------------------------- 要引导进入 FreeBSD 以外的系统,必须先安装 port `sysutils/grub2-bhyve `__\ 。 接下来,创建一个文件用作客户机的虚拟磁盘: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # truncate -s 16G linux.img 使用 bhyve 启动虚拟机分为两个步骤。首先要加载一个内核,然后启动客户机。通过 `sysutils/grub2-bhyve `__ 加载 Linux® 内核。创建 **device.map** 令 grub 将虚拟设备映射到宿主机上的镜像文件: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session (hd0) ./linux.img (cd0) ./somelinux.iso 使用 `sysutils/grub2-bhyve `__ 从 ISO 文件中加载 Linux® 内核: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # grub-bhyve -m device.map -r cd0 -M 1024M linuxguest 这将启动 grub。如果安装 CD 中包含 **grub.cfg**\ ,将会显示一个菜单;否则你需要手动指明并加载 ``vmlinuz`` 和 ``initrd`` 文件: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session 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® 内核就加载完毕了,可以启动客户机: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # 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 会在这时退出。请先销毁这个虚拟机实例,然后重新启动: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # bhyvectl --destroy --vm=linuxguest 现在客户机可以直接从磁盘镜像中启动了。首先加载内核: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # 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 引导进入虚拟机: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # 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,并销毁虚拟机实例: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # bhyvectl --destroy --vm=linuxguest 24.6.4.使用 UEFI 固件引导 bhyve 虚拟机 -------------------------------------- 除了 bhyveload 和 grub-bhyve,bhyve 虚拟机管理器还可使用 UEFI 用户空间固件来引导虚拟机。这可以兼容其他引导器不支持的客户机操作系统。 要利用 bhyve 的 UEFI 支持,首先要生成 UEFI 固件镜像。你可以通过 port 或软件包安装 `sysutils/bhyve-firmware `__ 来实现。 准备好固件之后,向 bhyve 命令添加标识 ``-l bootrom,/path/to/firmware``\ ,例如: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # 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 `sysutils/bhyve-firmware `__ 还包含了启用 CSM 的固件,若要在 legacy BIOS 模式中启动不支持 UEFI 的客户机,请这样运行: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # 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.6.5.为客户机设置图形化 UEFI 帧缓冲 ------------------------------------- UEFI 固件支持对主要使用图形化界面的客户机操作系统格外有用,例如 Microsoft Windows®。 对 UEFI-GOP framebuffer 的支持也可以用参数 ``-s 29,fbuf,tcp=0.0.0.0:5900`` 来启用。帧缓冲的分辨率可以通过如 ``w=800`` ``h=600`` 来设置。bhyve 也可以通过添加 ``wait`` 来等待 VNC 连接,之后再引导进入客户机。framebuffer 可以从宿主机或者 VNC 协议的网络连接访问。此外,可以添加 ``-s 30,xhci,tablet`` 来实现与宿主机之间精确的鼠标同步。 最后的 bhyve 命令可能类似这样: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # 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.6.6.在 bhyve 客户机中使用 ZFS -------------------------------- 如果在宿主机上可以使用 ZFS,在客户机上使用 ZFS 卷取代磁盘镜像可以显著提高性能。你可以这样新建一个 ZFS 卷: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # zfs create -V16G -o volmode=dev zroot/linuxdisk0 启动虚拟机时,指定 ZFS 卷作为磁盘驱动器: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # 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 24.6.7.虚拟机控制台 ------------------- 你可以使用类似于 `sysutils/tmux `__ 或者 `sysutils/screen `__ 这样的管理工具将 bhyve 控制台封装在一个会话中用来连接和断开控制台,这将带来一些好处。你还可以将一个空的调制解调器作为 bhyve 的控制台,然后使用 ``cu`` 来访问。若要这样做,请加载 **nmdm** 内核模块,然后将 ``-l com1,stdio`` 替换为 ``-l com1,/dev/nmdm0A``\ 。设备 **/dev/nmdm** 会自动按需创建并组成一对,对应着空的调制解调器的两端(\ **/dev/nmdm0A** 和 **/dev/nmdm0B**\ )。查阅 `nmdm(4) `__ 获取更多信息。 .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # 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: 24.6.8.管理虚拟机 ----------------- 对于每个虚拟机,在 **/dev/vmm** 下都会创建一个设备节点。这使得管理员很容易就能看到运行中的虚拟机列表: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # 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`` 可以销毁指定的虚拟机: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # bhyvectl --destroy --vm=guestname 24.6.9.持久化配置 ----------------- 要配置系统在启动时运行 bhyve 虚拟机,请进行如下配置: 1. **/etc/sysctl.conf** .. code:: shell-session net.link.tap.up_on_open=1 2. **/etc/rc.conf** .. code:: shell-session cloned_interfaces="bridge0 tap0" ifconfig_bridge0="addm igb0 addm tap0" kld_list="nmdm vmm"