SSD Nodes Learn 🎉 VPS từ $5.50/tháng
Hướng dẫn Matt ConnorBởi Matt Connor

VPS không khởi động được sau khi cập nhật kernel

Hướng dẫn khôi phục VPS qua console khi gặp lỗi kernel panic sau update. Cách chọn lại kernel cũ trong GRUB, sửa lỗi initramfs hoặc LVM để hệ thống SSH trở lại bình thường.

Việc cần làm đầu tiên khi VPS không khởi động được sau khi cập nhật kernel

Một VPS không khởi động được sau khi cập nhật kernel thường có thể khôi phục trong vài phút, vì bản cập nhật không xóa kernel cũ vẫn đang hoạt động. Ubuntu cài đặt kernel mới song song với kernel cũ và chỉ thay đổi mục mặc định mà GRUB khởi động. Do đó, bước đầu tiên không phải là sửa lỗi. Hãy chọn kernel trước đó trong menu khởi động, truy cập lại vào prompt đăng nhập, sau đó chẩn đoán từ hệ thống đang chạy.

Việc sửa lỗi này trên server khác với trên laptop, vì không có bàn phím gắn ngoài và không có màn hình hiển thị lỗi kernel panic. SSH cũng sẽ không phản hồi, vì máy chưa khởi động đến giai đoạn chạy sshd. Mọi thao tác dưới đây phải thực hiện thông qua console của nhà cung cấp dịch vụ.

Hãy đọc nội dung trên console trước khi thay đổi bất cứ điều gì. Văn bản trên màn hình đó quyết định loại lỗi bạn đang gặp phải, và hai server cùng "không khởi động được" có thể cần các cách khắc phục trái ngược nhau.

Làm thế nào để truy cập console khi SSH bị mất kết nối?

Hãy mở bảng điều khiển của nhà cung cấp VPS và tìm mục console. Các tên gọi phổ biến là VNC console, web console, noVNC và serial console. Ưu tiên dùng serial console nếu có cả hai, vì nó cung cấp văn bản thực để bạn có thể cuộn và sao chép, trong khi VNC chỉ là hình ảnh chụp màn hình. Hãy tìm tính năng này ngay bây giờ, khi máy chủ vẫn hoạt động bình thường và xác nhận nó mở được. Việc tìm kiếm nó trong lúc xảy ra sự cố sẽ khiến bạn mất đi sự bình tĩnh cần thiết. Kiểm tra này nên nằm trong mười phút đầu tiên trên một VPS mới, cùng với các quy tắc firewall và SSH keys.

Hầu hết các bảng điều khiển cũng cung cấp chế độ rescue mode hoặc recovery image. Nó khởi động một hệ thống nhỏ từ mạng của nhà cung cấp và gắn ổ đĩa của bạn như một thiết bị phụ, vì vậy không có gì trên ổ đĩa của bạn được chạy. Rescue mode là phương án dự phòng khi chính GRUB bị hỏng, và đây cũng là cách bạn sao chép dữ liệu ra khỏi máy chủ mà bạn đã quyết định không giữ lại.

Bạn thường sẽ cần thực hiện hard reset từ bảng điều khiển để truy cập menu khởi động, vì bạn không thể chạy sudo reboot trên một máy mà bạn không thể đăng nhập. Hard reset tương đương với việc ngắt nguồn điện. Các filesystem sẽ bị tắt không an toàn, vì vậy hãy chuẩn bị tinh thần cho việc kiểm tra filesystem ở lần khởi động tiếp theo.

Làm thế nào để chọn kernel cũ hơn trong menu GRUB?

Hãy quan sát console ngay từ thời điểm bạn nhấn reset. Nhấn liên tục Esc trong vài giây đầu tiên, hoặc giữ Shift trên máy chạy ở chế độ legacy BIOS. Cửa sổ thời gian này rất ngắn và trình xem console thường mất một giây để kết nối, vì vậy hãy bắt đầu nhấn sớm và nhấn liên tục.

