kdump安装及调试策略(详细)

本文基于redhat系的操作系统,debian系不太一样,仅供参考

1. kdump原理

kdump是一种内核崩溃转储机制,简单来说就是在内存中留出一块单独的区域放置一个内核,当现在运行中的系统发生不可恢复的崩溃后,会立即切换到此内核上,将内存中所有的数据保存到磁盘中,方便开发者之后分析内核崩溃的原因。其中,原始的内核叫做第一内核,也叫生产内核,崩溃后进入的内核是第二内核,也叫捕获内核。有几点要说明:

  • 预留出的内存是无法被其他程序使用的,所以一般预留的空间都不会很大
  • 转储实际上是进入第二内核后保存/proc/vmcore和崩溃前的dmesg日志,原始的vmcore和物理内存一样大,所以一般保存在/var/crash下的vmcore都压缩过,磁盘中vmcore的大小和崩溃前内存的占用率成正比,这是一个值得注意的点,个别情况下可能会因为磁盘空间不足而导致转储失败
  • 内核中要支持kdump机制,要确保打开“CONFIG_KEXEC,CONFIG_KEXEC_CORE,CONFIG_DEBUG_INFO,CONFIG_CRASH_DUMP,CONFIG_PROC_VMCORE”等配置项

2. kdump的部署

注:一般很多操作系统在安装时可默认启动kdump。

2.1 需要的包

yum install kexec-tools crash kernel-debuginfo

2.2 设置内核启动参数

确保内核参数有“crashkernel=auto”,crashkernel用于设置kdump需要的预留内存的大小,这里将会被kdump服务放入内核,系统崩溃后会启动此处的内核转储/proc/vmcore下的文件到磁盘路径/var/crash下,有如下格式:

  • crashkernel=X,high //强制使用高端内存,例:crashkernel=1024M,high
  • crashkernel=X,low //强制使用低端内存,例:crashkernel=256M,low
  • crashkernel=X@Y //让内核自行选择在X到Y之间大小的内存,例:crashkernel=128M@256M
  • crashkernel=ramsize-range:size[,...][@offset] //物理内存大小在ramsize到range范围内让内核选择size到offset大小的预留内存,例:crashkernel=1G-64G:160M@256M,64G-:512M

建议默认使用“crashkernel=auto”,除非kdump有问题,否则不建议手动修改。由于机型、系统环境、物理内存对预留均有影响,无法给出一个肯定的计算kdump预留空间范围的方法,只能提供如下建议:

  • 最小预留空间的大小,应大于/boot目录下vmlinuz和其对应的initramfs文件大小总和的两倍。
  • 最大内存取决于物理内存和内核支持情况,有些情况下即使设置很大的内存实际分配的也是默认的大小,注意检查/proc/iomem中“Crash kernel”项的空间。
  • 内核使用的内存空间和cpu核数正相关,核数越多,占用的内存越多,不过通常kdump的第二内核会加入“nr_cpus”参数限制使用的核数,这个参数要注意。
  • 在以往经验中,服务器平台,arm和龙芯的预留空间至少应>=128M,x86>=160M。

注:内核参数修改方法可以参见其他网络教程。

2.3 开启kdump服务

systemctl enable kdump
systemctl start kdump

2.4 测试kdump功能

linux内核提供了一个模拟触发的方法,开启kdump服务后,执行如下命令即可:

echo 1 > /proc/sys/kernel/sysrq
echo c > /proc/sysrq-trigger

2.5 分析转储文件

如果kdump工作正常,在/var/crash目录下会生成一个带有日期的文件夹,其中就存放了转储文件vmcore,可以使用crash解析:

crash /usr/lib/debug/lib/modules/‘对应转储文件的debuginfo内核’/vmlinux /var/crash/‘对应触发时间的文件夹’/vmcore

如果解析成功会出现交互界面,输入命令“bt”可以打印出栈,说明已经可以正常调试了。

3. 一些常见kdump问题的处理

分析方法一般是复现同时查看日志,在内核启动参数中加入“console=ttyS0,115200 loglevel=9”,其中ttyS0为串口设备,可以修改为确定能使用的串口,最好使用主板上的串口,不要使用pcie转接的串口,那会需要驱动模块支持,可能会在进入kdump以后没有输出。

接上串口后,使用2.4的命令触发kdump,在另一终端查看输出日志。

注:详细串口的使用方法可参考网络上的教程,这里不做过多说明

3.1 kdump服务启动失败

首先查看“/proc/cmdline”中是否设置了crashkernel,如果有再检查kdump的报错:

systemctl status kdump

