前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >容器OOM问题排查思路

容器OOM问题排查思路

作者头像
SRE运维实践
发布2019-07-08 13:27:13
4.3K1
发布2019-07-08 13:27:13
举报
文章被收录于专栏:SRE运维实践SRE运维实践

序言

又是一个冬季,在这寒冷的冬季,总是让人心动。。。迷雾之城

外界的刁难,挑战。。。其实并不是最难的,最难的总是内部难以安抚,OOM。。。内存泄漏,OOM killer了解一下。。。攘外必先安内。。。我可能要死在内部了。。。

抛出一个问题:容器是否需要限制内存的使用,限制CPU的使用呢?

OOM排查

背景:

微服务架构,几百个服务,运行在不同的容器上,总是莫名的同时出现十几个服务不可用,伴随着各个容器的状态异常,无法ping通,无法ssh上去,大量告警。。。总是莫名的有物理机宕机,每次查的时候总是无疾而终。。。

验尸报告:

Emmm,故障现场不够新鲜,检查的力度不够。。。

故障之间总是有关联的,查出根本的问题之后,就发现,莫名的物理机宕机和这次发生的问题是一样的,只是原来从来没有想过,内存泄漏导致物理机重启,未曾进行关联,当查出每次都是OOM之后,那么问题就可以联系在一起,其实两者的问题的本质是一样的。

收到告警,大量服务出现单点,查看相关的告警信息,大量的容器无法ping通,伴随着load值告警,而且这些所有的容器都分布在一台物理机上,有部门的服务在慢慢的恢复。。。经常看到这种情况的发生,也麻木了,等一会儿,慢慢就会自动恢复的。。。

等了两个多小时,还没有恢复,依据以往的经验,这个时候应该已经恢复了。。。Emmm,经验往往是不可靠的,所谓的黑天鹅事件了解一下。。。

大量的容器无法ping通,登录上主机,查看资源抢占情况*(示例图):

在以上的图中,主要看四个指标,一个是load,Emmm,假设CPU是56个,实际的load值达到了3K,那么这个时候,系统已经不堪重负了;一个是Tasks,主要看任务的运行数量,在图中,才2个在运行,实际也就几百个,但是sleeping状态的有几万个,而zombie状态的有300多个;一个就是内存的使用量,在实际情况中,内存基本使用完毕;最后一个就是使用交换空间,图中的未使用,实际上已经全部使用完毕。

系统资源不足,要不扩容试试。。。向上?还是水平扩展。。。Emm,当然是不可能的。。。

CPU的load太高,那么说起来其实也就两个队列,一个是运行的队列,一个block的队列,从而需要收集相关的进程信息,从而可以使用ps来查看进程的状态信息:

以上主要是为了统计:一个是进程的数量,一个是线程的数量。。。(需要多次执行,从而进行对比,可以知道哪些进程造成了相关的阻塞,数量庞大的必有蹊跷。。),统计的结果是大量状态为D的进程。。。在线程多的结果中,可以看到相关的PID,从而可以知道是哪个进程产生了大量的阻塞。。。

统计容器的数量,从容器的内存限制来查看是否容器的内存都达到了限制。

在查看结果的时候,发现很多容器使用的内存值和限制值差不多一致,而且falcnt也就是分页中断有几万次。。。当然缺页异常几万次,可能或许maybe属于正常情况。。

保存进程列表(主要是保存进程的树形结构,可以用来追查父进程):

突然出现。。。fork,Can't allocate memory!。。至此已经无法查看相关信息,只能。。。重启服务器了。。。所有的内存已经耗尽。。。。

重启之后查看相关的日志:对。。。重启是万能的。。。

在日志里面查看到大量的OOM信息,也就可以看到相关的进程被杀死,从而可以找到是哪些进程导致了内存泄漏,从而进行整改。。。在kern日志中可以看到被杀死的进程名,在dmesg中可以看到OOM,在message中,能追查到相关的容器id。。。

排查思路:根据load值偏高,查询进程的数量和线程的数量,从而从增加的数量查看到是什么样的进程阻塞了CPU的调度,查看系统日志,主要查看oom,从而对比两者的结果进程是否一致,从而看哪个进程OOM需要整改。。。可能你会说,查看单独进程的内存占用量,Emmm,这也是一个排查思路。。。

风言风语

在以上的问题追踪中,可以产生两个疑点:第一既然oom都杀死了进程,为什么内存还会溢出,杀死了进程应该已经将相关的内存进行回收了;第二:是什么导致了那么高的load值。。。

回答第一个问题就是:在oom killer进行杀死进程的时候,使用的是kill -9 ,从而能强行杀死进程,但是在进行oom的时候,oom的分值是给占用内存大的进程,而这个进程在等待IO,也就是等待分配内存,Emm。。。读取内存也是一种IO,所谓的缺页中断。。。在杀死这个进程的时候,这个进程的状态为D,也就是表示这个进程是不可中断睡眠,在等待分配内存。。。从而杀死这个进程可能根本就无法杀死。。。

还有一种情况是,进程已经变成了僵尸进程,从而在oom killer在进行杀死进程的时候,根据当前的进程号id杀,而僵尸进程要想杀死,必须杀掉其父进程,而当僵尸进程的父进程为1的时候,这个时候就相当于服务器重启了。

回答第二个问题就是:将一个进程杀死,变成了僵尸进程,自动拉起进程并不能识别变成了僵尸进程,从而会自动拉起服务,然后又内存溢出,再次杀,再次变成僵尸进程,死循环,最终导致内存耗尽。。。

还有一种情况就是,在容器中运行了很多进程,而oom分值高的进程是其中的一个子进程,而不是容器的根进程,也就是pid为1的进程,如果恰好是1的进程,那么很完美,相当于将容器进行重启,那么这种情况下会慢慢的恢复,不会增加load值;而当是一个普通进程之后,杀掉,有很大的概率变成僵尸进程。。。

容器也是一个进程,在其中又有很多进程,资源隔离还不是那么好。。。原因之一也在于使用不当。

最后解答开篇的问题:要不要设置cpu和容器的最高使用值。。。要

如果在容器的层面进行限制了内存的使用,那么就只有容器出现OOM,而不会影响这台机器上其他的容器,不会出现资源竞争的情况。。。在查看容器oom的时候,也可以通过docker inspect id来查看容器的OOM。。。

风言风语

有些东西,明明知道是对的,却不能说。。。。因为绝对的对并不是对的。。。

然而,并不能忍住不能说,所以,很多事。。。雪上加霜。。。明明知道前面是坑,不说,你会掉下去,说了,你就怪我。。。怪我咯。。。

看过了那么多的算法,却还不能算好这一生。。。。

看过了那么多数据结构,却还不能组织好生活,工作。。。

看过了那么多设计模式,却还不能八面玲珑。。。

技术一途,要么是0,要么是1.。。。还不能将所有的组织好,是因为暴露了不该暴露的接口,暴露了太多的内部实现。。。这也就是为什么类也要有那么多标准,为什么要各种模块的使用。。。

入门不难,坚持最难。。。懂了不难,执行下去才难。。。嘴上说了不难,心里记住才难。。。那一丝风。。。

无论你懂得与否。。。不能回头。。。放弃是一种心魔。。。别样的风景,别样的修行。。。

僵尸进程最难管,太轻狂。。。哈哈。。。最近有朋友说,瞎逼逼个啥。。。Emmm,你们吓得我都不敢写了。。。哈哈。。。心里委屈,心酸,还没人安慰。。。看了那么多算法,我都没算好你们喜欢看啥。。。伤悲的时候莫要听慢歌。。。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-11-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 SRE运维实践 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档