排查 Linux Compute Engine 实例启动问题

本文档可帮助您找出 Linux Compute Engine 实例无法启动的原因,并解决常见问题。

无法启动的计算实例通常会显示以下一种或多种症状:

  • 计算实例处于 RUNNING 状态,但您无法使用 SSH 连接到该实例。
  • 串行控制台输出在启动序列中途停止,或在紧急或救援提示处结束。
  • 串行控制台输出包含 FAILED、error:、Kernel panic 或 emergency mode。

如需解决启动问题,请先确定原因,然后从计算实例内部(如果您仍能连接)或通过将启动磁盘连接到另一个计算实例来离线修复问题。

如果计算实例完成启动,但您无法连接到该实例,请参阅排查 SSH 错误。

准备工作

  • 确保计算实例写入串行控制台输出。计算实例运行时,串行端口输出可用;如需在计算实例停止后保留串行端口输出,请启用将串行端口输出记录到 Cloud Logging 的功能。如需了解详情,请参阅查看串行端口输出。
  • 如果您尚未设置身份验证,请进行设置。身份验证用于验证您的身份,以便访问 Google Cloud 服务和 API。如需从本地开发环境运行代码或示例,您可以通过选择以下选项之一向 Compute Engine 进行身份验证:
    1. 安装 Google Cloud CLI,然后 使用联合身份登录 gcloud CLI。 登录后,运行以下命令来初始化 Google Cloud CLI:

      gcloud init
    2. 设置默认区域和可用区。

自动检测原因

在手动读取串行控制台输出之前,请使用以下工具之一。每个脚本都会读取计算实例最近一次启动的输出,报告最可能的原因,并链接到本文档中的相应部分。

控制台

  1. 在 Google Cloud 控制台中,前往虚拟机实例页面。

    转到虚拟机实例

  2. 在计算实例对应的行中,点击 SSH。

  3. 如果连接失败,请在连接对话框中点击问题排查。问题排查工具会运行连接检查,包括分析串行控制台输出的启动检查。

gcloud

如需检查无法通过 SSH 连接的计算实例,请运行 gcloud CLI SSH 问题排查工具,该工具会运行连接检查和启动检查:

gcloud compute ssh INSTANCE_NAME --zone=ZONE --troubleshoot

如需直接检查启动顺序,请运行启动诊断命令:

如需使用此命令,请确保您已安装 Alpha 版命令组件。

gcloud alpha compute diagnose boot INSTANCE_NAME --zone=ZONE

替换以下内容:

  • INSTANCE_NAME:计算实例的名称。
  • ZONE:包含计算实例的可用区。

如果检测到启动问题,输出会指明原因并提供修复链接。如果未发现任何问题,请继续执行手动步骤。

读取串行控制台输出

如果这些工具未检测到问题,或者您想确认原因,请自行读取串行控制台输出:

控制台

  1. 在 Google Cloud 控制台中,前往虚拟机实例页面。

    转到“虚拟机实例”页面

  2. 选择要查看串行端口输出的计算实例。

  3. 在日志下,点击串行端口 1(控制台)。

gcloud

gcloud compute instances get-serial-port-output INSTANCE_NAME --zone=ZONE

替换以下内容:

  • INSTANCE_NAME:计算实例的名称。
  • ZONE:包含计算实例的可用区。

前往上次启动。有用的行通常位于第一个 [FAILED] 行、Kernel panic 行或紧急提示之前。将您找到的内容与以下部分中的签名进行比较。

常见的启动问题

以下部分列出了 Linux 计算实例上常见的启动失败情况、相应的串行控制台输出签名,以及如何解决这些问题。大多数解决方案都需要您将启动磁盘挂接到救援虚拟机,如离线修复磁盘中所述。

无法装载 /etc/fstab 个文件条目

症状:串行控制台输出包含类似以下内容的行,后跟 You are in emergency mode:

