当因为更新导致 Amazon EC2 实例无法成功重启时,如何恢复到已知的稳定内核?

上次更新时间:2020 年 2 月 5 日

当因为更新导致 Amazon Elastic Compute Cloud (Amazon EC2) 实例无法成功重启时,如何恢复到稳定的内核?

简短描述

如果您对 EC2 Linux 实例执行内核更新,但是内核现已损坏,则实例无法重启。您无法使用 SSH 连接到受损实例。然而,您可以创建一个临时救援实例,然后将您的 Amazon Elastic Block Store (Amazon EBS) 卷重新挂载到该救援实例上。从该救援实例中,您可以将 GRUB 配置为使用以前的内核进行启动。

重要提示:请勿在实例存储支持的实例上执行此操作。由于此恢复方法需要首先停止然后再重启实例,该实例上的任何数据都将丢失。有关更多信息,请参阅确定实例的根设备类型

解决方法

将根卷连接到救援 EC2 实例

1.    为根卷创建 EBS 快照。有关更多信息,请参阅创建 Amazon EBS 快照

2.    打开 Amazon EC2 控制台

注意:请确保您位于正确的 区域。

3.    从导航窗格中选择实例,然后选择受损实例。

4.    依次选择操作实例状态停止

5.    在描述选项卡中的根设备下,选择 /dev/sda1,然后选择 EBS ID

注意:根设备因 AMI 而异,但 /dev/xvda/dev/sda1 始终为根设备预留。例如,Amazon Linux 1 和 2 使用 /dev/xvda,而 Ubuntu 14、16、18、CentOS 7 和 RHEL 7.5 等其他发行版则设置为 /dev/sda1

6.    依次选择操作分离卷,然后选择是,请分离。记下可用区。

7.    在同一可用区中启动一个救援 EC2 实例。

注意:您可能需要启动与操作系统类型相同的 EC2 实例,具体取决于产品代码。例如,如果受损的 EC2 实例是付费的 RHEL AMI,则您必须使用相同的产品代码启动 AMI。有关更多信息,请参阅获取实例的产品代码

8.    启动救援实例后,从导航窗格中选择,然后选择受损实例已分离的根卷。

9.    选择操作,然后选择挂载卷

10.    选择救援实例 ID (id-xxxxx),然后设置一个未使用的设备。我们的示例中使用的是 /dev/xvdb

挂载受损实例的卷

1.    使用 SSH 连接到救援实例。

2.    运行 lsblk 命令以查看可用的磁盘设备:

lsblk

以下是该输出的示例:

NAME    MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
xvda    202:0     0   15G  0 disk
└─xvda1 202:1     0   15G  0 part /
xvdb    202:0     0   15G  0 disk
    └─xvdb1 202:1 0   15G  0 part

注意:基于 Nitro 的实例会将 EBS 卷作为 NVMe 块储存设备公开。lsblk 命令在基于 Nitro 的实例上生成的输出显示磁盘名称为 nvme[0-26]n1。有关更多信息,请参阅 Linux 实例上的 Amazon EBS 和 NVMe

3.    创建一个挂载目录,然后将挂载卷的根分区挂载到此新目录。在上例中,挂载卷的根分区为 /dev/xvdb1。有关更多信息,请参阅使 Amazon EBS 卷可在 Linux 上使用

sudo mkdir /mount
sudo mount /dev/xvdb1 /mount

现在,您可以通过挂载目录,访问受损实例的数据。

4.    将救援实例的 /dev/run/proc/sys 挂载至与新挂载卷相同的路径:

sudo mount -o bind /dev /mount/dev
sudo mount -o bind /run /mount/run
sudo mount -o bind /proc /mount/proc 
sudo mount -o bind /sys /mount/sys

5.    调用 chroot 函数来更改为挂载目录:

sudo chroot /mount

更新 GRUB 引导程序中的默认内核

当前损坏的内核位于列表中的位置 0(零)。最新的稳定内核位于位置 1。要将损坏的内核替换为稳定的内核,请根据您的发行版选择以下其中一项操作:

适用于 Red Hat 6 和 Amazon Linux 的 GRUB1(旧版 GRUB)

适用于 Ubuntu 14 LTS 和 16.04 的 GRUB2

适用于 RHEL 7.5 和 Amazon Linux 2 的 GRUB2

适用于 RHEL 8 和 CentOS 8 的 GRUB2

适用于 Red Hat 6 和 Amazon Linux 1 的 GRUB1(旧版 GRUB)

使用 sed 命令,将损坏的内核替换为 /boot/grub/grub.conf 文件中的稳定内核。

sudo sed -i '/^default/ s/0/1/' /boot/grub/grub.conf

适用于 Ubuntu 14 LTS 和 16.04 的 GRUB2

1.    使用 /etc/default/grub 文件中稳定的 GRUB_DEFAULT-saved 值替换损坏的 GRUB_DEFAULT=0 默认菜单项:

sed -i 's/GRUB_DEFAULT=0/GRUB_DEFAULT=saved/g' /etc/default/grub

2.    更新 GRUB,以识别更改:

sudo update-grub

3.    运行 grub-set-default 命令,以便下次重启时加载稳定的内核。在本示例中,位置 0 中的 grub-set-default 被设置为 1

sudo grub-set-default 1

适用于 RHEL 7.5 和 Amazon Linux 2 的 GRUB2

