排查思路参考:https://mp.weixin.qq.com/s/3LEcc6ZZnw9dzaMBNROxrA

一、问题产生背景

我们在k8s里面搭了一套elk集群,使用nginx ingres将kibana,elasticsearch,logstash服务等代理出来,然后发现ingress内存和CPU使用异常高,可以把物理机的内存吃满,然后oom,又继续增长。见下图:

image-20210729110659435

临时解决办法,只能先将CPU内存限制在32C32G,但是依旧吃满32G内存,所以需要排查

image-20210730213825115

ingress容器里面dmesg显示OOM的信息,cgroup发现内存不足后,会选择一些进程kill掉

image-20210730214026879
image-20210730214105084

二、查看容器里面进程内存分配情况

image-20210730214219057

三、pmap命令查看nginx进程内存分配情况

pmap命令,gcore命令等都需要 特权模式下才可以正常执行。以特权模式,root身份进入ingress容器

(以下操作全部在容器内部进行)

~]$ docker exec -u root --privileged  -it 8e3 bash
# 分析107751这个进程的内存使用情况
~]$ pmap -x 107751 | less -N

可以看到有两块anon的东西占用了总共5个多g的内存

image-20210730214704833

四、定位内存泄露的地址范围

~]$ cat /proc/107751/smaps
image-20210730215027354

五、gcore转储内存映像及内存上下文

~]$ gcore 107751

这样就得到了一个core.107751的文件

注意: 一定要在容器里面执行,如果在容器外面执行会报下面这个错误:

~]$ gcore 834061
/usr/sbin/nginx: No such file or directory.
warning: Memory read failed for corefile section, 8192 bytes at 0xc1c9b000.
warning: Memory read failed for corefile section, 122880 bytes at 0xc1c9d000.
warning: Memory read failed for corefile section, 147456 bytes at 0xc1cbb000.
warning: Memory read failed for corefile section, 1048576 bytes at 0xc2751000.

六、使用gdb加载内存信息

~]$ gdb -core core.107751
image-20210730215525258

dump binary 导出泄露内存的内容 内存地址就是第四步拿到的那个内存地址

image-20210730215742126

七、分析二进制文件worker-pid.bin

可以直接使用hexdump命令来查看二进制文件

# -C表示输出格式为二进制+ASCII码的形式展示;-n 1000000表示只读取文件前1000000个字节
~]$ hexdump -C -n 1000000 worker-pid.bin &> worker.txt

然后就可以使用vim打开worker.txt文件了。

可以看到都是xxx:5044这些信息,这个是后端logstash的地址信息,因为是4层轮训的,所以显示的ip都不同

image-20210730220311446

并且在ingress日志里面,看到了ingress连接后端logstash的报错信息

image-20210730220610829

经过确认,后端logstash确实不通,导致大量的请求堆积在内存里面。 和ELK伙伴确认后,及时修复后端logstash问题,然后再观察ingress内存,终于恢复正常:

image-20210730220830894