浅谈Cgroups

开发 开发工具
随着容器技术的成熟,系统的定制和软件的打包变得越来越容易,同时,对容器进行监控成为了容器使用者所必备的技能。下来,作者将带领大家认识一下容器的资源管理工具Cgroups。

在开发一款软件时,为了延长软件的生命周期,需要一款配套软件来对发布的软件进行监控。随着容器技术的成熟,系统的定制和软件的打包变得越来越容易,同时,对容器进行监控成为了容器使用者所必备的技能。下来,作者将带领大家认识一下容器的资源管理工具Cgroups。

[[266064]]

说起容器监控,首先会想到通过Cadvisor, Docker stats等多种方式获取容器的监控数据,并同时会想到容器通过Cgroups实现对容器中的资源进行限制。但是这些数据来自哪里,并且如何计算的?答案是Cgroups。最近在写docker容器监控组件,在深入Cadvisor和Docker stats源码发现数据都来源于Cgroups。了解之余,并对Cgroups做下笔记。

一、Cgroups介绍

Cgroups 是 control groups 的缩写,是Linux内核提供的一种可以限制,记录,隔离进程组(process groups)所使用物理资源的机制。最初有google工程师提出,后来被整合进Linux的内核。因此,Cgroups为容器实现虚拟化提供了基本保证,是构建Docker,LXC等一系列虚拟化管理工具的基石。

二、Cgroups作用

  • 资源限制(Resource limiting): Cgroups可以对进程组使用的资源总额进行限制。如对特定的进程进行内存使用上限限制,当超出上限时,会触发OOM。
  • 优先级分配(Prioritization): 通过分配的CPU时间片数量及硬盘IO带宽大小,实际上就相当于控制了进程运行的优先级。
  • 资源统计(Accounting): Cgroups可以统计系统的资源使用量,如CPU使用时长、内存用量等等,这个功能非常适用于计费。
  • 进程控制(ControlCgroups): 可以对进程组执行挂起、恢复等操作。

三、Cgroups 组成

Cgroups主要由task,cgroup,subsystem及hierarchy构成。下面分别介绍下各自的概念。

  • task::在Cgroups中,task就是系统的一个进程。
  • cgroup: :Cgroups中的资源控制都以cgroup为单位实现的。cgroup表示按照某种资源控制标准划分而成的任务组,包含一个或多个子系统。一个任务可以加入某个cgroup,也可以从某个cgroup迁移到另外一个cgroup。
  • subsystem::Cgroups中的subsystem就是一个资源调度控制器(Resource Controller)。比如CPU子系统可以控制CPU时间分配,内存子系统可以限制cgroup内存使用量。
  • hierarchy::hierarchy由一系列cgroup以一个树状结构排列而成,每个hierarchy通过绑定对应的subsystem进行资源调度。hierarchy中的cgroup节点可以包含零或多个子节点,子节点继承父节点的属性。整个系统可以有多个hierarchy。

组件之间的关系:

Subsystems, Hierarchies,Control Group和Tasks之间有许多的规则,下面介绍下:

(1) 同一个hierarchy能够附加一个或多个subsystem。

如下图,将cpu和memory subsystems(或者任意多个subsystems)附加到同一个hierarchy。

(2) 一个subsystem只能附加到一个hierarchy上。

如下图,cpu subsystem已经附加到了hierarchy A,并且memory subsystem已经附加到了hierarchy B。因此cpusubsystem不能在附加到hierarchy B。

Cgroups

(3) 系统每次新建一个hierarchy时,该系统上的所有task默认构成了这个新建的hierarchy的初始化cgroup,这个cgroup也称为root cgroup。对于你创建的每个hierarchy,task只能存在于其中一个cgroup中,即一个task不能存在于同一个hierarchy的不同cgroup中,但是一个task可以存在在不同hierarchy中的多个cgroup中。如果操作时把一个task添加到同一个hierarchy中的另一个cgroup中,则会从第一个cgroup中移除。

如下图,cpu和memory被附加到cpu_mem_cg的hierarchy。而net_cls被附加到net_cls hierarchy。并且httpd进程被同时加到了cpu_mem_cg hierarchy的cg1 cgroup中和net hierarchy的cg3 cgroup中。并通过两个hierarchy的subsystem分别对httpd进程进行cpu,memory及网络带宽的限制。

Cgroups

(4) 系统中的任何一个task(Linux中的进程)fork自己创建一个子task(子进程)时,子task会自动的继承父task cgroup的关系,在同一个cgroup中,但是子task可以根据需要移到其它不同的cgroup中。父子task之间是相互独立不依赖的。

如下图,httpd进程在cpu_and_mem hierarchy的/cg1 cgroup中并把PID 4537写到该cgroup的tasks中。之后httpd(PID=4537)进程fork一个子进程httpd(PID=4840)与其父进程在同一个hierarchy的统一个cgroup中,但是由于父task和子task之间的关系独立不依赖的,所以子task可以移到其它的cgroup中。

Cgroups

四、Cgroups使用

我们直接使用shell 命令直接操作hierarchy并设置cgroup参数。在centos6上也可以直接使用libcgroup提供的工具可简化对cgroup的使用。

(1) Create a Hierarchy

