龙空技术网

centos7内核触发crash问题排查

SuperOps 464

前言:

眼前我们对“centos7各种问题”可能比较珍视,大家都需要了解一些“centos7各种问题”的相关内容。那么小编也在网上搜集了一些有关“centos7各种问题””的相关资讯,希望咱们能喜欢,你们一起来了解一下吧!

最近整理笔记发现2017年的一个内核bug debug过程整理,觉得有一些值得分享和借鉴的地方,专门整理出来。

问题简要

现象:线上接口docker容器化的服务器不定时重启

内核crash日志:

[10505290.375725] general protection fault: 0000 [#1] SMP[10505290.376798] Modules linked in: binfmt_misc ip_vs nf_nat nf_conntrack bridge stp llc overlay() team_mode_loadbalance team intel_powerclamp coretemp intel_rapl kvm_intel kvm crc32_pclmul ghash_clmulni_intel aesni_intel lrw gf128mul glue_helper ablk_helper cryptd mxm_wmi iTCO_wdt ipmi_devintf iTCO_vendor_support sg dcdbas pcspkr ipmi_ssif ipmi_si ipmi_msghandler sb_edac shpchp mei_me mei edac_core wmi lpc_ich mfd_core acpi_power_meter ip_tables xfs libcrc32c sd_mod crc_t10dif crct10dif_generic mgag200 syscopyarea sysfillrect sysimgblt drm_kms_helper crct10dif_pclmul crct10dif_common crc32c_intel ttm ahci drm igb libahci ptp pps_core libata dca i2c_algo_bit megaraid_sas i2c_core dm_mirror dm_region_hash dm_log dm_mod[10505290.384449] CPU: 9 PID: 152754 Comm: docker Tainted: G               ------------ T 3.10.0-327.18.2.el7.x86_64 #1[10505290.385873] Hardware name: Dell Inc. PowerEdge R630/0CNCJW, BIOS 2.0.1 02/12/2016[10505290.387330] task: ffff8820230a1700 ti: ffff8810b0fdc000 task.ti: ffff8810b0fdc000[10505290.388790] RIP: 0010:[<ffffffff810aa989>]  [<ffffffff810aa989>] down_read_trylock+0x9/0x30[10505290.390293] RSP: 0000:ffff8810b0fdf938  EFLAGS: 00010206[10505290.391786] RAX: 0000000000000000 RBX: ffff88202619c9c0 RCX: ffff88202619c9c0[10505290.393314] RDX: 0000000000000001 RSI: 0000000000000301 RDI: 3f5569f4906034fc[10505290.394843] RBP: ffff8810b0fdf938 R08: 0000000000706475 R09: ffff88202619c9c0[10505290.396393] R10: ffff88207ffd7000 R11: 0000000000000000 R12: ffff88202619c9c1[10505290.397931] R13: ffffea0042734980 R14: 3f5569f4906034fc R15: 0000000000000000[10505290.399488] FS:  000000000227d880(0063) GS:ffff88203ea80000(0000) knlGS:0000000000000000[10505290.401065] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033[10505290.402659] CR2: 000000000266a2a0 CR3: 00000017234d1000 CR4: 00000000001407e0[10505290.404279] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000[10505290.405896] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400[10505290.407503] Stack:[10505290.409101]  ffff8810b0fdf968 ffffffff811a3125 ffffea0042734980 ffffea0042734840[10505290.410763]  ffffea007d3ab6c0 0000000000000301 ffff8810b0fdf9b8 ffffffff811a3551[10505290.412439]  ffffea0042734980 ffff8810b0fdfa40 0000000000000001 ffffea0042734980[10505290.414127] Call Trace:[10505290.415806]  [<ffffffff811a3125>] page_lock_anon_vma_read+0x55/0x110[10505290.417518]  [<ffffffff811a3551>] try_to_unmap_anon+0x21/0x120[10505290.419236]  [<ffffffff811a369d>] try_to_unmap+0x4d/0x60[10505290.420942]  [<ffffffff811c7699>] migrate_pages+0x439/0x790[10505290.422661]  [<ffffffff8118e530>] ? isolate_freepages_block+0x380/0x380[10505290.424263]  [<ffffffff8118f529>] compact_zone+0x299/0x400[10505290.425864]  [<ffffffff8101c829>] ? read_tsc+0x9/0x10[10505290.427451]  [<ffffffff8118f72c>] compact_zone_order+0x9c/0xf0[10505290.429052]  [<ffffffff8118fae1>] try_to_compact_pages+0x121/0x1a0[10505290.430656]  [<ffffffff81630de3>] __alloc_pages_direct_compact+0xac/0x196[10505290.432281]  [<ffffffff811739c0>] __alloc_pages_nodemask+0x990/0xb90[10505290.433899]  [<ffffffff811b7b8a>] alloc_pages_vma+0x9a/0x140[10505290.435531]  [<ffffffff811cc4c3>] do_huge_pmd_anonymous_page+0x123/0x510[10505290.437162]  [<ffffffff81196f48>] handle_mm_fault+0x1a8/0xf50[10505290.438797]  [<ffffffff8119e965>] ? do_mmap_pgoff+0x305/0x3c0[10505290.440433]  [<ffffffff816416c0>] __do_page_fault+0x150/0x450[10505290.442066]  [<ffffffff816419e3>] do_page_fault+0x23/0x80[10505290.443702]  [<ffffffff8163dc48>] page_fault+0x28/0x30[10505290.445335] Code: 00 00 00 ba 01 00 00 00 48 89 de e8 12 fe ff ff eb ce 48 c7 c0 f2 ff ff ff eb c5 e8 72 06 fd ff 66 90 0f 1f 44 00 00 55 48 89 e5 <48> 8b 07 48 89 c2 48 83 c2 01 7e 07 f0 48 0f b1 17 75 f0 48 f7[10505290.448879] RIP  [<ffffffff810aa989>] down_read_trylock+0x9/0x30[10505290.450612]  RSP <ffff8810b0fdf938>
事件发生的主要原因

zabbix监控脚本并发调用docker stats指令会触发内核分配大页内存,由于Linux内核存在bug,在极端场景下会触发page_lock_anon_vma_read的bug,该bug会触发内核crash进而重启。

具体bug描述参见:

影响和损失评估前两次服务器重启快速在LVS层将该服务器摘除并进行人工修复,持续时间15分钟以内。第三次服务器重启服务器由于配置了开机启动项,所有的服务自动重启,持续时间5分钟以内。由于LVS可以自动识别后端服务的连通性,当后端连接的服务不通时会自动切换到其他服务器中,因此对线上的影响不是特别大,但是会造成后端服务的压力和负载增加。修复问题的方案

由于目前官方没有对该bug进行修复,我们对内核的代码不是特别熟悉,对内核的开发测试流程不擅长,为了避免人为修改内核代码引入更大的bug,因此采取的方案是尽量降低内核触发该bug的概率。

具体方案:

1,停止zabbix对容器资源的监控,避免该脚本触发docker daemon申请大页内存片。

2,给生产环境的所有docker服务器配置开机启动项,保证服务器重启后服务都能正常对外提供服务目前均部署了开机启动项。

3,避免生产环境yum update所有服务器,主要原因是yum update后会造成生产环境各个服务器的软件版本和内核版本不是严格一致;如果yum update后务必保证重启,避免更新内核后服务器没有重启,下次重启后自动使用新内核问题。

4,严格的预警策略,服务器重启目前zabbix agent会跟着挂掉导致报警不能实时报出来,建议增加远程ping操作之类的跨服务器预警策略。

得到的教训

1,第一次内核crash重启时,采用常规的排查问题方案:内存,CPU,磁盘,网络等资源占用场景去排查,结果没有找到根本原因,导致后续两次重启事故。

2,对内核的debug技能欠缺导致不知道如何下手,需要去专门学习Linux内核debug的技能。

3,生产环境服务器重启影响较大,必须引起足够重视,不能因为对生产环境没有重大影响就忽略。

4,必须要有线上生产环境重大问题的明确排查流程并自上而下去追进,避免有相似职能的技术团队互相推诿导致问题不能进一步明确。

内核问题排查步骤背景知识kdumpcentos操作系统kdump工具

kdump是系统崩溃的时候,用来转储运行内存的一个工具。系统一旦崩溃,内核就没法正常工作了,这个时候将由kdump提供一个用于捕获当前运行信息的内核,该内核会将此时内存中的所有运行状态和数据信息收集到一个dump core文件中以便之后分析崩溃原因。一旦内存信息收集完成,可以让系统将自动重启。kdump是RHEL5之后才支持的,2006被主线接收为内核的一部分。它的原理简单来说是在内存中保留一块区域,这块区域用来存放capture kernel,当production kernel发生crash的时候,通过kexec把保留区域的capure kernel给运行起来,再由捕获内核负责把产品内核的完整信息 - 包括CPU寄存器、堆栈数据等转储到指定位置的文件中。kdump工具的使用相关知识RHEL5开始,kexec-tools是默认安装的。如果需要调试kdump生成的vmcore文件,需要手动安装kernel-debuginfo包。

(1) 预留内存

可以修改内核引导参数,为启动捕获内核预留指定内存。在/etc/grub.conf (一般为/boot/grub/grub.conf的软链接)中:crashkernel=Y@X,Y是为kdump捕获内核保留的内存,X是保留部分内存的起始位置。默认为crashkernel=auto,可自行设定如crashkernel=256M。

(2) 配置文件

配置文件为/etc/kdump.conf,以下是几个常用配置:

# path /var/crash

默认的vmcore存放目录为/var/crash/%HOST-%DATE/包括两个文件:vmcore和vmcore-dmesg.txt

# ssh <user@service>

will copy /proc/vmcore to <user@server>:<path>/%HOST-%DATE/ via SSHmake sure user has necessary write permissions on server.

自动拷贝到远程机器上。

# default <reboot | halt | poweroff | shell | mount_root_run_init>Actions to perform in case dumping to intended target fails. 转储失败时执行。

(3) 启动服务

# chkconfig kdump on // 开机启动

# service kdump status // start、stop、restart等

kdump的执行流程背景知识crashcrash简介

当系统崩溃时,通过kdump可以获得当时的内存转储文件vmcore,但是该如何分析vmcore呢?crash是一个用于分析内核转储文件的工具,一般和kdump搭配使用。使用crash时,要求调试内核vmlinux在编译时带有-g选项,即带有调试信息。如果没有指定vmcore,则默认使用实时系统的内存来分析。值得一提的是,crash也可以用来分析实时的系统内存,是一个很强大的调试工具。crash使用gdb作为内部引擎,语法类似于gdb,命令的使用说明可以用<cmd> help来查看。使用crash需要安装crash工具包和内核调试信息包:crashkernel-debuginfo-commonkernel-debuginfocrash使用举例

(1) 错误类型 首先可以在vmcore-dmesg.txt中先查看错误类型,如:

1. divide error: 0000 [#1] SMP,除数为0造成内核崩溃,由1号CPU触发。

2. BUG: unable to handle kernel NULL pointer dereference at 000000000000012c,引用空指针。这样一来就能知道引发内核崩溃的错误类型。

(2) 错误地点 RIP为造成内核崩溃的指令,Call Trace为函数调用栈,通过RIP和Call Trace可以确定函数的调用路径,以及在哪个函数中的哪条指令引发了错误。

例如RIP为:[<ffffffff812cdb54>] ? tcp_enter_loss+0x1d3/0x23b[<ffffffff812cdb54>]是指令在内存中的虚拟地址。tcp_enter_loss是函数名(symbol)。0x1d3是这条指令相对于tcp_enter_loss入口的偏移,0x23b是函数编译成机器码后的长度。这样一来就能确定在哪个函数中引发了错误,以及错误的大概位置。Call Trace为函数的调用栈,是从下往上看的。可以用来分析函数的调用关系。

(4) crash常用命令

bt:打印函数调用栈,displays a task's kernel-stack backtrace,可以指定进程号

bt <pid>。

log:打印系统消息缓冲区,displays the kernel log_buf contents,如log | tail -n 30。

ps:显示进程的状态,>表示活跃的进程,如ps | grep RU。

sys:显示系统概况。

kmem -i:显示内存使用信息。

dis <addr>:对给定地址进行反汇编。

exception RIP即为造成错误的指令。

关于log命令:内核首先把消息打印到内核态的ring buffer,用户态的klogd负责读取并转发给syslogd,让它记录到磁盘。在内核崩溃时,可能无法把消息记录到磁盘,但是ring buffer中一般会有记录。所以log命令有时候能查看到系统日志中所缺失的信息。

生产环境debug crash步骤

1,安装crash工具:yum install crash

2,查看vmcore时内核的版本: crash -d7 vmcore 输出的信息中可以获取内核版本信息

3,安装对应的内核debug版本的rpm包,注意务必保证版本一致

kernel-debuginfo-3.10.0-229.el7.x86_64.rpm

kernel-debuginfo-common-x86_64-3.10.0-229.el7.x86_64.rpm

下载地址:

4,使用crash进行内核调试

crash /usr/lib/debug/lib/modules/3.10.0-327.13.1.el7.x86_64.debug/vmlinux /var/crash/127.0.0.1-2016-12-15-19\:22\:32/vmcore

5,使用crash常用的调试指令获取内核崩溃时的进程堆栈信息

6,经过排查发现内核崩溃的原因为:

7,确定crash的具体进程

通过crash中的ps指令发现触发内核崩溃的进程是docker进程但是其父进程不为1,说明中间可能由某个容器或者脚本调用了docker的指令,通过追溯其父进程的方式我们发现如下图所示的问题,所有的崩溃进程均可以追溯到zabbix_agent,于是从操作系统上zabbix的监控项中发现有一个docker_container.sh的监控脚本在作祟,因此目前触发崩溃的罪魁祸首已经找到即docker容器的监控脚本,但是追根问底这个问题产生的本质原因还是内核的问题,今天docker监控脚本触发了该bug,明天可能有其他的进程触发,所以只能寄希望官方kernel可以尽快修复。

监控脚本如下:

#!/bin/bash#***********************************************##        Filename: docker_container_status.sh##        Description: ---#        Create: 2016-06-01 10:59:48#        Last Modified: 2016-06-01 11:00:15#***********************************************:<<C$1 function name$2 container nameCctncpuper(){        sudo docker stats --no-stream  $1 | awk -F '  +' '$2 !~ /CPU/ {print $2}' | cut -d% -f1}ctnmem(){        sudo docker stats --no-stream  $1 | awk -F '  +' '$3 !~ /MEM/ {print $3}' | cut -d/ -f1}ctnmemper(){        sudo docker stats --no-stream  $1 | awk -F '  +' '$4 !~ /MEM/ {print $4}' | cut -d% -f1}ctnnetio(){        sudo docker stats --no-stream  $1 | awk -F '  +' '$5 !~ /NET/ {print $5}'}ctnblockio(){        sudo docker stats --no-stream  $1 | awk -F '  +' '$6 !~ /BLOCK/ {print $6}'}$1 $2
技术参考

Red_Hat_Enterprise_Linux-7-Kernel_Crash_Dump_Guide-en-US.pdf

Red_Hat_Enterprise_Linux-7-7.2_Release_Notes-zh-CN.pdf

华为服务器 操作系统 安装指南 08.pdf

CSDN关于内核debug步骤的讲解:

IBM关于内核debug的讲解:

标签: #centos7各种问题 #centos流量监控报警 #sstpcentos7 #centoscrash工具 #centos7服务器重启