Khi menu xuất hiện, hãy chọn "Advanced options for Ubuntu". Menu con đó liệt kê mọi kernel đã cài đặt, kernel mới nhất nằm trên cùng, kèm theo một mục recovery mode cho mỗi kernel. Hãy chọn mục bình thường thứ hai, đây là kernel ngay dưới phiên bản mới nhất, rồi nhấn Enter. Recovery mode là một trường hợp khác: nó khởi động vào hệ thống single user tối giản, dùng để sửa lỗi chứ không phải để đưa các dịch vụ của bạn hoạt động trở lại.

Nếu kernel cũ hơn khởi động được, bạn đã có lại một server đang chạy. Hãy xác nhận phiên bản bạn đang dùng và ghi lại các con số đó.

uname -r
dpkg -l 'linux-image-*' | grep '^ii'

Kết quả của dpkg là danh sách các kernel đã cài đặt của bạn. Nếu nó chỉ hiển thị một dòng, bạn hoàn toàn không có bản dự phòng nào, và đó là việc đầu tiên cần phải khắc phục.

Các cloud image thường đi kèm cấu hình ẩn menu này. Các image Ubuntu thường đặt timeout bằng 0 trong một file tại /etc/default/grub.d/, vì vậy kernel mới nhất sẽ khởi động ngay lập tức và bạn không có cơ hội nhấn phím nào cả.

Cũng có trường hợp ngược lại, khi menu hiển thị trên màn hình và dừng lại, trông giống như máy bị treo. GRUB ghi lại một lần boot thất bại, và ở lần khởi động tiếp theo, nó có thể giữ menu hiển thị cho đến khi có người nhấn phím. Trên một máy chủ không có bàn phím, quá trình chờ đợi này không bao giờ kết thúc. Nếu console của bạn hiển thị menu và không có gì thay đổi, đó chính là nguyên nhân. Hãy chọn một mục và tiếp tục.

Hãy khắc phục cả hai vấn đề này khi máy chủ vẫn đang hoạt động bình thường. Chỉnh sửa file /etc/default/grub:

GRUB_TIMEOUT_STYLE=menu
GRUB_TIMEOUT=10
GRUB_RECORDFAIL_TIMEOUT=10
GRUB_TERMINAL="console serial"
GRUB_SERIAL_COMMAND="serial --unit=0 --speed=115200"
GRUB_CMDLINE_LINUX_DEFAULT="console=tty1 console=ttyS0,115200"

Sau đó áp dụng thay đổi và kiểm tra xem cấu hình của bạn có được giữ lại không, vì các file trong /etc/default/grub.d/ được đọc sau /etc/default/grub và có thể ghi đè lên cấu hình của bạn.

sudo update-grub
grep -rE 'TIMEOUT|TERMINAL' /etc/default/grub /etc/default/grub.d/

GRUB_TERMINAL="console serial" gửi menu đến graphical console và cổng serial, giúp nó hiển thị trên bất kỳ trình xem nào mà bảng điều khiển của bạn cung cấp. Các tham số kernel console= cũng thực hiện điều tương tự cho các thông báo khởi động theo sau. Mười giây chờ đợi mỗi lần boot là cái giá rẻ để đổi lấy một menu mà bạn thực sự có thể truy cập vào lúc 2 giờ sáng.

Tôi đang gặp phải loại lỗi nào?

Hãy đọc hai mươi dòng cuối trước khi console ngừng chạy. Bốn kiểu lỗi phổ biến nhất thường xảy ra sau khi cập nhật kernel.

GRUB không tìm thấy file của chính nó. Bạn sẽ thấy prompt grub rescue>, hoặc thông báo lỗi về một phân vùng hay file không tồn tại, và không có thông báo nào từ kernel xuất hiện. Kernel chưa được nạp. Lỗi này thường do thay đổi ổ đĩa hoặc phân vùng, hoặc bootloader bị ghi vào sai thiết bị, chứ không phải do bản thân gói kernel.

Kernel khởi động nhưng không thể mount root. Các thông báo kernel chạy qua, sau đó bạn bị đẩy vào shell busybox với prompt (initramfs), hoặc quá trình boot kết thúc bằng lỗi panic do không thể mount root filesystem. Kernel đã được nạp. Initramfs, vốn là root tạm thời nhỏ để tìm và mount root filesystem thật, đã không tìm thấy ổ đĩa. Trên Ubuntu, shell này thường đi kèm thông báo về việc từ bỏ chờ đợi thiết bị root, kèm theo UUID mà nó cần. Hãy copy UUID đó và so sánh với kết quả của blkid sau này.

