docker-Cgroups

什么是Cgroups?

Cgroups提供了对一组进程及将来子进程的资源限制、控制和统 计的能力,这些资源包括 CPU、内存、存储、网络等 。 通过 Cgroups,可以方便地限制某个进 程的资源占用,并且可以实时地监控进程的监控和统计信息 。
Cgroups的接口是通过操作一个虚拟文件系统实现,一般挂载在/sys/fs/cgroup下。

Cgroups的组成

Cgroups包括三个组件:

  • cgroup是对进程分组的一种管理机制,一个cgroup包含一组进程。
  • subsystem是一组资源控制的模块,Cgroups依靠它来限制进程的资源管理,包括:
    blkio 设置对块设备(比如硬盘)输入输出的访问控制 。
    cpu 设置 cgroup 中进程的 CPU 被调度的策略。
    cpuacct 可以统计cgroup中进程的 CPU 占用 。
    cpuset 在多核机器上设置 cgroup 中进程可以使用的 CPU 和内存(此处内存仅使用于
    NUMA 架构) 。
    devices 控制 cgroup 中进程对设备的访问 。
    freezer 用于挂起( suspend)和恢复( resume) cgroup 中的进程 。
    memory 用于控制 cgroup 中进程的内存占用 。
    net_els 用于将 cgroup 中进程产生的网络包分类,以便 Linux 的 tc (traffic con位oller)可
    以根据分类区分出来自某个 cgroup 的包并做限流或监控 。
    net_prio 设置 cgroup 中进程产生的网络流量的优先级 。
    ns 这个 subsystem 比较特殊,它的作用是使 cgroup 中的进程在新的 Namespace 中 fork
    新进程 CNEWNS)时,创建出一个新的 cgroup,这个 cgroup包含新的 Namespace 中
    的进程 。
  • hierarchy是一组树状关系的cgroup,其中的cgroup有继承关系。

Cgroup的使用

挂载hierarchy

mkdir test-cgroup #创建一个hierarchy的挂载点

mount -t cgroup -o none,name=test-group  none test-cgroup #挂载一个hierarchy到这个目录

ls ./test-cgroup #查看这个目录下的文件

cg1  cgroup.clone_children  cgroup.sane_behavior  release_agent

cg2  cgroup.procs           notify_on_release     tasks

这些文件是刚刚创建的hierarchy根cgroup,每创建一个新的hierarchy都会默认创建一个根cgroup,系统中的所有进程都会加入到这个根cgroup中。
可以从文件cgroup.procs中看到系统的所用进程组,在tasks中可以看到所有进程的PID以验证上面的说法。

创建cgroup

cd test-cgroup #到挂载了hierarchy的目录中

mkdir cg1 #创建两个新目录

mkdir cg2 #这两个目录相当于在这个hierarchy中创建了两个子cgroup

