第21章 其他文件系统
附录 D. OpenPGP 密钥
22.6.使用 FreeBSD 上的 bhyve 虚拟机
BSD 许可的 bhyve 虚拟机管理器随着 FreeBSD 10.0-RELEASE 已经成为了底层系统的一部分。这个虚拟机管理器支持数种客户机,包括 FreeBSD,OpenBSD 和数个 Linux® 发行版。默认情况下,bhyve 提供对串行控制台的访问而不模拟图形化控制台。其利用较新的 CPU 上的 virtualization offload 功能来避免使用过时方法翻译指令和手动管理内存映射。
bhyve 的设计需要支持 Intel® Extended Page Tables(EPT)或 AMD® Rapid Virtualization Indexing(RVI)或 Nested Page Tables(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 一行查找 EPTUG 处理器功能标识(针对 Intel® 处理器)。

22.6.1. 准备宿主机

在 bhyve 中创建虚拟机的第一步是配置宿主操作系统。首先,加载 bhyve 内核模块:
1
# kldload vmm
Copied!
然后,创建 tap 介面以供虚拟机中的网络设备进行连接。为了让该网络设备加入网络,另外创建一个桥接介面,其中包含 tap 介面和物理网络介面作为成员。在下面的例子中,物理网络介面为 igb0
1
# ifconfig tap0 create
2
# sysctl net.link.tap.up_on_open=1
3
net.link.tap.up_on_open: 0 -> 1
4
# ifconfig bridge0 create
5
# ifconfig bridge0 addm igb0 addm tap0
6
# ifconfig bridge0 up
Copied!

22.6.2. 创建一个 FreeBSD 客户机

创建一个文件用作客户机的虚拟磁盘。指定这个虚拟磁盘的大小和名称:
1
# truncate -s 16G guest.img
Copied!
下载 FreeBSD 的安装镜像:
1
# fetch ftp://ftp.freebsd.org/pub/FreeBSD/releases/ISO-IMAGES/12.2/FreeBSD-12.2-RELEASE-amd64-bootonly.iso
2
FreeBSD-12.2-RELEASE-amd64-bootonly.iso 100% of 230 MB 570 kBps 06m17s
Copied!
FreeBSD 附带了一个在 bhyve 中运行虚拟机的示例脚本。这个脚本将会启动虚拟机并循环执行,所以将在其崩溃时自动重新启动。这个脚本可接受数个选项来配置虚拟机:-c 控制虚拟 CPU 的数量,-m 限制客户机的可用内存,-t 定义使用的 tap 设备,-d 指定其使用的磁盘镜像,-i 控制 bhyve 从 CD 镜像引导,而非从磁盘引导,-I 指定要使用的 CD 镜像。最后一个参数是虚拟机的名称,该名称将被用来追踪运行中的虚拟机。这个例子将在安装模式下启动虚拟机:
1
# sh /usr/share/examples/bhyve/vmrun.sh -c 1 -m 1024M -t tap0 -d guest.img -i -I FreeBSD-12.2-RELEASE-amd64-bootonly.iso guestname
Copied!
这个虚拟机将会引导并启动安装器。在虚拟机中完成系统安装并进入最后阶段,当系统提示是否进入 shell 时,选择 Yes
重新启动虚拟机。重启会导致 bhyve 退出,这时循环执行 bhyvevmrun.sh 脚本会自动重启虚拟机。这时请从引导器菜单中选择重启来跳出循环。之后,客户机就可以从虚拟磁盘中启动了:
1
# sh /usr/share/examples/bhyve/vmrun.sh -c 4 -m 1024M -t tap0 -d guest.img guestname
Copied!

22.6.3. 创建一个 Linux® 客户机

要引导进入 FreeBSD 以外的系统,必须先安装 sysutils/grub2-bhyve port。
接下来,创建一个文件用作客户机的虚拟磁盘:
1
# truncate -s 16G linux.img
Copied!
使用 bhyve 启动虚拟机分为两个步骤。首先要加载一个内核,然后启动客户机。Linux® 内核通过 sysutils/grub2-bhyve 加载。创建 device.map 令 grub 将虚拟设备映射到宿主机上的镜像文件:
1
(hd0) ./linux.img
2
(cd0) ./somelinux.iso
Copied!
使用 sysutils/grub2-bhyve 将 Linux® 内核从 ISO 文件中加载:
1
# grub-bhyve -m device.map -r cd0 -M 1024M linuxguest
Copied!
这将启动 grub。如果安装 CD 中包含 grub.cfg,将会显示一个菜单;否则你需要手动指明并加载 vmlinuzinitrd 文件:
1
grub> ls
2
(hd0) (cd0) (cd0,msdos1) (host)
3
grub> ls (cd0)/isolinux
4
boot.cat boot.msg grub.conf initrd.img isolinux.bin isolinux.cfg memtest
5
splash.jpg TRANS.TBL vesamenu.c32 vmlinuz
6
grub> linux (cd0)/isolinux/vmlinuz
7
grub> initrd (cd0)/isolinux/initrd.img
8
grub> boot
Copied!
现在 Linux® 内核就加载完毕了,可以启动客户机:
1
# 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 \
2
-s 4:0,ahci-cd,./somelinux.iso -l com1,stdio -c 4 -m 1024M linuxguest
Copied!
系统将会引导进入并启动安装器。在虚拟机中完成系统安装之后,重新启动虚拟机。bhyve 会在这时退出。请先销毁这个虚拟机实例,然后重新启动:
1
# bhyvectl --destroy --vm=linuxguest
Copied!
现在客户机可以直接从磁盘镜像中启动了。首先加载内核:
1
# grub-bhyve -m device.map -r hd0,msdos1 -M 1024M linuxguest
2
grub> ls
3
(hd0) (hd0,msdos2) (hd0,msdos1) (cd0) (cd0,msdos1) (host)
4
(lvm/VolGroup-lv_swap) (lvm/VolGroup-lv_root)
5
grub> ls (hd0,msdos1)/
6
lost+found/ grub/ efi/ System.map-2.6.32-431.el6.x86_64 config-2.6.32-431.el6.x
7
86_64 symvers-2.6.32-431.el6.x86_64.gz vmlinuz-2.6.32-431.el6.x86_64
8
initramfs-2.6.32-431.el6.x86_64.img
9
grub> linux (hd0,msdos1)/vmlinuz-2.6.32-431.el6.x86_64 root=/dev/mapper/VolGroup-lv_root
10
grub> initrd (hd0,msdos1)/initramfs-2.6.32-431.el6.x86_64.img
11
grub> boot
Copied!
引导进入虚拟机:
1
# bhyve -A -H -P -s 0:0,hostbridge -s 1:0,lpc -s 2:0,virtio-net,tap0 \
2
-s 3:0,virtio-blk,./linux.img -l com1,stdio -c 4 -m 1024M linuxguest
Copied!
虚拟机中的 Linux® 将会启动并提示你登录。当你不再使用虚拟机时,重新启动虚拟机来退出 bhyve,并销毁虚拟机实例:
1
# bhyvectl --destroy --vm=linuxguest
Copied!

22.6.4. 使用 UEFI 固件引导 bhyve 虚拟机

除了 bhyveload 和 grub-bhyve,bhyve 虚拟机管理器还可使用 UEFI 用户态固件来引导虚拟机。这可能兼容其他引导器不支持的客户机操作系统。
要利用 bhyve 的 UEFI 支持,首先要生成 UEFI 固件镜像。你可以通过 sysutils/bhyve-firmware port 或 package 来实现。
准备好固件之后,向 bhyve 命令添加标识 -l bootrom,/path/to/firmware,例如:
1
# bhyve -AHP -s 0:0,hostbridge -s 1:0,lpc \
2
-s 2:0,virtio-net,tap1 -s 3:0,virtio-blk,./disk.img \
3
-s 4:0,ahci-cd,./install.iso -c 4 -m 1024M \
4
-l bootrom,/usr/local/share/uefi-firmware/BHYVE_UEFI.fd \
5
guest
Copied!
sysutils/bhyve-firmware 还包含了启用 CSM 的固件,若要在 legacy BIOS 模式中启动不支持 UEFI 的客户机,请这样运行:
1
# bhyve -AHP -s 0:0,hostbridge -s 1:0,lpc \
2
-s 2:0,virtio-net,tap1 -s 3:0,virtio-blk,./disk.img \
3
-s 4:0,ahci-cd,./install.iso -c 4 -m 1024M \
4
-l bootrom,/usr/local/share/uefi-firmware/BHYVE_UEFI_CSM.fd \
5
guest
Copied!

22.6.5. 为客户机设置图形化 UEFI Framebuffer

UEFI 固件支持对主要使用图形化界面的客户机操作系统格外有用,例如 Microsoft Windows®。
对 UEFI-GOP framebuffer 的支持也可以用标识 -s 29,fbuf,tcp=0.0.0.0:5900 来启用。framebuffer 的分辨率可以通过如 w=800 h=600 来设置。bhyve 也可以通过添加 wait 来等待 VNC 连接,之后再引导进入客户机。framebuffer 可以从宿主机或者 VNC 协议的网络连接访问。此外,可以添加 -s 30,xhci,tablet 来实现与宿主机之间精确的鼠标同步。
最后的 bhyve 命令可能类似这样:
1
# bhyve -AHP -s 0:0,hostbridge -s 31:0,lpc \
2
-s 2:0,virtio-net,tap1 -s 3:0,virtio-blk,./disk.img \
3
-s 4:0,ahci-cd,./install.iso -c 4 -m 1024M \
4
-s 29,fbuf,tcp=0.0.0.0:5900,w=800,h=600,wait \
5
-s 30,xhci,tablet \
6
-l bootrom,/usr/local/share/uefi-firmware/BHYVE_UEFI.fd \
7
guest
Copied!
提示:
在模拟 BIOS 模式下,当控制从固件移交到宿主机操作系统后,framebuffer 会停止接收更新。

22.6.6. 在 bhyve 客户机中使用 ZFS

如果在宿主机上可以使用 ZFS,在客户机上使用 ZFS 卷取代磁盘镜像可以显著提高性能。你可以这样新建一个 ZFS 卷:
1
# zfs create -V16G -o volmode=dev zroot/linuxdisk0
Copied!
启动虚拟机时,指定 ZFS 卷作为磁盘驱动器:
1
# 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 \
2
-l com1,stdio -c 4 -m 1024M linuxguest
Copied!

22.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) 获取更多信息。
1
# kldload nmdm
2
# 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 \
3
-l com1,/dev/nmdm0A -c 4 -m 1024M linuxguest
4
# cu -l /dev/nmdm0B
5
Connected
6
7
Ubuntu 13.10 handbook ttyS0
8
9
handbook login:
Copied!

22.6.8. 管理虚拟机

对于每个虚拟机,在 /dev/vmm 下都会创建一个设备节点。这使得管理员很容易就能看到运行中的虚拟机列表:
1
# ls -al /dev/vmm
2
total 1
3
dr-xr-xr-x 2 root wheel 512 Mar 17 12:19 ./
4
dr-xr-xr-x 14 root wheel 512 Mar 17 06:38 ../
5
crw------- 1 root wheel 0x1a2 Mar 17 12:20 guestname
6
crw------- 1 root wheel 0x19f Mar 17 12:19 linuxguest
7
crw------- 1 root wheel 0x1a1 Mar 17 12:19 otherguest
Copied!
通过 bhyvectl 可以销毁指定的虚拟机:
1
# bhyvectl --destroy --vm=guestname
Copied!

22.6.9. 持久化配置

要配置系统在启动时运行 bhyve 虚拟机,请进行如下配置:
  1. 1.
    /etc/sysctl.conf
    1
    net.link.tap.up_on_open=1
    Copied!
  2. 2.
    /etc/rc.conf
    1
    cloned_interfaces="bridge0 tap0"
    2
    ifconfig_bridge0="addm igb0 addm tap0"
    3
    kld_list="nmdm vmm"
    Copied!