Linux CGroup学习 – 入门篇

对于hadoop和hbase公用的集群来说,经常会发生实时性要求较高的任务被大任务抢占资源,严重的情况下,region server进程也会挂掉,集群的资源竞争日益严重。在下一代hadoop yarn中采用了cgroup对系统资源进行隔离,目前的hadoop-2.0.5-alpha版只考虑了对内存和CPU资源的隔离。最近学习了下cgroup,记录在此。

CGroup简介

cgroup的全称是Control Group(控制群组),是linux kernel里的一种资源管理机制,用来限制,记录和隔离资源。最早是2006年由Google的工程师开发,后来合并到kernel 2.6.24中.

cgroup的特点和应用场景有:

  1. 限制资源的使用:比如某个应用程序占用了大部分的系统资源,导致别的程序无法执行,或者在多核机器上,让某个应用程序只能使用某些CPU,保留一些给其他程序使用,或者限制程序只能使用最多2G的内存。
  2. 使用资源的优先权:让某个程序比另外一个程序使用更多的CPU。
  3. 记录CPU的使用量以收取费用:对于某些提供计算资源的公司来说,需要对CPU的使用进行收费,但是如果计算使用者到底使用了多少CPU呢?传统的方法是统计整个系统上所有指令使用的CPU时间,然后进行分析,现在通过cgroup很容易实现。
  4. 隔离不同群组的进程:对于不同群组的进程做到隔离,可用于lxc(linux container)。
  5. freezing: 暂停和恢复任务

各个模块介绍

cgroup使用预定义的控制器(子系统)来决定具体的资源限制类型,以及具体的限制参数,通过挂载伪文件系统的方式来读取设置、应用控制细节。cgroup包含了多个孤立的子系统,每一个子系统代表一个单一的资源,具有集中管理的便利性。可用的控制子系统主要包括:

  • blkio: 限制每个块设备的输入输出控制。例如:磁盘,光盘以及usb等等。
  • cpu: 为任务所使用的cpu时间提供调度控制
  • cpuacct:为任务自动生成cpu资源使用报告
  • cpuset: 为任务分配独立CPU(对于多核处理器)和内存节点
  • devices: 允许或者拒绝某些任务访问指定的设备
  • freezer: 允许挂起或者恢复群组中的任务
  • memory:限制任务所使用的内存,并自动生成内存资源报告
  • net_cls: 用类标识符(classid)来标记网络包,以便Linux流量控制(tc)能够分辨 cgroup 中的特定任务所发出的数据包
  • ns: 允许为任务分配不同的名称空间

CGroup的使用

先检查当前系统是否支持cgroup:

[baoniu@search0404.sqa.cm1 ~]$ cat /proc/cgroups 
#subsys_name    hierarchy       num_cgroups     enabled
cpuset  0       1       1
ns      0       1       1
cpu     0       1       1
cpuacct 0       1       1
memory  0       1       1
devices 0       1       1
freezer 0       1       1
net_cls 0       1       1
blkio   0       1       1
perf_event      0       1       1

libcgroup工具

RHEL 6系统提供了libcgroup来管理Cgroups,该软件包中包含了一系列Cgroup工具及其使用手册。我们可以使用它来绑定Cgroups层次结构,设置Cgroups参数。如果不安装libcgroup,就需要自己手工mount挂载和用shell语句写文件的方式来设置参数了。

libcgroup的安装:

yum install libcgroup

cgconfig服务的启动和停止:

service cgconfig start|stop

cgconfig服务默认是不随系统启动的,我们可以使用chkconfig来配置它随系统启动,以便每次系统重启后都能自动恢复之前的Cgroups配置。

chkconfig cgconfig on

cgconfig服务启动时,会读取配置文件/etc/cgconfig.conf的内容,根据其内容创建和挂载指定的cgroup子系统。

启动cgconfig服务后,可以通过lsubsys命令查看对应的子系统被mount到哪个目录:

[baoniu@search0404.sqa.cm1 ~]$ lssubsys  -m
cpuset /cgroup/cpuset
cpu /cgroup/cpu
cpuacct /cgroup/cpuacct
memory /cgroup/memory
devices /cgroup/devices
freezer /cgroup/freezer
net_cls /cgroup/net_cls
blkio /cgroup/blkio