tree #查看目录树
.
|-- cg1
|   |-- cgroup.clone_children
|   |-- cgroup.procs
|   |-- notify_on_release
|   `-- tasks
|-- cg2
|   |-- cgroup.clone_children
|   |-- cgroup.procs
|   |-- notify_on_release
|   `-- tasks
|-- cgroup.clone_children
|-- cgroup.procs
|-- cgroup.sane_behavior
|-- notify_on_release
|-- release_agent
`-- tasks

tree的输出可以看到新创建的cg1、cg2中自动创建了cgroup的文件,也就意味这在上一步的根root之下创建了两个同级的cgroup。
cg1、cg2的cgroup.procstasks中没有任何内容,说明手动创建的非根cgroup不会默认添加任何进程和进程组。

使用subsystem

mount|grep cgroup #查看挂载,在什么是Cgroups中提到,Cgroups的本质是操作一个挂载类型为cgroup的虚拟文件系统
tmpfs on /sys/fs/cgroup type tmpfs (ro,nosuid,nodev,noexec,mode=755)
cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,xattr,release_agent=/lib/systemd/systemd-cgroups-agent,name=systemd)
cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpu,cpuacct)
cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,memory)
cgroup on /sys/fs/cgroup/net_cls,net_prio type cgroup (rw,nosuid,nodev,noexec,relatime,net_cls,net_prio)
cgroup on /sys/fs/cgroup/hugetlb type cgroup (rw,nosuid,nodev,noexec,relatime,hugetlb)
cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,devices)
cgroup on /sys/fs/cgroup/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,freezer)
cgroup on /sys/fs/cgroup/pids type cgroup (rw,nosuid,nodev,noexec,relatime,pids)
cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,cpuset)
cgroup on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,blkio)
cgroup on /sys/fs/cgroup/perf_event type cgroup (rw,nosuid,nodev,noexec,relatime,perf_event)
none on /root/test-cgroup type cgroup (rw,relatime,name=test-group)

从输出看到/sys/fs/cgroup的文件系统是tmpfs,而其中的多个目录的文件系统是cgroup,test-cgroup也一样。这说明了/sys/fs/cgroup/中的每一个目录对应一个hierarchy,这些hierarchy是系统默认创建的,其中每一个hierarchy默认对应了一个subsystem,从目录名可以看出本别是cpuacctmemory等等。

ls /sys/fs/cgroup/memory #查看系统创建的名为memory的hierarchy
cgroup.clone_children               memory.max_usage_in_bytes
cgroup.event_control                memory.move_charge_at_immigrate
cgroup.procs                        memory.numa_stat
cgroup.sane_behavior                memory.oom_control
init.scope                          memory.pressure_level
memory.failcnt                      memory.soft_limit_in_bytes
memory.force_empty                  memory.stat
memory.kmem.failcnt                 memory.swappiness
memory.kmem.limit_in_bytes          memory.usage_in_bytes
memory.kmem.max_usage_in_bytes      memory.use_hierarchy
memory.kmem.slabinfo                notify_on_release
memory.kmem.tcp.failcnt             ram_cg1
memory.kmem.tcp.limit_in_bytes      release_agent
memory.kmem.tcp.max_usage_in_bytes  system.slice
memory.kmem.tcp.usage_in_bytes      tasks
memory.kmem.usage_in_bytes          user.slice
memory.limit_in_bytes

系统的名为memory的hierarchy中包含了许多memory类型的subsystem生成的文件,意味着这个hierarchy附加了一个memory类型的subsystem。而之前创建的test-cgroup没有附加任何的subsystem,所以也就没有这些subsystem相关的文件。

cd /sys/fs/cgroup/memory

mkdir test-memory #在这个hierarchy中创建一个子cgroup

cd test-memory && ls ##查看新的cgroup的内容
cgroup.clone_children               memory.limit_in_bytes
cgroup.event_control                memory.max_usage_in_bytes
cgroup.procs                        memory.move_charge_at_immigrate
memory.failcnt                      memory.numa_stat
memory.force_empty                  memory.oom_control
memory.kmem.failcnt                 memory.pressure_level
memory.kmem.limit_in_bytes          memory.soft_limit_in_bytes
memory.kmem.max_usage_in_bytes      memory.stat
memory.kmem.slabinfo                memory.swappiness
memory.kmem.tcp.failcnt             memory.usage_in_bytes
memory.kmem.tcp.limit_in_bytes      memory.use_hierarchy
memory.kmem.tcp.max_usage_in_bytes  notify_on_release
memory.kmem.tcp.usage_in_bytes      tasks
memory.kmem.usage_in_bytes

echo $$ >> tasks #将当前shell的进程纳入了这个cgroup中
echo 100m >> memory.limit_in_bytes #限制这个cgroup使用100m内存

上面的操作在系统创建的的hierarchy中创建一个附加了memorysubsystemcgroup,并限制了100m的内存使用。

stress --vm-bytes 200m --vm-keep -m 1 #使用stress工具测试内存占用200m内存 stess启动失败

stress --vm-bytes 90m --vm-keep -m 1 #使用stress工具测试内存占用90m内存 stess能够启动成功

通过stress可以验证这个cgroupsubsystem成功把加入的进程内存占用在了100m。

docker

docker run -itd m 128m ubuntu #启动一个容器 限制128m内存
fc3e9a13ee2c5bc528ae59748cee00443469b2c87bcb4c752e7cfe0eb39df121

cd /sys/fs/cgroup/memory/docker && ls #查看docker在memory中创建的cgroup
cgroup.clone_children                                             memory.kmem.limit_in_bytes          memory.kmem.usage_in_bytes       memory.soft_limit_in_bytes
cgroup.event_control                                              memory.kmem.max_usage_in_bytes      memory.limit_in_bytes            memory.stat
cgroup.procs                                                      memory.kmem.slabinfo                memory.max_usage_in_bytes        memory.swappiness
fc3e9a13ee2c5bc528ae59748cee00443469b2c87bcb4c752e7cfe0eb39df121  memory.kmem.tcp.failcnt             memory.move_charge_at_immigrate  memory.usage_in_bytes
memory.failcnt                                                    memory.kmem.tcp.limit_in_bytes      memory.numa_stat                 memory.use_hierarchy
memory.force_empty                                                memory.kmem.tcp.max_usage_in_bytes  memory.oom_control               notify_on_release
memory.kmem.failcnt

cd c3e9a13ee2c5bc528ae59748cee00443469b2c87bcb4c752e7cfe0eb39df121 && ls
cgroup.clone_children  memory.kmem.failcnt             memory.kmem.tcp.limit_in_bytes      memory.max_usage_in_bytes        memory.soft_limit_in_bytes  notify_on_release
cgroup.event_control   memory.kmem.limit_in_bytes      memory.kmem.tcp.max_usage_in_bytes  memory.move_charge_at_immigrate  memory.stat                 tasks
cgroup.procs           memory.kmem.max_usage_in_bytes  memory.kmem.tcp.usage_in_bytes      memory.numa_stat                 memory.swappiness
memory.failcnt         memory.kmem.slabinfo            memory.kmem.usage_in_bytes          memory.oom_control               memory.usage_in_bytes
memory.force_empty     memory.kmem.tcp.failcnt         memory.limit_in_bytes               memory.pressure_level            memory.use_hierarchy

cat memory.limit_in_bytes
134217728

可以分析出docker容器限制内存的基本原理如下:

  1. docker在memoryhierarchy中创建名为docker的子cgroup
  2. 创建一个附加了-m参数的容器时,在memory/docker下创建一个新的cgroup,将-m限制的参数写入memory.limit_in_bytes
  3. 将容器的PID写入tasks,实现内存限制。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容