必威-必威-欢迎您

必威,必威官网企业自成立以来,以策略先行,经营致胜,管理为本的商,业推广理念,一步一个脚印发展成为同类企业中经营范围最广,在行业内颇具影响力的企业。

crashkernel在生成kdump时需要的内存越多必威:,一

2019-09-20 08:51 来源:未知
  1. Kdump工具

什么是Kdump?

Kdump是一个基于kexec的内核崩溃转储机制,当系统崩溃时,kdump使用kexec启动到第二个内核。地热个内核叫做捕获内核或者又叫“2nd kernel”,它以很少的内存启动捕获内核,并捕获转储镜像。Kdump的概念是目前最可靠的内核转储技术,已被主要的linux厂商使用。(例如Red Hat系列)

某天挂载了一个新硬盘后,我的centos7系统第二天就出现了崩溃现象,报错如题“failed to start crash recovery kernel arming”.

      最近一直在搞redhat。之前客户的机器都没有配置kdump,于是挨个给几百台虚机配kdump。我顺便就研究了下kdump的相关东西。

  Kdump的工作机制是在内核崩溃时, 通过kexec 工具由BIOS启动一个备用内核, 由备用内核执行一系列任务,保存内存中崩溃内核的状态, 供后续故障分析用.

什么是Kexec?

Kexec是一种能够根据已经运行内核的上下文快速启动新内核的一种机制,而不经过BIOS。BIOS的启动在一些大型机器或者有大量外设的机器上时特别耗时。这种机制能够节省需要在不同内核之间切换的开发人员的时间。
Kexec在内核空间和用户空间都有对应的组件,内核提供了几个kexec重启功能的系统调用。用户空间的软件包"kexec-tools"使用这些系统调用,并执行加载和引导第二个内核(捕获内核)。
Kexec由两部分组成,一是内核空间的系统调用kexec_load,负责在生产内核(或者叫第一个内核)启动时将捕获内核(或者叫第二个内核)加载到指定的位置。而是用户空间的kexec-tools,它将捕获内核(second kernel)的地址传递给生产内核(first kernel),让系统在崩溃的时候能够找到捕获内核(second kernel)的地址并运行。

意思大致为“内存崩溃捕获机制未能成功启动”,一搜才知道这是因为一个叫做kdump的服务无法启动导致的。

      kdump是用来分析内核问题的好东西。当内核运行出现问题时,比如常见的死机,操作系统就已经不工作了。当计时器超时,也就是判断内核已经失效后,系统会引导crashkernel,也就是用来下载kdump的另一个内核。当它启动后,会按照kdump配置中的信息,将指定的内存空间中的内容存到硬盘指定位置。这样我们就可以根据生成的vmcore文件来分析是什么原因导致了系统故障。

  本文默认AMD或INTEL X86_64架构, RHEL7系统环境. 

Kdump怎么工作?

在当前系统发生崩溃时,新的捕获内核被加载,然后根据已设置的命令去将当前之前发生崩溃的系统的内存保存到一个特殊的文件(vmcore)中。

下面以Fedora26做为测试演示。(Fedora和CentOS系列的系统已经在kenrel中打开了CONFIG_KEXEC*选项。)

首先需要在系统启动时预留出给第二个内核运行的内存。内核参数"crashkernel=160M"会在系统启动时预留出160M内存的空间给捕获内核运行使用。"crashkerel=xM"还支持其他的参数,详细的可以参考内核参数文档 内核参数。

# dmesg | grep -i reserving
[    0.000000] Reserving 160MB of memory at 656MB for crashkernel (System RAM: 2047MB)

系统启动后我们可以从上面的命令中看到已经预留出了160M的内存从内存的656M处。

安装用户态的包"kexec-tools",软件包中会提供kdump所需的服务和"kexec"快速内核启动命令,和压缩过滤内存的"makedumpfile"命令。

[root@localhost ~]# dnf install -y kexec-tools

配置,修改kdump相关的配置文件。

[root@localhost ~]# grep -v ^# /etc/kdump.conf 

path /var/crash
core_collector makedumpfile -l --message-level 1 -d 31


