Hướng dẫn sử dụng kexec trên Linux: Khởi động lại Kernel cực nhanh không cần qua BIOS/UEFI

Linux tutorial - IT technology blog
Linux tutorial - IT technology blog

Server reboot mất 3 phút chỉ vì BIOS POST — có cách nào nhanh hơn không?

Mỗi lần cập nhật kernel trên server production, mình đều phải chờ đợi cái quá trình khởi động dài dằng dặc: BIOS kiểm tra RAM, CPU, thiết bị, rồi mới trao quyền cho bootloader, rồi mới load kernel. Trên server vật lý cũ kỹ với 4GB RAM, giai đoạn POST một mình đã ngốn 90 giây. Nhân lên 10 server là gần 15 phút downtime mỗi đợt vá kernel.

Vấn đề không phải là Linux khởi động chậm — mà là phần cứng BIOS/UEFI không liên quan gì đến việc thay kernel, nhưng vẫn bắt cả hệ thống đi qua quy trình đó. kexec sinh ra để giải quyết đúng bài toán này.

kexec là gì và tại sao nó hoạt động được?

kexec (viết tắt của kernel execute) là một system call trong Linux kernel, cho phép kernel đang chạy load một kernel khác trực tiếp vào bộ nhớ rồi chuyển giao quyền điều khiển — hoàn toàn bỏ qua toàn bộ BIOS/UEFI và bootloader (GRUB).

Cơ chế hoạt động gồm 2 bước tách biệt:

  1. Load phase: Dùng lệnh kexec -l để đọc kernel image vào vùng nhớ dự phòng (reserved memory). Bước này xảy ra khi hệ thống đang chạy bình thường, không gây gián đoạn dịch vụ.
  2. Execute phase: Dùng lệnh kexec -e (hoặc systemctl kexec) để thực sự chuyển sang kernel mới. Tại đây, kernel hiện tại unmount filesystem, dừng processes, rồi nhảy thẳng vào entry point của kernel mới.

Không có POST. Không có memory test. Không có GRUB countdown. Kernel mới bắt đầu chạy từ điểm start_kernel() như thể vừa được bootloader trao quyền.

Trên server Ubuntu 22.04 với 4GB RAM mình đang quản lý, mình nhận thấy việc này giúp giảm đáng kể thời gian xử lý — từ ~3 phút reboot thông thường xuống còn dưới 30 giây bằng kexec.

Thực hành: Cài đặt và sử dụng kexec

Bước 1: Cài đặt kexec-tools

kexec-tools cung cấp userspace tool để tương tác với kernel system call kexec(2).

# Ubuntu / Debian
sudo apt install kexec-tools -y

# RHEL / AlmaLinux / Rocky
sudo dnf install kexec-tools -y

# Arch Linux
sudo pacman -S kexec-tools

Sau khi cài, trên Ubuntu/Debian sẽ xuất hiện systemd unit kexec-load.service — unit này tự động load kernel hiện tại vào bộ nhớ khi shutdown, sẵn sàng cho kexec reboot.

Bước 2: Xác định kernel và initrd đang dùng

Cần biết đúng đường dẫn kernel image và initramfs đang chạy:

# Xem kernel version đang chạy
uname -r
# Ví dụ output: 6.8.0-45-generic

# Đường dẫn thông thường trên Ubuntu
ls /boot/vmlinuz-$(uname -r)
ls /boot/initrd.img-$(uname -r)

# Xem cmdline đang dùng (tham số boot)
cat /proc/cmdline

Bước 3: Load kernel vào bộ nhớ

Bước này an toàn — không làm gián đoạn hệ thống đang chạy:

KERNEL_VER=$(uname -r)

sudo kexec -l /boot/vmlinuz-${KERNEL_VER} \
  --initrd=/boot/initrd.img-${KERNEL_VER} \
  --reuse-cmdline

# --reuse-cmdline: dùng lại toàn bộ tham số từ /proc/cmdline
# Không cần gõ lại "root=UUID=... quiet splash"

Kiểm tra kernel đã được load chưa:

cat /sys/kernel/kexec_loaded
# Output: 1 = đã load, 0 = chưa

Bước 4: Thực hiện kexec reboot

Có 3 cách để trigger kexec, tùy mức độ kiểm soát bạn muốn:

# Cách 1: systemctl (khuyến nghị — graceful shutdown trước)
sudo systemctl kexec

# Cách 2: kexec trực tiếp (graceful, dừng services trước)
sudo kexec -e

# Cách 3: Tích hợp vào reboot thông thường (chỉ Ubuntu/Debian)
# Khi kexec-tools được cài, lệnh reboot thường sẽ tự dùng kexec nếu có kernel đã load
sudo reboot