或者,查看/proc/mounts文件也能看到挂载的文件系统:

[baoniu@search0404.sqa.cm1 ~]$ cat /proc/mounts
rootfs / rootfs rw 0 0
/dev/root / ext3 rw,relatime,errors=continue,user_xattr,acl,barrier=1,data=ordered 0 0
/dev /dev tmpfs rw,relatime,mode=755 0 0
/proc /proc proc rw,relatime 0 0
/sys /sys sysfs rw,relatime 0 0
/dev/sda1 /boot ext3 
cgroup /cgroup/cpuset cgroup rw,relatime,cpuset 0 0
cgroup /cgroup/cpu cgroup rw,relatime,cpu 0 0
cgroup /cgroup/cpuacct cgroup rw,relatime,cpuacct 0 0
cgroup /cgroup/memory cgroup rw,relatime,memory 0 0
cgroup /cgroup/devices cgroup rw,relatime,devices 0 0
cgroup /cgroup/freezer cgroup rw,relatime,freezer 0 0
cgroup /cgroup/net_cls cgroup rw,relatime,net_cls 0 0
cgroup /cgroup/blkio cgroup rw,relatime,blkio 0 0

然后,查看 /cgroup 目录可以看到挂载后会出现响应的目录和文件:

[baoniu@search0404.sqa.cm1]$ ll /cgroup/
total 0
drwxr-xr-x 2 root root 0 Jun 25 10:01 blkio
drwxr-xr-x 2 root root 0 Jun 25 10:01 cpu
drwxr-xr-x 2 root root 0 Jun 25 10:01 cpuacct
drwxr-xr-x 2 root root 0 Jun 25 10:01 cpuset
drwxr-xr-x 2 root root 0 Jun 25 10:01 devices
drwxr-xr-x 2 root root 0 Jun 25 10:01 freezer
drwxr-xr-x 2 root root 0 Jun 25 10:01 memory
drwxr-xr-x 2 root root 0 Jun 25 10:01 net_cls
[baoniu@search0404.sqa.cm1]$ ll /cgroup/cpuset
total 0
-r--r--r-- 1 root root 0 Jun 25 10:01 cgroup.procs
-rw-r--r-- 1 root root 0 Jun 25 10:01 cpuset.cpu_exclusive
-rw-r--r-- 1 root root 0 Jun 25 10:01 cpuset.cpus
-rw-r--r-- 1 root root 0 Jun 25 10:01 cpuset.mem_exclusive
-rw-r--r-- 1 root root 0 Jun 25 10:01 cpuset.mem_hardwall
-rw-r--r-- 1 root root 0 Jun 25 10:01 cpuset.memory_migrate
-r--r--r-- 1 root root 0 Jun 25 10:01 cpuset.memory_pressure
-rw-r--r-- 1 root root 0 Jun 25 10:01 cpuset.memory_pressure_enabled
-rw-r--r-- 1 root root 0 Jun 25 10:01 cpuset.memory_spread_page
-rw-r--r-- 1 root root 0 Jun 25 10:01 cpuset.memory_spread_slab
-rw-r--r-- 1 root root 0 Jun 25 10:01 cpuset.mems
-rw-r--r-- 1 root root 0 Jun 25 10:01 cpuset.sched_load_balance
-rw-r--r-- 1 root root 0 Jun 25 10:01 cpuset.sched_relax_domain_level
-rw-r--r-- 1 root root 0 Jun 25 10:01 notify_on_release
-rw-r--r-- 1 root root 0 Jun 25 10:01 release_agent
-rw-r--r-- 1 root root 0 Jun 25 10:01 tasks

此时,可以通过shell命令或者libcgroup提供的工具来使用cgroup了。 比如有两个进程10318和10320,想让10318进程使用CPU的第1个核,而10320进程使用CPU的第5和6两个核,操作如下:

sudo mkdir /cgroup/cpuset/first_core       
sudo mkdir /cgroup/cpuset/second_core
sudo chown -R baoniu:users /cgroup/cpuset

