有一个虚拟磁盘文件,需要以物理磁盘(Physical Disk)的方式被挂载,且需要被拆分成若干个小文件。

        Windows本身支持的虚拟磁盘(vhd和vhdx)是不支持像Vmware虚拟磁盘(vmdk)一样被拆分成每个2G的小文件的,这就导致在一些场景下的不便,例如很多云盘仅支持小于4G甚至2G的文件上传。而Vmware虚拟磁盘并不支持挂载为物理磁盘,这就导致无法对其扩展一些仅支持物理磁盘的特性,例如BitLocker。

        笔者就在通过小米云备份一个将近60GB的vhdx文件时遇到了困难,小米云仅仅支持小于4GB的文件上传,这远远不够。于是笔者先是考虑vmdk本身支持的将虚拟磁盘文件以2G的大小分割,但vmdk的分割仅在配合虚拟机服务启停时会触发,查找了很多资料发现vmdk的挂载(映射)并不是通过物理磁盘的方式挂载的,而更像是仅仅模拟了一个带有盘符的文件夹。再是考虑不使用Vmware自带的磁盘挂载工具,转而使用第三方程序例如PowerISO、OFSMount,但OFSMount虽然可以选择模拟物理磁盘,但无法正确读取分割后的vmdk文件。

        几经周折后偶然发现Windows自带的存储管理功能,其最初的使用方法是“集结”各不同物理磁盘的空间为一个整体,进而通过备份、校验等方式提高文件存储安全性和在出现故障时的保全性。

        经过尝试后发现存储管理还支持通过若干个4GB及以上的Windows虚拟磁盘创建存储池。但如果创建并挂载的虚拟磁盘小于4GB,创建存储池时将不显示;恰好等于4GB时,创建存储池将提示“无法创建池,检查驱动器连接:不支持该请求(0x00000032)”的错误。这就陷入了僵局,要是每个都大于4GB,还是无法上传,难道通过存储管理也没有办法实现这个需求?

vhdx驱动器镜像文件还原_数据

于是去查看磁盘管理中该磁盘,发现磁盘的大小从创建时确定的4GB变为了3.88GB,差了正好128MB,这就是Windows中默认的一个保留分区的大小,于是在创建时将128MB加上,将虚拟硬盘大小设为4424MB,果然成功地创建了一个存储池。

vhdx驱动器镜像文件还原_数据_02

vhdx驱动器镜像文件还原_windows_03

         那么,只要将大的虚拟磁盘里的文件存储到通过许多个小虚拟磁盘组建的存储池中就可以了。但是由于虚拟磁盘的大小被设定为比4GB多了128MB,会不会最终的小虚拟磁盘文件们还是无法被上传呢。稍加思考,发现存储管理中有个“优化存储空间”的功能,它会使文件在各个物理驱动器中分布的更加均匀,也就是说最终每个虚拟磁盘文件的大小不会相差很多。那么在它们过大的时候,添加虚拟磁盘的个数,再通过均匀的分布就可以缩小它们每个文件的大小。

        接下来来创建足够多的虚拟磁盘,创建的个数取决于组建存储池后每个虚拟磁盘实际能存储的数据。通过测试发现,每个4GB的虚拟磁盘实际约能存储2GB不到的数据量,虽然乍一看利用率不到50%,但单个“装满的”虚拟磁盘文件在真正的物理磁盘中占用的实际空间远不会真正达到4GB,具体会比单个虚拟磁盘文件存放的有效数据多0.4GB左右,这也是可以接受的。

vhdx驱动器镜像文件还原_虚拟磁盘_04

        笔者大约需要存储60G的数据,那么大概就需要32个虚拟磁盘。将数据存入后,每个虚拟磁盘文件实际大约2GB左右,虽然在存储管理中的利用率和池容量显示的非常夸张,但好在可以无限创建并添加新的虚拟磁盘来扩大池容量,而实际组成存储池的虚拟磁盘文件占用并不会比实际的存储量大很多,这些数据便显得没有意义。同时,一旦单个虚拟磁盘文件接近我们能接受的上限,也可以通过增加它们的个数和优化驱动器使用率来降低每个虚拟磁盘中实际有意义的数据量大小。虽然vhdx不会自己压缩未经使用的空间,但可以使用Hyper-V管理控制台逐个压缩它们的大小,也可以使用Powershell的Hyper-V模块来通过脚本批量压缩。

        最终创建完成后的存储空间中的文件数据量和虚拟磁盘文件的实际大小总和对比,利用率大概在92%左右,这并不难接受。当然,如果在创建存储空间时选择“简单(无复原)”以外的复原类型,这相当于为每份数据进行了备份,但这并没有意义。所有的虚拟磁盘文件都存储在同一块物理硬盘上,很难发生由于丢失或删除它们其中的某一个而导致需要进行数据复原的情况,除非存储他们的一整块物理磁盘损坏,那将无法读取所有的虚拟磁盘文件,也就更无法复原任何数据。

        当然,这么做将会使部分数据安全性暴露于文件系统层之上,虚拟硬盘文件被删除、恶意损坏都会导致数据无法恢复,但好在这么做的目的就是为了备份这些文件。

vhdx驱动器镜像文件还原_windows_05

 

        最终:Bitlocker支持√,分割虚拟磁盘文件√,<4GB√。

最后,你在安装Powershell的Hyper-V模块后可以在Powershell控制台或脚本中使用

Mount-VHD
     [-Path] <String[]>
     [-NoDriveLetter]
     [-ReadOnly]
     [-SnapshotId <Guid>]
     [-Passthru]
     [-CimSession <CimSession[]>]
     [-ComputerName <String[]>]
     [-Credential <PSCredential[]>]
     [-WhatIf]
     [-Confirm]
     [<CommonParameters>]

挂载每个虚拟磁盘文件;使用

Dismount-VHD
        [-Path] <String[]>
        [-SnapshotId <Guid>]
        [-Passthru]
        [-CimSession <CimSession[]>]
        [-ComputerName <String[]>]
        [-Credential <PSCredential[]>]
        [-WhatIf]
        [-Confirm]
        [<CommonParameters>]

Optimize-VHD
        [-Path] <String[]>
        [-Mode <VhdCompactMode>]
        [-AsJob]
        [-Passthru]
        [-CimSession <CimSession[]>]
        [-ComputerName <String[]>]
        [-Credential <PSCredential[]>]
        [-WhatIf]
        [-Confirm]
        [<CommonParameters>]

 来分离和压缩它们的大小。