在我自己找到解决方案后我写下了这篇文章,因为这是一个非常奇怪的“陷阱”,值得记录下来。
虽然我在进行恢复时遇到了这个问题,但在将 ESXi 安装的启动驱动器连接到系统时启动到另一个操作系统的其他情况下也可能会遇到这种情况,特别是在磁盘大小发生变化的情况下。
我最近刚刚恢复了 VMware ESXi 安装的启动驱动器,其中还包含一个数据存储,其中保存了大多数虚拟机及其虚拟启动/系统磁盘,但我却发现这个所谓已知良好的状态不知为何却被破坏了。
根据服务器本地控制台上的显示,ESXi 似乎启动正常,但它表现出许多有问题的症状:
无法使用 vSphere Client 登录,提示“vSphere Client 无法连接到主持人。发生未知的连接错误。(由于连接失败,请求失败。(无法连接到远程服务器))”。
vSphere Client 的日志包含一个错误:
System.Net.Sockets.SocketException: No connection could be made because the target machine actively refused it
尝试使用网络浏览器登录服务器,浏览器报告连接被拒绝。
即使在本地控制台上启用此功能,也无法通过 SSH 进入服务器。
通过本地控制台重新启动管理网络和管理代理并不能解决问题。
在本地控制台上,发现
hostd
它没有运行,并且重新启动也无法解决问题。esxcli
命令总是给出:Connect to localhost failed: Connection failure
下面的目录比预期的要少
/vmfs/volumes
,而且似乎都不是我的数据存储区。即使在本地 UI 中“重置系统配置”也无法解决问题。(我之所以尝试这样做,只是因为我有一个可以再次恢复的已知良好的映像,我在解决问题后这样做了,尽管我不确定它是否改变了任何东西。)
我要恢复的备份副本是服务器关闭时获取的 RAID 逻辑磁盘的低级映像。删除可能损坏的 RAID 阵列并重新创建后,我使用连接到 HBA 的单独驱动器启动到物理 Windows Server 安装,以将映像复制到新的 RAID。我使用了 HDD Raw Copy Toolhddguru.com,它基本上是 Linux 命令的一个不那么神秘和令人紧张的替代品dd
。
(这是一种公认的野蛮的——尽管相当完整的—— VMware 备份方式,但该磁盘主要仅存储 VM 启动/系统磁盘,而不是数据,因此除非进行重大更改,否则不会频繁备份。我们有更好的主要数据备份系统。)
我把新的 RAID 逻辑磁盘设置得比备份的更大,因为我们已将 RAID 升级到更大的驱动器,而数据存储有点满了。在确认备份有效后,我计划扩大数据存储。
我刚完成原始复制,就启动 ESXi 发现它坏了。发生了什么?!
这是一个相当老的 ESXi 5.0 U3。(它已经很好地满足了我们目前的需求,而且我们没有任何全职 IT 人员来管理升级,修复升级经常导致的问题等。)
答案1
就我而言,损坏可能来自 Windows,但其他软件也可能导致同样的问题。
这肯定适用于 ESXi 5.0 U3,也可能适用于任何 ESXi 5.x,我猜也可能适用于任何 ESXi 6.x。它不太可能适用于使用不同、更简单的分区布局的 ESXi 7。
调查背景
当我终于开始弄清楚的时候,我几乎要进行一次全新安装。
在 中四处查看时,我注意到一件奇怪的事情,那就是所有目录中/vmfs/volumes
都有目录,这些目录包含文件,其内容与 Windows Explorer shell 扩展一致。在一个不是并且从未基于 Windows 的虚拟机管理程序的系统分区中发现这种情况有点奇怪。$RECYCLE.BIN
DESKTOP.INI
我立即怀疑我用来复制磁盘映像的 Windows 操作系统对它做了什么。ESXi 在其启动盘上使用多个 FAT 分区,因此 Windows 可能会利用它们。考虑到磁盘映像是从已知良好的状态获取的,但却失败了,什么也没做之内ESXi,这似乎是最有希望的研究方向。
当我通过十六进制编辑器发现这些$RECYCLE.BIN
目录也出现在磁盘映像中时,我最初感到沮丧。起初,我以为这意味着在拍摄映像之前就已经造成了损害——在 Windows Server 中也是如此。然而,事实证明这些是良性的,尽管它们引导我朝着正确的方向前进。Windows 很可能在看到原始逻辑磁盘时就添加了这些内容,而原始逻辑磁盘尚未升级——尽管磁盘一直处于“脱机”状态。
在十六进制编辑器中进一步探索(HxD - 十六进制编辑器和磁盘编辑器(真的很棒的工具)显示了磁盘映像中的 GPT 分区表与新 RAID 磁盘上的分区表之间存在一个奇怪的小差异。这不是分区编辑器会显示的差异,因为从逻辑上来说其实没什么区别据我所知。您必须在原始十六进制转储中四处寻找才能找到它。
根本原因
在这两种情况下,分区阵列中都有七个非空条目。但是,ESXi 最初写入阵列的方式,在前三个条目之后有一个空条目(所有 128 个字节都清零)的间隙,因此最后四个有效条目落入它们自己的 512 字节扇区中。在 ESXi 崩溃的活动磁盘上,最后四个有效条目已上移一个条目以填补间隙。否则,这些条目是相同的。
我不知道是谁做的,Windows 还是 HDD Raw Copy Tool,但我有点怀疑是 Windows。我再次测试了它,这个变化将会出现立即地复制完成后,即使在复制期间和复制后,RAID 逻辑驱动器在磁盘管理 MMC 管理单元中处于“脱机”状态。这显然是故意的改变,因为 CRC 都是正确的,备份 GPT 也同样发生了变化。
我的理论是,无论是谁在做这件事,都在重写 GPT,因为它与磁盘的大小不匹配,并且它不是精确复制现有阵列,而是将分区作为列表记住在某些内部结构中,然后直接重写阵列,这当然不会产生间隙。
附带说明一下,ESXi 写入的阵列中的条目与分区在磁盘上的物理顺序并不相同,但幸运的是,无论是什么程序弥补了这一差距,至少没有擅自对条目进行排序!
手动修复
我不知道有任何简单的方法可以重新创建这个间隙,因为通常任何分区编辑器都会做同样的事情:将现有表转换为工具使用的内部表示,对该表示进行您请求的更改,然后以 GPT 格式将表写回,使其具有正确的数据。据我所知,阵列条目的确切磁盘定位不应该相关,因此不会成为它写回的所谓“正确数据”的一部分。
但是,我预感到 ESXi 可能对确切的阵列布局很挑剔,所以我决定手动修复它,看看会发生什么。程序如下:
- 确保磁盘在磁盘管理 MMC 管理单元中处于“脱机”状态(作为预防措施)。
- 在十六进制编辑器中打开磁盘。在 HxD 中,它位于更多→打开磁盘...您必须从“物理磁盘”中选择。请务必取消选中“以只读方式打开”,默认情况下处于启用状态。您将收到有关此操作危险的适当警告。
- 在主 GPT 阵列中,通常从 LBA 2 开始(在 48h 处的标头四字处确认),通过复制范围、进一步向下粘贴,然后将间隙清零,将应该位于间隙之后的条目向下滑动。更好的方法是,只需从备份映像中复制实际表(如果有);但请注意,如果 LUN 的大小已更改,您不能只复制 GPT 标头,否则情况可能会重演,因为该标头的字段 20h 和 30h 的值会错误。
- 选择全部的GPT 数组的范围。从技术上讲,您必须使用 GPT 标头中 50h 和 54h 处的双字的乘积来确定范围,但这个数字通常为 16,384 字节。
- 取步骤 4 中选定范围的 CRC32。我无法在 UEFI 规范中找到 CRC32 算法的数学参数,但能够弄清楚它是一种非常常见的算法,即 ISO 802‑3 中的算法,其正则多项式为 04C11DB7h。您可以使用在线计算器计算它这里,确保将“输入类型”设置为十六进制。将其放入 GPT 标头中的 58h 处的 little-endian 中。
- 暂时将零放入 GPT 标头的 10h 处的四个字节中。
- 取出报头的 CRC32,其长度由报头本身的 0Ch 处的双字指定。将其放入报头的 10h 处。
- 对备份 GPT 重复步骤 3 到 7。阵列及其 CRC 将相同,因此您可以直接复制它们,但标头将不同,因此具有不同的 CRC。备份的标头通常位于磁盘的最后一个扇区,阵列紧挨着它,但从技术上讲,您应该检查主 GPT 标头中的四字 20h 和备份标头中的四字 48h 以进行确认。
- 如果你是完全确定如果您已正确完成所有操作,请点击“保存”。HxD 会再次在此处向您发出适当的警告提示。
您可以咨询维基百科文章了解 GPT 格式的基本技术细节。
截图
以下是“损坏的” GPT 阵列的一部分;请注意,有效条目以 77Fh 结束,并且在此之前没有长串的零:
以下是我修复它的方法;请注意,有效条目现在以 7FFh 结束:
结果
我其实没想到这个会起作用。我还没有研究过,但我认为 UEFI 规范并不重视数组条目的顺序或间距。事实上,每个分区都有一个唯一的 GUID恰恰所以你不必须依赖这种脆弱的启发式方法。因此,依赖数组索引与编写表格时相同不是一个好主意。
(再说,这也不是我第一次看到企业级软件和固件有坏主意。似乎每次我戴上系统管理员的帽子,我都会遇到一个或另一个愚蠢至极的编程……但我不要咆哮。)
因此,我小心翼翼地保存了调整后的表格,重新启动 RAID,ESXi 启动,vSphere Client 连接,一切恢复正常。
理想情况下,你通常最好使用 Veeam Backup 之类的产品,但在某些情况下特别指定解决方案可能是有序的,在这种情况下您可能会遇到这个错误。