Docker Cgroup 子系统 CPU/Memory

去启动虚拟机的时候都会要求虚拟机多少资源,之前的namespace对用户的进程进行隔离了,放在了不同的namespace,互相不可见了,但是事实上都是主机fork出来的,运行在同一个操作系统里面的进程,如果不加以管控一定会出现一些问题。

会出现什么问题呢?比如写了一个应用里面有个bug是死循环,这样可能吃掉很多cpu,这样主机可能会变慢了。其他的应用就会受到影响了。还有或者应用内存泄露,那么吃掉了宿主机上面的很多内存,这样主机就整个都不能访问了,因为可能没有内存了。还有磁盘空间也是类似。

除了给容器提供封闭的环境之外,还要做一件事情就是资源管控,比如cpu和内存。

Cgroups


cgroup也分不同的子系统,这些不同的子系统会控制不同的资源,这些资源在cgroup里面叫做subsystem,就是不同的子系统。

cgroup如何去管理进程的,因为进程是树状结构,一个进程会fork出很多的其他进程,cgroup也用了类似的层级结构,也就是(Hierarchy)的方式来组织管理,

  • Cgroups (Control Groups)是 Linux 下用于对一个或一组进程进行资源控制和监控的机制
  • 可以对诸如 CPU 使用时间、内存、磁盘 I/O 等进程所需的资源进行限制
  • 不同资源的具体管理工作由相应的 Cgroup 子系统(Subsystem)来实现
  • 针对不同类型的资源限制,只要将限制策略在不同的的子系统上进行关联即可 
  • Cgroups 在不同的系统资源管理子系统中以层级树(Hierarchy)的方式来组织管理:每个Cgroup 都可以包含其他的子 Cgroup,因此子 Cgroup 能使用的资源除了受本 Cgroup 配置的资源参数限制,还受到父 Cgroup 设置的资源限制 。

cgroup有不同的子系统,cpu是一个子系统,如果要管控cpu那么是使用cpu的子系统。如果要管控进程的内存,它是用内存子系统去管控的。

Cgroup是怎么管理的?以树状结构去管理的。

Linux 内核代码中 Cgroups 的实现


同样task_struct里面也有css_set这个结构体,这个结构体是用来描述,这个进程所在从group的一个状态的情况。(cgroup也是task_struct里面一个重要的属性)

可配额/可度量 - Control Groups (cgroups)


最下面是系统的硬件,在此之上是操作系统内核,它包含了cgroup。内核和用户空间是通过系统调用来调用的。任何操作系统都会有一个初始化的进程,如systemd,对于任何的容器进程都是由systemd fork出来的子进程再fork出来的。

可配额/可度量 - Control Groups (cgroups)


cgroups 实现了对资源的配额和度量。

  • blkio:这个子系统设置限制每个块设备的输入输出控制。例如:磁盘,光盘以及 USB 等
  • cpu:这个子系统使用调度程序为 cgroup 任务提供 CPU 的访问
  • cpuacct:产生 cgroup 任务的 CPU 资源报告
  • cpuset如果是多核心的CPU,这个子系统会为 cgroup 任务分配单独的 CPU 和内存(应用进程可以和cpu做绑定关系,比如说希望某些应用就绑在某个核上)(如果是多核的cpu,可以将某个进程绑定到某个cpu核上面,这样就减少进程的切换了,那么它的TLB表和缓存,都是可以永远复用的,那么你这个程序就可以高效)
  • devices:允许或拒绝 cgroup 任务对设备的访问
  • freezer:暂停和恢复 cgroup 任务
  • memory:设置每个 cgroup 的内存限制以及产生内存资源报告
  • net_cls:标记每个网络包以供 cgroup 方便使用
  • ns:名称空间子系统
  • pid: 进程标识子系统。