[root@localhost ~]# grep -v ^# /etc/sysconfig/kdump
KDUMP_KERNELVER=""

KDUMP_COMMANDLINE=""

KDUMP_COMMANDLINE_REMOVE="hugepages hugepagesz slub_debug quiet"

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 transparent_hugepage=never nokaslr"

KEXEC_ARGS=""

KDUMP_IMG="vmlinuz"

KDUMP_IMG_EXT=""

配置文件/etc/kdump.conf设置了kdump发生时vmcore文件的存储方式,此文件修改后需要重启kdump的服务。

配置文件/etc/sysconfig/kdump,如果只是修改了COMMANDLINE相关的参数,则不需要去重新build生成新的initramfs文件。

启动kdump服务:

[root@localhost ~]# systemctl restart kdump
[root@localhost ~]# systemctl status kdump
● kdump.service - Crash recovery kernel arming
   Loaded: loaded (/usr/lib/systemd/system/kdump.service; enabled; vendor preset: disabled)
   Active: active (exited) since Sat 2017-07-15 10:46:22 UTC; 36s ago
  Process: 2172 ExecStop=/usr/bin/kdumpctl stop (code=exited, status=0/SUCCESS)
  Process: 2180 ExecStart=/usr/bin/kdumpctl start (code=exited, status=0/SUCCESS)
 Main PID: 2180 (code=exited, status=0/SUCCESS)

Jul 15 10:46:21 localhost dracut[4264]: -rw-r--r--   1 root     root          127 Mar 28 02:15 usr/share/zoneinfo/Etc/UTC
Jul 15 10:46:21 localhost dracut[4264]: drwxr-xr-x   3 root     root            0 Jun 22 13:38 var
Jul 15 10:46:21 localhost dracut[4264]: lrwxrwxrwx   1 root     root           11 Jun 22 13:38 var/lock -> ../run/lock
Jul 15 10:46:21 localhost dracut[4264]: lrwxrwxrwx   1 root     root            6 Jun 22 13:38 var/run -> ../run
Jul 15 10:46:21 localhost dracut[4264]: drwxr-xr-x   2 root     root            0 Jun 22 13:38 var/tmp
Jul 15 10:46:21 localhost dracut[4264]: ========================================================================
Jul 15 10:46:21 localhost dracut[4264]: *** Creating initramfs image file '/boot/initramfs-4.11.9-300.fc26.x86_64kdump.img' done ***
Jul 15 10:46:22 localhost kdumpctl[2180]: kexec: loaded kdump kernel
Jul 15 10:46:22 localhost kdumpctl[2180]: Starting kdump: [OK]
Jul 15 10:46:22 localhost systemd[1]: Started Crash recovery kernel arming.

所有的服务都配置完成,如果此时系统发生了panic或者其他的一些导致系统崩溃的现象,这是kdump服务会将当时的内存镜像按照用户的配置保存起来。一个简单的方式是通过命令来触发:

[root@localhost ~]# echo c > /proc/sysrq-trigger

[some console log]
... ...
         Starting Kdump Vmcore Save Service...
kdump: dump target is /dev/vda1
kdump: saving to /sysroot//var/crash/127.0.0.1-2017-07-16-04:21:36/
[    2.718001] EXT4-fs (vda1): re-mounted. Opts: data=ordered
kdump: saving vmcore-dmesg.txt
kdump: saving vmcore-dmesg.txt complete
kdump: saving vmcore
Copying data                       : [100.0 %] -
kdump: saving vmcore complete
... ...
[/some console log]

当系统重启后就能在指定的目录下看到生成的vmcore文件。可以参考配置文件"/etc/kdump.conf"里的"path"字段。

[root@localhost ~]# ls -lt /var/crash/*/
total 33492
-rw-------. 1 root root 34253115 Jul 16 04:21 vmcore
-rw-r--r--. 1 root root    40360 Jul 16 04:21 vmcore-dmesg.txt

转储文件被保存后可以用"crash"这个软件包来分析这个"vmcore"文件。

