Linux Kdump内核崩溃转储部署详解

最近在回顾kdump内核崩溃转储技术,刚好可以整理下相关知识点,系统性地讲解下Kdump的部署过程以及原理。

kdump内核崩溃转储技术在处理linux内核遇到宕机等异常问题中,可以将其崩溃瞬间的内存映像(包括函数栈,内存,CPU等信息)都保留下来,方便开发者分析故障原因。类似于应用层的coredump机制。

部署Kdump过程需要了解几个知识点:

  1. 内核编译过程怎么开启?
  2. kexec机制?
  3. 系统启动怎么适配(依赖条件)?
  4. 怎么解析转储文件?


内核编译开启kdump

需要使能以下几个config参数并编译:

  1. 在"Processor type and features.“下使能"kexec system call”。 CONFIG_KEXEC=y
  2. 在"Filesystem" -> “Pseudo filesystems.“下使能"sysfs file system support”。 CONFIG_SYSFS=y
  3. 在"Kernel hacking.“下使能"Compile the kernel with debug info” 。 CONFIG_DEBUG_INFO=y
  4. 在"Processor type and features"下使能"kernel crash dumps”。 CONFIG_CRASH_DUMP=y
  5. 在"Filesystems" -> “Pseudo filesystems"下使能”/proc/vmcore support"。 CONFIG_PROC_VMCORE=y

kexec机制

kudmp机制实现的核心就是kexec,kexec可以将第二内核(捕获内核)转载到指定内存,当在第一内核崩溃瞬间,切换到第二内核(捕获内核)运行。
Kexec 来自于“kexec-tools”组件,编译 kexec-tools 工具包以得到 kexec工具(centos可以下载kexec-tools包直接安装)。内核要开启kexec,需要如上描述的开启CONFIG_KEXEC 选项

kexec命令调用语法如下:

  1. 装载捕获内核(捕获内核可以与第一内核相同镜像文件,一般都默认用同一个)

kexec -l < kernel-image > --initrd=< initramfsxxx.img > --append="< command-line-options >"

如:如果想要启动镜像 /boot/bzImage, /proc/cmdline 的内容是 “root=/dev/hda1” ,那么装载内核的命令将是:
kexec -l /boot/bzImage -append=“root=/dev/hda1” (即告知kexec入口)

  • kernel-image: 是您想要重新启动后的内核文件。
  • initramfsxxx.img:捕获内核的根文件系统
  • command-line-options: 需要传递到捕获内核的命令行cmdline参数。通常传递 /proc/cmdline 的内容参数即可。
  1. 手动切换到捕获内核运行。

kexec -e 系统自动切换到捕获内核运行(需要上述指定捕获内核入口)

  1. 为了内核崩溃后能自动跳转到捕获内核运行,则采用如下-p参数。

kexec -p < kernel-image > --initrd=< initramfsxxx.img > --append="< command-line-options >"

上述可知:kexec 需要捕获内核的文件,根文件系统文件。当发生内核崩溃时,会将第一内核的内存映像保存在/proc/vmcore


系统启动适配捕获内核

1、 crashkernel
为了开机每次自动适配捕获内核,在第一内核的cmdline下指定捕获内核的内存空间,即添加参数:crashkernel
crashkernel的内存选择可以参考:Documentation\kdump\ kdump.txt文件。当然,也可以直接用crashkernel=auto,系统自动分配。

While the “crashkernel=size[@offset]

  1. if the RAM is smaller than 512M, then don’t reserve anything (this is the “rescue” case)
  2. if the RAM size is between 512M and 2G (exclusive), then reserve 64M
  3. if the RAM size is larger than 2G, then reserve 128M

2、 initramfsxxx.img
initramfsxxx.img根文件系统文件,在切换到捕获内核里启动,我们可以对initramfsxxx.img里的内容人为做一些修改,比如启动时候需要挂载分区、运行一些程序或安装一些驱动。

如centos里,kdump服务能自动生成initramfsxxx.img,该镜像文件里有比较重要的一个kdump-initxxx.sh的脚本文件,用于对/proc/vmcore转储文件进行压缩(makedumpfile工具),以及盘分区挂载并拷贝文件到指定路径(默认拷贝到/var/log/crash下)。

当然,该img文件也可以手动通过mkinitramfs工具生成。

3、kexec -p xxx
每次启动需要执行kexec -p xxx 指定捕获内核入口。

在centos中通过kdump服务,开机自动完成了kexec设定了捕获内核的操作。如果/boot下没有捕获内核的根文件系统的镜像文件(xxxkdump.img),也将会自动生成。

centos为例,服务所在脚本里 /usr/bin/kdumpctl实际kexec装载命令如下:
/sbin/kexec -p --command-line="BOOT_IMAGE=/vmlinuz-3.10.0-123.el7.x86_64 root=UUID=79704805-e306-420b-827a-52849e1376c1 ro vconsole.keymap=us vconsole.font=latarcyrheb-sun16 rhgb quiet LANG=en_US.UTF-8 irqpoll nr_cpus=1 reset_devices cgroup_disable=memory mce=off numa=off udev.children-max=2 panic=10 rootflags=nofail acpi_no_memhotplug disable_cpu_apicid=0"   --initrd=/boot/initramfs-3.10.0-123.el7.x86_64kdump.img /boot/vmlinuz-3.10.0-123.el7.x86_64

第一内核下的cmdline

cat /proc/cmdline
BOOT_IMAGE=/vmlinuz-3.10.0-123.el7.x86_64 root=UUID=79704805-e306-420b-827a-52849e1376c1 ro vconsole.keymap=us crashkernel=auto vconsole.font=latarcyrheb-sun16 rhgb quiet LANG=en_US.UTF-8

/etc/sysconfig/kdump 配置文件里,增加了捕获内核cmdline传入额外补充

KDUMP_COMMANDLINE_APPEND="irqpoll nr_cpus=1 reset_devices cgroup_disable=memory mce=off numa=off udev.children-max=2 panic=10 rootflags=nofail acpi_no_memhotplug"

crash和vmlinux

通过echo c > /pros/sysrq-trigger 可触发使内核崩溃。然后生成转储文件vmcore。

当转储文件vmcore生成出来后,需要通过crash工具解析并分析,该工具依赖一个内核调试文件:vmlinux

1、 vmlinux
这里说的的vmlinux是一个基于ELF格式的文件,它不过是可用于调试的内核映像的未压缩版本。 而zImage或bzImage是内核映像的压缩版本,通常用于引导。

kernel 映像文件 vmlinux 在编译的时候必须指定了 -g 参数,即带有调试信息,编译后才可以生成(centos包里在:kernel-debuginfo–xxx.rpm内核包可找到)。

2、 crash
crash启动解析命令如下:

crash vmlinux vmcore

如果crash没有指定vmcore,则默认使用当前实时系统内存。

进入crash后,需要借助crash相关命令(命令略),可以获取第一内核宕机时的信息(如:各cpu调用栈,内存余量,进程信息等等),就可以分析出产生内核崩溃的具体原因了。

猜你喜欢

转载自blog.csdn.net/ludaoyi88/article/details/114194687