linux内存黑洞

时间:2022-09-25 22:57:07

1.问题

k8s集群中node节点的内存使用率居高不下,使用率达到90%多。通过以下命令可以发现此虚拟机分配的内存为15g,但是用户进程使用的内存总共为7个多g,并且slab和pageTables使用的内存为191868 kB和38316 kB。那么其它内存去哪了呢?

通过free命令查看内存情况:

[root@node158 vmware-root]# free -h
              total        used        free      shared  buff/cache   available
Mem:            15G         13G        325M         45M        1.7G        1.6G
Swap:            0B          0B          0B

查看所有进程耗损的内存情况:

[root@node158 vmware-root]# ps aux | awk '{sum+=$6} END {print sum / 1024}'
7349.84

查看所有进程损耗内存的详细情况:

[root@node158 vmware-root]# ps aux --sort -rss
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root     24477 28.5  9.1 3400528 1489188 ?     Sl   16:17  11:15 /usr/lib/jvm/default-jvm/jre/bin/java -server -Dinstall4j.jvmDir=/usr/lib/jvm/default-jvm/jre -Dexe4j.modu
mysql    14118  1.0  4.8 2233732 786604 ?      Ssl  13:08   2:28 /usr/lib/jvm/default-jvm/jre/bin/java -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=75 -XX:+U
root      1558  4.4  3.1 1215760 512796 ?      Ssl  813  65:28 kube-apiserver --insecure-port=0 --allow-privileged=true --kubelet-preferred-address-types=InternalIP,Ext
mysql    13524  0.7  3.1 1962088 510356 ?      Ssl  13:08   1:47 /usr/lib/jvm/default-jvm/jre/bin/java -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=75 -XX:+U
mysql    13567  0.6  3.0 1953412 496228 ?      Ssl  13:08   1:24 /usr/lib/jvm/default-jvm/jre/bin/java -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=75 -XX:+U
root     32057  0.1  2.5 2328428 422840 ?      Sl   813   1:39 java -Xmx700m -Djava.security.egd=file:/dev/./urandom -jar /app.jar
root     29612  0.2  1.4 3587588 231812 ?      Sl   09:20   0:55 java -Xmx64m -Dservice.a.url=http://service-a:8081/sa/info -Dservice.c.url=http://service-c:8083/sc/info -
root     27337  0.8  1.3 293024 214160 ?       Ssl  13:39   1:38 /usr/local/bin/mixs server --address unix:///sock/mixer.socket --configStoreURL=k8s:// --configDefaultName
root     29237  0.1  1.3 3587592 212328 ?      Sl   09:20   0:53 java -Xmx64m -Dservice.b.url=http://service-b:8082/sb/info -Dapp.version=v1 -Djava.security.egd=file:/dev/
root     29285  0.2  1.2 3584408 205916 ?      Sl   09:20   0:56 java -Xmx64m -Dapp.version=v1 -Djava.security.egd=file:/dev/./urandom -jar /app.jar
root     29117  0.2  1.2 3586412 200948 ?      Sl   09:20   0:55 java -Xmx64m -Dapp.version=v1 -Djava.security.egd=file:/dev/./urandom -jar /app.jar
root     27327  0.4  0.9 241136 161644 ?       Ssl  13:39   0:59 /usr/local/bin/mixs server --address unix:///sock/mixer.socket --configStoreURL=k8s:// --configDefaultName
root      1568  5.1  0.8 891020 144348 ?       Ssl  813  75:34 kubelet --resolv-conf=/etc/resolv.conf --allow-privileged=true --cluster-domain=dinfo.cn --v=2 --cadvisor
root      1599  2.8  0.8 10642544 136372 ?     Ssl  813  41:24 /usr/local/bin/etcd --peer-client-cert-auth --client-cert-auth --initial-cluster-token=etcd-cluster-1 --l
root       519  0.3  0.7 199032 128200 ?       Ss   813   4:33 /usr/lib/systemd/systemd-journald
root      1022  2.2  0.7 2255380 115880 ?      Ssl  813  33:08 /usr/bin/dockerd-current --add-runtime docker-runc=/usr/libexec/docker/docker-runc-current --default-runt
mysql    13411  0.4  0.6 1264468 106824 ?      Ssl  13:08   1:03 /usr/share/kibana/bin/../node/bin/node --no-warnings /usr/share/kibana/bin/../src/cli --cpu.cgroup.path.ov
root      9395 12.2  0.6 157332 98516 ?        Ssl  09:48  52:25 /usr/local/bin/pilot-discovery discovery
root      1026  0.0  0.4 575420 69036 ?        Ssl  813   1:02 /usr/sbin/rsyslogd -n
root     29385  0.2  0.3 290352 51328 ?        Sl   13:01   0:33 /usr/bin/ruby2.3 /usr/local/bin/fluentd --no-supervisor -q
1337     14023  0.4  0.2 181992 41328 ?        Sl   09:51   1:59 /usr/local/bin/envoy -c /etc/istio/proxy/envoy-rev2.json --restart-epoch 2 --drain-time-s 45 --parent-shut
1337     15190  0.4  0.2 181988 40780 ?        Sl   09:51   2:00 /usr/local/bin/envoy -c /etc/istio/proxy/envoy-rev2.json --restart-epoch 2 --drain-time-s 45 --parent-shut
1337     14153  0.4  0.2 181992 40724 ?        Sl   09:51   1:55 /usr/local/bin/envoy -c /etc/istio/proxy/envoy-rev2.json --restart-epoch 2 --drain-time-s 45 --parent-shut
1337     14845  0.4  0.2 181988 40576 ?        Sl   09:51   1:56 /usr/local/bin/envoy -c /etc/istio/proxy/envoy-rev2.json --restart-epoch 2 --drain-time-s 45 --parent-shut
1337     12459  0.5  0.2 173596 39728 ?        Sl   09:50   2:11 /usr/local/bin/envoy -c /etc/istio/proxy/envoy-rev3.json --restart-epoch 3 --drain-time-s 45 --parent-shut
root      1580  0.9  0.2 503816 34440 ?        Ssl  813  13:51 kube-scheduler --kubeconfig=/etc/kubernetes/ssl/kubecfg-kube-scheduler.yaml --leader-elect=true --v=2 --a
104      18312  0.1  0.2 590056 32700 ?        Ssl  14:07   0:10 /usr/sbin/grafana-server --homepath=/usr/share/grafana --config=/etc/grafana/grafana.ini cfg:default.log.m
nfsnobo+ 23768  0.0  0.1 377372 32364 ?        Sl   15:38   0:00 nginx: worker process
nfsnobo+ 23769  0.0  0.1 377372 30484 ?        Sl   15:38   0:00 nginx: worker process
nfsnobo+ 23770  0.0  0.1 377372 30484 ?        Sl   15:38   0:00 nginx: worker process
nfsnobo+ 23918  0.0  0.1 377372 30484 ?        Sl   15:38   0:00 nginx: worker process
root     27380  0.2  0.1  50748 28708 ?        Ssl  13:39   0:31 /nginx-ingress-controller --default-backend-service=ingress-nginx/default-http-backend --configmap=ingress
root     28361  5.1  0.1  47392 27724 ?        Sl   13:40  10:00 calico-felix
root      1569  0.1  0.1 495620 27436 ?        Ssl  813   2:43 kube-proxy --v=2 --healthz-bind-address=0.0.0.0 --cluster-cidr=10.42.0.0/16 --hostname-override=192.168.1
root     27447  0.0  0.1 115096 26200 ?        S    13:39   0:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
root      1593  0.0  0.1 502244 22716 ?        Ssl  813   0:32 kube-controller-manager --kubeconfig=/etc/kubernetes/ssl/kubecfg-kube-controller-manager.yaml --enable-ho
root     10890  0.2  0.1 152020 22160 ?        Sl   09:49   0:56 /usr/local/bin/envoy -c /etc/istio/proxy/envoy.yaml --restart-epoch 1 --drain-time-s 2 --parent-shutdown-t
root      9494  0.1  0.1 152020 20848 ?        Sl   09:48   0:43 /usr/local/bin/envoy -c /etc/istio/proxy/envoy.yaml --restart-epoch 0 --drain-time-s 2 --parent-shutdown-t
root     11294  0.1  0.1 152024 20820 ?        Sl   09:49   0:46 /usr/local/bin/envoy -c /etc/istio/proxy/envoy.yaml --restart-epoch 1 --drain-time-s 2 --parent-shutdown-t
root      2324  0.0  0.1 791756 16580 ?        Ssl  813   0:38 agent
[root@node158 vmware-root]# cat /proc/meminfo
MemTotal:       16267364 kB
MemFree:          238452 kB
MemAvailable:    1543876 kB
Buffers:             264 kB
Cached:          1552232 kB
SwapCached:            0 kB
Active:          7408296 kB
Inactive:         836604 kB
Active(anon):    6719740 kB
Inactive(anon):    19604 kB
Active(file):     688556 kB
Inactive(file):   817000 kB
Unevictable:           0 kB
Mlocked:               0 kB
SwapTotal:             0 kB
SwapFree:              0 kB
Dirty:             36204 kB
Writeback:             0 kB
AnonPages:       6692544 kB
Mapped:           340872 kB
Shmem:             46896 kB
Slab:             191868 kB
SReclaimable:     107296 kB
SUnreclaim:        84572 kB
KernelStack:       30032 kB
PageTables:        38316 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:     8133680 kB
Committed_AS:   16685588 kB
VmallocTotal:   34359738367 kB
VmallocUsed:      173828 kB
VmallocChunk:   34359339004 kB
HardwareCorrupted:     0 kB
AnonHugePages:   1619968 kB
CmaTotal:              0 kB
CmaFree:               0 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB
DirectMap4k:      362432 kB
DirectMap2M:     8026112 kB
DirectMap1G:    10485760 kB

2.相关技术概念

2.1. memory balloon

通常来说,要改变客户机占用的宿主机内存,是要先关闭客户机,修改启动时的内存配置,然后重启客户机才能实现。而内存的ballooning(气球)技术可以在客户机运行时动态地调整它所占用的宿主机内存资源,而不需要关闭客户机。

Ballooning技术形象地在客户机占用的内存中引入气球(Balloon)的概念,气球中的内存是可以供宿主机使用的(但不能被客户机访问或使用),所以,当宿主机内存使用紧张,空余内存不多时,可以请求客户机回收利用已分配给客户机的部分内存,客户机就会释放其空闲的内存,此时若客户机空闲内存不足,可能还会回收部分使用中的内存,可能会换出部分内存到客户机的交换分区(swap)中,从而使得内存气球充气膨胀,从而让宿主机回收气球中的内存可用于其他进程(或其他客户机)。反之,当客户机中内存不足时,也可以让客户机的内存气球压缩,释放出内存气球中的部分内存,让客户机使用更多的内存。

2.2.Memory Limit

Memory Limit,顾名思义,内存上限,就是Host可以分配给此VM的pRAM数的上限。
默认情况下是选中unlimited复选框的,也就是不设上限。不设上限不意味着没有上限,隐含的上限值是分配给VM的内存值。

Q: 什么情况下要设置Memory Limit呢?(或者说Memory Limt有什么好处?)
A: 一般情况下不用设置Memory Limt。

Limit通常用来管理用户预期。开始的时候,Host上的VM数量比较少,没有资源争用,因此VM的性能完全可以保证;随后,当一台又一台VM创建出来,对于资源的争用渐渐变的频繁起来。于是VM的性能下降了,用户便会产生抱怨。因此,设置limit可以从一开始就限定VM的性能,也就是让用户一开始就觉得他的VM就应该是这样的性能,当VM数量增加的时候,也不会感觉到性能的下降。当然,Memory
Limit设置在什么数值比较合理应该具体情况具体分析。
那为啥不把VM的内存(Configured

Size)设小呢?这也是考虑用户心理。有用户会觉得自己的应用就是需要4GB内存,虽然我们经过分析得出的结论是只需要1GB内存就够了,但是为了考虑用户的感受,就给他设置VM的内存为4GB,于是用户看见自己的OS显示有4GB内存,就很满意,但是他不知道的是我们给他的VM设置了1GB
的Memory Limt,这样,既保证了Host的资源可以更合理的利用,又让用户感到满意。

当用户的应用越来越频繁,其对内存的需求增加的时候,这时再来调整Memory
limt,以满足其对性能的要求。调整Memory
Limt无需停机,而如果开始时虚拟机的内存设的小了,此时调整内存数量就要停机了。设置Memory
limt的好处就在于减少了不必要的downtime。
调整memory limit的动作,其实就是通知Hypervisor将某一VM可用的pRAM放大,而无需通知GOS,所以无需GOS重启。(简单的说,就是改Hypervisor,而和GOS无关)
专用名词解释 Configured Size
Configured
Size可以翻译成配置内存,就是用户在创建一个VM的时候设定的内存值,也是Guest OS认为自己拥有的内存值。Configured
Size在VM看来就是自己可用内存的总量,有的时候我们也称之为Guest Physical Memory。

3.原因

 由于VMWare的工具Memory Balloon,在ESX接近物理内存不足时对其进行保护。会对内存进行限制,但是在虚拟机内存使用率很高的情况下没有自动扩容限制,使得本来分配的内存不能全部进行利用。使得157和158两台机器内存使用一直居高不下,达到90%多。
    例如:
      192.168.181.158机器分配了总内存为15G,但是memory balloon进行了内存限制8759M。最终程序可用内存为8759M.
 
     
[root@node158 vmware-root]# vmware-toolbox-cmd stat memlimit
8759 MB
[root@node158 vmware-root]# vmware-toolbox-cmd stat balloon
7097 MB

4.解决方案

vmware 设置memory limit大小为分配给此虚拟机的大小。这样就可以避免认为用户进程占用太多的内存资源,实际上却没有使用这么多的内存资源的问题。

参考资料:

https://blog.csdn.net/xiaoxinyu316/article/details/42581785/

https://blog.csdn.net/liukuan73/article/details/47044141

linux内存黑洞的更多相关文章

  1. Linux内存都去哪了:(1)分析memblock在启动过程中对内存的影响

    关键词:memblock.totalram_pages.meminfo.MemTotal.CMA等. 最近在做低成本方案,需要研究一整块RAM都用在哪里了? 最直观的的就是通过/proc/meminf ...

  2. 死磕内存篇 --- JAVA进程和linux内存间的大小关系

    运行个JAVA 用sleep去hold住 package org.hjb.test; public class TestOnly { public static void main(String[] ...

  3. 浅谈Linux内存管理机制

    经常遇到一些刚接触Linux的新手会问内存占用怎么那么多?在Linux中经常发现空闲内存很少,似乎所有的内存都被系统占用了,表面感觉是内存不够用了,其实不然.这是Linux内存管理的一个优秀特性,在这 ...

  4. linux内存管理

    一.Linux 进程在内存中的数据结构 一个可执行程序在存储(没有调入内存)时分为代码段,数据段,未初始化数据段三部分:    1) 代码段:存放CPU执行的机器指令.通常代码区是共享的,即其它执行程 ...

  5. Linux 内存管理

    查看Linux内存使用情况 free -m Linux内存清理:绝大多数情况下都不需要此操作,因为cache的内存在需要的时候是可以自动释放的- 最好先sync几次,再清理内存,有下面三个级别,数值越 ...

  6. MySQL 调优基础(二) Linux内存管理

    进程的运行,必须使用内存.下图是Linux中进程中的内存的分布图: 其中最重要的 heap segment 和 stack segment.其它内存段基本是大小固定的.注意stack是向低地址增长的, ...

  7. Linux内存管理原理

    本文以32位机器为准,串讲一些内存管理的知识点. 1. 虚拟地址.物理地址.逻辑地址.线性地址 虚拟地址又叫线性地址.linux没有采用分段机制,所以逻辑地址和虚拟地址(线性地址)(在用户态,内核态逻 ...

  8. linux内存分配

    在linux的内存分配机制中,优先使用物理内存,当物理内存还有空闲时(还够用),不会释放其占用内存,就算占用内存的程序已经被关闭了,该程序所占用的内存用来做缓存使用,对于开启过的程序.或是读取刚存取过 ...

  9. 了解linux内存管理机制(转)

    今天了解了下linux内存管理机制,在这里记录下,原文在这里http://ixdba.blog.51cto.com/2895551/541355 根据自己的理解画了张图: 下面是转载的内容: 一 物理 ...

随机推荐

  1. 有关bootstrap之排版

    1.标题 HTML中的所有标题标签,从<h1> 到 <h6> 均可用.另外,还提供了.h1 到.h6 class,为的是给inline属性的文本赋予标题的样式. 在标题内还可以 ...

  2. javascript函数声明方式

    javascript中函数的声明有三种方式: 最常见的函数声明: fun();//可以调用,因为这种声明方式会被浏览器优先加载. function fun() { alert("声明式的函数 ...

  3. Java中UIManager的几种外观的详细讲解

    Java'中的几种Look and Feel 1.Metal风格 (默认) String lookAndFeel = "javax.swing.plaf.metal.MetalLookAnd ...

  4. C&num;保存登录用户名供其他页面调用

    一.保存登录用户名供其他页面调用 步骤: (1)项目自带的Program.cs,类方法里定义登录的用户名为全局变量loginid,这样整个项目都可以调用它 static class Program { ...

  5. php和apache安装心得

    又一次安装apache和php~~ 又一次心碎的体验~ 本想参考之前的apache配置之间进行安装(在windows 下编辑,然后传到linux上),怎耐,一直有问题,打开浏览器直接进行下载.发现是浏 ...

  6. 使用pdb调试python

    python pdb调试 python -m pdb myscript.py #注意这会重启myscript.py,这样启动的话,代码每一行都是一个节点 也可以在程序中这么设置断点: import p ...

  7. JavaBean中DAO设计模式介绍&lpar;转&rpar;

    一.信息系统的开发架构 客户层-------显示层-------业务层---------数据层---------数据库 1.客户层:客户层就是客户端,简单的来说就是浏览器. 2.显示层:JSP/Ser ...

  8. gnuplot使用

    直接用yum安装gnuplot即可,例如 sudo sh -c "yum install gnuplot.x86_64 " 安装以后就可以使用了 编写gnuplot脚本 # grp ...

  9. Objective-C开发编码规范:4大方面解决开发中的规范性问题

    Objective-C 编码规范,内容来自苹果.谷歌的文档翻译,自己的编码经验和对其它资料的总结. 概要 Objective-C 是一门面向对象的动态编程语言,主要用于编写 iOS 和 Mac 应用程 ...

  10. H5 页面调试小帮手-UC 开发者工具

    调试web页面难 接触过app自动化的同学都比较清楚,如果想要对web应用或者Hybrid应用进行调试时(获取页面元素信息等等),必定绕不开的就是chrome浏览器的inspect功能了:在chrom ...