1.    使用 /etc/default/grub 文件中稳定的 GRUB_DEFAULT-saved 值替换损坏的 GRUB_DEFAULT=0 默认菜单项:

sed -i 's/GRUB_DEFAULT=0/GRUB_DEFAULT=saved/g' /etc/default/grub

2.    更新 GRUB,以重新生成 /boot/grub2/grub.cfg 文件:

sudo grub2-mkconfig -o /boot/grub2/grub.cfg

3.    运行 grub2-set-default 命令,以便下次重启时加载稳定的内核。在本示例中,位置 0 中的 grub2-set-default 被设置为 1

sudo grub2-set-default 1

4.    键入 exit 以退出 chroot 环境。

适用于 RHEL 8 和 CentOS 8 的 GRUB2

RHEL 8 和 Centos 8 中的 GRUB2 将 blscfg 文件和 /boot/loader 中的条目用作启动配置,不再使用以前的 grub.cfg 格式。建议使用 grubby 工具来管理 blscfg 文件和检索 /boot/loader/entries/ 中的信息。如果在此缺失 blscfg 文件或该文件损坏,则 grubby 不会显示任何结果。您必须重新生成文件才能恢复功能。因此,内核的索引取决于位于 /boot/loader/entries 下的 .conf 文件和内核版本。索引被配置为保留具有最低索引的最新内核。有关如何重新生成 BLS 配置文件的信息,请参阅如何恢复因 Grub2 BLS 配置文件问题而启动失败的 Red Hat 8 或 CentOS 8 实例?

1.    运行 grubby --default-kernel 命令以查看当前默认内核:

grubby --default-kernel

2.    运行 grubby --info=ALL 命令以查看所有可用的内核及其索引:

grubby --info=ALL

下面是 --info=ALL 命令的示例输出:

[root@ip-10-10-1-111 ~]# grubby --info=ALL
index=0
kernel="/boot/vmlinuz-4.18.0-147.3.1.el8_1.x86_64"
args="ro console=ttyS0,115200n8 console=tty0 net.ifnames=0 rd.blacklist=nouveau crashkernel=auto $tuned_params"
root="UUID=a727b695-0c21-404a-b42b-3075c8deb6ab"
initrd="/boot/initramfs-4.18.0-147.3.1.el8_1.x86_64.img $tuned_initrd"
title="Red Hat Enterprise Linux (4.18.0-147.3.1.el8_1.x86_64) 8.1 (Ootpa)"
id="2bb67fbca2394ed494dc348993fb9b94-4.18.0-147.3.1.el8_1.x86_64"
index=1
kernel="/vmlinuz-0-rescue-2bb67fbca2394ed494dc348993fb9b94"
args="ro console=ttyS0,115200n8 console=tty0 net.ifnames=0 rd.blacklist=nouveau crashkernel=auto"
root="UUID=a727b695-0c21-404a-b42b-3075c8deb6ab"
initrd="/initramfs-0-rescue-2bb67fbca2394ed494dc348993fb9b94.img"
title="Red Hat Enterprise Linux (0-rescue-2bb67fbca2394ed494dc348993fb9b94) 8.1 (Ootpa)"
id="2bb67fbca2394ed494dc348993fb9b94-0-rescue"
index=2
kernel="/boot/vmlinuz-4.18.0-80.4.2.el8_0.x86_64"
args="ro console=ttyS0,115200n8 console=tty0 net.ifnames=0 rd.blacklist=nouveau crashkernel=auto $tuned_params"
root="UUID=a727b695-0c21-404a-b42b-3075c8deb6ab"
initrd="/boot/initramfs-4.18.0-80.4.2.el8_0.x86_64.img $tuned_initrd"
title="Red Hat Enterprise Linux (4.18.0-80.4.2.el8_0.x86_64) 8.0 (Ootpa)"
id="c74bc11fb3d6436bb2716196dd0e7a47-4.18.0-80.4.2.el8_0.x86_64"

请记下您希望为实例设置为默认值的内核的路径。在上例中,索引 2 处内核的路径为 /boot/vmlinuz- 0-4.18.0-80.4.2.el8_1.x86_64

3.    运行 grubby --set-default 命令以更改实例的默认内核:

grubby --set-default=/boot/vmlinuz-0-rescue-4.18.0-80.4.2.el8_1.x86_64

注意:4.18.0-80.4.2.el8_1.x86_64 替换为您的内核版本号。

4.    要验证上述命令正常运行,请运行 grubby --default-kernel 命令以查看当前默认内核:

grubby --default-kernel

5.    退出 chroot 并卸载 /dev/run/proc/sys

exit
sudo umount /mount/dev
sudo umount /mount/run
sudo umount /mount/proc
sudo umount /mount/sys
sudo umount /mount

从救援实例中分离根卷并将其连接到受损实例

1.    从 Amazon EC2 控制台中,选择 Instances (实例),然后选择救援实例。

2.    依次选择操作实例状态停止是,请停止

3.    从救援实例中分离根卷 vol-xxx

4.    将您在第 3 步中分离的根卷作为根卷 (/dev/sda1) 连接到受损实例,然后启动该实例。

注意:根卷可能会因发行版而异。对于 Amazon Linux 1 和 2,根卷必须是 /dev/xvda。否则,您将收到错误消息。同样,如果发行版是 RHEL、CentOS 或 Ubuntu,则根卷必须是 /dev/sda1

现在将加载稳定的内核,并重启实例。


这篇文章对您有帮助吗?

我们可以改进什么?


需要更多帮助?