内存使用差异:cgroup memory.usage_in_bytes vs.RSS 在 docker 容器内



"Kubernetes"(v1.10.2(说我的pod(包含一个容器(使用了大约5GB的内存。在容器内部,RSS更像是681MiB。任何小马都可以解释如何使用以下数据从 681MiB 到 5GB(或描述如何使用我省略的另一个命令弥补差异,无论是从容器还是从在 kubernetes 中运行此容器的 docker 主机(?

kubectl top pods 说 5GB:

% kubectl top pods -l app=myapp
NAME                             CPU(cores)   MEMORY(bytes)
myapp-56b947bf6d-2lcr7           39m          5039Mi

Cadvisor报告了类似的数字(可能来自略有不同的时间,所以请忽略微小的差异(:

container_memory_usage_bytes{pod_name=~".*myapp.*"}      5309456384
5309456384 / 1024.0 / 1024 ~= 5063 ~= 5039

在容器内部,此文件似乎是 cadvisor 获取其数据的位置:

% kubectl exec -it myapp-56b947bf6d-2lcr7 bash
meme@myapp-56b947bf6d-2lcr7:/app# cat /sys/fs/cgroup/memory/memory.usage_in_bytes
5309456384

容器内的驻留集大小 (RSS( 不匹配(小于 1GB(:

meme@myapp-56b947bf6d-2lcr7:/app# kb=$(ps aux | grep -v grep | grep -v 'ps aux' | grep -v bash | grep -v awk | grep -v RSS | awk '{print $6}' | awk '{s+=$1} END {printf "%.0f", s}'); mb=$(expr $kb / 1024); printf "Kb: $kbnMb: $mbn"
Kb: 698076
Mb: 681

完整的 ps aux 如果有帮助:

meme@myapp-56b947bf6d-2lcr7:/app# ps aux | grep -v grep | grep -v 'ps aux' | grep -v bash | grep -v awk
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
meme         1  0.0  0.0 151840 10984 ?        Ss   Jun04   0:29 /usr/sbin/apache2 -D FOREGROUND
www-data    10  0.0  0.0 147340  4652 ?        S    Jun04   0:00 /usr/sbin/apache2 -D FOREGROUND
www-data    11  0.0  0.0 148556  4392 ?        S    Jun04   0:16 /usr/sbin/apache2 -D FOREGROUND
www-data    12  0.2  0.0 2080632 11348 ?       Sl   Jun04  31:58 /usr/sbin/apache2 -D FOREGROUND
www-data    13  0.1  0.0 2080384 10980 ?       Sl   Jun04  18:12 /usr/sbin/apache2 -D FOREGROUND
www-data    68  0.3  0.0 349048 94272 ?        Sl   Jun04  47:09 hotapp
www-data   176  0.2  0.0 349624 92888 ?        Sl   Jun04  43:11 hotapp
www-data   179  0.2  0.0 349196 94456 ?        Sl   Jun04  42:20 hotapp
www-data   180  0.3  0.0 349828 95112 ?        Sl   Jun04  44:14 hotapp
www-data   185  0.3  0.0 346644 91948 ?        Sl   Jun04  43:49 hotapp
www-data   186  0.3  0.0 346208 91568 ?        Sl   Jun04  44:27 hotapp
www-data   189  0.2  0.0 350208 95476 ?        Sl   Jun04  41:47 hotapp

docker 的容器统计信息 API 中的内存部分:

curl --unix-socket /var/run/docker.sock 'http:/v1.24/containers/a45fc651e7b12f527b677e6a46e2902786bee6620484922016a135e317a42b4e/stats?stream=false' | jq . # yields:
"memory_stats": {
"usage": 5327712256,
"max_usage": 5368344576,
"stats": {
"active_anon": 609095680,
"active_file": 74457088,
"cache": 109944832,
"dirty": 28672,
"hierarchical_memory_limit": 5368709120,
"inactive_anon": 1687552,
"inactive_file": 29974528,
"mapped_file": 1675264,
"pgfault": 295316278,
"pgmajfault": 77,
"pgpgin": 85138921,
"pgpgout": 84964308,
"rss": 605270016,
"rss_huge": 0,
"shmem": 5513216,
"total_active_anon": 609095680,
"total_active_file": 74457088,
"total_cache": 109944832,
"total_dirty": 28672,
"total_inactive_anon": 1687552,
"total_inactive_file": 29974528,
"total_mapped_file": 1675264,
"total_pgfault": 295316278,
"total_pgmajfault": 77,
"total_pgpgin": 85138921,
"total_pgpgout": 84964308,
"total_rss": 605270016,
"total_rss_huge": 0,
"total_shmem": 5513216,
"total_unevictable": 0,
"total_writeback": 0,
"unevictable": 0,
"writeback": 0
},
"limit": 5368709120
},

对 https://github.com/google/cadvisor/issues/638 的评论断言:

总计 (memory.usage_in_bytes( = RSS + 缓存

https://www.kernel.org/doc/Documentation/cgroup-v1/memory.txt 说:

usage_in_bytes:为了提高效率,与其他内核组件一样,内存 cgroup 使用了一些优化 以避免不必要的缓存行错误共享。usage_in_bytes受到 方法,并且不显示内存(和交换(使用情况的"精确"值,它是一个模糊 高效访问的价值。(当然,必要时,它是同步的。 如果你想更确切地了解内存使用情况,你应该使用 RSS+CACHE(+SWAP( 内存中的值.stat(参见 5.2(。

https://docs.docker.com/engine/reference/commandline/stats/#parent-command 说:

注意:在 Linux 上,Docker CLI 通过从总内存使用量中减去页面缓存使用情况来报告内存使用情况。API 不执行此类计算,而是提供总内存使用量和页面缓存量,以便客户端可以根据需要使用数据。

事实上,容器中/sys/fs/cgroup/memory/memory.stat 中的大多数内容都显示在上面的 docker stats api 响应中(对不起,与在不同时间取样略有不同(:

meme@myapp-56b947bf6d-2lcr7:/app# cat /sys/fs/cgroup/memory/memory.stat
cache 119492608
rss 607436800
rss_huge 0
shmem 5525504
mapped_file 1675264
dirty 69632
writeback 0
pgpgin 85573974
pgpgout 85396501
pgfault 296366011
pgmajfault 80
inactive_anon 1687552
active_anon 611213312
inactive_file 32800768
active_file 81166336
unevictable 0
hierarchical_memory_limit 5368709120
total_cache 119492608
total_rss 607436800
total_rss_huge 0
total_shmem 5525504
total_mapped_file 1675264
total_dirty 69632
total_writeback 0
total_pgpgin 85573974
total_pgpgout 85396501
total_pgfault 296366011
total_pgmajfault 80
total_inactive_anon 1687552
total_active_anon 611213312
total_inactive_file 32800768
total_active_file 81166336
total_unevictable 0

来自kubectl describe pod <pod>的内存信息:

Limits:
memory:  5Gi
Requests:
memory:   4Gi

这是pmap在容器内说的话。在这个单行中,我获取所有进程 ID,对它们运行 pmap -x,并从 pmap 结果中提取 KB 列。总结果是 256 兆字节(部分小于 ps 的 RSS,我认为部分,因为许多进程不返回 pmap -x 的输出(:

ps aux | awk '{print $2}' | grep -v PID | xargs sudo pmap -x | grep total | grep -v grep | awk '{print $3}' | awk '{s+=$1} END {printf "%.0f", s}'; echo
256820

ps_mem.py在 https://stackoverflow.com/a/133444/6090676 中提到。它检查/proc/$pid/statm/proc/$pid/smaps。这里没有照明(同样,它似乎忽略了一些过程(:

# python ps_mem.py
Private  +   Shared  =  RAM used    Program
1.7 MiB +   1.0 MiB =   2.7 MiB   apache2
2.0 MiB +   1.0 MiB =   3.0 MiB   bash (3)
---------------------------------
5.7 MiB
=================================

在 cadvisor 错误报告容器内存使用情况中还有另一个与此类似的问题(但信息较少(。谢谢!

我不知道你是否已经找到了答案,但让我给你一些可能会有所帮助的信息。

  • cAdvisor 提取了许多与内存相关的指标。我们将专注于:

    1. container_memory_usage_bytes=/sys/fs/cgroup/memory/memory.usage_in_bytes 文件中的值。(内存的使用(

    2. container_memory_working_set_bytes=container_memory_usage_bytes-total_inactive_file(来自/sys/fs/cgroup/memory/memory.stat(,这是在 cAdvisor 中计算的,<=container_memory_usage_bytes

    3. container_memory_rss= 来自/sys/fs/cgroup/memory/memory.stat 的total_rss

  • 现在您知道了这些指标是如何收集的,您需要知道,当您使用kubectl top pods命令时,您将获得container_memory_working_set_bytes而不是container_memory_usage_bytes指标的值。

    所以从你的价值观来看:

    5039Mi "工作集 来自 kubectl 命令" ~= 5064 "来自内存.usage file" - 28 "来自 docker 容器统计 API 的内存部分total_inactive_file">

  • 还值得一提的是,当container_memory_usage_bytes的值达到极限时,您的 Pod 不会被杀死。但是,如果达到container_memory_working_set_bytescontainer_memory_rss极限,吊舱将被杀死。

我没有看到你在这里检查的一件事是内核内存。 这在memory.usage_in_bytes图中也有说明,但没有出现在memory.stat中。 你可以通过查看找到/sys/fs/cgroup/memory/memory.kmem.usage_in_bytes.

我曾经看到我们的一个 .NET core 应用程序发生了类似的事情,但我无法弄清楚到底发生了什么(可能是 .NET core 中的内存泄漏,因为它是我们的应用程序无法控制的非托管内存(。

也许这对你来说是另一个面包屑。 这取决于您的应用程序是否正常使用,但就 cgroups 而言,我相信默认情况下内核内存使用不受约束。

最新更新