由于操作系统出现问题,我的 EC2 Linux 实例未通过实例状态检查。如何解决此问题?

上次更新时间:2021 年 5 月 6 日

由于操作系统出现问题,我的 Amazon Elastic Compute Cloud(Amazon EC2)Linux 实例未通过实例状态检查。现在,它不能成功启动。如何解决此问题?

简短描述

EC2 Linux 实例可能会因下列原因而不能通过实例状态检查:

  • 您已经更新了内核,而新内核无法启动。
  • /etc/fstab 中的文件系统条目不正确,或文件系统损坏。
  • 实例上的网络配置不正确。

解决方法

有 3 种方法可以排查操作系统问题。

重要提示:

方法 2 和 3 需要停止并启动实例。但应注意以下几点:

  • 如果您的实例受实例存储支持或具有包含数据的实例存储卷,则在实例停止时数据将丢失。有关更多信息,请参阅确定实例的根设备类型
  • 如果您的实例是 Amazon EC2 Auto Scaling 组的一部分,停止实例可能会终止实例。如果您使用 Amazon EMR、AWS CloudFormation 或 AWS Elastic Beanstalk 启动实例,则您的实例可能是 AWS Auto Scaling 组的一部分。在这种情况下,是否会发生实例终止取决于您的 Auto Scaling 组的实例缩减保护设置。如果您的实例是 Auto Scaling 组的一部分,则在开始执行解决步骤之前,暂时从 Auto Scaling 组中删除该实例
  • 停止和启动实例会更改实例的公共 IP 地址。在将外部流量路由到您的实例时,最佳做法是使用弹性 IP 地址而不是公有 IP 地址。如果您使用 Amazon Route 53,您可能必须在公有 IP 更改时更新 Route 53 DNS 记录

方法 1:使用 EC2 串行控制台

如果您为 Linux 启用了 EC2 串行控制台,则可以使用它来排查受支持的基于 Nitro 的实例类型问题。串行控制台可帮助您排查启动问题、网络配置和 SSH 配置问题。串行控制台无需网络连接即可连接到您的实例。您可以使用 Amazon EC2 控制台或 AWS 命令行界面 (AWS CLI) 访问串行控制台。

在使用串行控制台之前,请在账户层面授予对串行控制台的访问权限。然后,创建 AWS Identity and Access Management(IAM)策略,授予对 IAM 用户的访问权限。此外,每个使用串行控制台的实例都必须至少包含一个基于密码的用户。如果您的实例无法访问,并且尚未配置对串行控制台的访问权限,请按照方法 2 中的说明进行操作。有关为 Linux 配置 EC2 串行控制台的信息,请参阅配置对 EC2 串行控制台的访问权限

注意:如果在运行 AWS CLI 命令时遇到错误,请确保您使用的是最新版本的 AWS CLI

方法 2:运行 EC2Rescue for Linux 工具

EC2Rescue for Linux 会自动诊断并排查无法访问的实例上的操作系统问题。有关更多信息,请参阅如何使用 EC2Rescue for Linux 排查操作系统级问题?

方法 3:使用救援实例手动纠正错误

1.    使用同一 Amazon Machine Image(AMI)在您的 Virtual Private Cloud(VPC)中启动一个新的 EC2 实例。在受损实例所在的可用区中启动此新实例。此新实例将成为您的救援实例。

您也可使用您能够访问的现有实例,但前提是该实例使用与受损实例相同的 AMI,并且位于同一可用区中。

2.    停止受损的实例

3.    从受损实例中分离 Amazon Elastic Block Store (Amazon EBS) 根卷/dev/xvda/dev/sda1)。记下根卷的设备名称(/dev/xvda/dev/sda1)。

4.    将卷作为辅助设备(/dev/sdf)挂载到救援实例。

5.    使用 SSH 连接到您的救援实例

6.    为挂载到救援实例的新卷创建挂载点目录(/rescue):

