这几天搞了搞我的服务器,昨天给 Kubernetes 集群中的 Ubuntu 20.04 虚拟机做了一次系统升级,重启之后就进不去系统了,喜提 20+ 小时的全站 down time。今天终于解决了这个问题,在此记录一下。
故障表现
- Ubuntu 20.04 LTS 系统更新内核后,重启无法进入系统。
- 主机端观察虚拟机 CPU、内存占用低,且 ACPI 重启无响应,只能 Reset 硬重启。
- 使用 VNC / Terminal 观察启动日志,可以看到以下日志:
/init: conf/conf.d/zz-resume-auto: line 1: syntax error: unexpected "("
Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000200
- 使用 LiveCD 进入系统后,执行
lsinitramfs /boot/initrd.img
可以观察到类似下图的conf/conf.d/zz-resume-auto
错误文件。
故障原因
直接原因是 Ubuntu 系统更新时更新了内核版本,生成 initrd.img
时引入了错误的文件。根本原因还不好确定,在 Launchpad 上面有类似的 bug 挂了几年都没修复。
修理方法
进入恢复环境
因为系统无法启动,首先要进入恢复环境。其实最简单的方法是进到上一个版本的内核,正常启动系统之后来修复。但是因为我的虚拟机用的是 cloud-init image,试了网上的方法都没法让 Grub 菜单显示出来。下面介绍如何用 Live CD 挂载的方式进入恢复环境。
- 下载 Ubuntu Live Server ISO 并引导启动。在我的虚拟机环境比较简单,如果是其他 VPS 服务商或物理机,请自行搜索启动方式,或使用其它 Live Recovery 环境。
- 进入安装界面后不要继续,按 Ctrl+Alt+F2 切换至 TTY 命令行。
在恢复环境中重新生成 initrd.img
进入到恢复环境后,按照下列步骤挂载原系统,并生成一个新的 initrd.img
文件。
- 挂载原系统根目录,然后切换至原系统环境下:
sudo mount /dev/sda1 /mnt # /dev/sda1 替换成原系统根目录,可以用 lsblk 找一下
sudo mount --bind /dev /mnt/dev
sudo mount --bind /proc /mnt/proc
sudo mount --bind /sys /mnt/sys
sudo chroot /mnt - 执行命令重新生成正确的
initrd.img
:update-initramfs -cu -k 5.4.0-136-generic
(最后一个参数要替换成最新内核的完整版本,可以ls /lib/modules
找到正确的版本号) - 检查新生成的
initrd.img
文件,确保没有上述的zz-resume-auto
错误文件:lsinitramfs /boot/initrd.img | grep conf
(应该输出上面图片中除了zz-resume-auto
的其他正常文件) - 按 Ctrl-D 退出原系统环境,然后执行
sudo umount /mnt/dev /mnt/proc /mnt/sys /mnt
卸载所有目录。 - 重启系统,从硬盘启动试试看是否修复。
参考文献:https://forum.level1techs.com/t/solved-kernel-panic/120146