UUID=1234abcd-... does not exist
Timed out waiting for device /dev/sdb1
mount: special device /dev/sdb1 does not exist
[DEPEND] Dependency failed for /mnt/data.mount

原因:/etc/fstab 中的某个条目引用了未附加到计算实例的设备或 UUID,或者无法装载文件系统。systemd 服务停止启动并进入紧急模式。

解决方法:在抢救虚拟机上,更正已装载磁盘上 /etc/fstab 中的条目,或将其移除。如需了解相关程序,请参阅排查因 fstab 错误导致的 Linux 虚拟机启动问题。 如需了解可防止丢失的设备阻止启动的装载选项,请参阅装载磁盘。

GRUB 无法加载其配置或内核

症状:启动在 GRUB 提示符处停止,并且串行控制台输出包含如下所示的行:

error: file '/boot/grub/grub.cfg' not found
error: file '/vmlinuz-6.1.0-18-amd64' not found
error: no such partition
error: no such device
error: unknown filesystem
error: you need to load the kernel first
grub rescue>
Minimal BASH-like line editing is supported

原因:GRUB 引导加载程序找不到其配置文件、模块或配置所引用的内核和初始 RAM 磁盘。此问题会在以下情况下发生:软件包升级失败、分区布局发生变化、/boot 分区重新格式化或损坏,或者克隆的磁盘的文件系统 UUID 发生变化。

解决方法:在救援虚拟机上,装载启动磁盘并按照救援虚拟机中的说明进入 chroot 环境,然后按照配置引导加载程序中的说明重新生成 GRUB 配置文件。 如果无法修复引导加载程序,请从快照恢复磁盘。

初始 RAM 磁盘无法装载根文件系统

症状:串行控制台输出包含如下所示的行:

dracut-initqueue[452]: Warning: dracut-initqueue timeout - starting timeout scripts
dracut: FATAL: ...
Failed to mount /sysroot
ALERT! UUID=1234abcd-... does not exist. Dropping to a shell!
Gave up waiting for root file system device
VFS: Unable to mount root fs on unknown-block(0,0)

原因:初始 RAM 磁盘 (initramfs) 已启动,但无法找到或装载根文件系统。常见原因是 root= 内核参数或 UUID 不再与磁盘匹配、initramfs 映像缺少磁盘驱动程序,或者 initramfs 映像已损坏。在采用 NVMe 磁盘接口的机器系列上,通过设备路径(例如 /dev/sda)命名磁盘的启动配置不再匹配;请改用 UUID。

解决方法:确认初始 RAM 磁盘正在寻找的根文件系统是否存在于已装载的磁盘上,然后为您的操作系统重新构建初始 RAM 磁盘。如需了解相关过程,请参阅排查因内核崩溃导致的 Linux 虚拟机启动问题和修复磁盘离线问题。

文件系统损坏

症状:串行控制台输出包含如下所示的行:

Bad magic number in super-block
EXT4-fs error (device sda1): ...
XFS (sda1): Metadata corruption detected
XFS (sda1): log mount/recovery failed
BTRFS error (device sda1): ...
UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.

原因:启动磁盘上的文件系统损坏,通常是在不干净的关机、磁盘已满或出现 I/O 错误后发生。

解决方案:创建磁盘的快照。然后,在救援虚拟机上,检查并修复未装载磁盘上的文件系统,如确定启动磁盘未启动的原因中所述。如果检查无法修复文件系统,请从快照恢复磁盘。

内核崩溃

症状:串行控制台输出包含 Kernel panic - not syncing:,后跟原因,例如 Attempted to kill init!、Fatal exception、hung_task: blocked tasks、Out of memory、Fatal Machine check 或 NMI: Not continuing。损坏的内核映像会更早地停止,并显示 -- System halted。

原因:内核遇到了不可恢复的错误。冒号后面的原因标识了类别:init 崩溃、硬件机器检查、内存耗尽 panic 或内核映像损坏。

解决方案:重置计算实例。如果崩溃再次发生,请参阅内核崩溃导致的 Linux 虚拟机启动问题排查。