echo 0 > /cgroup/cpuset/first_core/cpuset.mems 
echo 1 > /cgroup/cpuset/first_core/cpuset.cpus 
echo 10318 > /cgroup/cpuset/first_core/tasks

echo 0 > /cgroup/cpuset/second_core/cpuset.mems 
echo 5-6 > /cgroup/cpuset/second_core/cpuset.cpus   
echo 10320 > /cgroup/cpuset//second_core/tasks

其中,在设置cpuset.cpus之前需要先设置内存节点cpuset.mems,详见NUMA

cgroup配置文件

/etc/cgconfig.conf是cgroup配置工具libcgroup用来进行cgroup组的定义,参数设定以及挂载点定义的配置文件,主要由mount和group两个section构成。(参考:cgroup介绍、安装和配置文件解析 

(1) mount section的语法格式如下:

mount {
    <controller> = <path>;
    ...
}
#########################################
# controller:内核子系统的名称
# path:该子系统的挂载点
#########################################

例如:

mount {
    cpu = /cgroup/cpu_test;
}

上面的定义相当于如下shell指令:

mkdir /cgroup/cpu_test
mount -t cgroup -o cpu cpu_test /cgroup/cpu_test

(2) group section的语法格式如下:

group <name> {
  [<permissions>]
  <controller> {
    <param name> = <param value>;
    …
  }
  …
 }
  ################################################################################
  ## name: 指定cgroup的名称
  ## permissions:可选项,指定cgroup对应的挂载点文件系统的权限,root用户拥有所有权限。
  ## controller:子系统的名称
  ## param name 和 param value:子系统的属性及其属性值
  #################################################################################

例如:

mount { ## 定义需要创建的cgroup子系统及其挂载点,这里创建cpu与cpuacct(统计)两个cgroup子系统
  cpu = /mnt/cgroups/cpu;
  cpuacct = /mnt/cgroups/cpu;
}

group daemons/www { ## 定义daemons/www(web服务器进程)组
perm {    ## 定义这个组的权限
    task {
        uid = root;
        gid = webmaster;
            }
            admin {
                uid = root;
                    gid = root;
            }
        }

    cpu {    ## 定义cpu子系统的属性及其值,即属于此组的任务的权重为1000
        cpu.shares = 1000;
        }
}

group daemons/ftp { ## 定义daemons/ftp(ftp进程)组
perm {
    task {
        uid = root;
        gid = ftpmaster;
                 }
    admin {
        uid = root;
        gid = root;
    }
}
    cpu {  ## 定义此组的任务的权重为500
        cpu.shares = 500;
    }
}

上面配置文件定义相当于执行了如下shell命令:

mkdir /mnt/cgroups/cpu
mount -t cgroup -o cpu,cpuacct cpu /mnt/cgroups/cpu
mkdir /mnt/cgroups/cpu/daemons
mkdir /mnt/cgroups/cpu/daemons/www
chown root:root /mnt/cgroups/cpu/daemons/www/*
chown root:webmaster /mnt/cgroups/cpu/daemons/www/tasks
echo 1000 > /mnt/cgroups/cpu/daemons/www/cpu.shares
mkdir /mnt/cgroups/cpu/daemons/ftp
chown root:root /mnt/cgroups/cpu/daemons/ftp/*
chown root:ftpmaster /mnt/cgroups/cpu/daemons/ftp/tasks
echo 500 > /mnt/cgroups/cpu/daemons/ftp/cpu.shares

注: 修改 /etc/cgconfig.conf 之后,需要重启cgconfig服务来使配置生效。

libcgroup命令行工具

libcgroup提供了很多工具,可以方便操作cgroup, 如使用cgcreate命令创建一个cgroup

cgcreate -g cpu,net_cls:/test-subgroup

此外,还有cgclassify,cgclear,cgconfigparser,cgdelete,cgexec,cgget,cgset…等一系列命令,可以用man查看这些命令的用法,如

man cgclear

CGroup学习资料

linux kernel中关于cgroup的文档

RedHat的红​​​帽​​​企​​​业​​​版​​​ Linux 6 资​​​源​​​管​​​理​​​指​​​南(中文版)​​​ | 更多RedHat的文档…

发表评论

电子邮件地址不会被公开。 必填项已用*标注