浅谈Cgroups

奇技指南在开发一款软件时,为了延长软件的生命周期,需要一款配套软件来对发布的软件进行监控。随着容器技术的成熟,系统的定制和软件的打包变得越来越容易,同时,对容器进行监控成为了容器使用者所必备的技能。下来,作者将带领大家认识一下容器的资源管理工具Cgroups。说起容器监控,首先会想到通过Cadvisor, Docker stats等多种方式获取容器的监控数据,并同时会想到容器通过Cgroups实现对容器中的资源进行限制。但是这些数据来自哪里,并且如何计算的?答案是Cgroups。最近在写docker容器监控组件,在深入Cadvisor和Docker stats源码发现数据都来源于Cgroups。了解之余,并对Cgroups做下笔记。 01、Cgroups介绍Cgroups 是 control groups 的缩写,是Linux内核提供的一种可以限制,记录,隔离进程组(process groups)所使用物理资源的机制。最初有google工程师提出,后来被整合进Linux的内核。因此,Cgroups为容器实现虚拟化提供了基本保证,是构建Docker,LXC等一系列虚拟化管理工具的基石。 02、Cgroups作用资源限制(Resource limiting):Cgroups可以对进程组使用的资源总额进行限制。如对特定的进程进行内存使用上限限制,当超出上限时,会触发OOM。优先级分配(Prioritization): 通过分配的CPU时间片数量及硬盘IO带宽大小,实际上就相当于控制了进程运行的优先级。资源统计(Accounting): Cgroups可以统计系统的资源使用量,如CPU使用时长、内存用量等等,这个功能非常适用于计费。进程控制(ControlCgroups): 可以对进程组执行挂起、恢复等操作。03、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。 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及网络带宽的限制。 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中。 04、Cgroups使用我们直接使用shell 命令直接操作hierarchy并设置cgroup参数。在centos6上也可以直接使用libcgroup提供的工具可简化对cgroup的使用。 Create a Hierarchy使用shell命令创建hierarchy并附加subsystems到该hierarchy上。 作为root为hierarchy创建一个mount point。并且在mount point中包含cgrou的名字。 例如: 接下来使用mount命令去挂载hierarchy并附加一个或多个subsystem到该hierarchy上。 例如: 如果想在已有的hierarchy上attch或detach subsystem,可以使用remount操作,例如我们想detach掉memory subsystem。 ...

May 24, 2019 · 1 min · jiezi

Cgroups原理及其在CephFS-io限流上的应用

奇技指南Cgroups的全称是ControlGroups,它是Linux内核提供的一种能够对cpu,内存等资源实现精细化控制的机制。本文介绍了它的原理以及其在CephFSio限流上的应用。 Cgroups架构“Control Groups”的主要功能是将线程及其子线程分为多个组,以便对他们进行分别控制。其具体工作包括: 将线程分组为用户提供控制每组线程的操作接口(/sys/fs文件)每个control group关联一个cgroup subsystem(controller)。每个subsystem用于控制某项特殊的资源(如可以被调度的cpu核,内存使用总量等),subsystem之间可以存在依赖关系。目前linux默认会加载的subsystem包括:blkio、cpu、cpuacct、cpuset、devices、freezer、hugetlb、memory、net_cls、net_cls,net_prio、net_prio、perf_event、pids、systemd。 如上图所示,在内核中,cgroup会为每个/sys/fs/cgroup下的子目录(subsystem对应目录除外)创建一个css(cgroup_subsys_state)结构,该结构用于关联该目录对应的cgroup结构和所属的subsystem。每个内核线程的task结构中应一个css_set域,可以通过获取其中的css结构,获得其所属的control group信息。 Cgroup的代码实现大致可分为三部分: 在系统启动时(start_kernel), 初始化cgroup_root,init_css_set(init线程的css_set), 各个subsystem;将cgroup_root挂载至/sys/fs/cgroup在线程fork时, 将父线程的css_set赋予子线程, 即:子线程继承父线程的css_set根据各subsystem需求,创建/sys/fs下的subsystem控制接口文件,用户可以通过向这些文件写入数据实现对某个control group的控制,也可通过读取相应文件,获得当前该control group的状态。添加cgroup subsystem/controller添加一个子系统需要完成以下工作: 1、实现一组cgroup要求subsystem实现的api(如下图所示),其中css_alloc和css_free是强制要求实现的,其余均可选;css_alloc用于分配cgroup_subsys_state结构所需的内存,用户可在该函数里初始化自己的subsystem,css_free用于卸载该subsystem时回收相应内存 2、每个子系统拥有一个独立的自定义name,每个子系统需要定义一个struct cgroup_subsys类型的全局变量,该变量名为<name>_cgrp_subsys;将上面实现的cgroup subsystem api赋予该变量相应的域 3、在 inclue/linux/cgroup_subsys.h里,添加属下entry: #if IS_ENABLED(CONFIG_CGROUP_XXX) SUBSYS(<name>) #endif 实现cephfs客户端io限流Cephfs客户端限流的目标:限制cephfs内核客户端元数据/数据操作速率(ops/byte per second)。目前我们采用的限流算法是令牌桶算法。 实现步骤如下: 1、添加include/linux/cgroup_cephfs.h头文件,定义cephfscg结构,其中包含cgroup_subsys_state域;同时定义其他所需类型(如令牌桶限流阀token_bucket_throttle) 2、实现cgroup cephfs subsystem a)实现css_alloc和css_free函数 b)定义cephfs subsystem的接口文件,其中meta_ops和data_ops用于设置元数据操作和数据操作令牌桶的更新周期,meta_ops.iops和data_ops.iops用于设置元数据/数据操作的iops限制,data_ops.band用于设置数据操作的吞吐量限制;除定位文件外,还需要设置这些文件的读写处理函数,这里所有读写操作均由cephfscg_set_throttle_params和cephfscg_throttle_params_read完成; c)定义cephfs_cgrp_subsys变量 d)在Include/linux/cgroup_subsys.h增加相应的entry 3、在cephfs文件操作执行路径上增加相应的控制操作(获取当前task的css结构,并调用其对应的限流接口) 本文介绍了cgroups架构以及添加子系统的方法,并通过cgroups在cephfs中的应用,进一步展示了cgroups精细化控制能力。希望通过整篇文章的介绍,读者能够大致了解cgroups的功能。 相关推荐 浅谈Cgroups (360技术原创内容,转载务必注明出处保存文末二维码图片,谢谢配合。)关注360技术,发现更多有料干货~

May 23, 2019 · 1 min · jiezi