当因为更新导致 Amazon EC2 实例无法成功重启时,如何恢复到已知的稳定内核?
当因为更新导致 Amazon Elastic Compute Cloud(Amazon EC2)实例无法成功重启时,如何恢复到稳定的内核?
简短描述
如果您已对 EC2 Linux 实例执行内核更新,但是内核现已损坏,则实例无法重启。您无法使用 SSH 连接到受损实例。
要恢复到以前的版本,请执行以下操作:
1. 访问实例的根卷。
2. 更新 GRUB 引导程序中的默认内核。
解决方法
访问实例的根卷
有两种方法可以访问根卷:
方法 1:使用 EC2 串行控制台
如果您为 Linux 启用了 EC2 串行控制台,则可以使用它来排查受支持的基于 Nitro 的实例类型问题。串行控制台可帮助您排查启动问题、网络配置和 SSH 配置问题。串行控制台无需网络连接即可连接到您的实例。您可以使用 Amazon EC2 控制台或 AWS Command Line Interface(AWS CLI)访问串行控制台。
在使用串行控制台之前,请在账户层面授予对串行控制台的访问权限。然后,创建 AWS Identity and Access Management (IAM) 策略,授予对 IAM 用户的访问权限。此外,每个使用串行控制台的实例都必须至少包含一个基于密码的用户。如果您的实例无法访问,并且尚未配置对串行控制台的访问权限,请按照方法 2 中的说明进行操作。有关为 Linux 配置 EC2 串行控制台的信息,请参阅配置对 EC2 串行控制台的访问权限。
注意:如果在运行 AWS CLI 命令时遇到错误,请确保您使用的是最新版本的 AWS CLI。
方法 2:使用救援实例
创建一个临时救援实例,然后将您的 Amazon Elastic Block Store (Amazon EBS) 卷重新挂载到该救援实例上。从该救援实例中,您可以将 GRUB 配置为使用以前的内核进行启动。
**重要提示:**请勿在实例存储支持的实例上执行此操作。由于此恢复方法需要首先停止然后再重启实例,该实例上的任何数据都将丢失。有关更多信息,请参阅确定实例的根设备类型。
1. 为根卷创建 EBS 快照。有关更多信息,请参阅创建 Amazon EBS 快照。
2. 打开 Amazon EC2 控制台。
**注意:**请确保您位于正确的区域。
3. 从导航窗格中选择实例,然后选择受损的实例。
4. 选择 Instance State(实例状态)、Stop Instance(停止实例),然后选择 Stop(停止)。
5. 在 **Storage(存储)**选项卡的 **Block devices(块储存设备)**下,为 /dev/sda1 或 /dev/xvda 选择 Volume ID(卷 ID)。
**注意:**根设备因 AMI 而异,但 /dev/xvda 或 /dev/sda1 将为根设备预留。例如,Amazon Linux 1 和 2 使用 /dev/xvda。其他发行版(如 Ubuntu 14、16、18、CentOS 7 和 RHEL 7.5)使用 /dev/sda1。
6. 依次选择操作、断开卷,然后选择是,请分离。记下可用区。
**注意:**您可以在分离 EBS 卷之前对其进行标记,以便在后面的步骤中识别它。
7. 在同一可用区中启动一个救援 EC2 实例。
**注意:**您可能需要启动与操作系统类型相同的 EC2 实例,具体取决于产品代码。例如,如果受损的 EC2 实例是付费的 RHEL AMI,则您必须使用相同的产品代码启动 AMI。有关更多信息,请参阅获取实例的产品代码。
如果原始实例正在运行 SELinux(例如 RHEL、CentOS 7 或 8),请从使用 SELinux 的 AMI 启动救援实例。如果您选择运行其他操作系统的 AMI(例如 Amazon Linux 2),则原始实例上的任何修改后的文件都会损坏 SELinux 标签。
8. 启动救援实例后,从导航窗格中选择卷,然后选择受损实例已分离的根卷。
9. 依次选择操作、附加卷。
10. 选择救援实例 ID (id-xxxxx),然后设置一个未使用的设备。在本示例中为 /dev/sdf。
11. 使用 SSH 连接到救援实例。
12. 运行 lsblk 命令以查看可用的磁盘设备:
lsblk
以下是该输出的示例:
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT xvda 202:0 0 15G 0 disk └─xvda1 202:1 0 15G 0 part / xvdf 202:0 0 15G 0 disk └─xvdf1 202:1 0 15G 0 part
**注意:**基于 Nitro 的实例会将 EBS 卷作为 NVMe 块储存设备公开。lsblk 命令在基于 Nitro 的实例上生成的输出显示磁盘名称为 nvme[0-26]n1。有关更多信息,请参阅 Linux 实例上的 Amazon EBS 和 NVMe。以下是在基于 Nitro 的实例上的 lsblk 命令输出示例:
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT nvme0n1 259:0 0 8G 0 disk └─nvme0n1p1 259:1 0 8G 0 part / └─nvme0n1p128 259:2 0 1M 0 part nvme1n1 259:3 0 100G 0 disk └─nvme1n1p1 259:4 0 100G 0 part /
13. 运行以下命令以成为根:
sudo -i
14. 将已挂载卷的根分区挂载到 /mnt。在上例中,已挂载卷的根分区为 /dev/xvdf1 或 /dev/nvme1n1p1。有关更多信息,请参阅使 Amazon EBS 卷可在 Linux 上使用。注意,在以下示例中,将 /dev/xvdf1 替换为卷的正确根分区。
mount -o nouuid /dev/xvdf1 /mnt
**注意:**如果您的配置中不存在 /mnt,请创建一个挂载目录,然后将已挂载卷的根分区挂载到此新目录。
mkdir /mnt mount -o nouuid /dev/xvdf1 /mnt
现在,您可以通过挂载目录,访问受损实例的数据。
15. 将救援实例的 /dev、/run、/proc 和 /sys 挂载至与新挂载卷相同的路径:
for m in dev proc run sys; do mount -o bind {,/mnt}/$m; done
调用 chroot 函数来更改为挂载目录。
**注意:**如果您有一个单独的 /boot 分区,请在运行以下命令之前将其挂载到 /mnt/boot。
chroot /mnt
更新 GRUB 引导程序中的默认内核
当前损坏的内核位于列表中的位置 0(零)。最新的稳定内核位于位置 1。要将损坏的内核替换为稳定的内核,请根据您的发行版使用以下其中一项操作:
- 适用于 Red Hat 6 和 Amazon Linux 的 GRUB1(旧版 GRUB)
- 适用于 Ubuntu 14 LTS、16.04 和 18.04 的 GRUB2
- 适用于 RHEL 7 和 Amazon Linux 2 的 GRUB2
- 适用于 RHEL 8 和 CentOS 8 的 GRUB2
适用于 Red Hat 6 和 Amazon Linux 1 的 GRUB1(旧版 GRUB)
使用 sed 命令,将损坏的内核替换为 /boot/grub/grub.conf 文件中的稳定内核:
sed -i '/^default/ s/0/1/' /boot/grub/grub.conf
适用于 Ubuntu 14 LTS、16.04 和 18.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. 运行 update-grub 命令以便 GRUB 识别更改:
update-grub
3. 运行 grub-set-default 命令,以便下次重启时加载稳定的内核。在本示例中,位置 0 中的 grub-set-default 被设置为 1:
grub-set-default 1
适用于 RHEL 7 和 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 文件:
grub2-mkconfig -o /boot/grub2/grub.cfg
3. 运行 grub2-set-default 命令,以便下次重启时加载稳定的内核。在本示例中,位置 0 中的 grub2-set-default 被设置为 1:
grub2-set-default 1
适用于 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-172-31-29-221 /]# grubby --info=ALL index=0 kernel="/boot/vmlinuz-4.18.0-305.el8.x86_64" args="ro console=ttyS0,115200n8 console=tty0 net.ifnames=0 rd.blacklist=nouveau nvme_core.io_timeout=4294967295 crashkernel=auto $tuned_params" root="UUID=d35fe619-1d06-4ace-9fe3-169baad3e421" initrd="/boot/initramfs-4.18.0-305.el8.x86_64.img $tuned_initrd" title="Red Hat Enterprise Linux (4.18.0-305.el8.x86_64) 8.4 (Ootpa)" id="0c75beb2b6ca4d78b335e92f0002b619-4.18.0-305.el8.x86_64" index=1 kernel="/boot/vmlinuz-0-rescue-0c75beb2b6ca4d78b335e92f0002b619" args="ro console=ttyS0,115200n8 console=tty0 net.ifnames=0 rd.blacklist=nouveau nvme_core.io_timeout=4294967295 crashkernel=auto" root="UUID=d35fe619-1d06-4ace-9fe3-169baad3e421" initrd="/boot/initramfs-0-rescue-0c75beb2b6ca4d78b335e92f0002b619.img" title="Red Hat Enterprise Linux (0-rescue-0c75beb2b6ca4d78b335e92f0002b619) 8.4 (Ootpa)" id="0c75beb2b6ca4d78b335e92f0002b619-0-rescue" index=2 kernel="/boot/vmlinuz-4.18.0-305.3.1.el8_4.x86_64" args="ro console=ttyS0,115200n8 console=tty0 net.ifnames=0 rd.blacklist=nouveau nvme_core.io_timeout=4294967295 crashkernel=auto $tuned_params" root="UUID=d35fe619-1d06-4ace-9fe3-169baad3e421" initrd="/boot/initramfs-4.18.0-305.3.1.el8_4.x86_64.img $tuned_initrd" title="Red Hat Enterprise Linux (4.18.0-305.3.1.el8_4.x86_64) 8.4 (Ootpa)" id="ec2fa869f66b627b3c98f33dfa6bc44d-4.18.0-305.3.1.el8_4.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-4.18.0-305.3.1.el8_4.x86_64
**注意:**将 4.18.0-305.3.1.el8_4.x86_64 替换为您的内核版本号。
4. 运行 grubby --default-kernel 命令以验证上述命令是否有效:
grubby --default-kernel
如果您使用 EC2 串行控制台访问实例,那么稳定的内核现在会进行加载,您可以重启实例。
如果您使用的是救援实例,请完成以下部分中的步骤。
卸载卷,从救援实例中分离根卷并将其连接到受损实例
注意:如果您采用的是方法 2:使用救援实例,请完成以下步骤。
1. 退出 chroot 并卸载 /dev、/run、/proc 和 /sys:
exit umount /mnt/{dev,proc,run,sys,}
2. 从 Amazon EC2 控制台中,选择 Instances (实例),然后选择救援实例。
3. 选择 Instance State(实例状态)、Stop instance(停止实例),然后选择 Stop(停止)。
4. 从救援实例中分离根卷 id-xxxxx(来自受损实例的卷)。
5. 将您在第 4 步中分离的根卷作为根卷 (/dev/sda1) 连接到受损实例,然后启动该实例。
注意:根设备因 AMI 而异。名称 /dev/xvda 或 /dev/sda1 将始终预留给根设备。例如,Amazon Linux 1 和 2 使用 /dev/xvda。其他发行版(如 Ubuntu 14、16、18、CentOS 7 和 RHEL 7.5)使用 /dev/sda1。
现在将加载稳定的内核,并重启实例。
相关内容
- AWS 官方已更新 2 年前
- AWS 官方已更新 1 年前
- AWS 官方已更新 2 年前
- AWS 官方已更新 2 年前