$ sudo mkdir /rescue

7.    将该卷挂载到您在第 6 步中创建的目录:

$ sudo mount /dev/xvdf1 /rescue

注意:设备(/dev/xvdf1)可能会以不同的设备名称挂载到救援实例。使用 lsblk 命令查看可用磁盘设备及其挂载点,以确定正确的设备名称。

8.    如果您不知道发生了什么错误,请检索实例的系统日志以确认发生的错误。后续步骤取决于系统日志中列出的错误消息。下面是可能导致实例状态检查失败的常见错误列表。有关其他错误,请参阅对基于 Linux 的实例进行系统日志错误排查

Kernel Panic(内核崩溃)

如果 system log(系统日志)中出现 Kernel Panic(内核崩溃)错误消息,则内核可能不具有 vmlinuzinitramfs 文件。您需要有 vmlinuzinitramfs 文件才能成功启动。

1.    运行以下命令:

cd /rescue/boot
ls -l

2.    检查输出,以验证您打算启动的内核版本是否有对应的 vmlinuzinitramfs 文件。

以下输出示例针对采用内核版本 4.14.165-131.185.amzn2.x86_64 的 Amazon Linux 2 实例。/boot 目录中包含文件 initramfs-4.14.165-131.185.amzn2.x86_64.imgvmlinuz-4.14.165-131.185.amzn2.x86_64,因此,将会成功启动。

uname -r
4.14.165-131.185.amzn2.x86_64

cd /boot; ls -l
total 39960
-rw-r--r-- 1 root root      119960 Jan 15 14:34 config-4.14.165-131.185.amzn2.x86_64
drwxr-xr-x 3 root root     17 Feb 12 04:06 efi
drwx------ 5 root root       79 Feb 12 04:08 grub2
-rw------- 1 root root 31336757 Feb 12 04:08 initramfs-4.14.165-131.185.amzn2.x86_64.img
-rw-r--r-- 1 root root    669087 Feb 12 04:08 initrd-plymouth.img
-rw-r--r-- 1 root root    235041 Jan 15 14:34 symvers-4.14.165-131.185.amzn2.x86_64.gz
-rw------- 1 root root   2823838 Jan 15 14:34 System.map-4.14.165-131.185.amzn2.x86_64
-rwxr-xr-x 1 root root   5718992 Jan 15 14:34 vmlinuz-4.14.165-131.185.amzn2.x86_64

3.    如果 initramfs 和/或 vmlinuz 文件不存在,请尝试使用具有这两个文件的早期版本内核启动实例。有关如何使用早期版本内核启动实例的说明,请参阅当因为更新导致 Amazon EC2 实例无法成功重启时,如何恢复到已知的稳定内核?

4.    运行 unmount 命令以从您的救援实例中卸载辅助设备:

$ sudo umount /rescue

如果卸载操作不成功,您可能需要停止或重启救援实例,以实现干净卸载。

5.    将辅助卷 (/dev/sdf) 与救援实例分离,然后以 /dev/xvda(根卷)的形式将其附加到原始实例。

6.    启动实例,然后验证实例是否正常响应。

有关解决内核崩溃错误的其他信息,请参阅在升级内核或尝试重启 EC2 Linux 实例后,我收到“内核崩溃”错误。如何修复此问题?

未能成功挂载或依赖项失败

如果您在系统日志中看到“未能成功挂载”或“依赖项失败”之类的错误,则 /etc/fstab 文件可能有不正确的挂载点条目。

1.    验证 /etc/fstab 中的挂载点条目正确。有关更正 /etc/fstab 文件条目的信息,请参阅我的 EC2 实例为什么没有启动,为什么进入紧急模式?自动挂载因 /etc/fstab 文件中的不正确条目而失败部分

2.    最佳实践是运行 fsck 或 xfs_repair 工具来更正文件系统错误。如果文件系统中有任何不一致性,fsck 或 xfs_repair 工具会更正它们。

