在上一篇说完 namespace 给容器技术提供了隔离之后,我们在介绍一下容器的“限制”问题

也许你会好奇,我们不是已经通过 Linux Namespace 给容器创建了一个容器了吗,为什么还需要对容器做限制呢?

因为在 linux 进程中,容器进程并不是物理隔离的,在运行时是和宿主机上的其他进程共享同一个 cpu 和内存,如果不加以限制,必定会造成资源竞争。

在容器中,第 1 号进程在“障眼法”的干扰下只能看到容器里的情况,但是宿主机上,它作为第 100 号进程与其他所有进程之间依然是平等的竞争关系。这就意味着,虽然第 100 号进程表面上被隔离了起来,但是它所能够使用到的资源(比如 CPU、内存),却是可以随时被宿主机上的其他进程(或者其他容器)占用的。当然,这个 100 号进程自己也可能把所有资源吃光。这些情况,显然都不是一个“沙盒”应该表现出来的合理行为。

Linux Cgroups 就是 Linux 内核中用来为进程设置资源限制的一个重要功能

Linux Cgroups 的全称是 Linux Control Group。它最主要的作用,就是限制一个进程组能够使用的资源上限,包括 CPU、内存、磁盘、网络带宽等等。

在 Linux 中,Cgroups 给用户暴露出来的操作接口是文件系统,即它以文件和目录的方式组织在操作系统的 /sys/fs/cgroup 路径下。在 Centos 机器里,我可以用 mount 指令把它们展示出来,这条命令是:

$ mount -t cgroup
cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,xattr,release_agent=/usr/lib/systemd/systemd-cgroups-agent,name=systemd)
cgroup on /sys/fs/cgroup/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,freezer)
cgroup on /sys/fs/cgroup/hugetlb type cgroup (rw,nosuid,nodev,noexec,relatime,hugetlb)
cgroup on /sys/fs/cgroup/net_cls,net_prio type cgroup (rw,nosuid,nodev,noexec,relatime,net_prio,net_cls)
cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpuacct,cpu)
cgroup on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,blkio)
cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,memory)
cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,cpuset)
cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,devices)
cgroup on /sys/fs/cgroup/pids type cgroup (rw,nosuid,nodev,noexec,relatime,pids)
cgroup on /sys/fs/cgroup/perf_event type cgroup (rw,nosuid,nodev,noexec,relatime,perf_event)

如果没有挂载则直接使用 yum install libcgroup 安装 cgroups 模块

可以看到,在 /sys/fs/cgroup 下面有很多诸如 cpuset、cpu、 memory 这样的子目录,也叫子系统。这些都是我这台机器当前可以被 Cgroups 进行限制的资源种类。而在子系统对应的资源种类下,你就可以看到该类资源具体可以被限制的方法。比如,对 CPU 子系统来说,我们就可以看到如下几个配置文件,这个指令是:

$ ls /sys/fs/cgroup/cpu
aegis cgroup.clone_children cgroup.procs cpuacct.stat cpuacct.usage_percpu cpu.cfs_quota_us cpu.rt_runtime_us cpu.stat notify_on_release system.slice user.slice
assist cgroup.event_control cgroup.sane_behavior cpuacct.usage cpu.cfs_period_us cpu.rt_period_us cpu.shares docker release_agent tasks

如果熟悉 Linux CPU 管理的话,你就会在它的输出里注意到 cfs_period 和 cfs_quota 这样的关键词。这两个参数需要组合使用,可以用来限制进程在长度为 cfs_period 的一段时间内,只能被分配到总量为 cfs_quota 的 CPU 时间。而这样的配置文件又如何使用呢?你需要在对应的子系统下面创建一个目录,比如,我们现在进入 /sys/fs/cgroup/cpu 目录下:

root@centos:/sys/fs/cgroup/cpu$ mkdir container
root@centos/sys/fs/cgroup/cpu$ ls container/
cgroup.clone_children cpu.cfs_period_us cpu.rt_period_us cpu.shares notify_on_release
cgroup.procs cpu.cfs_quota_us cpu.rt_runtime_us cpu.stat tasks

这个目录就称为一个“控制组”。你会发现,操作系统会在你新创建的 container 目录下,自动生成该子系统对应的资源限制文件。现在,我们在后台执行这样一条脚本:

$ while : ; do : ; done &
[1] 226

