我想了解 IO 是如何从虚拟机发送到硬盘块的。
在虚拟机中拥有 XFS 或 ext3 或 ext4 等真的很重要吗,或者它仅仅取决于主机的文件系统?
与虚拟机和物理机相比,对 IO 有何影响?
以下只是我根据自己所知做出的假设。如有错误,请指正:
假设我正在使用 RAW 图像!
示例 1: Preallocation=full
(Virtual Size = Disk Size)
- 如果我理解正确的话,用于虚拟机的磁盘块在这种模式下是预先分配的,未使用的数据用零填充。
- 一旦在该原始磁盘上安装了客户操作系统,所有这些物理磁盘块都会映射到虚拟磁盘块(硬编码映射?)。
- 对于虚拟机内部发出的任何 IO 请求,Guest OS 内核首先会对其进行处理,并向虚拟磁盘发送请求,然后由某种虚拟抽象服务(我猜是 libvirtd)处理该请求,并将其发送到硬盘控制器。但我不明白的是,如果物理磁盘块是预先分配的,IO 请求应该包含所有块地址或块映射,以便数据仅写入其中一个磁盘块中。但是,这种 IO 请求是如何向硬盘控制器发出的,这似乎确实是一个重大的性能问题。
在这个例子中,我完全排除了主机的文件系统。我找不到关联它的方法。
再次重申,以上所有内容都是我的大胆假设。我感觉我对上述想法确实错了。但我希望有人能纠正我。
示例 2: preallocation=off
(Disk Size = Actual usage)
- 虚拟机的磁盘块不是预先分配的,仅根据实际磁盘使用情况进行分配。
- 示例 1 中的相同步骤在此适用,直到向硬盘控制器发出 IO 请求,但这里不需要请求覆盖特定块,因为这里没有进行预分配。
那么,回到我实际的问题。看来虚拟机上的文件系统确实会产生影响,因为所有对 IO 的调用都是从 Guest OS 内核发起的,之后才开始。
呵呵,困惑啊!!!!:(
答案1
您可以使用或不使用文件系统来访问块设备。您可以执行以下操作:
echo "hi" > /dev/sda # (please don't do this! :)
你可以这样做:
mount /dev/sda /mnt
echo "hi" > /mnt/myfile
虚拟化系统的作用完全相同。您可以配置它们以使用原始分区或某些文件模拟客户硬盘。在第一种情况下,主机的文件系统无关紧要,因为实际上没有文件系统。在第二种情况下,您选择的文件系统将产生(轻微)影响。
我认为您最关心的是第二种方式,所以让我们集中精力讨论这一点。基于文件的虚拟化“硬盘”只是文件。它们可以是简单的原始文件(您将在其中看到与 cat 真实硬盘时完全相同的位),也可以是带有标头信息甚至压缩的特殊格式文件(如 qcow)。无论如何,它们只是文件。
当然,底层(主机)文件系统确实很重要,因为它托管着这个大文件。一些(大多数现代)文件系统可以处理稀疏文件有些文件系统在处理/删除大文件方面表现更好,比如 XFS。有些文件系统可以在网络上传播文件,比如 GlusterFS。事实上,你可以拥有多层文件系统。从虚拟化系统的角度来看,整个过程都是透明的,只需要文件即可。
对硬盘上物理设备块的访问可以很好地抽象化。在极端情况下,您可能希望从物理磁盘构建 RAID 阵列,在该 RAID 设备上创建 LVM 卷,然后创建一个新的 LVM 分区,在该分区上创建 XFS 文件系统,从该文件系统创建 GlusterFS 网络文件系统(以及在其他机器上进行一些类似的设置)。假设您创建了一个虚拟机,它使用位于此 glusterFS 上的 qcow 文件。在虚拟机中创建的 ext4 文件系统上的磁盘写入将传播到所有层。客户内核的磁盘 IO 将由虚拟化层转换为文件写入,然后由 gluster、XFS、LVM 和 raid 处理。当然,这会带来一些开销,而且肯定比直接访问慢。
您可以轻松模拟虚拟化在原始文件情况下所做的事情。使用 dd 创建一个大文件,在其上创建分区,在该分区上创建文件系统。您将拥有一个“硬盘”,即一个文件。现在,您可以挂载该文件系统、复制操作系统、卸载,并使用您的文件作为磁盘启动虚拟机!(不过,您必须从其他设备(如虚拟 CD)启动,或者必须在磁盘文件启动时安装 grub)。