在一些业务环境的VMware Guest
虚拟机上安装我们的内核模块后,偶尔虚拟机会变成无响应的状态。重启后登录系统查看,处于无响应状态的那段时间在/var/log/messages
中却没有任何信息,完全没有分析问题原因的头绪。
经过调研,找到两种方法可以帮助排查定位这类系统失去响应的问题,分别是:
- 发送
NMI: Non-Maskable Interupt
给虚拟机 - VMware内存快照
发送NMI给虚拟机
NMI
是不可屏蔽的硬件中断。在虚拟化环境中,Hypervisor
可以向Guest
虚拟机发送NMI
中断。Guest
虚拟机收到NMI
后产生dump
文件, 继而从dump
文件中分析系统状态。
只是Linux
系统对于NMI
中断的默认处理行为是发送到stdout
,并不会panic
并产生dump
文件。为了在接收到NMI
时产生dump
文件,我们需要在Guest
的Linux
系统中完成这些配置:
安装
kexec-tools
, 并启动kdump
服务:1
systemctl start kdump.service
配置
sysctl
参数,令Linux
系统接收到NMI
时panic
:1
2sysctl -w kernel.panic_on_unrecovered_nmi=1
sysctl -w kernel.unknown_nmi_panic=1
在VCenter
的GUI
界面中, 可以在相应Guest
虚拟机的导出系统日志
操作中向虚拟机发送NMI
, 如图:
这种方式对VCenter
登录帐号的管理权限有所要求。
在相应的ESXi
主机上也可以通过命令行向虚拟机发送NMI
:
1 | vm-support -a HungVM:Send_NMI_To_Guest --vm=/vmfs/volumes/Path/of/VMname.vmx |
可以参考官方KB:
如果是RHEV
和oVirt
环境, 可以使用virsh
命令发送NMI
:
1 | virsh inject-nmi guest1 |
具体可以参考链接:
内存快照
另外一种方法就是基于VMware的快照。VMware官方提供了一个工具可以将快照文件转换成crash
工具可以读取的dump
文件。
工具使用说明:
工具下载地址:
但经过尝试,发现转换完成的dump
文件使用crash
并不能正常读取。
和Redhat
这篇KB
上描述的错误一致:
crash
无法读取的根本原因是从7.5
版本开始,RHEL
内核默认启用了KASLR
特性:
1 | Starting 7.5, RHEL kernels feature KASLR (Kernel Address Space Linear Randomization) enabled by default. KASLR is a security feature that enables the kernel to relocate itself to a random location on each boot, making writing exploits that depend on local resources significantly harder. |
可以参考这里:
但它也提到,crash
可以直接读取VMware的快照文件,步骤如下:
- 复制
ESXi
主机上Guest
所在目录下的.vmss
/.vmsn
和.vmem
文件到一个目录 - 保持文件名称不变
- 使用
crash
工具打开.vmsn
/.vmss
文件,crash
会自动加载相应的.vmem
文件
如:
1 | # crash <NAME>.vmsn /cores/retrace/repos/kernel/x86_64/usr/lib/debug/lib/modules/<kernel version>/vmlinux |
不过在生成快照时,需要注意勾选包括虚拟机的内存
:
有时侯系统可能会连NMI
也无法响应,这种场景下就只能使用快照方式。但快照方式本身需要从ESXi
主机上获取快照文件,也不是很方便。总之各有利弊,看情况选择使用哪种方法。
因为使用crash
工具分析dump
文件,需要对应内核版本的debuginfo
包。有时我们拿到dump
文件,却不知道内核版本。我们可以从dump
文件中直接查找字符串来搜索, 如:
1 | [root@localhost centos76-Snapshot1]# strings vmss.core |grep -i 'BOOT_IMAGE' |
参考:
- https://support.delphix.com/Continuous_Data_Engine_(formerly_Virtualization_Engine)/Platforms/How_to_Generate_a_non-maskable_interrupt_in_VMware_ESX__(KBA1129)
- https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/virtualization_deployment_and_administration_guide/sect-generic_commands-injecting_nmi
- https://kb.vmware.com/s/article/1015180
- https://kb.vmware.com/s/article/2149185
- https://kb.vmware.com/s/article/67438
- https://kb.vmware.com/s/article/2003941
- https://flings.vmware.com/vmss2core
- https://access.redhat.com/articles/3587631
- https://access.redhat.com/solutions/210063
- https://access.redhat.com/solutions/3622951
- https://knowledge.broadcom.com/external/article/181598/how-to-convert-a-vmware-virtual-machine.html