这样,我们可以用 top 指令来确认一下 CPU 有没有被打满:

$ top
%Cpu0 :100.0 us, 0.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st

在输出里可以看到,CPU 的使用率已经 100% 了(%Cpu0 :100.0 us)。而此时,我们可以通过查看 container 目录下的文件,看到 container 控制组里的 CPU quota 还没有任何限制(即:-1),CPU period 则是默认的 100 ms(100000 us):

$ cat /sys/fs/cgroup/cpu/container/cpu.cfs_quota_us
-1
$ cat /sys/fs/cgroup/cpu/container/cpu.cfs_period_us
100000

接下来,我们可以通过修改这些文件的内容来设置限制。比如,向 container 组里的 cfs_quota 文件写入 20 ms(20000 us):

$ echo 20000 > /sys/fs/cgroup/cpu/container/cpu.cfs_quota_us

结合前面的介绍,你应该能明白这个操作的含义,它意味着在每 100 ms 的时间里,被该控制组限制的进程只能使用 20 ms 的 CPU 时间,也就是说这个进程只能使用到 20% 的 CPU 带宽。接下来,我们把被限制的进程的 PID 写入 container 组里的 tasks 文件,上面的设置就会对该进程生效了:

$ echo 226 > /sys/fs/cgroup/cpu/container/tasks 

我们可以用 top 指令查看一下:

$ top
%Cpu0 : 20.3 us, 0.0 sy, 0.0 ni, 79.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st

可以看到,计算机的 CPU 使用率立刻降到了 20%(%Cpu0 : 20.3 us)。

除 CPU 子系统外,Cgroups 的每一个子系统都有其独有的资源限制能力,比如:

  • blkio,为​​​块​​​设​​​备​​​设​​​定​​​I/O 限​​​制,一般用于磁盘等设备;
  • cpuset,为进程分配单独的 CPU 核和对应的内存节点;
  • memory,为进程设定内存使用的限制。

Linux Cgroups 的设计还是比较易用的,简单粗暴地理解呢,它就是一个子系统目录加上一组资源限制文件的组合。而对于 Docker 等 Linux 容器项目来说,它们只需要在每个子系统下面,为每个容器创建一个控制组(即创建一个新目录),然后在启动容器进程之后,把这个进程的 PID 填写到对应控制组的 tasks 文件中就可以了。

而至于在这些控制组下面的资源文件里填上什么值,就靠用户执行 docker run 时的参数指定了,比如这样一条命令:

$ docker run -it --cpu-period=100000 --cpu-quota=20000 ubuntu /bin/bash

在启动这个容器后,我们可以通过查看 Cgroups 文件系统下,CPU 子系统中,“docker”这个控制组里的资源限制文件的内容来确认:

$ cat /sys/fs/cgroup/cpu/docker/5d5c9f67d/cpu.cfs_period_us
100000
$ cat /sys/fs/cgroup/cpu/docker/5d5c9f67d/cpu.cfs_quota_us
20000

所以你看,docker 容器时候的技术其实并没有什么特别大的创新,只是统一了linux相关功能,整合起来,形成容器技术。