Logical volume không xuất hiện. Đây là trường hợp tương tự như trên nhưng với nguyên nhân cụ thể. Tại prompt (initramfs), hãy chạy ls /dev/mapper. Nếu kết quả chỉ có control, nghĩa là không có volume LVM (logical volume manager) nào được kích hoạt, nên thiết bị root chưa tồn tại. Hãy kích hoạt các volume group bằng tay:

lvm vgchange -ay
ls /dev/mapper
exit

exit sẽ trả quyền điều khiển lại cho script initramfs để thử mount lại. Nếu hệ thống boot thành công, nghĩa là initramfs mới đang thiếu các thành phần LVM, và cách sửa là rebuild lại image đó thay vì can thiệp vào kernel.

Không có bất kỳ thông tin nào từ Linux. Console chỉ hiển thị văn bản của firmware, shell UEFI (unified extensible firmware interface), màn hình trống không có output từ kernel, hoặc bị lặp lại quá trình reset. Lỗi xảy ra trước khi Linux chạy. Hãy kiểm tra chế độ boot thực tế của server sau khi hệ thống hoạt động trở lại, vì nhiều VPS boot ở chế độ legacy BIOS và không hề đụng đến đường dẫn EFI:

[ -d /sys/firmware/efi ] && echo UEFI || echo BIOS
mountpoint /boot/efi
sudo efibootmgr -v

Việc /boot/efi không được mount trong quá trình nâng cấp là nguyên nhân phổ biến trên các máy UEFI, vì các gói quản lý phân vùng hệ thống EFI đã ghi dữ liệu vào một thư mục trống thông thường thay vì phân vùng boot. Firmware sẽ tiếp tục khởi động entry cũ cho đến khi entry đó không còn khớp với dữ liệu trên đĩa.

Còn một kiểu nữa không hẳn là lỗi boot. Nếu bạn vào được root shell và thấy hệ thống báo đang ở chế độ emergency, nghĩa là kernel đã boot xong nhưng userspace bị dừng. Lỗi này thường do một dòng cấu hình sai trong /etc/fstab hoặc filesystem bị lỗi kiểm tra. Hãy chạy journalctl -xb trong shell đó và đọc tên unit bị lỗi.

Gói kernel bị lỗi hay initramfs?

Hai trường hợp này nhìn qua console thì giống hệt nhau nhưng cách sửa chữa lại khác biệt. Hãy boot vào kernel cũ, sau đó so sánh các file.

ls -l /boot/vmlinuz-* /boot/initrd.img-*
df -h /boot

Bạn cần một vmlinuz- và một initrd.img- tương ứng cho mỗi phiên bản đã cài đặt, mỗi file phải có dung lượng hợp lý. Nếu thiếu initrd, hoặc file có dung lượng nhỏ hơn nhiều so với các file khác, nghĩa là quá trình tạo initramfs đã thất bại. Nguyên nhân thường gặp là do /boot bị đầy, và bằng chứng nằm trong các file log của gói:

sudo grep -iE 'no space|update-initramfs' /var/log/apt/term.log
sudo tail -n 40 /var/log/apt/history.log

history.log cũng liệt kê chính xác những gói nào đã được cài đặt trong các lần chạy gần nhất và thời gian cụ thể, giúp làm rõ mọi nghi vấn về những thay đổi đã xảy ra.

Hãy giải phóng dung lượng trước nếu /boot bị đầy, sau đó build lại image cho phiên bản bạn cần và làm mới menu. Lấy chuỗi phiên bản từ kết quả lệnh ls của chính bạn, vì phần giữ chỗ bên dưới không phải là một bản release thực tế:

KVER=6.8.0-XX-generic
sudo update-initramfs -c -k "$KVER"
sudo update-grub
ls -l /boot/initrd.img-$KVER

Lệnh ls cuối cùng là bước kiểm tra. Một file có dung lượng bình thường nghĩa là image đã xuất hiện. Nếu thay vào đó, bản thân kernel image bị hỏng, hoặc dpkg -l hiển thị gói ở bất kỳ trạng thái nào khác ngoài ii, hãy cài đặt lại gói đó:

sudo apt install --reinstall linux-image-$KVER
sudo dpkg --configure -a

Sửa lỗi từ chế độ rescue khi kernel không khởi động được

Nếu mọi mục trong menu boot đều thất bại, hãy khởi động image rescue của nhà cung cấp và sửa chữa ổ đĩa từ bên ngoài. Ổ đĩa của bạn sẽ xuất hiện dưới dạng thiết bị chưa mount, vì vậy không có tiến trình nào đang chạy trên đó và không có gì cản trở bạn.

Quy trình sửa chữa chroot đầy đủ

Chạy lsblk -f trước và đọc tên thiết bị thực tế trên máy của bạn. /dev/vda thường thấy trên KVM, và các bản cài đặt Ubuntu server thường đặt root trên LVM dưới dạng /dev/ubuntu-vg/ubuntu-lv.

sudo lsblk -f
sudo vgchange -ay
sudo mount /dev/ubuntu-vg/ubuntu-lv /mnt
sudo mount /dev/vda2 /mnt/boot
sudo mount /dev/vda1 /mnt/boot/efi

Bỏ qua các dòng không áp dụng cho trường hợp của bạn. Nhiều image không có phân vùng /boot riêng biệt và không có phân vùng EFI. Sau đó, bind các giao diện kernel vào và truy cập hệ thống:

for d in dev proc sys run; do sudo mount --rbind /$d /mnt/$d; done
sudo chroot /mnt /bin/bash

Bên trong chroot, bạn đang làm việc trên hệ thống bị lỗi trong khi một kernel khỏe mạnh đang chạy bên dưới. Thực hiện sửa chữa tại đó:

df -h /boot
update-initramfs -u -k all
update-grub
grub-install /dev/vda
exit

grub-install chiếm toàn bộ ổ đĩa trên hệ thống BIOS, không phải một phân vùng. Trên hệ thống UEFI, hãy sử dụng grub-install --target=x86_64-efi --efi-directory=/boot/efi và xác nhận thư mục đó đã được mount trước khi chạy lệnh. Thoát bằng exit, unmount mọi thứ bằng sudo umount -R /mnt, sau đó chuyển bảng điều khiển trở lại chế độ boot bình thường và khởi động lại.

Kiểm tra kernel mới mà không lo mất khả năng boot

GRUB có thể khởi động một mục duy nhất một lần rồi tự động quay về mặc định. Hãy đặt mặc định là kernel bạn tin tưởng, sau đó khởi động kernel mới chỉ cho một lần boot. Nếu kernel mới lỗi, bạn chỉ cần hard reset từ bảng điều khiển (panel) là hệ thống sẽ tự quay về kernel cũ mà không cần canh thời gian để can thiệp vào console.

Thiết lập GRUB_DEFAULT=saved trong /etc/default/grub, chạy sudo update-grub, sau đó liệt kê các tiêu đề mục để bạn có thể chọn chính xác tên:

grep -E "(menuentry|submenu) " /boot/grub/grub.cfg | cut -d"'" -f2
sudo grub-set-default "Advanced options for Ubuntu>Ubuntu, with Linux 6.8.0-XX-generic"
sudo grub-editenv list
sudo grub-reboot 0
sudo reboot

grub-editenv list sẽ in ra tiêu đề bạn đã chọn dưới dạng saved_entry. Kết quả này chứng minh cơ chế hoạt động, vì việc lưu cấu hình yêu cầu /boot/grub/grubenv phải ở chế độ ghi được, và trên một số layout thì thao tác này có thể thất bại âm thầm. Mục 0 là mục đầu tiên trong menu, thường là kernel mới nhất. Sử dụng tiêu đề sẽ an toàn hơn dùng số thứ tự, vì số thứ tự sẽ thay đổi mỗi khi bạn cài đặt hoặc gỡ bỏ kernel.

Tại sao autoremove lại rủi ro trên máy chủ headless

APT duy trì một danh sách các gói kernel không được phép tự động gỡ bỏ. Hãy kiểm tra danh sách của bạn:

cat /etc/apt/apt.conf.d/01autoremove-kernels
dpkg -l 'linux-image-*' | grep -c '^ii'

