systemd-logind高负载和内存泄漏问题排查
处理用户的一个线上虚拟机
systemd-logind异常消耗CPU资源的异常,记录相关的排查方法以及进一步的学习。
异常现象
top显示systemd-logind和dbus-daemon两个进程占用了接近100%的CPU资源
top - 18:09:08 up 39 days, 7:25, 2 users, load average: 3.37, 3.57, 3.59
Tasks: 127 total, 3 running, 124 sleeping, 0 stopped, 0 zombie
%Cpu(s): 49.9 us, 26.5 sy, 0.1 ni, 21.5 id, 0.0 wa, 0.0 hi, 2.0 si, 0.0 st
KiB Mem : 8010880 total, 461688 free, 4174468 used, 3374724 buff/cache
KiB Swap: 0 total, 0 free, 0 used. 2324852 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1334 root 20 0 809416 608856 1396 R 99.7 7.6 0:17.46 systemd-logind
420 dbus 20 0 30252 5144 1120 R 89.3 0.1 5198:35 dbus-daemon
5953 admin 20 0 4320808 2.126g 11648 S 79.7 27.8 291:06.39 java
6253 admin 20 0 84312 25208 1320 S 7.0 0.3 18:10.09 tengine
6252 admin 20 0 86360 24716 1320 S 6.0 0.3 18:19.18 tengine
17 root 20 0 0 0 0 S 5.7 0.0 194:55.55 rcuos/3ssh登陆非常缓慢,并且登陆后
sudo切换账号也非常缓慢(虽然vm的cpu分配了8个,从负载看还是有比较充裕的计算资源)
排查
检查服务
观察到上述
systemd-logind和dbus-daemon负载过高,观察这两个进程的堆栈
检查
dbus服务
可以安康到服务启动运行状态
检查
systemd-logind服务
也是启动运行状态
检查journel日志
systemd提供了非常好的日志检查功能命令journalctl
journalctl
检查journel日志,发现有大量的 systemd-logind.service watchdog timeout 以及 pam_systemd 创建会话时没有从消息总线接收到响应
通过
journalctl检查系统日志可以看到systemd-logind.service主进程被杀死重启
注意:这里可以看到systemd-logind.service主进程被杀死,并且不断被systemd再次启动。那么我们需要佩查为何操作系统要杀死systemd-logind。
持续观察针对某个服务的日志
journalctl提供了指定服务的日志观察方法:
这样可以只观察systmed-logind服务日志。
由于观察到
systemd-logind不断重启,我们来观察重启的规律:
可以看到每分钟都出现一次systemd-logind服务被杀死重启:
开启
journalctl -f动态查看日志,发现这个系统内存不足,导致不断有java和tengine和systemd-logind进程被oom杀死:
仔细检查发现
systemd-logind内存泄漏非常快,从top上查看,很快就达到了2G,导致被oom杀掉
使用valgrind排查内存泄漏
systemd-logind位于/usr/lib/systemd目录下,采用以下脚本替换
check_systemd-logind:
安装
回退
但是日志显示:
暂时没有找到排查方法
systemd的一些排查方法
systemd提供了一个非常好的工具可以观察cgroup的资源使用
以下观察到内存使用从6.8G突然降低到4.0G是因为systemd-logind被oom-kill导致:
systemd-analyze dump提供了dump信息
检查了CentOS的版本,发现原来alios 7.2已经把最新的CentOS 7.4所用的systemd版本backport回来的,最新的systemd版本就是 systemd-219-42.el7_4.4.x86_64.rpm
通过strace排查
strace 采用如下方法检查
systemd_logind进程访问系统函数情况
检查发现有大量的
然后出现不断重复的
通过
strace统计
可以大量的时间消耗在 recvmsg并且有接近1/6的调用错误,而且mkdir系统调用100%错误。
systemd的sessions
为何系统会有重复的
观察了 /run/systemd/sessions 目录下有大量的会话文件
注意,在/run/systemd/sessions目录下,有大量数字字符串命名的文件,以及以c开头的数字字符串命名的文件,其中部分文件还有一个配对的.ref后缀的文件,类似如下:
参考 help understand /var/run/systemd/sessions/2 file / or hacked?
我检查可以看到有2000+个.ref文件
但是,使用loginctl指令无法显示会话,显示消息总线响应超时(Failed to get session: Message did not receive a reply (timeout by message bus))
正常情况下loginctl是可以显示服务器会话的详细信息的,例如:
显然,上述异常服务器中会话管理出现了问题,特别明显的是 message bus 没有响应。
另外,我明白了,为何在前面 strace -c -p $systemd_logind_pid 会出现以下内容
原来这个"# This is private data. Do not p"实际上就是session文件开头的第一行:
也就是说,有大量的会话连接存在。
搜索到CentOS 7的一个bug报告 0014278: systemd update causes /run tmpfs to fill up with sessions,报告称升级了systemd之后/run/systemd/sessions堆积了大量会话文件,导致分区被占满。
类似检查了一下服务器
同样表明/run/systemd/sessions目录下会话文件没有清理。解决的方法是升级了systemd之后重启一次操作系统。
这个问题已经在systemd上游项目中发现,上游systemd版本已经修复。导致的原因是因为systemd丢失了dbus连接。
存在异常的centos 7 服务器,所有 ls -ld /run/systemd/system/session-*.scope* |wc -l 输出结果都是3万以上。
显示大量的用户会话都是root账号。
在 Bug 1439989 - why so many sessions scope file didn't been deleted? 说明在docker容器中,存在于/run/systemd/systme/目录下会有大量的session-xxx.scope.d文件和目录。而且这个bug报告的系统systemd和dbus版本恰恰和当前运行服务器版本相同:
这个bug说明中显示,systemd-219-19.el7_2.13容易有泄漏,并且参考 Leak of scope units slowing down "systemctl list-unit-files" and delaying logins #1961 可以看到完全相同的案例:
在
/run/systemd/system目录下有大量泄漏的scope unit文件PID 1使用了100% CPU资源并导致登陆延迟
使用journalctl -b -u systemd-logind观察。
参考 Raman Gupta 2017-04-28 13:24:58 EDT 在 Bug 1271394 - All logins, like ssh, sudo, su take many seconds 提供的解决方法
如果第一个命令systemctl daemon-reload失败,可以尝试一下命令重启:
删除session文件
删除session目录
然后删除abandoned sessions
最后再次尝试上述命令。
不过,实际验证发现
systemctl daemon-reload始终超时,无法正确完成。并且systemd-logind的负载不能下降。google发现CentOS的buglist中报告,当前版本的systemd升级后必须重启操作系统。只有上游的最新版本的systemd可以支持升级后无需重启操作系统。
升级systemd解决
systemd解决果然,升级以后重启操作系统,观察到恢复正常
并且 /run/systemd/sessions 目录下只有少量session
参考
Last updated
Was this helpful?