第一次接触kexec是在数据中心服务器维护时。当时需要为20台物理机更新内核版本,按照传统方式得逐台重启,耗时长达两小时。直到运维组长甩给我这条命令:"试试kexec -l后接kexec -e,比喝咖啡还快"。
kexec是Linux内核内置的"热替换"机制,允许在不经过完整硬件重启的情况下,从当前运行的内核直接引导加载新内核。其原理可以理解为"内核层面的接力跑"——旧内核将CPU控制权、内存状态等关键资源完整移交给新内核,跳过了BIOS/UEFI自检环节。根据实测数据,使用kexec重启内核的平均耗时仅为传统重启的1/5。
注意:kexec需要CONFIG_KEXEC=y内核编译选项支持,且对ARM架构的兼容性较x86稍差
传统Linux重启流程:
kexec热重启流程:
通过跳过硬件检测和bootloader阶段,kexec节省了约70%的重启时间。下图是内存状态转换示意:
| 阶段 | 传统重启内存状态 | kexec内存状态 |
|---|---|---|
| 准备阶段 | 完全清空 | 保留内核镜像区域 |
| 执行阶段 | 从磁盘加载新内核 | 内存中直接切换内核 |
| 完成阶段 | 全新初始化 | 保留部分硬件状态 |
kexec实现依赖三个关键组件:
当执行kexec -l /boot/vmlinuz-5.15.0时:
首先验证内核支持情况:
bash复制# 检查内核编译选项
grep KEXEC /boot/config-$(uname -r)
# 确认kexec-tools已安装
which kexec || sudo apt install kexec-tools -y
典型的生产环境配置示例:
bash复制# 预留256M内存给kexec(添加到/etc/default/grub)
GRUB_CMDLINE_LINUX="crashkernel=256M"
# 更新GRUB后重启
sudo update-grub && sudo reboot
加载新内核(以Ubuntu 22.04为例):
bash复制sudo kexec -l /boot/vmlinuz-5.15.0-78-generic \
--initrd=/boot/initrd.img-5.15.0-78-generic \
--append="root=UUID=3e5f1c2a-... ro quiet splash"
关键参数说明:
-l:加载模式(load)--append:必须与原内核启动参数一致,特别关注root=参数--initrd:匹配新内核版本的initramfs立即执行切换:
bash复制sudo kexec -e
此时系统会立即跳转到新内核,控制台可能短暂黑屏(约2-5秒)
对于需要批量维护的场景,可创建kexec预加载脚本(/usr/local/bin/prepare_kexec.sh):
bash复制#!/bin/bash
KERNEL_VER=$(ls /boot/vmlinuz-* | sort -V | tail -n1)
INITRD="${KERNEL_VER/vmlinuz/initrd.img}"
CMDLINE=$(cat /proc/cmdline)
kexec -l "$KERNEL_VER" \
--initrd="$INITRD" \
--append="$CMDLINE"
echo "New kernel loaded, run 'kexec -e' to switch"
添加可执行权限后,可通过SSH批量预加载:
bash复制parallel-ssh -h hosts.txt -i "sudo /usr/local/bin/prepare_kexec.sh"
| 错误现象 | 原因分析 | 解决方案 |
|---|---|---|
| kexec: Unknown load failed | 内核未开启CONFIG_KEXEC | 重新编译内核或使用标准发行版内核 |
| Failed to load initramfs | initrd路径或版本不匹配 | 使用uname -r确认当前运行版本 |
| Kernel panic after kexec -e | 启动参数不一致 | 检查root=UUID和ro等关键参数 |
| ARM设备执行后卡死 | 架构特定限制 | 添加--dtb=指定设备树文件 |
内存预留优化:
bash复制# 监控kexec内存使用
cat /sys/kernel/kexec_crash_size
# 动态调整(单位:MB)
echo 512 > /sys/kernel/kexec_crash_size
快速回滚方案:
bash复制# 保留旧内核在内存中
sudo kexec -l /boot/vmlinuz-$(uname -r) --initrd=/boot/initrd.img-$(uname -r)
# 新内核测试失败后立即切回
sudo kexec -e
企业级部署建议:
kexec --load-preserve-context保持PCIe设备状态在某次金融系统零停机升级中,我们实现了以下操作序列:
关键配置片段:
bash复制# 保持网络连接
echo 1 > /proc/sys/net/ipv4/tcp_tw_reuse
# 防止内存碎片
sysctl vm.drop_caches=3
在Kubernetes节点维护时,结合kexec可实现"无感知内核升级":
实测对比数据:
| 指标 | 传统重启方案 | kexec方案 |
|---|---|---|
| 节点不可用时间 | 4分12秒 | 38秒 |
| Pod重建数量 | 73个 | 0个 |
| CPU负载波动 | 58% → 92% | 平稳过渡 |
企业级部署必须考虑的安全措施:
bash复制kexec -l vmlinuz --append="..." --kexec-file-sigcheck
bash复制# 在/etc/audit/rules.d/kexec.rules中添加
-a always,exit -F arch=b64 -S kexec_load -F key=kexec_ops
bash复制setsebool -P secure_kexec 1
性能与安全平衡建议:
/var/log/kexec.log中的加载记录