File đó được tạo lại mỗi khi các gói kernel thay đổi, nó bảo vệ kernel đang chạy và các phiên bản mới nhất. Bẫy nằm ở thời điểm thực hiện. Nếu chạy sudo apt autoremove --purge ngay sau khi reboot vào một kernel mới, danh sách được bảo vệ đã cập nhật, khiến kernel cũ mà bạn đang dựa vào không còn được bảo vệ nữa. Trên máy tính có bàn phím, đây chỉ là sự bất tiện. Trên server headless, đó là sự khác biệt giữa việc chọn một mục trong menu boot và việc phải mount ổ đĩa từ một rescue image.

Hãy giữ lại ít nhất hai kernel, và ba kernel nếu /boot còn đủ dung lượng. Hãy gỡ bỏ các kernel cũ theo tên sau khi kiểm tra bằng uname -r, để đảm bảo bạn không bao giờ xóa nhầm kernel đang chạy:

uname -r
sudo apt purge linux-image-6.8.0-XX-generic
dpkg -l 'linux-image-*' | grep '^ii'

Sau đó, hãy chạy lại lệnh cuối cùng một lần nữa. Nếu số lượng giảm từ ba xuống hai, đó là dọn dẹp an toàn. Nếu số lượng giảm xuống còn một, đó là sự cố chờ chực cho lần reboot tiếp theo.

Chụp snapshot trước khi nâng cấp

Snapshot được chụp trước apt upgrade là phương án khôi phục duy nhất không phụ thuộc vào việc khởi động bất kỳ thứ gì. Việc khôi phục snapshot đưa ổ đĩa trở lại trạng thái mà kernel cũ vẫn là mặc định, và bạn có thể thử lại quá trình nâng cấp khi console đã mở sẵn. Snapshot của một máy đang chạy là crash consistent, nghĩa là nó ghi lại ổ đĩa như thể nguồn điện vừa bị ngắt, vì vậy hãy tắt server trước nếu nhà cung cấp của bạn hỗ trợ snapshot offline. Snapshot cũng không phải là bản backup, vì nó thường nằm trên cùng hạ tầng với volume mà nó sao chép. Hiểu rõ sự khác biệt giữa VPS snapshot và backup thực thụ sẽ quyết định phương án nào cứu bạn khi sự cố nghiêm trọng hơn một lỗi kernel.

Điều này quan trọng nhất trong quá trình nâng cấp bản phát hành, nơi kernel, các công cụ initramfs, bootloader và cấu hình GRUB đều thay đổi trong một lần chạy. Hãy chụp snapshot ngay trước khi bạn bắt đầu nâng cấp Ubuntu 24.04 lên 26.04, không phải từ đêm hôm trước, để điểm khôi phục khớp chính xác với trạng thái máy chủ mà bạn sắp thay đổi.

Cách unattended-upgrades xử lý các gói kernel

Tính năng unattended-upgrades trên Ubuntu tự động cài đặt các bản cập nhật bảo mật mà không cần xác nhận, và các gói kernel cũng được cập nhật thông qua kho lưu trữ bảo mật giống như mọi gói khác. Có hai hệ quả xảy ra.

Thứ nhất, kernel mới được cài đặt nhưng chưa chạy. Kernel chỉ có hiệu lực khi khởi động lại hệ thống. File /var/run/reboot-required sẽ xuất hiện, và /var/run/reboot-required.pkgs ghi lại yêu cầu khởi động lại, nhưng hệ thống sẽ không tự khởi động lại trừ khi bạn đã bật Unattended-Upgrade::Automatic-Reboot trong /etc/apt/apt.conf.d/50unattended-upgrades.

cat /var/run/reboot-required.pkgs
grep -E 'Automatic-Reboot|Blacklist' /etc/apt/apt.conf.d/50unattended-upgrades

Thứ hai, khoảng thời gian chờ này che giấu nguyên nhân gây lỗi. Một máy chủ có thể cài đặt kernel vào tháng 3 và khởi động lại vào tháng 6 vì một lý do không liên quan, sau đó không thể khởi động được. Thay đổi gây lỗi boot đã có từ ba tháng trước, nên các thao tác bạn thực hiện trong ngày hôm đó không giải thích được sự cố. /var/log/apt/history.log là nơi bạn tìm thấy tiến trình đã cài đặt kernel khiến hệ thống của bạn gặp lỗi hiện tại.

