Kdump在生产环境中经常被当作一个“开启了就行”的功能,但真正出事故时,很多人发现生成的vmcore文件要么损坏,要么根本就没保存下来。问题往往出在内存转储的安全配置上,不是Kdump本身没生效,而是默认参数在内存不足、存储空间有限或安全策略严格的环境下根本跑不通。
内存预留值不是越大越好,也不是越小越省资源Crashkernel的内存预留是Kdump能否成功的基础。很多人习惯用 crashkernel=auto,这个参数在CentOS 7和8上的行为差异很大。CentOS 7上auto通常只预留160MB左右,对于现在动辄几十GB内存的服务器来说,这点空间连基本的vmcore都装不下。CentOS 8的auto会根据总内存动态计算,但在内存超过1TB时,预留值可能飙升到1GB以上,造成生产环境可用内存的浪费。
手动指定crashkernel值更稳妥。对于大多数通用服务器,crashkernel=256M或512M是合理的起点。如果服务器运行了大量内核模块或挂载了复杂存储,建议至少512M。预留内存的公式可以参考:基础值128M,加上每TB物理内存增加64M。比如一台256GB内存的服务器,128 + (0.25 * 64) ≈ 144M,向上取整给256M足够。但如果你用了kdump的压缩功能,可以适当减少预留,因为压缩后的vmcore体积会缩小到原来的30%到50%。
修改crashkernel参数后必须重新生成grub配置。在CentOS 7上编辑 /etc/default/grub,在GRUB_CMDLINE_LINUX行追加 crashkernel=512M,然后执行 grub2-mkconfig -o /boot/grub2/grub.cfg。CentOS 8的路径相同,但注意UEFI引导的机器grub.cfg在 /boot/efi/EFI/centos/grub.cfg。改完重启后用 cat /proc/cmdline 确认参数已生效。
转储目标路径的安全性直接决定vmcore能否落盘Kdump默认把vmcore写到 /var/crash 目录,但这个路径在生产环境存在三个致命问题。第一,/var分区通常不大,vmcore的大小等于崩溃时刻内核使用的物理内存量,几十GB的vmcore直接撑爆/var分区会导致系统其他服务异常。第二,/var是系统运行时的活跃分区,如果崩溃原因是磁盘故障或文件系统损坏,vmcore根本写不进去。第三,部分安全基线要求/var以noexec或nosuid挂载,虽然不影响写入,但某些企业安全策略会限制该目录的大文件写入。
推荐的做法是单独挂载一个专用分区或使用NFS远程存储。如果使用本地分区,创建一个独立于根文件系统的XFS或ext4分区,挂载到 /crash 或 /var/crash 并确保该分区不存放其他数据。分区大小至少设置为服务器物理内存的1.2倍,给压缩后的vmcore和可能的多次转储留出余量。在 /etc/kdump.conf 中修改path参数:
path /crash
如果使用NFS远程存储,需要注意Kdump在崩溃时运行在极简的initramfs环境中,网络配置必须内嵌到kdump的initrd里。在 /etc/kdump.conf 中添加NFS目标时,直接用IP地址不要用主机名,因为崩溃环境下DNS解析不可用:
nfs 192.168.10.20:/kdump_dumps
同时要在 /etc/sysconfig/kdump 中设置 KDUMP_NETCONFIG 参数,指定崩溃时使用的网卡和网络配置。如果服务器有多张网卡,必须明确指定用于转储的接口,否则kdump可能选错网卡导致网络不通。
压缩和过滤机制是控制vmcore体积的核心手段不压缩的vmcore体积等于崩溃时内核占用的全部物理内存,一台256GB内存的机器生成的vmcore就是256GB,无论存储空间还是转储时间都难以接受。Kdump支持通过makedumpfile工具在转储过程中实时压缩和过滤。核心参数是 core_collector,在 /etc/kdump.conf 中配置:
core_collector makedumpfile -c -d 31
-c 参数启用压缩,默认使用zlib压缩,压缩比大约在3:1到5:1。-d 参数指定过滤级别,取值范围0到31,数字越大过滤越激进。31是最彻底的过滤,只保留内核崩溃时的关键数据结构,包括内核栈、进程信息、内存管理信息等,丢弃用户态进程的内存页和文件缓存。对于绝大多数内核崩溃分析,-d 31完全够用,vmcore体积可以压缩到物理内存的3%到10%。
如果你的应用场景需要分析用户态进程的内存状态,比如怀疑是某个应用程序触发了内核bug,可以把过滤级别降低到 -d 15 或 -d 7,保留更多用户态页面。但要注意这会显著增大vmcore体积。还有一种折中方案是用 -d 31 配合 KDUMP_COMMANDLINE_APPEND 参数在崩溃时自动收集应用层的coredump,两者互补。
对于安全要求高的环境,压缩算法可以换成lzo或snappy,牺牲一点压缩比换取更快的转储速度,减少崩溃后系统停机时间。配置方法是在makedumpfile中加 -c -l 参数启用lzo压缩。但要注意lzo压缩的vmcore需要对应版本的crash工具才能解析,确保分析环境的crash工具版本不低于7.2.0。
内核启动参数中的安全选项会阻断Kdump正常流程很多安全加固指南会建议在内核启动参数中添加 iommu=off、intel_iommu=off、pci=noaer 等参数来规避硬件兼容性问题,但这些参数可能导致Kdump捕获内核在初始化硬件时卡死。Kdump的捕获内核是从零开始重新初始化的,如果禁用了IOMMU,某些服务器芯片组在崩溃重启时DMA控制器处于不确定状态,捕获内核可能直接panic,形成“二次崩溃”。
解决方法是给捕获内核传递不同的启动参数。在 /etc/sysconfig/kdump 中通过 KDUMP_COMMANDLINE_APPEND 变量为捕获内核单独设置参数,覆盖主内核的参数。例如主内核关闭了IOMMU,但捕获内核需要开启:
KDUMP_COMMANDLINE_APPEND="iommu=on intel_iommu=on reset_devices"
reset_devices 参数尤其重要,它告诉捕获内核在初始化时复位所有硬件设备到已知状态,避免继承崩溃前设备的不确定状态。这个参数在CentOS 7和8的默认kdump配置中已经包含,但如果你自定义了 KDUMP_COMMANDLINE_APPEND,必须确保 reset_devices 没有被覆盖掉。
安全审计要求vmcore的访问控制和完整性校验vmcore文件包含崩溃时刻的全部内核内存内容,里面可能有进程的敏感数据、加密密钥的残片、网络缓冲区中的未加密数据。默认生成的vmcore文件权限是600,属主root,但这只是最基本的保护。在多管理员环境中,需要确保只有授权人员能访问vmcore,并且vmcore在传输到分析环境的过程中不被篡改。
在 /etc/kdump.conf 中可以用 core_collector 配合管道对vmcore进行实时加密。例如用openssl在转储时加密:
core_collector makedumpfile -c -d 31 | openssl enc -aes-256-cbc -pass file:/etc/kdump/keyfile
密钥文件 /etc/kdump/keyfile 必须预先生成并妥善保管,权限设为400。这个方案的问题是如果密钥文件在根文件系统上,而根文件系统在崩溃时可能已损坏,导致加密失败。更可靠的做法是把加密密钥编译进kdump的initramfs中,但这需要自定义dracut模块,复杂度较高。
对于大多数场景,更实用的安全措施是:vmcore本地落盘后立即由监控脚本通过scp或rsync over SSH传输到专用分析服务器,传输完成后删除本地vmcore。在 /etc/kdump.conf 中配置 default action 为执行自定义脚本:
default /usr/local/bin/kdump_post.sh
脚本内容大致为:检查vmcore完整性(用makedumpfile --check),通过SSH密钥认证传输到远程服务器,校验传输后的文件哈希,删除本地文件。SSH密钥必须专用于此用途,私钥放在 /root/.ssh/ 下权限600,公钥配置在远程服务器的专用账号下并限制该账号只能写入指定目录。
测试Kdump配置不是可选项,是必须执行的验证步骤绝大多数“配置了Kdump但崩溃时没生成vmcore”的案例,都是因为从来没测试过。Kdump的测试不是简单的 systemctl status kdump 看服务状态,而是要真实触发一次内核崩溃。CentOS提供了SysRq触发方式,安全且可控:
echo 1 > /proc/sys/kernel/sysrq echo c > /proc/sysrq-trigger
执行前务必确认:生产环境已切换到备用节点,当前节点可以重启;/var/crash或你配置的转储路径有足够空间;如果有iLO/iDRAC等带外管理,确保可以远程控制重启,因为有些硬件在SysRq崩溃后不会自动重启,需要手动断电。
触发崩溃后观察服务器是否自动重启,重启后检查转储目录是否生成了 vmcore 文件,以及 /var/log/messages 中是否有 kdump 相关的成功日志。用 makedumpfile --dump-dmesg vmcore 命令提取崩溃时的内核日志,确认vmcore可读且包含崩溃原因。如果vmcore没生成,检查 /var/log/kdump.log 中的错误信息,常见原因包括:crashkernel预留内存不足、捕获内核启动参数错误导致硬件初始化失败、存储驱动未加载导致无法挂载转储分区。
CentOS 7到8的迁移中Kdump配置的兼容性陷阱CentOS 8默认使用 kernel-core 而非 kernel 包,kdump的依赖关系有变化。CentOS 8的kdump使用dracut生成initramfs时,默认只包含崩溃恢复所需的最小驱动集。如果服务器使用了第三方存储驱动(比如某些RAID卡或FC HBA卡),必须在 /etc/dracut.conf.d/ 下添加配置文件强制包含这些驱动模块:
add_drivers+="mpt3sas megaraid_sas lpfc"
然后重新生成kdump的initramfs:
kdumpctl rebuild
另一个陷阱是CentOS 8默认启用了KASLR(内核地址空间布局随机化),这会影响makedumpfile的地址过滤效率。可以在主内核启动参数中加 nokaslr 关闭,但这会降低安全性。更好的做法是让捕获内核关闭KASLR,在 KDUMP_COMMANDLINE_APPEND 中加 nokaslr,这样不影响主内核的安全特性。
如果你的环境已经迁移到CentOS Stream或Rocky Linux,上述配置基本通用,但要注意Rocky Linux 9开始kdump默认使用systemd的kdump服务而非传统的init脚本,配置文件的语法有细微调整,path和core_collector参数保持不变,但网络相关参数需要检查 /etc/kdump.conf.d/ 目录下的分片配置。
配置好Kdump只是第一步,持续的监控和定期测试才是保证崩溃时能拿到有效vmcore的关键。建议每月在维护窗口执行一次SysRq触发测试,验证端到端的转储流程。同时监控 /var/crash 或远程存储的空间使用率,设置告警阈值,避免空间耗尽导致后续转储失败。对于安全敏感环境,建立vmcore的访问审批和审计流程,确保每次vmcore的生成、传输、分析、销毁都有记录可查。