Load kernel MỚI (sau khi apt upgrade)

Đây mới là use case thực tế nhất — cập nhật kernel mà downtime tối thiểu:

# Cập nhật kernel
sudo apt update && sudo apt upgrade -y

# Tìm kernel mới nhất vừa cài
NEW_KERNEL=$(ls /boot/vmlinuz-* | sort -V | tail -1 | sed 's|/boot/vmlinuz-||')
echo "Kernel mới: ${NEW_KERNEL}"

# Load kernel mới vào memory (CHƯA reboot)
sudo kexec -l /boot/vmlinuz-${NEW_KERNEL} \
  --initrd=/boot/initrd.img-${NEW_KERNEL} \
  --reuse-cmdline

# Chuẩn bị: dừng dịch vụ không cần thiết, sync data
sudo sync

# kexec reboot — bỏ qua BIOS/UEFI hoàn toàn
sudo systemctl kexec

# Sau khi boot lên, kiểm tra
uname -r

Script automation cho nhiều server

Mình dùng script này khi cần roll out kernel update cho nhiều node:

#!/bin/bash
# fast-reboot.sh — kexec reboot với kernel mới nhất
set -e

NEW_KERNEL=$(ls /boot/vmlinuz-* | sort -V | tail -1 | sed 's|/boot/vmlinuz-||')
CURR_KERNEL=$(uname -r)

if [ "${NEW_KERNEL}" = "${CURR_KERNEL}" ]; then
  echo "Không có kernel mới. Đang dùng: ${CURR_KERNEL}"
  # Load lại chính kernel hiện tại (vẫn nhanh hơn cold reboot)
fi

echo "Load kernel: ${NEW_KERNEL}"
kexec -l "/boot/vmlinuz-${NEW_KERNEL}" \
  --initrd="/boot/initrd.img-${NEW_KERNEL}" \
  --reuse-cmdline

echo "Bắt đầu kexec reboot trong 5 giây..."
sleep 5
systemctl kexec

Những điều cần chú ý khi dùng kexec

kexec không phù hợp trong mọi tình huống

Vài trường hợp bạn vẫn nên reboot thông thường:

  • Firmware/BIOS update: Cần đi qua POST đầy đủ để flash firmware mới.
  • Lỗi kernel panic hoặc memory corruption: kexec có thể inherit hardware state bị hỏng từ kernel cũ.
  • Thay đổi phần cứng (thêm RAM, thêm disk): BIOS cần detect lại thiết bị mới.
  • Hệ thống EFI Secure Boot: Một số distro không hỗ trợ kexec với Secure Boot bật (phụ thuộc kernel config).

Kiểm tra kernel có hỗ trợ kexec không

# Kiểm tra CONFIG_KEXEC
grep CONFIG_KEXEC /boot/config-$(uname -r)
# Cần thấy: CONFIG_KEXEC=y

# Kiểm tra CONFIG_KEXEC_FILE (kexec -l dùng cái này)
grep CONFIG_KEXEC_FILE /boot/config-$(uname -r)
# CONFIG_KEXEC_FILE=y

Hầu hết kernel mặc định của Ubuntu, Debian, RHEL đã bật sẵn cả hai. Với kernel tự build, nhớ enable trong make menuconfig ở mục Processor type and features.

kdump và kexec: liên quan gì?

kdump — công cụ capture kernel crash dump — cũng dùng kexec bên dưới. kdump load một capture kernel nhỏ vào vùng nhớ reserved, và khi kernel chính panic, nó tự động kexec sang capture kernel để ghi core dump. Nếu bạn đang dùng kdump, đừng lo — nó dùng vùng nhớ riêng biệt, không xung đột với kexec reboot thông thường.

Kết luận

kexec là một trong những tính năng ít được biết đến nhưng cực kỳ thực dụng của Linux. Với server production cần minimize downtime khi vá kernel, đây là giải pháp đơn giản và hiệu quả hơn nhiều so với live patching phức tạp như kpatch hay livepatch.

Quy trình điển hình: apt upgradekexec -l kernel mới → xử lý graceful shutdown dịch vụ → systemctl kexec. Toàn bộ quá trình reboot xong trong dưới 30 giây thay vì 3 phút. Với hệ thống chạy nhiều node, con số này cộng lại rất đáng kể.

Nếu bạn đang vận hành server Linux và chưa biết đến kexec, thử ngay lần cập nhật kernel tới — sự khác biệt rõ ràng ngay từ lần đầu dùng.

Share: