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. Java——IO流 对象的序列化和反序列化流ObjectOutputStream和ObjectInputStream

    对象的输入输出流 : 主要的作用是用于写入对象信息与读取对象信息. 对象信息一旦写到文件上那么对象的信息就可以做到持久化了 对象的输出流: ObjectOutputStream 对象的输入流:  Ob ...

  2. Error occurred during initialization of VM Could not reserve enough space for object heap

    Error occurred during initialization of VM Could not reserve enough space for object heap Java虚拟机(JV ...

  3. 缓冲区 subprocess 黏包 黏包的解决方案

    缓冲区: 将程序和网络解耦输入缓冲区输出缓冲区 print('>>>>', server.getsockopt(SOL_SOCKET, SO_SNDBUF)) 查看输出缓冲区大 ...

  4. Android 开发 PopupWindow弹窗

    简介 PopupWindow,顾名思义弹窗.PopupWindow是与AlertDialog在形式上类似的弹窗功能,都是为了在activity最上层显示一个弹窗.但是区别是PopupWindow可以自 ...

  5. python调用GDAL实现几何校正

    引自https://blog.csdn.net/qq_27045589/article/details/81062586 def main(): infile = "F:\\Temp_Dat ...

  6. for循环,while循环,do while循环

    for循环: for循环格式: for(初始化语句;判断条件语句;控制条件语句) { 循环体语句; } 例子:取五位数各个位数的练习 public static void main(String[] ...

  7. 36_react_ui_antd

    1:最流行的开源react ui组件库 1.1:material-ui(国外) 1.2:ant-design(推荐:国内蚂蚁金服) 2.如何使用 方式一(页面引入): 在<head>标签内 ...

  8. ESLint具体规则设置

    "no-alert": 0,//禁止使用alert confirm prompt "no-array-constructor": 2,//禁止使用数组构造器 & ...

  9. elk报警监控之sentinl 钉钉+邮件告警

    注:我的elk sentinl版本都是6.5.1 前期知识 es的查询语法.es watcher使用方法. https://www.cnblogs.com/pilihaotian/p/5830754. ...

  10. 使用hexo在GitHub上无法上传博客

    原以为是秘钥或者其他错误,后来发现是邮箱设置的问题 在GitHub的你账号网页上右上角,个人的登录退出的位置,找到setting: setting->emails->Keep my ema ...