Docker 容器内存监控原理及应用
Docker容器内存监控
linux内存监控
要明白docker容器内存是如何计算的,首先要明白linux中内存的相关概念。
使用free命令可以查看当前内存使用情况。
[root@localhost~]$free totalusedfreesharedbufferscached Mem:26442068421385351250567172718226882095364175733516 -/+buffers/cache:36024632228396052 Swap:16777212127796415499248
这里有几个概念:
- mem:物理内存
- swap:虚拟内存。即可以把数据存放在硬盘上的数据
- shared:共享内存。存在在物理内存中。
- buffers:用于存放要输出到disk(块设备)的数据的
- cached:存放从disk上读出的数据
可以参考这里。
为方便说明,我对free的结果做了一个对应。
[root@localhost~]$free totalusedfreesharedbufferscached Mem:total_memused_memfree_memshared_membuffercache -/+buffers/cache:real_usedreal_free Swap:total_swapused_swapfree_swap
名称 | 说明 |
---|---|
total_mem | 物理内存总量 |
used_mem | 已使用的物理内存量 |
free_mem | 空闲的物理内存量 |
shared_mem | 共享内存量 |
buffer | buffer所占内存量 |
cache | cache所占内存量 |
real_used | 实际使用的内存量 |
real_free | 实际空闲的内存量 |
total_swap | swap总量 |
used_swap | 已使用的swap |
free_swap | 空闲的swap |
一般认为,buffer和cache是还可以再进行利用的内存,所以在计算空闲内存时,会将其剔除。
因此这里有几个等式:
real_used=used_mem-buffer-cache real_free=free_mem+buffer+cache total_mem=used_mem+free_mem
了解了这些,我们再来看free的数据源。其实其数据源是来自于/proc/memeinfo文件。
[root@localhost~]$cat/proc/meminfo MemTotal:264420684kB MemFree:50566436kB Buffers:2095356kB Cached:175732644kB SwapCached:123688kB Active:165515340kB Inactive:37004224kB Active(anon):92066880kB Inactive(anon):4455076kB Active(file):73448460kB Inactive(file):32549148kB Unevictable:362900kB Mlocked:74696kB SwapTotal:16777212kB SwapFree:15499248kB Dirty:2860kB Writeback:0kB AnonPages:24932928kB Mapped:58165040kB Shmem:71822688kB Slab:8374496kB SReclaimable:8163096kB SUnreclaim:211400kB KernelStack:45824kB PageTables:606296kB NFS_Unstable:0kB Bounce:0kB WritebackTmp:0kB CommitLimit:148987552kB Committed_AS:114755628kB VmallocTotal:34359738367kB VmallocUsed:772092kB VmallocChunk:34225428328kB HardwareCorrupted:0kB AnonHugePages:22083584kB HugePages_Total:0 HugePages_Free:0 HugePages_Rsvd:0 HugePages_Surp:0 Hugepagesize:2048kB DirectMap4k:7168kB DirectMap2M:2015232kB DirectMap1G:266338304kB
docker
说完linux的内存,我们再来看下docker的内存监控。docker自身提供了一种内存监控的方式,即可以通过dockerstats对容器内存进行监控。
该方式实际是通过对cgroup中相关数据进行取值从而计算得到。
cgroup
cgroup中的memory子系统为hierarchy提供了如下文件。
[root@localhost~]$ll/cgroup/memory/docker/53a11f13c08099dd6d21030dd2ddade54d5cdd7ae7e9e68f5ba055ad28498b6f/ 总用量0 --w--w--w-1rootroot02月2212:51cgroup.event_control -rw-r--r--1rootroot05月2517:07cgroup.procs -rw-r--r--1rootroot02月2212:51memory.failcnt --w-------1rootroot02月2212:51memory.force_empty -rw-r--r--1rootroot03月3017:06memory.limit_in_bytes -rw-r--r--1rootroot02月2212:51memory.max_usage_in_bytes -rw-r--r--1rootroot02月2212:51memory.memsw.failcnt -rw-r--r--1rootroot03月3017:06memory.memsw.limit_in_bytes -rw-r--r--1rootroot02月2212:51memory.memsw.max_usage_in_bytes -r--r--r--1rootroot02月2212:51memory.memsw.usage_in_bytes -rw-r--r--1rootroot02月2212:51memory.move_charge_at_immigrate -rw-r--r--1rootroot02月2212:51memory.oom_control -rw-r--r--1rootroot03月3017:06memory.soft_limit_in_bytes -r--r--r--1rootroot02月2212:51memory.stat -rw-r--r--1rootroot02月2212:51memory.swappiness -r--r--r--1rootroot02月2212:51memory.usage_in_bytes -rw-r--r--1rootroot02月2212:51memory.use_hierarchy -rw-r--r--1rootroot02月2212:51notify_on_release -rw-r--r--1rootroot02月2212:51tasks
这些文件的具体含义可以查看相关资料cgroupmemory。
这里主要介绍几个与docker监控相关的。
文件名 | 说明 |
---|---|
memory.usage_in_bytes | 已使用的内存量(包含cache和buffer)(字节),相当于linux的used_meme |
memory.limit_in_bytes | 限制的内存总量(字节),相当于linux的total_mem |
memory.failcnt | 申请内存失败次数计数 |
memory.memsw.usage_in_bytes | 已使用的内存和swap(字节) |
memory.memsw.limit_in_bytes | 限制的内存和swap容量(字节) |
memory.memsw.failcnt | 申请内存和swap失败次数计数 |
memory.stat | 内存相关状态 |
以下为一个容器的样例。
[root@localhost53a11f13c08099dd6d21030dd2ddade54d5cdd7ae7e9e68f5ba055ad28498b6f]$catmemory.usage_in_bytes 135021858816 [root@localhost53a11f13c08099dd6d21030dd2ddade54d5cdd7ae7e9e68f5ba055ad28498b6f]$catmemory.memsw.usage_in_bytes 135679291392 [root@localhost53a11f13c08099dd6d21030dd2ddade54d5cdd7ae7e9e68f5ba055ad28498b6f]$catmemory.stat cache134325506048 rss695980032 mapped_file16155119616 pgpgin21654116032 pgpgout21705492352 swap655171584 inactive_anon4218880 active_anon74202603520 inactive_file8365199360 active_file52449439744 unevictable0 hierarchical_memory_limit137438953472 hierarchical_memsw_limit274877906944 total_cache134325506048 total_rss695980032 total_mapped_file16155119616 total_pgpgin21654116032 total_pgpgout21705492352 total_swap655171584 total_inactive_anon4218880 total_active_anon74202603520 total_inactive_file8365199360 total_active_file52449439744 total_unevictable0
memory.stat
memory.stat包含有最丰富的
统计 | 描述 |
---|---|
cache | 页缓存,包括tmpfs(shmem),单位为字节 |
rss | 匿名和swap缓存,不包括tmpfs(shmem),单位为字节 |
mapped_file | memory-mapped映射的文件大小,包括tmpfs(shmem),单位为字节 |
pgpgin | 存入内存中的页数 |
pgpgout | 从内存中读出的页数 |
swap | swap用量,单位为字节 |
active_anon | 在活跃的最近最少使用(least-recently-used,LRU)列表中的匿名和swap缓存,包括tmpfs(shmem),单位为字节 |
inactive_anon | 不活跃的LRU列表中的匿名和swap缓存,包括tmpfs(shmem),单位为字节 |
active_file | 活跃LRU列表中的file-backed内存,以字节为单位 |
inactive_file | 不活跃LRU列表中的file-backed内存,以字节为单位 |
unevictable | 无法再生的内存,以字节为单位 |
hierarchical_memory_limit | 包含memorycgroup的层级的内存限制,单位为字节 |
hierarchical_memsw_limit | 包含memorycgroup的层级的内存加swap限制,单位为字节 |
active_anon+inactive_anon=anonymousmemory+filecachefortmpfs+swapcache
active_file+inactive_file=cache-sizeoftmpfs
docker原生内存监控
再来说到docker原生的dockerstats。其具体实现在libcontainer中可以看到。其将容器的内存监控分为cache,usage,swapusage,kernelusage,kerneltcpusage。
其中cache是从memory.stat中的cache中获取。
usage是使用memory.usage_in_bytes和memory.limit_in_bytes进行相除来计算使用率。这一方式有一个弊端,就是不够细化,没有区分出cache部分,不能真正反映内存使用率。因为一般来说cache是可以复用的内存部分,因此一般将其计入到可使用的部分。
可以考虑的改进计算方式
改进方式在统计内存使用量时将cache计算排除出去。类似于linux中计算real_used时将buffer和cache排除一样。
cache并不能直接应用memory.stat中的cache,因为其中包括了tmpfs,而tmpfs算是实际使用的内存部分。
tmpfs即sharememory,共享内存
因为在memory.stat中存在有
active_file+inactive_file=cache-sizeoftmpfs
因此可以计算实际使用的内存量为
real_used=memory.usage_in_bytes-(rss+active_file+inactive_file)
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!