SELinux 政策无法加载

症状:串行控制台输出包含以下内容之一,并且启动停止:

Failed to load SELinux policy
Unable to load SELinux policy

您可能还会看到 Warning -- SELinux targeted policy relabel is required,这不是错误:计算实例会重新标记文件系统,然后自行重新启动。

原因:磁盘上的 SELinux 政策存储区缺失或损坏,或者在恢复或离线更改后文件标签不一致。

解决方法:在救援虚拟机上,将已装载的磁盘标记为在下次启动时进行完整的 SELinux 重新标记,或者如果政策存储区已损坏,请为您的操作系统重新安装 SELinux 政策软件包。在基于 RHEL 的操作系统映像上,您可以将 SELinux 设置为宽容模式,以便在修复政策时让计算实例启动,如将 SELinux 更改为宽容模式中所述。

系统无法启动 init 进程

症状:串行控制台输出包含如下所示的行:

Failed to switch root
Target filesystem doesn't have requested /sbin/init
No working init found
run-init: /sbin/init: No such file or directory
/sbin/init: error while loading shared libraries: ...

原因:根文件系统已装载,但 init 程序(例如 systemd)缺失、不可执行或依赖于缺失的共享库。此问题通常发生在软件包升级中断或恢复不完整之后。

解决方法:在救援虚拟机上,按照救援虚拟机中所述进入 chroot 环境,验证 init 程序是否存在且其库是否完好无损,如果不存在或不完好,请使用发行版的软件包管理系统重新安装 init 系统软件包。

紧急模式和锁定的 root 账号

症状:串行控制台输出以以下内容之一结尾:

You are in emergency mode. After logging in, type "journalctl -xb" to view system logs
Give root password for maintenance (or press Control-D to continue):
Cannot open access to console, the root account is locked.

原因:某个单元在启动期间失败,并且 systemd 停止在紧急目标。在 Google 提供的操作系统映像上,root 账号没有密码,因此无法通过串行控制台使用紧急 shell。

解决方法:紧急提示名称之前的行会指明发生故障的单元。失败通常是由以下某项问题引起的:

离线修复原因,如离线修复磁盘中所述;请勿尝试使用紧急 shell。

固件找不到可启动的磁盘

症状:串行控制台输出在任何内核消息之前包含以下内容之一:

No bootable device.
BdsDxe: failed to load Boot0001
Invalid partition table!
Verification failed: (0x1A) Security Violation

原因:启动磁盘未作为启动设备挂接,其分区表或启动记录已损坏,或者在具有安全启动的安全强化型虚拟机实例上,启动加载程序或内核未正确签名。

解决方案:确认磁盘已作为计算实例的启动磁盘挂接;请参阅分离和重新挂接磁盘。 如果分区表或引导记录损坏,请按照 GRUB 无法加载其配置或内核中所述修复引导加载程序。无法通过修改磁盘来修复安全启动违规问题:请恢复已签名的内核和启动加载程序,或按照修改虚拟机实例的安全强化型虚拟机选项中所述,在计算实例上停用安全启动。

离线修复磁盘

大多数启动问题都无法在计算实例内部解决,因为计算实例永远不会显示登录提示。而是将启动磁盘挂接到临时抢救虚拟机,装载该磁盘,进行更改,然后将磁盘移回。如需了解相关过程,请参阅修复无法访问的虚拟机。

本文档中的解决方案假定原始启动磁盘已连接到抢救虚拟机并已装载到该虚拟机上。在更换磁盘之前,请创建快照,以便在修复失败时恢复磁盘。如需了解相关步骤,请参阅创建归档磁盘快照和标准磁盘快照。

如果磁盘无法修复,请恢复计算实例

如果所有解决方法都不起作用,或者文件系统无法修复,请从快照恢复启动磁盘,或者从快照或自定义操作系统映像创建新的计算实例,并将数据移至其中。

后续步骤