Hãy chủ động khởi động lại vào ngày bạn chọn, với cửa sổ console đang mở sẵn. Thói quen đơn giản này biến một sự cố bí ẩn thành một thao tác chọn menu mất hai phút. Nếu bạn muốn tự động hóa mà không gặp bất ngờ, hãy giữ tính năng cài đặt tự động và tắt tính năng tự động khởi động lại, sau đó xem cách cấu hình unattended-upgrades trên Ubuntu để biết các thiết lập chính xác. Việc giữ (hold) các gói kernel bằng sudo apt-mark hold linux-image-generic sẽ ngăn chặn hoàn toàn việc cập nhật chúng, đồng thời cũng chặn luôn các bản vá bảo mật kernel, vì vậy hãy coi đây là một sự đánh đổi mà bạn đã quyết định thực hiện thay vì một biện pháp an toàn.

FAQ

Làm thế nào để boot vào kernel cũ trên VPS khi không có bàn phím?

Hãy mở console của nhà cung cấp (VNC hoặc serial) và thực hiện hard reset từ bảng điều khiển, vì bạn không thể đăng nhập để reboot theo cách thông thường. Khi máy khởi động lại, hãy nhấn liên tục Esc, hoặc giữ Shift trên các hệ thống BIOS cũ, để giữ menu GRUB. Chọn "Advanced options for Ubuntu" và chọn mục nằm dưới kernel mới nhất. Khi đã thấy prompt đăng nhập, hãy chạy uname -r để xác nhận kernel hiện tại và dpkg -l 'linux-image-*' để xem các kernel khác đã cài đặt. Chỉ tiến hành chẩn đoán sau khi hệ thống đã chạy ổn định.

Tại sao VPS của tôi không hiển thị menu GRUB?

Các image trên cloud thường đặt timeout của GRUB là 0 trong một file tại /etc/default/grub.d/, khiến kernel mới nhất khởi động ngay lập tức mà không cho phép bạn can thiệp. Hãy đặt GRUB_TIMEOUT=10GRUB_TIMEOUT_STYLE=menu trong /etc/default/grub, thêm GRUB_TERMINAL="console serial" để menu hiển thị cả trên serial console, sau đó chạy sudo update-grub. Kiểm tra lại bằng grep -r TIMEOUT /etc/default/grub /etc/default/grub.d/, vì các file trong thư mục đó được đọc sau file chính và có thể ghi đè lên cấu hình của bạn.

Tôi có nên xóa các kernel cũ để giải phóng dung lượng trong /boot không?

Hãy xóa các kernel cũ nhất và giữ lại ít nhất hai bản. Một phân vùng /boot bị đầy là một lỗi nghiêm trọng, vì quá trình tạo initramfs sẽ thất bại và bạn sẽ bị kẹt với một kernel không có image hoạt động. Hãy xóa bằng tên gói chính xác sau khi kiểm tra uname -r, để đảm bảo kernel đang chạy không bị xóa nhầm. Tránh dùng lệnh sudo apt autoremove --purge hàng loạt trên máy chủ không có màn hình (headless), vì danh sách kernel được bảo vệ sẽ được tạo lại sau mỗi lần thay đổi kernel; nếu chạy không đúng thời điểm, bạn có thể chỉ còn lại một kernel duy nhất và không có phương án dự phòng trong menu.

Liệu unattended-upgrades có làm hỏng quá trình boot của tôi không?

Nó có thể cài đặt một kernel bị lỗi khi boot, nhưng nó không tự khởi động lại máy trừ khi Unattended-Upgrade::Automatic-Reboot được đặt thành true trong /etc/apt/apt.conf.d/50unattended-upgrades. Kịch bản thường gặp là lỗi bị trì hoãn: kernel được cài đặt trong một lần chạy tự động, /var/run/reboot-required xuất hiện, và vấn đề chỉ lộ ra ở lần reboot tiếp theo của bạn sau đó vài tuần. Hãy chủ động reboot khi đã mở sẵn console, và đọc /var/log/apt/history.log để tìm xem lần chạy nào đã cài đặt kernel mà bạn đang boot.