专业的编程技术博客社区

网站首页 > 博客文章 正文

Docker内核技术原理(八)之内存 Cgroup

baijin 2025-01-09 10:18:43 博客文章 7 ℃ 0 评论

上一篇文章介绍了cgroup关于CPU限制,相比CPU限制,内存的限制相对简单很多,Docker 支持在启动时设定容器的内存使用如下参数

-m, --memory string     #内存限制
--memory-swap string    #内存+swap

主要是设置内存以及交换内存的大小。譬如

# docker run -it -m 300M busybox sh -c “cat /sys/fs/cgroup/memory/memory.limit_in_bytes 
&& cat /sys/fs/cgroup/memory/memory.memsw.limit_in_bytes“       
314572800
629145600

这里我故意省去了memory-swap参数设置,因为在设置了内存的情况下,默认的交换分区大小和内存相同,那么总的内存(内存+交换)就是内存的两倍。

首先看一下cgroup关于内存的限制有哪些参数,当进入cgroup挂载目录(/sys/fs/cgroup/memory/)下主要有以下这些参数

 cgroup.event_control       #用于eventfd的接口
 memory.usage_in_bytes      #显示当前已用的内存
 memory.limit_in_bytes      #设置/显示当前限制的内存额度
 memory.failcnt             #显示内存使用量达到限制值的次数
 memory.max_usage_in_bytes  #历史内存最大使用量
 memory.soft_limit_in_bytes #设置/显示当前限制的内存软额度
 memory.stat                #显示当前cgroup的内存使用情况
 memory.use_hierarchy       #设置/显示是否将子cgroup的内存使用情况统计到当前cgroup里面
 memory.force_empty         #触发系统立即尽可能的回收当前cgroup中可以回收的内存
 memory.pressure_level      #设置内存压力的通知事件,配合cgroup.event_control一起使用
 memory.swappiness          #设置和显示当前的swappiness
 memory.move_charge_at_immigrate #设置当进程移动到其他cgroup中时,它所占用的内存是否也随着移动过去
 memory.oom_control         #设置/显示oom controls相关的配置
 memory.numa_stat           #显示numa相关的内存

可以看到主要有两个方面的作用:一方面是控制相关,另一方面是统计监控相关,下面通过例子介绍一下如何通过cgroup控制top命令的内存使用。

# cd /sys/fs/cgroup/memory/test/
# sh -c “echo $ >> cgroup.procs“
# top

打开一个新的窗口,查看top命令已经加入cgroup

# cat tasks 
1271    /*上面的bash*/
3562    /*上面的top*/

这里回顾之前cgroup基本知识,bash fork出来的子进程top默认也会加入cgroup中。并且可以看到top的限制使用的内存和当前使用的内存

#  cat  memory.limit_in_bytes    
9223372036854771712   /*目前还未限制*/
#  cat  memory.usage_in_bytes 
1642496

可以看到使用了1604KB的内存,下面开始限制他的内存使用

echo 1000K > memory.limit_in_bytes

然后查看top命令的内存占用

# cat memory.limit_in_bytes 
1022976

可以看到已经通过cgroup限制了top命令的内存占用,上述的实验在部分内核执行会出现“Device or resource busy”的错误,那是因为在内核不允许设置上限小于当前使用内存,不过这并不影响实验效果,我们可以先设置内存使用,然后执行一些消耗内存的进程。看下面的例子

# cd /sys/fs/cgroup/memory/
# mkdir foo
# cd foo
# echo 8000000 > memory.limit_in_bytes
# echo 8000000 > memory.memsw.limit_in_bytes
# echo $ > tasks
# dd if=/dev/zero | read x

这个例子非常简单,首先设置内存和交换分区为8MB,然后读取不停地将数据读入内存,很快便会触发OOM。关于OOM的文章参考之前文章:OOM时候会杀死哪个进程,这里补充一下上面的参数类别中的memory.oom_control,它主要是控制当出现OOM的时候是否执行杀死进程。

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表