使用shell命令创建hierarchy并附加subsystems到该hierarchy上。 作为root为hierarchy创建一个mount point。并且在mount point中包含cgrou的名字。

Cgroups

例如:

接下来使用mount命令去挂载hierarchy并附加一个或多个subsystem到该hierarchy上。

例如:

如果想在已有的hierarchy上attch或detach subsystem,可以使用remount操作,例如我们想detach掉memory subsystem。

(2) Unmounting a Hierarchy

可以直接用umount命令来unmount一个已有的Hierarchy:

Cgroups

例如:

Cgroups

(3) Creating Control Groups

直接使用shell命令mkdir创建一个子cgroup:

Cgroups

例如:

(4) Setting Control Cgroup Parameters

在group1中使用echo命令插入0-1到cpuset.cpus,来限制该cgroup中的tasks只能跑在0和1的cpu core上。如下:

(5) Moving a Process to a Control Group

只要将想要限制的进程PID,追加到想要的cgroup的tasks文件中就可以了。例如:将PID=1701的进程放到“/cgroup/cpu_and_mem/group1/”的cgroup中。

五、Subsystem 介绍

  • blkio: blkio 子系统控制并监控cgroup中的task对块设备的I/O的访问。如:限制访问及带宽等。
  • cpu: 主要限制进程的cpu使用率。
  • cpuacct: 可以统计cgroup中进程的cpu使用报告。
  • cpuset: 可以为cgroup中的进程分配独立的cpu和内存节点。
  • memory: 自动生成cgroup中task使用的内存资源报告,并对该cgroup的task进行内存使用限制。
  • devices: 可以控制进程能否访问某些设备。
  • net_cls: 使用等级标识符(clssid)标记网络数据包,可允许Linux流量控制程序(tc)识别从具体cgroup中生成的数据包。
  • freezer: 可以挂起或回复cgroup中的进程。
  • ns: 可以使不同cgroup中的进程使用不同的namespace。

六、容器使用Cgroups进行资源限制

无论是使用docker run方式直接创建容器,还是通过各类容器编排工具(如:Kubernetes)创建容器,对于容器的限制本质都是通过Cgroups。我们分别使用这两种方式来创建容器并观察cgroups:

测试环境:

Cgroups

1. 使用docker run方式创建容器

(1) 限制CPU share,创建两个容器,则会在运行该容器宿主的/sys/fs/cgroup/cpu/docker/ 下分别创建两个子cgroup,格式如下。

Cgroups

(2) 创建一个容器,并设置--cpu-shares参数为:1024*10。

Cgroups

查看该容器cgroup的cpu.shares文件内容如下。

Cgroups

(3) 创建一个容器,并设置--cpu-shares参数为: 1024*14。

查看该容器cgroup的cpu.shares文件内容如下。

(4) 两个容器使用cpu的stats,一个容器分到14核的相对cpu计算时间,另一个容器分到10核的相对cpu计算时间:

Cgroups

2. 限制容器内存使用量

(1) 创建一个容器,限制容器能使用的内存上限为1024M。

Cgroups

(2) 查看容器memory的stats,内存使用率100%。

Cgroups

(3) 当容器使用的内存量超过1024M,则容器会被kill -9掉。

Cgroups

3. 使用Kubenetes容器编排工具创建容器

使用kubernetes编排工具创建的容器,则与容器关联的cgroup均在运行该容器宿主机的/sys/fs/cgroup/cpu/kubepods/下,具体的格式如下所示:

Cgroups

使用Pod创建一个容器,对应的yaml文件内容如下:

在运行该容器的宿主机上查看该容器的cgroup信息,会观察到cpu.shares为1核,memory.limit_in_bytes为2G。

相关文章:

  • https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/resource_management_guide/ch01
  • https://www.kernel.org/doc/Documentation/cgroup-v1/cgroups.txt
  • http://www.infoq.com/cn/articles/docker-kernel-knowledge-cgroups-resource-isolation

【本文是51CTO专栏机构360技术的原创文章,微信公众号“360技术( id: qihoo_tech)”】

戳这里,看该作者更多好文

责任编辑:赵宁宁 来源: 51CTO专栏
相关推荐

2019-07-11 06:22:51

Cgroups容器监控

2014-03-14 13:32:52

cgroupsLinux容器

2021-08-18 10:39:13

Ubuntu 21.1Linux 内核开发人员

2023-12-26 00:55:51

资源隔离CPU

2014-12-01 13:44:03

cgroupscpulimitlinux

2015-06-05 10:08:27

CgroupsIaaSPaaS

2021-01-29 18:09:05

DockerCgroupsLinux

2009-06-08 15:14:54

CMDB运维管理摩卡

2009-12-01 10:29:42

BSM

2011-06-01 14:18:41

JVM

2009-09-09 15:44:22

Linq DataCo

2017-02-23 07:00:25

2012-12-24 13:50:54

2009-06-26 17:34:29

Spring入门

2023-03-06 08:42:45

KCP移动开发

2009-09-15 16:31:15

LINQ Custom

2010-09-16 16:02:26

PPPoA配置

2009-07-16 16:01:55

EventQueue

2013-11-25 14:57:04

TCPTCP优化

2009-09-23 17:07:31

Hibernate C
点赞
收藏

51CTO技术栈公众号