Docker容器基础入门认知-Cgroup的更多相关文章

  1. Docker容器基础入门认知-网络篇

    这篇文章中,会从 docker 中的单机中的 netns 到 veth,再到单机多个容器之间的 bridge 网络交互,最后到跨主机容器之间的 nat 和 vxlan 通信过程,让大家对 docker ...

  2. docker容器基础

    一.docker容器基础6种名称空间:UTS.MOunt.IPC.PID.User.Net (1) Linux Namespaces:namespace 系统调用参数 隔离内容 内核版本  UTS   ...

  3. Docker容器基础认知

    ## 一. [docker](http://www.itxdm.me/archives/tag/docker/)概念 [Docker](http://www.itxdm.me/wp-content/p ...

  4. Docker 容器的资源限制 cgroup(九)

    目录 一.cgroup简介 二.CPU资源配额控制 1.CPU份额控制 2.CPU周期控制 3.CPU core控制 4.CPU配额控制参数的混合使用 二.对内存的限额 三.对 Block IO 的限 ...

  5. Docker容器使用 (入门到精通)

    Docker容器 CentOS安装Docker Docker 分为 CE 和 EE 两大版本.CE 即社区版(免费,支持周期 7 个月),EE 即企业版,强调安全,付费使用,支持周期 24 个月. D ...

  6. Docker容器基础知识学习

    Docker作为操作系统层面的轻量级的虚拟化技术,凭借简易的使用.快速的部署以及灵活敏捷的集成等优势,迅速发展目前最为火热的技术. 1.云计算服务是一种资源管理的资源服务,该模式可以实现随时随地.便捷 ...

  7. Kubernetes 普及系列:容器基础入门

    随着云原生时代的来临,云以及分布式计算已经是时下最受欢迎的技术之一了.其中 Docker 作为最知名的容器平台,到底有着怎样的魅力来让其无人不知无人不晓?废话不多说,让我们开始逐层掀开容器技术的神秘面 ...

  8. Docker容器技术入门

    独立容器分开的条件: 1.Namespace命名空间 1.主机名和域名,UTS 2.文件系统,mount 3.进程间通信,IPC 4.独立的进程树PID 5.独立的用户User 6.独立的IP地址tc ...

  9. Docker容器入门到精通

    Docker 容器 快速入门 第一章:Docker容器 第二章:Dockerfile指令与Docker-compose容器编排-搭建docker私有仓库 h1 { color: rgba(0, 60, ...

  10. 1.Docker容器学习之新生入门必备基础知识

    0x00 Docker 快速入门 1.基础介绍 描述:Docker [ˈdɑ:kə(r)] 是一个基于Go语言开发实现的遵循Apache 2.0协议开源项目,目标是实现轻量级的操作系统虚拟化解决方案: ...

随机推荐

  1. HOCON:nginx配置文件后缀conf是什么格式类型文件夹?intellij如何编辑

    nginx的配置为*.conf ,这个conf是么子文件?之前确实不清楚. HOCON 简介HOCON(Human-Optimized Config Object Notation)是一个易于使用的配 ...

  2. 1024程序员节献礼,火山引擎ByteHouse带来三重产品福利

    更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流.   随着信息技术飞速发展,互联网.Web3.物联网.人工智能相继出现. 在这近三十年的高速发展中,"程序 ...

  3. 【开源项目推荐】——纯中文本地GPT知识库搭建项目.assets

    大家好,我是独孤风. 又到了本周的开源项目推荐.近一年多的时间,人工智能迎来了大爆发.GPT相关的大模型的发展让很多领域都发生了巨大的变化. 但是虽然GPT的自然语言识别功能异常的强大,但回答给我们的 ...

  4. 【Django-Vue】手机号是否存在接口 多方式登录接口 腾讯云短信介绍和申请 api与sdk

    目录 昨日回顾 今日内容 0 登录注册功能设计 1 短信登录接口 视图类 2 多方式密码登录接口 视图类 序列化类 路由 3 腾讯云短信介绍和申请 3.1api与sdk 补充 练习 昨日回顾 # 你的 ...

  5. 将应用程序注册为Linux系统服务,并设置开机自启动

    1.新建服务文件 vim /usr/lib/systemd/system/statagent.service 其中statagent是自定义的服务名称 2.文件内容 [Unit] Descriptio ...

  6. 【LibCurl】C++使用libcurl实现HTTP POST和GET、PUT

    libcurl简介 libcurl是一个跨平台的网络协议库,支持http, https, ftp, gopher, telnet, dict, file, 和ldap 协议.libcurl同样支持HT ...

  7. SpringCloud学习 系列四、微服务中心 Eureka介绍及创建一个Eureka中心服务

    系列导航 SpringCloud学习 系列一. 前言-为什么要学习微服务 SpringCloud学习 系列二. 简介 SpringCloud学习 系列三. 创建一个没有使用springCloud的服务 ...

  8. shell读取配置文件中的参数

    shell读取配置文件中的参数 配置文件 配置文件config.properties如下: user=bk age=25 ip=192.168.37.1  一.使用cat+awk语句过滤并赋值变量 u ...

  9. windows10/liunx创建空大文件

    1.windows10创建空大文件打开cmd命令,进入需要创建文件的目录,使用以下命令创建 fsutil file createnew test001.txt 1073741824 最后的数字代表文件 ...

  10. 房贷LPR该如何选择

    一.新政是否和你有关? 原文:是指2020年1月1日前金融机构已发放的和已签订合同但未发放的参考贷款基准利率定价的浮动利率贷款(不包括公积金个人住房贷款).   二.新政如何调整? 一种是按照LPR加 ...