【服务故障问题排查心得】「内存诊断系列」Docker 容器经常被 kill 掉,k8s 中该节点的 pod 也被驱赶,怎么分析?
背景介绍
最近的 docker 容器经常被 kill 掉,k8s 中该节点的 pod 也被驱赶。
我有一个在主机中运行的 Docker 容器(也有在同一主机中运行的其他容器)。该 Docker 容器中的应用程序将会计算数据和流式处理,这可能会消耗大量内存。
该容器会不时退出。我怀疑这是由于内存不足,但不是很确定。我需要找到根本原因的方法。那么有什么方法可以知道这个集装箱的死亡发生了什么?
容器层级判断检测
提到 docker logs container_id 以查看状态的详细信息,例如:
重要的一行是“ OOMKilled”,如果您超出了容器的内存限制,并且 Docker 杀死了您的应用程序,则该行将为 true。您可能还需要查找退出代码,以查看其是否标识出您的应用退出的原因。
Docker 内部,这仅表示 docker 本身是否会杀死您的进程,并要求您在容器上设置内存限制。
Docker 外部,如果主机本身内存不足,Linux 内核可以销毁进程。发生这种情况时,Linux 通常会在/ var / log 中写入日志。使用 Windows 和 Mac 上的 Docker Desktop,您可以在 docker 设置中调整分配给嵌入式 Linux VM 的内存。
可以通过阅读日志来了解容器内的进程是否被 OOM 杀死。OOMkill 是由内核启动的,因此每次发生时,都会在中包含很多行/var/log/kern.log,例如:
Linux 操作系统的进程服务发生被 killed 的原因是什么
在 Linux 中,经常会遇到一些重要的进程无缘无故就被 killed,而大多数的经验之谈就是系统资源不足或内存不足所导致的。
当 Linux 系统资源不足时,Linux 内核可以决定终止一个或多个进程,内存不足时会在系统的物理内存耗尽时触发 OOM killed,可以利用“dmesg | tail -N”命令来查看 killed 的近 N 行日志。
常规的宕机监控之类
在服务宕机或者重启之前我们的常规操作就是采用 ps 指令判定服务的增长趋势以及展示真实使用的资源的大小的前几位排名。
Linux 下显示系统进程的命令 ps,最常用的有 ps -ef 和 ps aux。这两个到底有什么区别呢?
ps -ef
指令代表着'SystemV 风格',而ps aux
代表着’BSD 风格‘。
由上图所示,可以分析出对应的数据结构模型。
其中 CPU 算是第 3 个位置、内存 MEM 算是第 4 个位置,虚拟内存 VSZ 是第 5 个位置,记住这个后面我们会使用这个方式进行排序。
查看当前系统内 CPU 占用最多的前 10 个进程(栏位属于第 3 个)
ps auxw 指令(BSD 风格)
u:以用户为主的格式来显示程序状况
x:显示所有程序,不以终端机来区分
w:采用宽阔的格式来显示程序状况
sort 排序指令
-n 是按照数字大小排序(-n 这代表着排除 n 行的操作处理),-r 是以相反顺序,-k 是指定需要排序的栏位
内存消耗最多的前 10 个进程(栏位属于第 4 个)
虚拟内存使用最多的前 10 个进程(栏位属于第 5 个)
去掉 x 参数的结果
stat 取值含义
dmesg 的命令分析
有几个工具/脚本/命令 可以更轻松地从该虚拟设备读取数据,其中最常见的是 dmesg 和 journalctl。
输入 dmesg 指令进行 egrep 正则表达式匹配 killed 的进程信息,将输出对应的进程信息。
或
以上的指令就可以输出最近 killed 的信息,其中-B100,表示 'killed process’之前的 100 行内容,与 head 的指令非常的相似。
如果我们看到了 oom-kill 的字样之后,就可以判断它是被内存不足所导致的 kill,oom-kill 之后,就是描述那个被 killed 的程序的 pid 和 uid。
total_vm 和 rss 的指标值
total_vm:总共使用的虚拟内存 Virtual memory use (in 4 kB pages),8117956/1024(得到 MB)/1024(得到 GB)=7.741GB
rss:常驻内存使用 Resident memory use (in 4 kB pages) 5649844/1024/1024=5.388GB
案例 1:查看到 pod 被驱赶的原因
案例 2:查看到 docker 容器被 kill 的原因
journalctl 命令 – 查看指定的日志信息
当内存不足时,内核会将相关信息记录到内核日志缓冲区中,该缓冲区可通过 /dev/kmsg 获得。除了上面的 dmesg 之外,还有一个 journalctl。
语法格式: journalctl [参数]
常用参数:
查看 Killed 日志
使用 sudo dmesg | tail -7 命令(任意目录下,不需要进入 log 目录,这应该是最简单的一种)而 journalctl 命令来自于英文词组“journal control”的缩写,其功能是用于查看指定的日志信息。
journalctl 指令介绍
在 RHEL7/CentOS7 及以后版本的 Linux 系统中,Systemd 服务统一管理了所有服务的启动日志,带来的好处就是可以只用 journalctl 一个命令,查看到全部的日志信息了。
查看所有日志(默认情况下 ,只保存本次启动的日志)
查看内核日志(不显示应用日志)
查看系统本次启动的日志
查看上一次启动的日志(需更改设置)
查看指定时间的日志
显示尾部的最新 10 行日志
显示尾部指定行数的日志
实时滚动显示最新日志
查看指定服务的日志
比如查看 docker 服务的日志
查看某个 Unit 的日志
实时滚动显示某个 Unit 的最新日志
合并显示多个 Unit 的日志
版权声明: 本文为 InfoQ 作者【洛神灬殇】的原创文章。
原文链接:【http://xie.infoq.cn/article/3dbdc83e67e3d78338f9a5d61】。文章转载请联系作者。
评论