วิธีแก้ปัญหา VPS บูตไม่ขึ้นหลังอัปเดต Kernel
วิธีแก้ไขเซิร์ฟเวอร์บูตไม่ขึ้นหลังอัปเดต Kernel ผ่านคอนโซลผู้ให้บริการ ตั้งแต่การเลือก GRUB kernel เดิม การซ่อมแซม initramfs และ LVM ไปจนถึงแนวทางการป้องกันปัญหาในอนาคต
สิ่งที่ควรทำเป็นอันดับแรกเมื่อ VPS ไม่สามารถบูตได้หลังการอัปเดต kernel
VPS ที่ไม่สามารถบูตได้หลังการอัปเดต kernel มักจะสามารถกู้คืนได้ภายในเวลาไม่กี่นาที เนื่องจากกระบวนการอัปเดตไม่ได้ลบ kernel เดิมที่ใช้งานได้ตามปกติออกไป Ubuntu จะติดตั้ง kernel ใหม่ควบคู่ไปกับ kernel เดิม และเปลี่ยนเพียงรายการที่ GRUB จะเรียกใช้งานเป็นค่าเริ่มต้นเท่านั้น ดังนั้นขั้นตอนแรกไม่ใช่การซ่อมแซม แต่เป็นการเลือก kernel ก่อนหน้าในเมนูบูตเพื่อให้เข้าสู่ระบบได้ จากนั้นจึงค่อยวินิจฉัยปัญหาจากระบบที่ทำงานอยู่
การแก้ไขปัญหานี้บนเซิร์ฟเวอร์จะแตกต่างจากการแก้ไขบนแล็ปท็อป เนื่องจากไม่มีคีย์บอร์ดเชื่อมต่ออยู่และไม่มีหน้าจอแสดงผลข้อความ kernel panic การเชื่อมต่อผ่าน SSH จะไม่สามารถทำได้เนื่องจากเครื่องยังไม่ถึงขั้นตอนที่ sshd จะเริ่มทำงาน ทุกขั้นตอนต่อไปนี้ต้องดำเนินการผ่านคอนโซลของผู้ให้บริการของคุณ
โปรดอ่านข้อความบนคอนโซลของคุณก่อนที่จะทำการเปลี่ยนแปลงใดๆ ข้อความบนหน้าจอนั้นจะเป็นตัวกำหนดว่าปัญหาของคุณอยู่ในประเภทใด และเซิร์ฟเวอร์สองเครื่องที่ "บูตไม่ได้" เหมือนกัน อาจต้องการวิธีการแก้ไขที่ตรงกันข้ามกัน
ฉันจะเข้าถึงคอนโซลได้อย่างไรเมื่อ SSH ใช้งานไม่ได้
ให้เปิดแผงควบคุมของผู้ให้บริการของคุณแล้วมองหาเมนูคอนโซล ชื่อที่พบบ่อยคือ VNC console, web console, noVNC และ serial console หากมีให้เลือกทั้งสองแบบ ให้เลือกใช้ serial console เพราะจะแสดงผลเป็นข้อความจริงที่คุณสามารถเลื่อนดูและคัดลอกได้ ในขณะที่ VNC จะเป็นเพียงภาพหน้าจอเท่านั้น ให้ค้นหาเมนูนี้ในขณะที่เครื่องยังทำงานปกติและตรวจสอบให้แน่ใจว่าสามารถเปิดใช้งานได้ การมาหาเมนูนี้ในระหว่างที่ระบบล่มจะทำให้คุณเสียความใจเย็นที่จำเป็นต้องใช้ การตรวจสอบนี้ควรทำใน สิบนาทีแรกบน VPS ใหม่ ควบคู่ไปกับการตั้งค่า firewall และ SSH keys
แผงควบคุมส่วนใหญ่ยังมีโหมดกู้คืน (rescue mode) หรือ recovery image ให้ใช้งาน โหมดนี้จะบูตระบบขนาดเล็กจากเครือข่ายของผู้ให้บริการและเชื่อมต่อดิสก์ของคุณเป็นอุปกรณ์เสริม ทำให้ไม่มีโปรแกรมใดบนดิสก์ของคุณทำงาน โหมดกู้คืนเป็นทางเลือกสุดท้ายเมื่อ GRUB เสียหาย และยังเป็นวิธีที่คุณใช้คัดลอกข้อมูลออกจากเซิร์ฟเวอร์ที่คุณตัดสินใจว่าจะไม่ใช้งานต่อแล้ว
โดยปกติคุณจำเป็นต้องสั่ง hard reset จากแผงควบคุมเพื่อเข้าสู่เมนูบูต เนื่องจากคุณไม่สามารถรันคำสั่ง sudo reboot บนเครื่องที่คุณไม่สามารถล็อกอินเข้าไปได้ การทำ hard reset เทียบเท่ากับการตัดกระแสไฟฟ้า ซึ่งจะทำให้ระบบไฟล์ปิดตัวลงอย่างไม่สมบูรณ์ ดังนั้นให้เตรียมใจไว้ว่าระบบอาจต้องทำ filesystem check ในการบูตครั้งถัดไป
ฉันจะเลือก kernel เวอร์ชันเก่าในเมนู GRUB ได้อย่างไร
ให้เฝ้าดูคอนโซลตั้งแต่จังหวะที่คุณกดรีเซ็ตเครื่อง ให้กด Esc ซ้ำๆ ในช่วงไม่กี่วินาทีแรก หรือกด Shift ค้างไว้หากเครื่องของคุณบูตในโหมด legacy BIOS ช่วงเวลาดังกล่าวมีจำกัดและคอนโซลมักใช้เวลาเชื่อมต่อสักครู่ ดังนั้นให้เริ่มกดตั้งแต่เนิ่นๆ และกดต่อไปเรื่อยๆ
เมื่อเมนูปรากฏขึ้น ให้เลือก "Advanced options for Ubuntu" เมนูย่อยนั้นจะแสดงรายการ kernel ที่ติดตั้งไว้ทั้งหมดโดยเรียงจากเวอร์ชันล่าสุด พร้อมรายการ recovery mode สำหรับแต่ละเวอร์ชัน ให้เลือกรายการปกติรายการที่สอง ซึ่งเป็น kernel เวอร์ชันถัดจากตัวล่าสุด แล้วกด Enter ส่วน recovery mode นั้นเป็นคนละเรื่องกัน โดยจะบูตเข้าสู่ระบบ single user แบบจำกัดเพื่อใช้สำหรับงานซ่อมแซม ไม่ใช่เพื่อนำบริการของคุณกลับมาออนไลน์
หาก kernel เวอร์ชันเก่าบูตได้สำเร็จ คุณจะมีเซิร์ฟเวอร์ที่ใช้งานได้อีกครั้ง ให้ตรวจสอบว่าคุณกำลังใช้งานเวอร์ชันใดอยู่และจดเลขเวอร์ชันนั้นไว้
uname -r
dpkg -l 'linux-image-*' | grep '^ii'ผลลัพธ์จาก dpkg คือรายการ kernel ที่ติดตั้งอยู่ในระบบ หากมีเพียงบรรทัดเดียว แสดงว่าคุณไม่มี kernel สำรองเลย ซึ่งนั่นคือสิ่งแรกที่คุณต้องแก้ไข
เมนู GRUB ไม่แสดงขึ้นมา ต้องทำอย่างไร
อิมเมจบนระบบคลาวด์มักมีการตั้งค่าที่ซ่อนเมนูนี้ไว้ โดยปกติอิมเมจของ Ubuntu จะตั้งค่า timeout เป็น 0 ไว้ในไฟล์ภายใต้ /etc/default/grub.d/ ทำให้เคอร์เนลเวอร์ชันล่าสุดเริ่มทำงานทันทีโดยไม่มีจังหวะให้กดปุ่มใดๆ
นอกจากนี้ยังมีกรณีตรงกันข้าม คือเมนูค้างอยู่บนหน้าจอและรอการตอบสนองจนดูเหมือนเครื่องค้าง GRUB จะบันทึกสถานะการบูตที่ล้มเหลวไว้ และในการเริ่มระบบครั้งถัดไป มันอาจจะค้างเมนูไว้จนกว่าจะมีคนกดปุ่ม หากเป็นเครื่องที่ไม่มีคีย์บอร์ดต่ออยู่ การรอนั้นจะไม่มีวันสิ้นสุด หากคอนโซลของคุณแสดงเมนูและไม่มีอะไรเกิดขึ้น แสดงว่าเกิดเหตุการณ์นี้ขึ้น ให้เลือกรายการบูตแล้วดำเนินการต่อ
แก้ไขปัญหาทั้งสองกรณีในขณะที่เครื่องยังทำงานได้ปกติ โดยแก้ไขไฟล์ /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"จากนั้นให้นำการตั้งค่าไปใช้และตรวจสอบว่าการแก้ไขของคุณยังคงอยู่ เนื่องจากไฟล์ใน /etc/default/grub.d/ จะถูกอ่านหลังจาก /etc/default/grub และอาจเขียนทับการตั้งค่าของคุณได้
sudo update-grub
grep -rE 'TIMEOUT|TERMINAL' /etc/default/grub /etc/default/grub.d/GRUB_TERMINAL="console serial" จะส่งเมนูไปยังคอนโซลแบบกราฟิกและพอร์ตซีเรียล เพื่อให้เมนูแสดงผลในโปรแกรมดูคอนโซลที่คุณใช้งานอยู่ ส่วนอาร์กิวเมนต์เคอร์เนล console= จะทำหน้าที่เดียวกันกับข้อความการบูตที่ตามมา การตั้งค่าหน่วงเวลาไว้ 10 วินาทีต่อการบูตหนึ่งครั้งถือเป็นราคาที่คุ้มค่า เพื่อแลกกับการเข้าถึงเมนูได้จริงในยามฉุกเฉิน
ฉันกำลังเผชิญกับความล้มเหลวประเภทใด?
ให้อ่านข้อความ 20 บรรทัดสุดท้ายก่อนที่คอนโซลจะหยุดนิ่ง รูปแบบความผิดพลาด 4 ประการต่อไปนี้ครอบคลุมเหตุการณ์ส่วนใหญ่ที่เกิดขึ้นหลังจากการอัปเดตเคอร์เนล
GRUB ไม่พบไฟล์ของตัวเอง คุณจะพบกับพรอมต์ grub rescue> หรือข้อความแจ้งเตือนเกี่ยวกับพาร์ทิชันหรือไฟล์ที่ไม่มีอยู่จริง โดยไม่มีข้อความจากเคอร์เนลปรากฏขึ้นเลย กรณีนี้เคอร์เนลยังไม่ได้เริ่มทำงาน ซึ่งมักเกิดจากการเปลี่ยนแปลงดิสก์หรือพาร์ทิชัน หรือการเขียน bootloader ลงในอุปกรณ์ที่ไม่ถูกต้อง มากกว่าที่จะเกิดจากตัวแพ็กเกจเคอร์เนลเอง
เคอร์เนลเริ่มทำงานแต่ไม่สามารถ mount root ได้ ข้อความจากเคอร์เนลจะเลื่อนผ่านไป จากนั้นคุณจะเข้าสู่ busybox shell ที่มีพรอมต์เป็น (initramfs) หรือการบูตจบลงด้วยอาการ panic ว่าไม่สามารถ mount root filesystem ได้ เคอร์เนลโหลดขึ้นมาแล้ว แต่ initramfs ซึ่งเป็น root ชั่วคราวขนาดเล็กที่ทำหน้าที่ค้นหาและ mount root filesystem จริงของคุณ ไม่พบดิสก์ที่ต้องการ บน Ubuntu มักจะมีข้อความแจ้งก่อนเข้าสู่ shell นี้ว่าระบบยอมแพ้ในการรอ root device พร้อมระบุ UUID ที่ต้องการ ให้คัดลอก UUID นั้นไว้เพื่อนำไปเปรียบเทียบกับผลลัพธ์ของ blkid ในภายหลัง
Logical volume ไม่ปรากฏขึ้น นี่คือความล้มเหลวประเภทเดียวกับข้างต้นแต่มีสาเหตุเฉพาะเจาะจง ที่พรอมต์ (initramfs) ให้รันคำสั่ง ls /dev/mapper หากรายการที่ปรากฏมีเพียง control แสดงว่าไม่มี LVM (logical volume manager) volume ใดถูกเปิดใช้งาน ทำให้ root device ยังไม่มีตัวตน ให้เปิดใช้งาน volume group ด้วยตนเองดังนี้:
lvm vgchange -ay
ls /dev/mapper
exitexit จะส่งการควบคุมกลับไปยังสคริปต์ initramfs เพื่อให้ลอง mount ใหม่อีกครั้ง หากระบบบูตได้สำเร็จ แสดงว่า initramfs ตัวใหม่ขาดส่วนประกอบของ LVM วิธีแก้ไขคือการสร้างอิมเมจ initramfs ขึ้นใหม่แทนที่จะไปยุ่งกับตัวเคอร์เนล
ไม่มีข้อความจาก Linux ปรากฏเลย คอนโซลแสดงข้อความจากเฟิร์มแวร์, UEFI (unified extensible firmware interface) shell, หน้าจอว่างเปล่าโดยไม่มีข้อความจากเคอร์เนล หรือเกิดการรีเซ็ตวนซ้ำ ความล้มเหลวนี้เกิดขึ้นก่อนที่ Linux จะเริ่มทำงาน ให้ตรวจสอบว่าเซิร์ฟเวอร์ของคุณใช้โหมดใดเมื่อระบบกลับมาใช้งานได้ปกติ เนื่องจาก VPS หลายแห่งบูตในโหมด legacy BIOS และไม่ได้ใช้งาน EFI path เลย:
[ -d /sys/firmware/efi ] && echo UEFI || echo BIOS
mountpoint /boot/efi
sudo efibootmgr -vการที่ /boot/efi ไม่ได้ถูก mount ระหว่างการอัปเกรดเป็นสาเหตุที่พบบ่อยในเครื่อง UEFI เนื่องจากแพ็กเกจที่ดูแล EFI system partition ได้เขียนข้อมูลลงในไดเรกทอรีว่างธรรมดาแทน เฟิร์มแวร์จึงยังคงพยายามบูตผ่าน boot entry เดิมจนกว่า entry นั้นจะไม่ตรงกับข้อมูลบนดิสก์อีกต่อไป
ยังมีอีกรูปแบบหนึ่งที่ไม่ใช่ความล้มเหลวในการบูต หากคุณเข้าสู่ root shell ที่แจ้งว่าระบบอยู่ในโหมดฉุกเฉิน (emergency mode) แสดงว่าเคอร์เนลบูตสำเร็จแล้วแต่ userspace หยุดทำงาน ซึ่งมักหมายถึงมีบรรทัดที่ผิดพลาดใน /etc/fstab หรือ filesystem ตรวจสอบความถูกต้องไม่ผ่าน ให้รันคำสั่ง journalctl -xb ใน shell นั้นเพื่ออ่านชื่อของ unit ที่ล้มเหลว
แพ็กเกจ kernel เสียหายหรือว่าเป็นที่ initramfs?
อาการทั้งสองอย่างนี้ดูเหมือนกันเมื่อมองจากคอนโซล แต่ต้องใช้วิธีซ่อมแซมที่ต่างกัน ให้บูตเข้า kernel เวอร์ชันเก่าแล้วเปรียบเทียบไฟล์ดู
ls -l /boot/vmlinuz-* /boot/initrd.img-*
df -h /bootคุณควรมีไฟล์ vmlinuz- หนึ่งไฟล์และ initrd.img- ที่ตรงกันหนึ่งไฟล์สำหรับทุกเวอร์ชันที่ติดตั้งไว้ โดยแต่ละไฟล์ควรมีขนาดที่สมเหตุสมผล หากไฟล์ initrd หายไปหรือมีขนาดเล็กกว่าไฟล์อื่นอย่างเห็นได้ชัด แสดงว่าการสร้าง initramfs ล้มเหลว สาเหตุทั่วไปคือพื้นที่ใน /boot เต็ม ซึ่งหลักฐานจะปรากฏอยู่ใน log ของแพ็กเกจ:
sudo grep -iE 'no space|update-initramfs' /var/log/apt/term.log
sudo tail -n 40 /var/log/apt/history.loghistory.log ยังแสดงรายการแพ็กเกจที่ติดตั้งในการรันครั้งล่าสุดอย่างละเอียดพร้อมระบุเวลา ซึ่งจะช่วยยุติข้อโต้แย้งว่ามีการเปลี่ยนแปลงอะไรไปบ้าง
ให้เพิ่มพื้นที่ว่างก่อนหาก /boot เต็ม จากนั้นสร้างอิมเมจใหม่สำหรับเวอร์ชันที่คุณต้องการและรีเฟรชเมนู โดยให้ใช้สตริงเวอร์ชันจากผลลัพธ์ของ ls ในเครื่องของคุณเอง เนื่องจากตัวยึดตำแหน่งด้านล่างไม่ใช่เวอร์ชันจริง:
KVER=6.8.0-XX-generic
sudo update-initramfs -c -k "$KVER"
sudo update-grub
ls -l /boot/initrd.img-$KVERคำสั่ง ls สุดท้ายนั้นใช้สำหรับตรวจสอบ หากไฟล์มีขนาดปกติแสดงว่าอิมเมจถูกสร้างขึ้นแล้ว แต่หากตัวไฟล์ kernel เองเสียหาย หรือ dpkg -l แสดงสถานะของแพ็กเกจเป็นอย่างอื่นที่ไม่ใช่ ii ให้ติดตั้งแพ็กเกจนั้นใหม่:
sudo apt install --reinstall linux-image-$KVER
sudo dpkg --configure -aการซ่อมแซมจากโหมดกู้คืนเมื่อไม่สามารถบูต kernel ได้
หากทุกรายการในเมนูบูตล้มเหลว ให้บูตเข้าสู่ rescue image ของผู้ให้บริการแล้วซ่อมแซมดิสก์จากภายนอก ดิสก์ของคุณจะปรากฏเป็นอุปกรณ์ที่ไม่ได้ mount ดังนั้นจะไม่มีกระบวนการใดบนดิสก์ทำงานอยู่และไม่มีสิ่งใดขัดขวางการทำงานของคุณได้
ลำดับขั้นตอนการซ่อมแซมแบบ chroot เต็มรูปแบบ
เรียกใช้ lsblk -f ก่อนเพื่ออ่านชื่ออุปกรณ์จริงจากเครื่องของคุณ /dev/vda เป็นชื่อที่พบบ่อยบน KVM และการติดตั้ง Ubuntu server มักจะวาง root ไว้บน LVM ในชื่อ /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ข้ามบรรทัดที่ไม่เกี่ยวข้องกับระบบของคุณ image จำนวนมากไม่มี /boot แยกต่างหากและไม่มี EFI partition จากนั้นให้ bind kernel interfaces เข้าไป แล้วเข้าสู่ระบบ:
for d in dev proc sys run; do sudo mount --rbind /$d /mnt/$d; done
sudo chroot /mnt /bin/bashภายใน chroot คุณกำลังทำงานบนระบบที่เสียหายในขณะที่ kernel ที่สมบูรณ์ทำงานอยู่เบื้องหลัง ให้ดำเนินการซ่อมแซมที่นั่น:
df -h /boot
update-initramfs -u -k all
update-grub
grub-install /dev/vda
exitgrub-install จะใช้กับดิสก์ทั้งลูกบนระบบ BIOS ไม่ใช่แค่ partition สำหรับระบบ UEFI ให้ใช้ grub-install --target=x86_64-efi --efi-directory=/boot/efi และตรวจสอบให้แน่ใจว่า directory นั้นถูก mount แล้วก่อนที่คุณจะเรียกใช้คำสั่ง ออกจาก chroot ด้วย exit, unmount ทุกอย่างด้วย sudo umount -R /mnt จากนั้นสลับโหมดในแผงควบคุมกลับเป็นโหมดบูตปกติแล้วรีสตาร์ทเครื่อง
การทดสอบ kernel ใหม่โดยไม่ส่งผลกระทบต่อการบูตครั้งถัดไป
GRUB สามารถเริ่มการทำงานของรายการบูตรายการใดรายการหนึ่งได้เพียงครั้งเดียว จากนั้นจะกลับไปใช้ค่าเริ่มต้นที่คุณเลือกไว้ ให้ตั้งค่าเริ่มต้นไปยัง kernel ที่คุณเชื่อถือได้ จากนั้นจึงสั่งเริ่ม kernel ใหม่สำหรับการบูตเพียงครั้งเดียว หากเกิดความล้มเหลว การทำ hard reset จากแผงควบคุมจะนำคุณกลับไปยัง kernel ที่ใช้งานได้ปกติโดยไม่ต้องกังวลเรื่องการจับเวลาที่หน้าจอ console
ตั้งค่า GRUB_DEFAULT=saved ใน /etc/default/grub, รัน sudo update-grub จากนั้นแสดงรายการชื่อรายการบูตเพื่อให้คุณระบุชื่อได้อย่างถูกต้อง:
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 rebootgrub-editenv list ควรแสดงชื่อที่คุณเลือกไว้ในรูปแบบ saved_entry ผลลัพธ์นี้เป็นหลักฐานว่ากลไกดังกล่าวทำงานได้จริง เนื่องจากการบันทึกค่าจำเป็นต้องใช้ /boot/grub/grubenv ที่สามารถเขียนข้อมูลได้ ซึ่งในบางโครงสร้างไฟล์อาจไม่สามารถเขียนได้โดยไม่มีการแจ้งเตือน รายการที่ 0 คือรายการบนสุดของเมนูซึ่งเป็น kernel ใหม่ล่าสุด การใช้ชื่อรายการมีความปลอดภัยมากกว่าการใช้ตัวเลข เนื่องจากลำดับตัวเลขจะเปลี่ยนไปทุกครั้งที่มีการติดตั้งหรือลบ kernel ออก
เหตุใดการใช้ autoremove บนเซิร์ฟเวอร์แบบ headless จึงมีความเสี่ยง
APT จะเก็บรายการแพ็กเกจ kernel ที่ห้ามลบโดยอัตโนมัติไว้ คุณสามารถตรวจสอบรายการของคุณได้ดังนี้:
cat /etc/apt/apt.conf.d/01autoremove-kernels
dpkg -l 'linux-image-*' | grep -c '^ii'ไฟล์ดังกล่าวจะถูกสร้างขึ้นใหม่ทุกครั้งที่มีการเปลี่ยนแปลงแพ็กเกจ kernel เพื่อป้องกันไม่ให้ kernel ที่กำลังใช้งานอยู่และเวอร์ชันล่าสุดถูกลบออก ปัญหาคือเรื่องของจังหวะเวลา หากคุณรันคำสั่ง sudo apt autoremove --purge ทันทีหลังจากรีบูตเข้าสู่ kernel เวอร์ชันใหม่ รายการที่ได้รับการป้องกันจะถูกอัปเดตไปแล้ว ทำให้ kernel เวอร์ชันเก่าที่คุณต้องการเก็บไว้ไม่ได้รับการป้องกันอีกต่อไป สำหรับเครื่องที่มีคีย์บอร์ดต่ออยู่ นี่อาจเป็นเพียงความไม่สะดวก แต่สำหรับเซิร์ฟเวอร์แบบ headless นี่คือความแตกต่างระหว่างการเลือกเมนูบูตกับการต้อง mount ดิสก์จาก rescue image
ควรเก็บ kernel ไว้เป็นพื้นฐานอย่างน้อย 2 เวอร์ชัน และเก็บ 3 เวอร์ชันเมื่อ /boot มีพื้นที่เพียงพอ ให้ลบเวอร์ชันเก่าออกโดยระบุชื่อหลังจากตรวจสอบด้วย uname -r เพื่อให้มั่นใจว่าคุณจะไม่มีทางลบ kernel ที่กำลังใช้งานอยู่:
uname -r
sudo apt purge linux-image-6.8.0-XX-generic
dpkg -l 'linux-image-*' | grep '^ii'หลังจากนั้นให้รันคำสั่งสุดท้ายอีกครั้ง หากจำนวนลดลงจาก 3 เหลือ 2 ถือเป็นการทำความสะอาดปกติ แต่หากลดลงเหลือ 1 แสดงว่าระบบกำลังรอที่จะเกิดปัญหาในการรีบูตครั้งถัดไป
สร้าง snapshot ก่อนเริ่มการอัปเกรด
การสร้าง snapshot ก่อนดำเนินการ apt upgrade เป็นช่องทางการกู้คืนเพียงวิธีเดียวที่ไม่ต้องพึ่งพาการบูตระบบใหม่ การกู้คืน snapshot จะทำให้ดิสก์กลับไปอยู่ในสถานะที่ kernel เวอร์ชันเดิมเป็นค่าเริ่มต้น ซึ่งช่วยให้คุณสามารถลองอัปเกรดใหม่ได้โดยที่หน้าจอ console ยังคงเปิดอยู่ การทำ snapshot ขณะเครื่องทำงานจะเป็นแบบ crash consistent ซึ่งหมายความว่าระบบจะบันทึกสถานะดิสก์เสมือนว่าไฟฟ้าถูกตัด ดังนั้นหากผู้ให้บริการของคุณรองรับการทำ snapshot แบบ offline ให้ปิดเซิร์ฟเวอร์ก่อนดำเนินการ ทั้งนี้ snapshot ไม่ใช่การสำรองข้อมูล (backup) เนื่องจากโดยปกติแล้ว snapshot จะถูกเก็บไว้บนโครงสร้างพื้นฐานเดียวกับ volume ที่คัดลอกมา การเข้าใจ ความแตกต่างระหว่าง VPS snapshots และการสำรองข้อมูลจริง จะช่วยให้คุณตัดสินใจได้ว่าวิธีใดจะช่วยคุณได้เมื่อเกิดความล้มเหลวที่รุนแรงเกินกว่าปัญหาเรื่อง kernel
เรื่องนี้มีความสำคัญอย่างยิ่งในการอัปเกรดเวอร์ชันหลัก (release upgrade) ซึ่ง kernel, เครื่องมือ initramfs, bootloader และการตั้งค่า GRUB จะถูกเปลี่ยนแปลงทั้งหมดในการทำงานครั้งเดียว ให้สร้าง snapshot ทันทีก่อนที่คุณจะเริ่ม การอัปเกรด Ubuntu 24.04 ไปเป็น 26.04 ไม่ใช่สร้างไว้ล่วงหน้าตั้งแต่คืนก่อนหน้า เพื่อให้จุดกู้คืนตรงกับสถานะของเครื่องที่คุณกำลังจะทำการเปลี่ยนแปลงจริง
วิธีการที่ unattended-upgrades จัดการกับแพ็กเกจ kernel
unattended-upgrades ของ Ubuntu จะติดตั้งอัปเดตความปลอดภัยโดยอัตโนมัติ และแพ็กเกจ kernel ก็จะถูกส่งผ่านช่องทาง security pocket เช่นเดียวกับแพ็กเกจอื่น ซึ่งส่งผลตามมา 2 ประการ
ประการแรก kernel ใหม่จะถูกติดตั้งลงในระบบแต่ยังไม่ได้ทำงาน เนื่องจาก kernel จะมีผลก็ต่อเมื่อทำการบูตเครื่องใหม่เท่านั้น ไฟล์ /var/run/reboot-required จะปรากฏขึ้น และ /var/run/reboot-required.pkgs จะระบุสาเหตุที่ต้องการให้รีบูต แต่ระบบจะไม่รีสตาร์ทเองเว้นแต่คุณจะเปิดใช้งาน Unattended-Upgrade::Automatic-Reboot ไว้ใน /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ประการที่สอง ช่องว่างระหว่างการติดตั้งกับการบูตทำให้หาสาเหตุได้ยาก เซิร์ฟเวอร์อาจติดตั้ง kernel ใหม่ในเดือนมีนาคมและมารีบูตในเดือนมิถุนายนด้วยเหตุผลอื่นที่ไม่เกี่ยวข้องกัน แล้วพบว่าระบบไม่สามารถบูตขึ้นมาได้ การเปลี่ยนแปลงที่ทำให้ระบบบูตไม่ได้นั้นเกิดขึ้นมานานถึง 3 เดือนแล้ว ดังนั้นสิ่งที่ทำในวันนั้นจึงไม่ใช่สาเหตุของปัญหา /var/log/apt/history.log คือที่ที่คุณสามารถตรวจสอบประวัติการรันที่ติดตั้ง kernel ซึ่งทำให้ระบบของคุณมีปัญหาในขณะนี้
ควรทำการรีบูตด้วยตนเองในวันที่คุณกำหนดไว้ โดยเปิดหน้าต่าง console ทิ้งไว้เสมอ นิสัยเพียงอย่างเดียวนี้จะเปลี่ยนเหตุการณ์ระบบล่มที่หาสาเหตุไม่ได้ให้กลายเป็นการเลือกเมนูเพียง 2 นาที หากคุณต้องการระบบอัตโนมัติโดยไม่ต้องการความประหลาดใจ ให้เปิดการติดตั้งอัตโนมัติไว้แต่ปิดการรีบูตอัตโนมัติ และดู วิธีการตั้งค่า unattended-upgrades บน Ubuntu สำหรับการตั้งค่าที่ถูกต้อง การระงับแพ็กเกจ kernel ด้วย sudo apt-mark hold linux-image-generic จะหยุดการอัปเดตทั้งหมด ซึ่งรวมถึงการแก้ไขช่องโหว่ความปลอดภัยของ kernel ด้วย ดังนั้นให้ถือว่านี่เป็นการแลกเปลี่ยนที่คุณตัดสินใจเลือกเอง ไม่ใช่มาตรการรักษาความปลอดภัยปกติ
FAQ
ฉันจะบูต kernel เวอร์ชันเก่าบน VPS ที่ไม่มีคีย์บอร์ดได้อย่างไร?
ให้เปิดคอนโซลของผู้ให้บริการ (VNC หรือ serial) แล้วสั่ง hard reset จากแผงควบคุม เนื่องจากคุณไม่สามารถล็อกอินเพื่อสั่งรีบูตตามปกติได้ ในขณะที่เครื่องกำลังเริ่มทำงาน ให้กด Esc ซ้ำๆ หรือกด Shift ค้างไว้หากเป็นระบบ BIOS แบบเก่า เพื่อหยุดหน้าจอ GRUB menu ไว้ จากนั้นเลือก "Advanced options for Ubuntu" แล้วเลือกรายการที่อยู่ถัดจาก kernel เวอร์ชันล่าสุด เมื่อเข้าสู่หน้าล็อกอินได้แล้ว ให้รัน uname -r เพื่อยืนยันว่าคุณกำลังใช้ kernel เวอร์ชันใดอยู่ และใช้ dpkg -l 'linux-image-*' เพื่อดูว่ามี kernel อื่นติดตั้งไว้อีกบ้าง ให้เริ่มการวินิจฉัยปัญหาหลังจากที่ระบบกลับมาทำงานได้อีกครั้งเท่านั้น
ทำไม VPS ของฉันถึงไม่แสดงหน้า GRUB menu เลย?
อิมเมจบนคลาวด์มักตั้งค่า GRUB timeout เป็น 0 ไว้ในไฟล์ภายใต้ /etc/default/grub.d/ ทำให้ kernel เวอร์ชันล่าสุดเริ่มทำงานทันทีโดยไม่มีโอกาสให้กดปุ่มใดๆ ให้ตั้งค่า GRUB_TIMEOUT=10 และ GRUB_TIMEOUT_STYLE=menu ใน /etc/default/grub เพิ่ม GRUB_TERMINAL="console serial" เพื่อให้เมนูแสดงผลผ่าน serial console ด้วย จากนั้นรัน sudo update-grub แล้วตรวจสอบความถูกต้องด้วย grep -r TIMEOUT /etc/default/grub /etc/default/grub.d/ เนื่องจากไฟล์ในไดเรกทอรีดังกล่าวจะถูกอ่านหลังจากไฟล์หลักและอาจเขียนทับการตั้งค่าของคุณได้
ฉันควรลบ kernel เก่าเพื่อเพิ่มพื้นที่ใน /boot หรือไม่?
ให้ลบเฉพาะเวอร์ชันที่เก่าที่สุดออกและเก็บไว้อย่างน้อย 2 เวอร์ชัน หาก /boot เต็มจะทำให้เกิดความล้มเหลวในตัวเอง เนื่องจากกระบวนการสร้าง initramfs จะทำไม่สำเร็จและคุณจะเหลือเพียง kernel ที่ไม่มีอิมเมจที่ใช้งานได้ ให้ลบโดยระบุชื่อแพ็กเกจให้ถูกต้องหลังจากตรวจสอบ uname -r แล้ว เพื่อให้แน่ใจว่า kernel ที่กำลังใช้งานอยู่จะไม่ถูกลบออก หลีกเลี่ยงการใช้คำสั่ง sudo apt autoremove --purge แบบเหมาเข่งบนเครื่องที่ไม่มีหน้าจอ (headless) เนื่องจากรายการ kernel ที่ได้รับการป้องกันจะถูกสร้างใหม่ทุกครั้งที่มีการเปลี่ยนแปลง kernel และการรันคำสั่งในช่วงเวลาที่ไม่เหมาะสมอาจทำให้คุณเหลือ kernel เพียงตัวเดียวโดยไม่มีรายการสำรองในเมนูบูต
unattended-upgrades สามารถทำให้ระบบบูตไม่ขึ้นได้หรือไม่?
มันสามารถติดตั้ง kernel ที่ทำให้บูตไม่ขึ้นในภายหลังได้ แต่ระบบจะไม่รีสตาร์ทเองเว้นแต่จะตั้งค่า Unattended-Upgrade::Automatic-Reboot เป็น true ใน /etc/apt/apt.conf.d/50unattended-upgrades รูปแบบที่พบบ่อยคือความล้มเหลวที่ล่าช้า: kernel ถูกติดตั้งระหว่างการอัปเดตอัตโนมัติ มี /var/run/reboot-required ปรากฏขึ้น และปัญหาจะแสดงตัวออกมาเมื่อคุณรีบูตเครื่องในอีกหลายสัปดาห์ถัดมา ให้รีบูตอย่างตั้งใจโดยเปิดคอนโซลทิ้งไว้ และอ่าน /var/log/apt/history.log เพื่อดูว่าการรันครั้งใดที่เป็นตัวติดตั้ง kernel ที่คุณกำลังบูตอยู่