在CentOS系统中配置kdump实现内核崩溃转储,核心操作就是三步:安装kexec-tools工具包、配置/etc/kdump.conf指定转储路径和核心收集参数、通过systemctl启用kdump服务并预留崩溃内核内存。配置完成后用echo c > /proc/sysrq-trigger触发一次内核崩溃来验证转储是否成功生成vmcore文件。这套流程在CentOS 7和CentOS 8/Stream上基本一致,但细节参数有差异,下面我会逐一拆解。
kdump本质上是基于kexec机制的双内核方案。当系统内核发生panic时,kexec会加载一个预先准备好的捕获内核(capture kernel),这个捕获内核启动后把崩溃时的内存镜像(vmcore)dump到指定存储位置。运维人员拿到vmcore后,可以用crash工具配合对应的vmlinux和调试符号文件进行离线分析,定位内核崩溃根因。这是生产环境排查内核oops、kernel panic、硬件故障的必备手段。
一、环境准备和kdump组件安装
在CentOS 7上,直接用yum安装即可:
yum install kexec-tools -y
在CentOS 8/Stream上,包名有所变化:
dnf install kexec-tools -y
安装完成后,确认kexec服务已安装但不要启动它(kexec是手动触发重启用的,不是常驻服务)。我们要启用的是kdump服务:
systemctl enable kdump systemctl start kdump
这里有一个很多人忽略的关键点:kdump需要在系统启动时预留一块独立的内存区域给捕获内核使用。如果你的机器内存是16GB,默认可能只预留很小一块,导致捕获内核无法正常启动。需要在GRUB引导参数中显式指定crashkernel的大小。
二、配置GRUB引导参数预留崩溃内核内存
编辑/etc/default/grub文件,找到GRUB_CMDLINE_LINUX这一行,追加crashkernel参数。根据内存大小,推荐配置如下:
# 内存4GB以下 GRUB_CMDLINE_LINUX="crashkernel=128M" # 内存4GB-8GB GRUB_CMDLINE_LINUX="crashkernel=256M" # 内存8GB-16GB GRUB_CMDLINE_LINUX="crashkernel=512M" # 内存16GB以上 GRUB_CMDLINE_LINUX="crashkernel=512M"
CentOS 8/Stream使用GRUB2,修改后需要重新生成配置:
grub2-mkconfig -o /boot/grub2/grub.cfg
CentOS 7使用的是grub,命令是:
grub2-mkconfig -o /boot/grub2/grub.cfg
改完之后重启系统,用以下命令验证crashkernel是否生效:
cat /proc/cmdline | grep crashkernel dmesg | grep -i crash
如果看到类似"Memory: 16384MB ... crashkernel=512M@160M"的输出,说明预留成功。
三、详细配置kdump.conf转储参数
kdump的主配置文件是/etc/kdump.conf,这个文件决定了vmcore存到哪里、怎么存、存什么内容。一个生产环境推荐的配置模板如下:
path /var/crash core_collector makedumpfile -l --message-level 1 -d 31 default reboot
逐行解释:path指定转储文件的存放目录,默认是/var/crash,你也可以改成NFS挂载点或者本地磁盘分区。core_collector指定使用makedumpfile工具来压缩和过滤vmcore,其中-l表示使用lzo压缩,-d 31表示过滤掉空闲页和部分用户态页面,能大幅减小vmcore体积。default reboot表示转储完成后自动重启系统,生产环境一般都选这个。
如果你需要通过网络传输vmcore,可以配置netdump或者nfsdump。例如使用SSH传输:
path /var/crash core_collector makedumpfile -l --message-level 1 -d 31 ssh root@192.168.1.100 sshkey /root/.ssh/kdump_id_rsa
这里sshkey指向一个专门用于kdump传输的私钥,需要提前在目标机器上配置好免密登录。另外,如果你的环境用的是iSCSI或者NFS存储,也可以直接把path指向挂载点。
还有一个容易踩坑的地方:如果你的系统启用了透明大页(THP),kdump可能会出现内存预留不足的问题。建议在kdump.conf中加入:
kdump_args --no-hugepages
或者直接在GRUB中禁用THP:
GRUB_CMDLINE_LINUX="transparent_hugepage=never crashkernel=512M"
四、触发内核崩溃进行转储测试
配置完成并重启后,就可以手动触发一次内核崩溃来验证kdump是否正常工作。最安全的方式是通过sysrq触发:
echo c > /proc/sysrq-trigger
执行这条命令后,系统会立即触发kernel panic,然后kdump捕获内核启动,把内存镜像写入/var/crash目录。整个过程通常需要1-3分钟,取决于内存大小和makedumpfile的过滤程度。完成后系统会自动重启。
重启后检查转储结果:
ls -lh /var/crash/
你应该能看到类似这样的文件:
vmlinuz-3.10.0-1160.el7.x86_64 vmcore-3.10.0-1160.el7.x86_64.20240101-120000
如果目录为空或者没有vmcore文件,说明转储失败。常见失败原因包括:crashkernel内存预留不足、SELinux阻止写入、磁盘空间不够、makedumpfile参数错误。排查方法是查看kdump服务日志:
journalctl -u kdump -xe
以及查看dmesg中的kdump相关信息:
dmesg | grep -i kdump
五、用crash工具分析vmcore文件
拿到vmcore后,需要安装crash工具和对应内核的debuginfo包才能分析:
yum install crash kernel-debuginfo-$(uname -r) -y
然后启动crash:
crash /usr/lib/debug/lib/modules/$(uname -r)/vmlinux /var/crash/vmcore-$(uname -r)
进入crash交互界面后,最常用的命令是bt(backtrace)查看崩溃时的内核调用栈:
crash> bt PID: 12345 TASK: ffff88001a2b3c40 CPU: 2 COMMAND: "nginx" #0 [ffff88001a2b3c40] machine_kexec at ffffffff8103a120 #1 [ffff88001a2b3c80] crash_kexec at ffffffff810c1234 #2 [ffff88001a2b3cc0] panic at ffffffff810c4567 ...
通过调用栈可以定位到具体是哪个内核模块或函数导致了崩溃。如果是驱动问题,还可以用mod命令查看加载的模块,用log命令查看内核日志。
六、生产环境的注意事项和常见问题
第一,kdump不要和业务争抢资源。crashkernel预留的内存是从系统总内存中扣掉的,如果预留过大会影响业务性能。一般512M对大多数场景够用,除非你的vmcore经常很大需要完整内存镜像。
第二,/var/crash目录要确保有足够空间。一个16GB内存的机器,经过makedumpfile压缩后vmcore可能还有2-4GB,如果不压缩可能达到10GB以上。建议单独挂一个分区或者用NFS远程存储。
第三,CentOS 8上kdump的默认行为有变化,makedumpfile可能需要单独安装:
dnf install makedumpfile -y
第四,如果你的系统使用了LVM或者加密磁盘,kdump可能无法正常写入。需要确保/var/crash所在的文件系统在捕获内核启动时可以正常挂载。建议把path设置在一个简单的ext4或xfs分区上。
第五,不要在虚拟机上测试kdump时忘记关闭虚拟机的内存气球(memory balloon)功能,这会导致crashkernel预留失败。在KVM环境下,需要在虚拟机XML中禁用balloon或者固定内存大小。
第六,自动化运维场景下,建议把kdump测试纳入定期巡检脚本。可以写一个简单的cron任务,每月触发一次sysrq崩溃测试并检查vmcore生成情况,确保kdump随时可用。毕竟真正出故障的时候才发现kdump没配好,那就晚了。
七、总结
CentOS上配置kdump并不复杂,核心就是装工具、配GRUB预留内存、改kdump.conf、启用服务、触发测试、分析结果这六步。但细节决定成败,crashkernel大小、THP处理、存储路径、SELinux策略、makedumpfile参数每一个都可能成为坑。建议在测试环境完整跑通一遍流程,确认vmcore能正常生成和分析后,再推广到生产集群。内核崩溃不可避免,但有了kdump,你就有了事后定位问题的能力,这是运维基本功中非常重要的一环。
