谷歌计算引擎VM实例:VFS:无法在未知块上挂载根文件系统

3
我的Google Compute Engine实例由于启动顺序问题而无法启动。
因此,我创建了另一个实例并重新配置了我的机器。
我的问题:
1. 当我托管一些网站时,如何处理这些问题? 2. 如何从旧磁盘中恢复我的数据?
日志:
[ 0.348577] 注册了可信密钥类型 [ 0.349232] 注册了加密密钥类型 [ 0.349769] AppArmor: 启用了AppArmor sha1策略散列 [ 0.351070] ima: 没有发现TPM芯片,激活TPM-bypass! [ 0.351549] 魔数:11:333:138 [ 0.352077] 块ram3:哈希匹配 [ 0.352550] rtc_cmos 00:00: 将系统时钟设置为2015-12-19 17:06:53 UTC (1450544813) [ 0.353492] BIOS EDD facility v0.16 2004-Jun-25,未找到设备 [ 0.354108] EDD信息不可用。 [ 0.536267] 输入:AT Translated Set 2键盘 /devices/platform/i8042/serio0/input/input2 [ 0.537862] md:在自动检测之前等待所有设备可用 [ 0.538979] md:如果您不使用RAID,请使用raid=noautodetect [ 0.539969] md:自动检测RAID阵列。 [ 0.540699] md:扫描了0个设备并添加了0个设备。 [ 0.541565] md:autorun... [ 0.542093] md:...autorun DONE。 [ 0.542723] VFS:无法打开根设备“sda1”或未知块(0,0):错误-6 [ 0.543731] 请添加正确的“root=”引导选项;以下是可用的分区: [ 0.545011] Kernel panic - not syncing: VFS:无法挂载未知块(0,0)上的根文件系统 [ 0.546199] CPU:0 PID:1 Comm:swapper/0 Not tainted 3.19.0-39-generic #44~14.04.1-Ubuntu [ 0.547579] 硬件名称:Google Google,BIOS Google 01/01/2011 [ 0.548728] ffffea00008ae140 ffff880024ee7db8 ffffffff817af92b 000000000000111e [ 0.549004] ffffffff81a7c7c8 ffff880024ee7e38 ffffffff817a976b ffff880024ee7dd8 [ 0.549004] ffffffff00000010 ffff880024ee7e48 ffff880024ee7de8 ffff880024ee7e38 [ 0.549004] 调用跟踪: [ 0.549004] [] dump_stack+0x45/0x57 [ 0.549004] [] panic+0xc1/0x1f5 [ 0.549004] [] mount_block_root+0x210/0x2a9 [ 0.549004] [] mount_root+0x54/0x58 [ 0.549004] [] prepare_namespace+0x16d/0x1a6 [ 0.549004] [] kernel_init_freeable+0x1f6/0x20b [ 0.549004] [] ? initcall_blacklist+0xc0/0xc0 [ 0.549004] [] ? rest_init+0x80/0x80 [ 0.549004] [] kernel_init+0xe/0xf0 [ 0.549004] [] ret_from_fork+0x58/0x90 [ 0.549004] [] ? rest_init+0x80/0x80 [ 0.549004] 内核偏移量:从0xffffffff81000000到0xffffffffbfffffff的重定位范围中的

请提供更多信息,例如您从哪个VM映像启动的,对实例进行了哪些修改等。 - Misha Brukman
刚刚发生了这种情况。我甚至没有做任何重要的事情,似乎是在 WordPress 实例的简单数据库写入期间出现了问题。 - Dan
@Dan 是的。经过几次来回的电子邮件后,我终于找到了一个知道自己在做什么的支持技术人员。一旦我验证了根本原因并且修复方案可以跨更新保持持久,那么我就会在这里发布解决方案。最多再给我一天时间。 - Nostalg.io
@Dan 如果那个答案有帮助,请告诉我。 - Nostalg.io
@halfnibble,它起作用了!太神奇了!非常感谢。现在的问题是,既然我已经拿回了我的数据,是否继续使用GCE还是转向AWS。此外,请发布一个链接到您对我的问题的答案,以便我也可以在那里接受您的答案!http://stackoverflow.com/questions/34821926/google-compute-instance-wont-mount-persistent-disk-maintains-100-cpu - Dan
显示剩余3条评论
4个回答

6

是什么导致了这个问题?

这是一个百万美元的问题。在检查我的GCE VM之后,我发现安装了14个不同的内核,占用了几百MB的空间。大多数内核没有相应的initrd.img文件,因此无法启动(包括3.19.0-39-generic)。

我肯定从未试图安装随机内核,一旦删除,它们就不再作为可用的升级出现,所以我不知道发生了什么。说真的,到底发生了什么?

编辑:来自Google Cloud Support的新回复。

我收到了另一个令人不安的回复。这可能解释了额外的错误内核。

"在极少数情况下,需要将VM从一个物理主机迁移到另一个物理主机。在这种情况下,谷歌可能会应用内核升级和安全补丁。"

1. "我如何在托管一些网站时处理这些问题?"

我的第一反应是建议使用AWS而不是GCE。然而,GCE更便宜。在进行任何升级之前,请确保拍摄快照,并尝试重新启动服务器以查看升级是否会破坏任何内容。

2. 如何从旧磁盘中恢复数据?

更好的方法 - 如何恢复您的实例...

在来回多次的电子邮件后,我终于收到了支持部门的回复,这使我能够解决问题。请注意,您将需要更改内容以匹配您的独特VM。

  1. 首先拍摄磁盘快照,以防我们需要回滚以下任何更改。

  2. 编辑损坏实例的属性,禁用此选项:"删除实例时删除引导磁盘"

  3. 删除损坏的实例。

    重要提示:确保不选择删除引导磁盘选项。否则,磁盘将被永久删除!

  4. 启动新的临时实例。

  5. 将损坏的磁盘(这将显示为/dev/sdb1)附加到临时实例

  6. 当临时实例启动时,请执行以下操作:

在临时实例中:

# Run fsck to fix any disk corruption issues
$ sudo fsck.ext4 -a /dev/sdb1

# Mount the disk from the broken vm
$ sudo mkdir /mnt/sdb
$ sudo mount /dev/sdb1 /mnt/sdb/ -t ext4

# Find out the UUID of the broken disk. In this case, the uuid of sdb1 is d9cae47b-328f-482a-a202-d0ba41926661
$ ls -alt /dev/disk/by-uuid/
lrwxrwxrwx. 1 root root 10 Jan 6 07:43 d9cae47b-328f-482a-a202-d0ba41926661 -> ../../sdb1
lrwxrwxrwx. 1 root root 10 Jan 6 05:39 a8cf6ab7-92fb-42c6-b95f-d437f94aaf98 -> ../../sda1

# Update the UUID in grub.cfg (if necessary)
$ sudo vim /mnt/sdb/boot/grub/grub.cfg

注意:这是我的偏离支持指南的地方。相反,我删除了所有设置root=/dev/sda1的条目,并删除了每个没有设置initrd.img文件的条目。在我的情况下,具有正确参数的顶部启动条目最终是3.19.0-31-generic。但你的可能不同。
# Flush all changes to disk
$ sudo sync

# Shut down the temporary instance
$ sudo shutdown -h now

最后,将硬盘从临时实例中分离出来,并基于修复后的磁盘创建一个新实例。希望它能够启动。假设它能够启动,你还有很多工作要做。如果你像我一样有许多未使用的内核,那么你可能需要清除这些内核(特别是因为某些内核缺少相应的initrd.img文件)。我使用此askubuntu问题中的第二个答案(基于终端的方案)来清除其他内核。注意:确保不要清除您所使用的内核!

我在重新启动实例后又遇到了这个问题。 - krundru
是的,我也一样。我完全不知道这个问题会发生。GCE真的需要研究并解决发生了什么,但我怀疑他们会这样做。 - Nostalg.io
1
只需使用临时实例上启动目录的内容替换损坏实例上启动目录的内容,并在 grub.cfg 中更改 uuid 为损坏文件系统的 uuid,然后使用损坏磁盘启动新实例。 - gtsiolis
如果两个实例具有相同的虚拟硬件,那么这应该可以工作,但我不能推荐它,因为可能存在细微差别。 - Nostalg.io

2
  1. 如何处理在我托管一些网站时出现的这些问题?

我不确定您是如何陷入这种情况的,但如果能提供更多信息(请参阅我的上面的评论),我们就可以理解导致此问题的原因。

  1. 如何从旧磁盘中恢复我的数据?

连接和挂载磁盘

假设您在删除实例时没有删除原始磁盘,则可以从另一个VM中挂载该磁盘以读取其中的数据。具体操作如下:

  1. 将磁盘连接到另一个VM实例,例如:

    gcloud compute instances attach-disk $INSTANCE --disk $DISK

  2. 挂载磁盘:

    sudo mkdir -p /mnt/disks/[MNT_DIR]

    sudo mount [OPTIONS] /dev/disk/by-id/google-[DISK_NAME] /mnt/disks/[MNT_DIR]

    注意:您需要替换适当的值,例如:

    • MNT_DIR:目录
    • OPTIONS:适用于您的磁盘和文件系统的选项
    • DISK_NAME:将其附加到VM后磁盘的ID

卸载和分离磁盘

当您完成使用磁盘时,请按反向步骤操作:

注意:在分离非根磁盘之前,请先卸载磁盘。分离已挂载的磁盘可能导致不完整的I/O操作和数据损坏。

  1. 卸载磁盘

    sudo umount /dev/disk/by-id/google-[DISK_NAME]

  2. 从VM中分离磁盘

    gcloud compute instances detach-disk $INSTANCE --device-name my-new-device


1
在我的情况下,grub (/boot/grub/grub.cfg) 的第一个菜单项 (3.19.0-51-generic) 缺少 initrd 条目,无法启动。
进一步调查后,查看特定内核的 dpkg,发现其标记为失败和未配置。
dpkg -l | grep 3.19.0-51-generic
     iF  linux-image-3.19.0-51-generic       3.19.0-51.58~14.04.1         
     iU  linux-image-extra-3.19.0-51-generic 3.19.0-51.58~14.04.1 

这一切的根源是由于Google提供的Ubuntu映像启用了无人值守升级。由于某种原因,在构建时initrd被杀死,然后其他东西过来运行了update-grub2。
 unattended-upgrades-dpkg_2016-03-10_06:49:42.550403.log:update-initramfs: Generating /boot/initrd.img-3.19.0-51-generic
 Killed
 E: mkinitramfs failure cpio 141 xz -8 --check=crc32 137
 unattended-upgrades-dpkg_2016-03-10_06:49:42.550403.log:update-initramfs: failed for /boot/initrd.img-3.19.0-51-generic with 1.

为了解决即时问题,请运行以下操作。

 dpkg --force-confold --configure -a

尽管理论上自动升级是个好主意,但默认启用它可能会产生不受监控的后果。

0

内核在处理无initrd的引导时可能会出现一些问题。禁用GRUB_FORCE_PARTUUID选项以便使用initrd进行引导。


这并没有回答问题。一旦您拥有足够的声望,您将能够评论任何帖子;相反,提供不需要询问者澄清的答案。- 来自审核 - Nur

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接