CPU 子系统


  • cpu.shares 相对值:可出让的能获得 CPU 使用时间的相对值。(假设主机上面有3个cpu,定义了两个cgroup,将第一个进程放到第一个cgroup,将第二个进程放到第二个cgroup,将第一个进程里面的cpu设置为512,将第二个进程里面的cpu设置为1024,那么这就是1:2的比例,这样意味着操作系统在调用这些进程的时候对时间的分配是按照1:2去分配的,这是一个相对值,按照cpu占用时间去分配的)
  • cpu.cfs_period_us 绝对值cfs_period_us 用来配置时间周期长度,单位为 us(微秒)。
  • cpu.cfs_quota_us:cfs_quota_us 用来配置当前 Cgroup 在 cfs_period_us 时间内最多能使用的 CPU时间数,单位为 us(微秒)。(绝对值是按照两个文件去配置的,一个文件叫做cpu.cfs_period_us,另外一个叫做cpu.cfs_quota_us,在10w的cpu时间片里面,可以使用多少个时间片
  • cpu.stat :Cgroup 内的进程使用的 CPU 时间统计。
  • nr_periods :经过 cpu.cfs_period_us 的时间周期数量。
  • nr_throttled :在经过的周期内,有多少次因为进程在指定的时间周期内用光了配额时间而受到限制。
  • throttled_time :Cgroup 中的进程被限制使用 CPU 的总用时,单位是 ns(纳秒)。

cpu share和cpu qutoa区别:cpu share定义的是相对值,相对值意味着有人竞争的时候,大家就按照这个百分比去划分,如果没有人竞争就可以一直使用,B group里面的进程虽然使用了2/3的时间片,但是里面什么都没有跑,没有耗费任何cpu,那么A就可以将所有cpu吃掉。

但是绝对时间,给你设置了0.1的cpu,你就不可能超过它。

可以看到不同的子系统

[root@docker ~]# cd /sys/fs/cgroup/
[root@docker cgroup]# ls
blkio  cpu  cpuacct  cpu,cpuacct  cpuset  devices  freezer  hugetlb  memory  net_cls  net_cls,net_prio  net_prio  perf_event  pids  rdma  systemd

 cpu子系统当中的配置,这些配置是用来配置目录下面的进程能够使用多少cpu的

[root@docker cgroup]# cd cpu
[root@docker cpu]# ls
cgroup.clone_children  cpuacct.stat       cpuacct.usage_percpu       cpuacct.usage_sys   cpu.cfs_quota_us   cpu.shares  notify_on_release  tasks
cgroup.procs           cpuacct.usage      cpuacct.usage_percpu_sys   cpuacct.usage_user  cpu.rt_period_us   cpu.stat    release_agent      user.slice
cgroup.sane_behavior   cpuacct.usage_all  cpuacct.usage_percpu_user  cpu.cfs_period_us   cpu.rt_runtime_us  docker      system.slice

cpu.shares是一个相对值,约定一个cpu的相对值。假设有两个不同的文件目录,这个不同的文件目录里面都有cpu.shares。这个cpu.shares就是约定一个相对值,两个cgroup能够使用的cpu是几比几的,也就是比例。

[root@docker cpu]# cat cpu.shares 
1024

 cpu.cfs_quota_us cpu.cfs_period_us 这两个文件是用来控制一个进程使用cpu的绝对值。 

 cpu.cfs_period_us:可以简单理解为cpu的时间片 

 cpu.cfs_quota_us:是指在这么多时间片下面,我能够使用多少cpu

[root@master cpu]# cat cpu.cfs_quota_us cpu.cfs_period_us 
-1
100000

实战  Cgroup对CPU限制


 在cpu子系统下面创建一个demo。之前所说的文件都会被创建出来。

 这里有个程序,里面就是跑着死循环,吃cpu资源,现在运行这个程序。

可以看到占用了200%的cpu,如果有这种的应用就会将内存白白吃光了,这是非常危险的,因为没有独立的操作系统。

 有什么办法来控制呢?这个进程的PID是62261,要通过cgroup去控制这个进程,怎么控制呢?

将这个进程cgroup.procs写入到这个文件告诉cgroup要控制的进程是哪个。 

现在要控制cpu了,控制cpu的参数有两个,cpu.cfs_period_us  cpu.cfs_quota_us ,死循环进程现在占用了两个cpu,-1代表不做任何的资源限制。现在设置为100000,也就是使用一个cpu。

可以看到cpu降下去了,只使用了一个cpu。设置为10000的意思呢?

现在cpu.cfs_period_us  cpu.cfs_quota_us是相等的,意味着在100000个cpu时间片里面,被控制的进程能够拿到100000个cpu时间片,也就是能够拿到1个cpu。

通过这种方式,控制了这个进程使用的cpu。

cpu这种资源叫做可压缩资源,本来程序是消耗两个cpu的,但是给你一个cpu你也可以跑,但是这样程序一定会慢下来,所以在做容器化的时候,本来应用进程跑的好好的,突然部署到某一个地方发现慢了,发一个request就timeout了,这就得看看进程的cpu是不是给少了。

还有一种是不可压缩资源,比如内存。

可不可以在容器当中看cpu资源的使用率呢,进入到容器里面按top是不行的,看到的是主机的top,所以你要在容器里面通过top,通过cpuinfo,memifo来看资源利用率是不行的。

cpuacct 子系统


如果要看cpu怎么看呢? 通过cgroup cpu子系统的cpuacct去查看,这里面会告诉你cpu的使用情况。

[root@docker cpu]# cat cpuacct.usage
5666263771
[root@docker cpu]# cat cpuacct.stat 
user 191
system 340

用于统计 Cgroup 及其子 Cgroup 下进程的 CPU 的使用情况。

  • cpuacct.usage
包含该 Cgroup 及其子 Cgroup 下进程使用 CPU 的时间,单位是 ns(纳秒)。
  • cpuacct.stat
包含该 Cgroup 及其子 Cgroup 下进程使用的 CPU 时间,以及用户态和内核态的时间

Memory 子系统


memory.usage_in_bytes

  • cgroup 下进程使用的内存,包含cgroup 及其子 cgroup下的进程使用的内存

memory.max_usage_in_bytes

  • Cgroup下进程使用内存的最大值,包含子cgroup 的内存使用量。

memory.limit_in_bytes

  • 设置Cgroup 下进程最多能使用的内存。如果设置为-1,表示对该cgroup 的内存使用不做限制。

memory.oom_Control

  • 设置是否在 Cgroup中使用 OOM(Out of Memory)Killer,默认为使用。当属于该cgroup的进程使用的内存超过最大的限定值时,会立刻被 OOM Killer 处理。

操作系统的资源像cpu这种资源,是可压缩资源,虽然我这个进程很忙,可能需要两个cpu,但是给他0.1个cpu也是ok的,只不过进程会变慢,但是内存不一样,内存给其限制了,那么超出的内存在做内存申请的时候就申请不出来,导致OOM。

 Cgroup driver


上面可以看到cgroup是通过一系列的文件来管控所有的资源分配的,包括创建了一个cgroup,同时将一个cgroup和这个进程进行关联,也就是将进程号echo到那个procs文件里面,同时修改cpu的quota来限制其使用的资源,这一整套都是cgroup的文件系统,cgroup本身可以有不同的driver。

  • SyStemd:(整个操作系统是使用了systemd cgroup driver,当使用kubernetes的时候,要将两者统一,如果其他进程是使用systemd拉起来的,systemd拉起来的那些进程就由systemd这套系统去管控的,docker拉起的进程是由cgroupfs这套系统去管控的,这就会出现同一套资源被两套系统往外分,当系统压力大的时候就会引发不必要的问题,所以kubernetes在启动的时候会做一些检查,在启动kubelet的时候,去判断docker使用了哪一个cgroup driver,如果docker本身不是使用systemd,那么它就会默认报错不启动)

当操作系统使用systemd作为init system时,初始化进程生成一个根cgroup目录结构并作为cgroup管理器。

systemd与cgroup紧密结合,并且为每个systemd unit分配cgroup。

  • cgroupfs:

docker默认用cgroupfs作为cgroup驱动。

存在问题∶

  • 因此,在systemd作为init system的系统中,默认并存着两套groupdriver。
  • 这会似的系统中docker和kubelet管理的进程被cgroupfs驱动管,而systemd拉起的服务由systemd驱动管,让cgroup管理混乱且容易在资源紧张时引发问题。

因此kubelet会默认--cgroup-driver=systemd,若运行时cgroup不一致时,kubelet会报错

所以在搭建kubrnetes集群的时候,你往往需要去修改docker本身的cgroup driver,那么kubelet才能够启动起来。

总结 


实现了在主机上面启动的进程,但是通过cgroup控制使用多少资源,就算你程序有bug也是不能多使用资源。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: registry-1.docker.io/v2/ 是一个Docker镜像仓库。Docker镜像是一种轻量级虚拟化技术,它允许开发者将应用程序和其依赖项打包在一个可移植的容器中。然后,这些容器可以在不同的操作系统上运行,提供了更高的灵活性和便携性。 registry-1.docker.io/v2/ 是Docker官方的公共镜像仓库,也是最常用的镜像仓库之一。在这个仓库中,开发者可以找到各种类型的镜像,如操作系统镜像、数据库镜像、Web服务器镜像等。这些镜像是由Docker社区维护和更新的,有许多开发者可以共享和使用。 通过访问 registry-1.docker.io/v2/ ,开发者可以搜索并获取所需的镜像。他们还可以上传自己的镜像,以便与其他人分享。通过使用这个镜像仓库,开发者可以节省大量的时间和精力,因为他们可以直接使用他人共享的镜像,而不需要从头开始构建。 registry-1.docker.io/v2/ 的存在使得Docker生态系统更加强大和精简。它提供了一个集中存储镜像的地方,帮助开发者快速获取、分享和部署容器化应用程序。这个仓库是Docker技术的重要组成部分,为开发者提供了更好的使用体验和更高效的开发工作流程。 ### 回答2: egistry-1.docker.io/v2/是一个Docker镜像仓库的地址。Docker是一种容器化技术,用于轻量级的应用程序和服务的封装和分发。它可以将应用程序及其依赖项打包成一个镜像,并在不同的环境中运行。镜像仓库是存储和共享这些Docker镜像的地方。 egistry-1.docker.io/v2/是Docker官方的一个镜像仓库地址。在这个仓库中,用户可以下载和上传各种Docker镜像。这个地址中的"/v2"表示使用的是Docker镜像版本2的仓库。 使用egistry-1.docker.io/v2/可以实现很多功能。首先,用户可以通过该地址获取他们需要的Docker镜像。例如,如果用户想要一个包含特定操作系统和软件的镜像,他们可以使用该地址在仓库中搜索并下载满足他们需求的镜像。 同时,用户也可以将他们自己制作的Docker镜像上传到该地址。这样其他人就可以通过该地址进行下载和使用。这种共享镜像的方式可以节省时间和资源,提高开发效率。 除了下载和上传功能外,egistry-1.docker.io/v2/还提供了一些其他的功能。例如,用户可以在该地址注册一个帐户,以便管理和跟踪他们下载和上传的镜像。他们还可以查看有关特定镜像的信息,如版本、构建日期和作者等。 总之,egistry-1.docker.io/v2/是一个功能强大的Docker镜像仓库地址,可以帮助用户下载和上传各种Docker镜像,实现高效的软件开发和部署。 ### 回答3: registry-1.docker.io/v2/ 是一个Docker镜像仓库的URL。Docker镜像仓库是一个用于存储和管理Docker镜像的服务器。Docker镜像是一个可重复部署的软件包,其中包含了运行一个应用程序所需的所有依赖项。registry-1.docker.io/v2/ 是Docker官方的公共镜像仓库,可以通过该URL访问到它的第二个版本。在这个镜像仓库中,用户可以浏览和下载各种不同的Docker镜像,这些镜像可以用于快速构建和部署容器化应用程序。 Docker镜像仓库中的镜像是通过标签进行识别和区分的。每个镜像可以有多个不同的标签,每个标签对应一个版本。当用户拉取(pull)一个镜像时,可以通过给定镜像的标签来指定所需的版本。registry-1.docker.io/v2/ 中存储了大量常用的Docker镜像,例如操作系统的镜像、开发语言的镜像等等,用户可以根据自己的需求选择合适的镜像来构建自己的应用程序。 该URL中的/v2/表示该镜像仓库正在使用Docker Registry V2的协议。Docker Registry V2是Docker镜像仓库的一种升级版本,它提供了更好的性能和可扩展性。通过/v2/路径,可以访问到该镜像仓库的V2版本,从而能够利用V2协议的新特性和功能。 总之,registry-1.docker.io/v2/ 是Docker官方的公共镜像仓库的URL,用户可以通过该URL访问到大量常用的Docker镜像,并使用这些镜像来构建和部署自己的容器化应用程序。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值