POD 内存利用率和 RSS 与 Node 的差异 ps

Discrepancy in POD memory utilization and RSS from Node's ps

我已经在我的 K8s 集群(版本 1.15)中部署了 metrics-server
我认为这是执行简单内存利用率检查的标准方法

我有一个包含多个进程的 POD(用 dumb-init 包装以便进程收割)

我想知道我的 POD 当前确切的内存使用情况。

输出kube-capacity --util --pods

NODE      NAMESPACE           POD                               CPU REQUESTS   CPU LIMITS   CPU UTIL      MEMORY REQUESTS   MEMORY LIMITS   MEMORY UTIL
sj-k8s1   kube-system         kube-apiserver-sj-k8s1            250m (6%)      0m (0%)      77m (1%)      0Mi (0%)          0Mi (0%)        207Mi (2%)

...
sj-k8s3   salt-provisioning   salt-master-7dcf7cfb6c-l8tth      0m (0%)        0m (0%)      220m (5%)     1536Mi (19%)      3072Mi (39%)    1580Mi (20%)

显示 salt-master POD 当前使用 ~1.6Gi,kubeapi 使用 ~200Mi

但是在 sj-k8s3 上执行命令 ps aux | awk ' ~ /salt-master/ {sum += } END {print sum}'(来自 PS 输出的 RSS 总和):

2051208

也就是~2Gi,/sys/fs/cgroup/memory/memory.stats的输出:

cache 173740032
rss 1523937280
rss_huge 0
shmem 331776
mapped_file 53248
dirty 4096
writeback 0
pgpgin 34692690
pgpgout 34278218
pgfault 212566509
pgmajfault 6
inactive_anon 331776
active_anon 1523916800
inactive_file 155201536
active_file 18206720
unevictable 0
hierarchical_memory_limit 2147483648
total_cache 173740032
total_rss 1523937280
total_rss_huge 0
total_shmem 331776
total_mapped_file 53248
total_dirty 4096
total_writeback 0
total_pgpgin 34692690
total_pgpgout 34278218
total_pgfault 212566509
total_pgmajfault 6
total_inactive_anon 331776
total_active_anon 1523916800
total_inactive_file 155201536
total_active_file 18206720
total_unevictable 0

这个POD实际上包含两个docker个容器,所以RSS的实际总和是:

2296688

更大:2.3Gi

在 apiserver 节点上,仅执行 ps aux 显示进程 RSS 是:447948 /sys/fs/cgroup/memory/memory.stats的输出:

cache 78499840
rss 391188480
rss_huge 12582912
shmem 0
mapped_file 69423104
dirty 0
writeback 0
pgpgin 111883
pgpgout 1812
pgfault 100603
pgmajfault 624
inactive_anon 0
active_anon 215531520
inactive_file 253870080
active_file 270336
unevictable 0
hierarchical_memory_limit 8361357312
total_cache 78499840
total_rss 391188480
total_rss_huge 12582912
total_shmem 0
total_mapped_file 69423104
total_dirty 0
total_writeback 0
total_pgpgin 111883
total_pgpgout 1812
total_pgfault 100603
total_pgmajfault 624
total_inactive_anon 0
total_active_anon 215531520
total_inactive_file 253870080
total_active_file 270336
total_unevictable 0

有人可以解释为什么报告的 POD 内存利用率与简单 ps 相差近 40%(对于 apiserver 进程相差 100)吗?

编辑:我更新了内存报告值以包括 /sys/fs/cgroup/memory/memory.stat 的输出,这似乎 +- 对应于 kube-capacity
报告的 POD 利用率 正如第一条评论中所建议的:这是否意味着区别仅在于共享内存(由 PS 报告,而不是由 POD metrics/cgroup 报告)?
差别挺大的

ps 不反映应用程序实际使用的内存量,而只反映为其保留的内存量。如果页面由多个进程共享或通过使用某些动态链接库共享,则可能会产生很大的误导。

Understanding memory usage on Linux 是一篇很好的文章,描述了 Linux 中的内存使用情况以及 ps 实际报告的内容。

Why ps is "wrong"

Depending on how you look at it, ps is not reporting the real memory usage of processes. What it is really doing is showing how much real memory each process would take up if it were the only process running. Of course, a typical Linux machine has several dozen processes running at any given time, which means that the VSZ and RSS numbers reported by ps are almost definitely wrong.

这就是为什么ps不应该用于一些内存消耗的详细数据。

ps 的替代方法是 smem。 它报告物理内存使用情况,将共享内存页面考虑在内。然后在 USS(唯一集大小)处报告非共享内存。所以当你想忽略共享内存时可以使用USS

非共享内存 (USS) 加上进程共享内存的比例在 PSS(比例集大小)处报告。基本上它添加 USS 以及共享内存的一部分除以共享该内存的进程数。

另一方面,RSS(驻留集大小)是每个进程使用的共享内存加上非共享内存的数量。如果任何进程共享内存,这将简短报告超过实际使用的内存量。

Linux 使用编程中使用的资源管理技术来有效地实现 duplicatecopy 操作。这叫做copy-on-write。因此,当您有父进程和子进程时,它们都将显示相同的 RSS。使用 copy-on-write linux 可确保两个进程真正使用相同的内存。