注意:在运行 fsck 或 xfs_repair 工具之前应创建文件系统的备份。

运行 unmount 命令以卸载您的挂载点,然后再运行 fsck 或 xfs_repair 工具:

$ sudo umount /rescue

根据您的文件系统运行 fsk 或 xfs_repair 工具。

对于 ext4 文件系统:

$ sudo fsck /dev/sdf
fsck from util-linux 2.30.2
e2fsck 1.42.9 (28-Dec-2013)
/dev/sdf: clean, 11/6553600 files,
459544/26214400 blocks

对于 XFS 文件系统:

$ sudo xfs_repair /dev/sdf
xfs_repair /dev/xvdf
Phase 1 - find and verify superblock...
Phase 2 - using internal log
        - zero log...
        - scan filesystem freespace and inode maps...
        - found root inode chunk
Phase 3 - for each AG...
        - scan and clear agi unlinked lists...
        - process known inodes and perform inode discovery...
        - agno = 0
        - agno = 1
        - agno = 2
        - agno = 3
        - process newly discovered inodes...
Phase 4 - check for duplicate blocks...
        - setting up duplicate extent list...
        - check for inodes claiming duplicate blocks...
        - agno = 0
        - agno = 1
        - agno = 2
        - agno = 3
Phase 5 - rebuild AG headers and trees...
        - reset superblock...
Phase 6 - check inode connectivity...
        - resetting contents of realtime bitmap and summary inodes
        - traversing filesystem ...
        - traversal finished ...
        - moving disconnected inodes to lost+found ...
Phase 7 - verify and correct link counts...
done

3.    将辅助卷 (/dev/sdf) 与救援实例分离,然后以 /dev/xvda(根卷)的形式将其附加到原始实例。

4.    启动实例,然后验证实例是否有响应。

Bringing up interface eth0: failed(调出接口 eth0:失败)

如果您看到错误“Bringing up interface eth0: failed”(调出接口 eth0:失败)错误,请验证 ifcfg-eth0 文件是否拥有正确的网络条目。与主接口 eth0 对应的网络配置文件位于 /etc/sysconfig/network-scripts/ifcfg-eth0。如果主接口的设备名称不是 eth0,则实例上的目录 /etc/sysconfig/network-scripts 中有一个以 ifcfg 开头,然后接设备名称的文件。

1.    运行 cat 命令以查看主接口 eth0 的网络配置文件。

下面是位于 /etc/sysconfig/network-scripts/ifcfg-eth0 的网络配置文件的正确条目。

注意:用主接口的名称(如果不同)替换以下命令中的 eth0

$ sudo cat /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
BOOTPROTO=dhcp
ONBOOT=yes
TYPE=Ethernet
USERCTL=yes
PEERDNS=yes
DHCPV6C=yes
DHCPV6C_OPTIONS=-nw
PERSISTENT_DHCLIENT=yes
RES_OPTIONS="timeout:2 attempts:5"
DHCP_ARP_CHECK=no

2.    验证 ONBOOT 已设置为yes(是),如上述示例所示。如果 ONBOOT 未设置为 yes(是),则 eth0(或您的主网络接口)没有被配置为在启动时调出。

要更改 ONBOOT 的值:

在编辑器中打开该文件。此处的示例使用了 vi 编辑器。

$ sudo vi /etc/sysconfig/network-scripts/ifcfg-eth0

按下 I 以插入。

将光标滚动到 ONBOOT 条目,然后将值更改为

通过按下 :wq! 保存并退出文件。

3.    运行 unmount 命令以从您的救援实例中卸载辅助设备:

$ sudo umount /rescue

如果卸载操作不成功,您可能需要停止或重启救援实例,以实现干净卸载。

4.    将辅助卷(/dev/sdf)与救援实例分离,然后以 /dev/xvda(根卷)的形式将其挂载到原始实例。

5.    启动实例,然后验证实例是否正常响应