开始提到了Kexec内核部分提供了一些系统调用,"kexec_load()" 和 "kexec_file_load()",其中一个用来加载捕获内核 - "kexec -l",另外一个来提供系统重启 - "kexec -e"。

系统调用"kexec_load()"可以加载一个新的内核并之后能够被"reboot()"调用。它是被这样定义的:

long kexec_load(unsigned long entry, unsigned long nr_segments,
                       struct kexec_segment *segments, unsigned long flags);

其中一个比较重要的是"kexec_segment"结构体:

struct kexec_segment {
    void   *buf;        /* Buffer in user space */
    size_t  bufsz;      /* Buffer length in user space */
    void   *mem;        /* Physical address of kernel */
    size_t  memsz;      /* Physical address length */
};

当reboot()的参数为"LINUX_REBOOT_CMD_KEXEC"并被调用时,则启动新的内核时就调用"kexec_load()"系统调用。另外“CONFIG_KEXEC”必须在编译kernel时被打开。

系统调用"kexec_load_file()"会设置2个参数"kernel"和"initramfs"给"kexec"命令。"kexec"会读取这些数据来创建对应的数据段。

long kexec_file_load(int kernel_fd, int initrd_fd,
                           unsigned long cmdline_len, const char *cmdline,
                           unsigned long flags);

同样的"CONFIG_KEXEC_FILE"参数也要在内核编译时被打开。

目前的大多数发行版都已经打开了"KEXEC"相关的配置参数。

以上就是一个kdump的简单流程。有关"kdump"能够捕获到的内核崩溃时间可以参考文档"/usr/share/doc/kexec-tools/kexec-kdump-howto.txt"。或者请参考我们写的测试用例 kdump-test。

参考资料:
kdump-paper
kdump-introduction
fedora-kexec-tools

那么什么是kdump呢?

      kdump的配置可以直接redhat官网上去找,官方有提供配置的脚本,会自动备份你的配置并根据你的系统配置(主要是内存容量)修改对应配置文件里的参数。

1.1 内核管理工具Kdump安装

kdump 是一种先进的基于 kexec 的内核崩溃转储机制。当系统崩溃时,kdump 使用 kexec 启动到第二个内核。第二个内核通常叫做捕获内核,以很小内存启动以捕获转储镜像。第一个内核保留了内存的一部分给第二内核启动用。由于 kdump 利用 kexec 启动捕获内核,绕过了 BIOS,所以第一个内核的内存得以保留。这是内核崩溃转储的本质。详细的在:http://www.ibm.com/developerworks/cn/linux/l-cn-kdump1/index.html#major3

      其他的配置网上也都有,就不多说了。主要说几个点吧:

  Kdump是RHEL7中自带的内核管理工具.在RHEL7.1之前的版本,kdump作为安装完成之后的可选组件自动安装,从RHEL7.1开始kdump被植入安装界面,作为系统基础工具供安装选择.

那接下来查找失败的原因:

      一个是/boot/grub/grub.conf里的crashkernel。crashkernel参数是指定给crashkernel留出多少内存空间的,你的内存越大,crashkernel在生成kdump时需要的内存越多,所以这个选项与内存大小有关,具体的需要去查一下,另外,redhat 5版本这个参数的写法是crashkernel=memory@offset的写法,但是在redhat 6中offset已经没有了,就是crashkernel=memory。

可以通过下面命令直接RPM包安装.

看到一个博文中说与启动文件配置有关

      第二个是/etc/kdump.conf中的core_collector makedumpfile -c --message-level 1 -d 17。这条配置中-d是指定dumplevel,这里设置的是17,你可以根据redhat给出的说明修改为其他值。这个dumplevel会影响dump时dump内存哪些部分;尤其对于服务器来说,因为内存都非常大,如果全部页都dump的话,耗时长而且生成的vmcore非常的大,很占存储空间;通过指定不同的dumplevel,crashkernel会忽略一些没什么用的内存页,比如空白页,空白页里面没有数据,但是默认情况下它也会被dump下来。

yum -y install kexec-tools
rpm -q kexec-tools