如果类似如下的日志,特别是“No memory reserved for crash kernel”,说明crashkernel设置的不对,可以尝试调整大小和格式,也可能是内核不支持某些上述格式。

[root@ai66 test_k8s_log]# systemctl status kdump.service 
● kdump.service - Crash recovery kernel arming
   Loaded: loaded (/usr/lib/systemd/system/kdump.service; enabled; vendor preset: enabled)
   Active: failed (Result: exit-code) since Wed 2023-11-01 15:24:49 CST; 6 days ago
  Process: 1070 ExecStart=/usr/bin/kdumpctl start (code=exited, status=1/FAILURE)
 Main PID: 1070 (code=exited, status=1/FAILURE)

Nov 01 15:24:49 ai66 systemd[1]: Starting Crash recovery kernel arming...
Nov 01 15:24:49 ai66 kdumpctl[1070]: No memory reserved for crash kernel
Nov 01 15:24:49 ai66 kdumpctl[1070]: Starting kdump: [FAILED]
Nov 01 15:24:49 ai66 systemd[1]: kdump.service: main process exited, code=exited, status=1/FAILURE
Nov 01 15:24:49 ai66 systemd[1]: Failed to start Crash recovery kernel arming.
Nov 01 15:24:49 ai66 systemd[1]: Unit kdump.service entered failed state.
Nov 01 15:24:49 ai66 systemd[1]: kdump.service failed.

3.2 kdump触发后卡死

发现kdump卡死一般有以下几个原因:

  • 开启了内存加密,表现为屏幕黑屏,没有任何输出,按大小写键,键盘灯不亮。kdump不能和内存加密共存,不要在开启kdump的情况下打开内存加密功能,在内核启动参数中加入“mem_encrypt=off”可以关闭内存加密。
  • 配置问题,kdump的配置文件位于“/etc/kdump.conf”,其中有一个配置项“failure_action”,表示进入第二内核执行kdump失败后的默认行为,一般是被注释掉不使用的,可配置为“reboot | halt | poweroff | shell | dump_to_rootfs”等参数。如果屏幕上没有任何输出,可能会因为kdump失败而呈现假卡死的状态,分析时可以捎带检查一下这里。
  • 硬件故障或内核问题无法在kdump内核中重启系统,具体情况参见串口输出的日志。

3.3 没有生成转储文件

还是要查看进入第二内核后串口输出的日志,其中可能会有以下情况:

  • 日志中出现大量OOM输出,这是linux的一个机制,系统内存不足时,会抛出此错误日志,同时根据一定的规则杀死一些进程。在kdump中这种情况表示使用crashkernel预留的内存空间不足,需要扩大空间,在部分机器中可能需要较大的空间,因为第二内核的initramfs文件可能会由于用户的系统环境而包含一些占内存很大的服务。要注意的是,修改crashkernel重启后,最好检查一下/proc/iomem中crash预留的空间,计算一下实际预留的大小。部分内核可能会由于你设置的参数不对而使用默认的预留大小,造成不管怎么改都不行的情况。
  • 日志中有类似下面的输出,特别是存在“Missing the log_buf symbol”,表示vmcore-dmesg命令与内核不匹配,或者说是kexec-tools包与内核不匹配。kexec-tools包和内核是关联度非常高的,绝对要保持版本一致
    kdump: saving vmcore-dmesg.txt
    Missing the log_buf symbol
    kdump: saving vmcore-dmesg.txt failed
    kdump: saving vmcore
    kdump: saving vmcore failed
    [FAILED] Failed to start Kdump Vmcore Save Service.

    其实不只是kexec-tools包,这些包都与内核关联度比较高,系统中要保证这些包和当前运行的内核版本一致:crash linux-sgx-driver prefetch_tuning txgbe vdo dracut dpdk kpatch kmod-kvdo kae_driver kmod kexec-tools

4. 一些要注意的点

  • redhat系kdump的控制命令是kdumpctl,这是一个bash脚本,位于/bin/kdumpctl,修改此脚本也是调试的一种办法,需要个人有一定shell脚本经验。
  • 注意检查第二内核的启动参数中是否有“nr_cpus”参数,此参数限制内核使用的核数,如果没有,可能会导致预留内存不够内核使用。通常默认为“nr_cpus=1”或者“nr_cpus=2”
  • 部分架构中,第一和第二内核并不是同一个内核,比如早期的龙芯和powerpc架构的系统,参见龙芯的文档:kdump | 龙芯开源社区。现在较新的龙芯内核已经支持仅使用一个内核了

你可能感兴趣的:(linux,linux,运维,centos,kdump,crash,openeuler,UOS)