什么是Kdump券犁?
Kdump是一個基于kexec的內(nèi)核崩潰轉(zhuǎn)儲機制油吭,當系統(tǒng)崩潰時矫钓,kdump使用kexec啟動到第二個內(nèi)核。地熱個內(nèi)核叫做捕獲內(nèi)核或者又叫“2nd kernel”铁瞒,它以很少的內(nèi)存啟動捕獲內(nèi)核妙色,并捕獲轉(zhuǎn)儲鏡像。Kdump的概念是目前最可靠的內(nèi)核轉(zhuǎn)儲技術(shù)慧耍,已被主要的linux廠商使用身辨。(例如Red Hat系列)
什么是Kexec?
Kexec是一種能夠根據(jù)已經(jīng)運行內(nèi)核的上下文快速啟動新內(nèi)核的一種機制芍碧,而不經(jīng)過BIOS煌珊。BIOS的啟動在一些大型機器或者有大量外設(shè)的機器上時特別耗時兼蜈。這種機制能夠節(jié)省需要在不同內(nèi)核之間切換的開發(fā)人員的時間固灵。
Kexec在內(nèi)核空間和用戶空間都有對應(yīng)的組件,內(nèi)核提供了幾個kexec重啟功能的系統(tǒng)調(diào)用锣光。用戶空間的軟件包"kexec-tools"使用這些系統(tǒng)調(diào)用踪危,并執(zhí)行加載和引導第二個內(nèi)核(捕獲內(nèi)核)蔬浙。
Kexec由兩部分組成,一是內(nèi)核空間的系統(tǒng)調(diào)用kexec_load贞远,負責在生產(chǎn)內(nèi)核(或者叫第一個內(nèi)核)啟動時將捕獲內(nèi)核(或者叫第二個內(nèi)核)加載到指定的位置畴博。而是用戶空間的kexec-tools,它將捕獲內(nèi)核(second kernel)的地址傳遞給生產(chǎn)內(nèi)核(first kernel)蓝仲,讓系統(tǒng)在崩潰的時候能夠找到捕獲內(nèi)核(second kernel)的地址并運行俱病。
Kdump怎么工作官疲?
在當前系統(tǒng)發(fā)生崩潰時,新的捕獲內(nèi)核被加載亮隙,然后根據(jù)已設(shè)置的命令去將當前之前發(fā)生崩潰的系統(tǒng)的內(nèi)存保存到一個特殊的文件(vmcore)中途凫。
下面以Fedora26做為測試演示。(Fedora和CentOS系列的系統(tǒng)已經(jīng)在kenrel中打開了CONFIG_KEXEC*選項咱揍。)
首先需要在系統(tǒng)啟動時預(yù)留出給第二個內(nèi)核運行的內(nèi)存颖榜。內(nèi)核參數(shù)"crashkernel=160M"會在系統(tǒng)啟動時預(yù)留出160M內(nèi)存的空間給捕獲內(nèi)核運行使用。"crashkerel=xM"還支持其他的參數(shù)煤裙,詳細的可以參考內(nèi)核參數(shù)文檔 內(nèi)核參數(shù)掩完。
# dmesg | grep -i reserving
[ 0.000000] Reserving 160MB of memory at 656MB for crashkernel (System RAM: 2047MB)
系統(tǒng)啟動后我們可以從上面的命令中看到已經(jīng)預(yù)留出了160M的內(nèi)存從內(nèi)存的656M處。
安裝用戶態(tài)的包"kexec-tools"硼砰,軟件包中會提供kdump所需的服務(wù)和"kexec"快速內(nèi)核啟動命令且蓬,和壓縮過濾內(nèi)存的"makedumpfile"命令。
[root@localhost ~]# dnf install -y kexec-tools
配置题翰,修改kdump相關(guān)的配置文件恶阴。
[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設(shè)置了kdump發(fā)生時vmcore文件的存儲方式,此文件修改后需要重啟kdump的服務(wù)豹障。
配置文件/etc/sysconfig/kdump冯事,如果只是修改了COMMANDLINE相關(guān)的參數(shù),則不需要去重新build生成新的initramfs文件血公。
啟動kdump服務(wù):
[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.
所有的服務(wù)都配置完成昵仅,如果此時系統(tǒng)發(fā)生了panic或者其他的一些導致系統(tǒng)崩潰的現(xiàn)象,這是kdump服務(wù)會將當時的內(nèi)存鏡像按照用戶的配置保存起來累魔。一個簡單的方式是通過命令來觸發(fā):
[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]
當系統(tǒng)重啟后就能在指定的目錄下看到生成的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
轉(zhuǎn)儲文件被保存后可以用"crash"這個軟件包來分析這個"vmcore"文件吕世。
開始提到了Kexec內(nèi)核部分提供了一些系統(tǒng)調(diào)用,"kexec_load()" 和 "kexec_file_load()"梯投,其中一個用來加載捕獲內(nèi)核 - "kexec -l"命辖,另外一個來提供系統(tǒng)重啟 - "kexec -e"。
系統(tǒng)調(diào)用"kexec_load()"可以加載一個新的內(nèi)核并之后能夠被"reboot()"調(diào)用分蓖。它是被這樣定義的:
long kexec_load(unsigned long entry, unsigned long nr_segments,
struct kexec_segment *segments, unsigned long flags);
其中一個比較重要的是"kexec_segment"結(jié)構(gòu)體:
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()的參數(shù)為"LINUX_REBOOT_CMD_KEXEC"并被調(diào)用時吮龄,則啟動新的內(nèi)核時就調(diào)用"kexec_load()"系統(tǒng)調(diào)用。另外“CONFIG_KEXEC”必須在編譯kernel時被打開咆疗。
系統(tǒng)調(diào)用"kexec_load_file()"會設(shè)置2個參數(shù)"kernel"和"initramfs"給"kexec"命令。"kexec"會讀取這些數(shù)據(jù)來創(chuàng)建對應(yīng)的數(shù)據(jù)段母债。
long kexec_file_load(int kernel_fd, int initrd_fd,
unsigned long cmdline_len, const char *cmdline,
unsigned long flags);
同樣的"CONFIG_KEXEC_FILE"參數(shù)也要在內(nèi)核編譯時被打開午磁。
目前的大多數(shù)發(fā)行版都已經(jīng)打開了"KEXEC"相關(guān)的配置參數(shù)尝抖。
以上就是一個kdump的簡單流程。有關(guān)"kdump"能夠捕獲到的內(nèi)核崩潰時間可以參考文檔"/usr/share/doc/kexec-tools/kexec-kdump-howto.txt"迅皇∶亮桑或者請參考我們寫的測試用例 kdump-test。