查看/etc/grub.conf 文件,发现crashkernel=auto,

      第三个还是/etc/kdump.conf里的参数'default reboot,这条很简单,但是很有用。不配置这条并不会影响kdump正常工作,但是kdump默认情况下是不会自动重启机器的,也就是说在kdump完成之后,就一直处在待机状态。而此时你通过显示屏看不出内核是正在dump或是已经dump完成,因为屏幕什么也不显示。为了保险起见你只能多等一会,等内核dump完成再手动重启。另外,如果服务器故障后做了dump,你又没有发现这件事,那服务器就一直处在不工作的状态,这样很可能影响使用这台服务器的人的正常工作。如果你装的是物理机,又不支持ipmi和kvm console,机房又在别的地方。。。。。那不就坑爹了?你只有大老远跑一趟机房手动去按电源开关了。

同时,Kdump还配备了图形化管理工具,可以通过下面命令安装.

系统对crashkernel=auto的定义为:

      /etc/init.d/kdump status,这条可以查看kdump的运行状态,当然如果是刚配置了kdump,必须要重启才能生效。

yum -y install system-config-kdump

如果系统的内存 <= 8 GB 对kdump kernel不会保留任何内容;也就是说,crashkernel=auto 等

      echo c > /proc/sysrq-trigger,这条是测试kdump的。记得输入这条命令之后系统内核会panic!!所以如果要测试需要在维护期间,不然业务都中断啦。成功的话,在你指定的目录下会生成vmcore文件(在新生成的文件夹里面),默认是/var/crash。

  对于RHEL7.4及之后的版本,kdump支持INTEL IOMMU. 而不支持RHEL7.3及之前的版本.

于关掉了机器上的kdump功能;

      kdump生成成功了,那么怎么分析kdump呢?分析kdump需要下载相应的包才行。

1.2 通过命令行配置kdump内存容量

如果系统的内存> 8 GB但是<= 16 GB,crashkernel=auto会保留256M,等同于crashkernel=256M;

      需要的包中,kexec-tools在redhat 5以后都自带了,不用安装。另外两个是:

  kdump能监控系统内核运行状态,其地位比较特殊. kdump的内存空间是在系统启动时,由引导程序分配的,相对于系统内核,kdump内存是一个独立的空间.

如果系统内存> 16GB, crashkernel=auto会保留512M, 等同于crashkernel=512M

      kernel-debuginfo-common-x86_64-2.6.32-xxx.el6.x86_64.rpm和

可以通过如下命令指定kdump的内存空间大小.

安装虚拟机时,给虚拟机设置的内存为1G,所以说系统关掉了kdump。

      kernel-debuginfo-2.6.32-xxx.el6.x86_64.rpm

crashkernel=128M     #为kdump保留128M的内存空间.

接下来就是改写配置,但是没能在系统中找到博文中所说的/etc/grub.conf这个文件,后来想到从Centos 7之后启动就采用grub2 了,所以vi /etc/grub2.cfg把其中的crashkernel=auto改成crashkernel=256M重启就成功了。

      将xxx替换为相应的内核版本号就是要下载的包了注意这两个包在redhat的安装镜像中是没有的,yum源似乎也没有,需要自己到网上去下载。我是在

   crashkernel的值可以设置成“auto",在一些拥有较大内存的系统中,利于实现Kdump的自动化管理.

      注意这里的版本号,不是和你的内核版本对应,而是和vmcore的版本号对应。如果你是本机生成了vmcore,在本机上分析,那么不存在这个问题;如果是一台6.2的redhat生成了vmcore,你把它传到了redhat 6.5的机器上去分析,那么你应当在这台6.5上安装6.2版本的kernel-debuginfo-common和kernel-debuginfo。注意这两个包只能安装一个,也就是说不同版本的kernel-debuginfo-common(和kernel-debuginfo),只能在一台机器上安装一个,如果要分析不同版本的vmcore,只能先删除原先的包,再安装另一个版本了。

crashkernel=auto

      环境准备完成,接下来分析vmcore了。分析使用的是crash命令:

TAG标签:
版权声明:本文由必威发布于必威-操作系统,转载请注明出处:crashkernel在生成kdump时需要的内存越多必威:,一