CGroup 介紹、應用實例及原理描述


CGroup 介紹

CGroup 是 Control Groups 的縮寫,是 Linux 內核提供的一種可以限制、記錄、隔離進程組 (process groups) 所使用的物力資源 (如 cpu memory i/o 等等) 的機制。2007 年進入 Linux 2.6.24 內核,CGroups 不是全新創造的,它將進程管理從 cpuset 中剝離出來,作者是 Google 的 Paul Menage。CGroups 也是 LXC 為實現虛擬化所使用的資源管理手段。

CGroup 功能及組成

CGroup 是將任意進程進行分組化管理的 Linux 內核功能。CGroup 本身是提供將進程進行分組化管理的功能和接口的基礎結構,I/O 或內存的分配控制等具體的資源管理功能是通過這個功能來實現的。這些具體的資源管理功能稱為 CGroup 子系統或控制器。CGroup 子系統有控制內存的 Memory 控制器、控制進程調度的 CPU 控制器等。運行中的內核可以使用的 Cgroup 子系統由/proc/cgroup 來確認。

CGroup 提供了一個 CGroup 虛擬文件系統,作為進行分組管理和各子系統設置的用戶接口。要使用 CGroup,必須掛載 CGroup 文件系統。這時通過掛載選項指定使用哪個子系統。

Cgroups提供了以下功能:
    1.限制進程組可以使用的資源數量(Resource limiting )。比如:memory子系統可以為進程組設定一個memory使用上限,一旦進程組使用的內存達到限額再申請內存,就會出發OOM(out of memory)。
    2.進程組的優先級控制(Prioritization )。比如:可以使用cpu子系統為某個進程組分配特定cpu share。
    3.記錄進程組使用的資源數量(Accounting )。比如:可以使用cpuacct子系統記錄某個進程組使用的cpu時間
    4.進程組隔離(Isolation)。比如:使用ns子系統可以使不同的進程組使用不同的namespace,以達到隔離的目的,不同的進程組有各自的進程、網絡、文件系統掛載空間。
    5.進程組控制(Control)。比如:使用freezer子系統可以將進程組掛起和恢復。

CGroup 支持的文件種類

表 1. CGroup 支持的文件種類
文件名 R/W 用途

Release_agent

RW

刪除分組時執行的命令,這個文件只存在於根分組

Notify_on_release

RW

設置是否執行 release_agent。為 1 時執行

Tasks

RW

屬於分組的線程 TID 列表

Cgroup.procs

R

屬於分組的進程 PID 列表。僅包括多線程進程的線程 leader 的 TID,這點與 tasks 不同

Cgroup.event_control

RW

監視狀態變化和分組刪除事件的配置文件

CGroup 相關概念解釋

  1. 任務(task)。在 cgroups 中,任務就是系統的一個進程;

  2. 控制族群(control group)。控制族群就是一組按照某種標准划分的進程。Cgroups 中的資源控制都是以控制族群為單位實現。一個進程可以加入到某個控制族群,也從一個進程組遷移到另一個控制族群。一個進程組的進程可以使用 cgroups 以控制族群為單位分配的資源,同時受到 cgroups 以控制族群為單位設定的限制;

  3. 層級(hierarchy)。控制族群可以組織成 hierarchical 的形式,既一顆控制族群樹。控制族群樹上的子節點控制族群是父節點控制族群的孩子,繼承父控制族群的特定的屬性;

  4. 子系統(subsystem)。一個子系統就是一個資源控制器,比如 cpu 子系統就是控制 cpu 時間分配的一個控制器。子系統必須附加(attach)到一個層級上才能起作用,一個子系統附加到某個層級以后,這個層級上的所有控制族群都受到這個子系統的控制。

相互關系

  1. 每次在系統中創建新層級時,該系統中的所有任務都是那個層級的默認 cgroup(我們稱之為 root cgroup,此 cgroup 在創建層級時自動創建,后面在該層級中創建的 cgroup 都是此 cgroup 的后代)的初始成員;

  2. 一個子系統最多只能附加到一個層級;

  3. 一個層級可以附加多個子系統;

  4. 一個任務可以是多個 cgroup 的成員,但是這些 cgroup 必須在不同的層級;

  5. 系統中的進程(任務)創建子進程(任務)時,該子任務自動成為其父進程所在 cgroup 的成員。然后可根據需要將該子任務移動到不同的 cgroup 中,但開始時它總是繼承其父任務的 cgroup。

圖 1. CGroup 層級圖
圖 1. CGroup 層級圖

圖 1 所示的 CGroup 層級關系顯示,CPU 和 Memory 兩個子系統有自己獨立的層級系統,而又通過 Task Group 取得關聯關系。

CGroup 特點

在 cgroups 中,任務就是系統的一個進程。

控制族群(control group)。控制族群就是一組按照某種標准划分的進程。Cgroups 中的資源控制都是以控制族群為單位實現。一個進程可以加入到某個控制族群,也從一個進程組遷移到另一個控制族群。一個進程組的進程可以使用 cgroups 以控制族群為單位分配的資源,同時受到 cgroups 以控制族群為單位設定的限制。

層級(hierarchy)。控制族群可以組織成 hierarchical 的形式,既一顆控制族群樹。控制族群樹上的子節點控制族群是父節點控制族群的孩子,繼承父控制族群的特定的屬性。

子系統(subsytem)。一個子系統就是一個資源控制器,比如 cpu 子系統就是控制 cpu 時間分配的一個控制器。子系統必須附加(attach)到一個層級上才能起作用,一個子系統附加到某個層級以后,這個層級上的所有控制族群都受到這個子系統的控制。

子系統的介紹

blkio   -- 這個子系統為塊設備設定輸入/輸出限制,比如物理設備(磁盤,固態硬盤,USB 等等)。
cpu     -- 這個子系統使用調度程序提供對 CPU 的 cgroup 任務訪問。
cpuacct -- 這個子系統自動生成 cgroup 中任務所使用的 CPU 報告。
cpuset  -- 這個子系統為 cgroup 中的任務分配獨立 CPU(在多核系統)和內存節點。
devices -- 這個子系統可允許或者拒絕 cgroup 中的任務訪問設備。

freezer -- 這個子系統掛起或者恢復 cgroup 中的任務。
memory  -- 這個子系統設定 cgroup 中任務使用的內存限制,並自動生成由那些任務使用的內存資源報告。
net_cls -- 這個子系統使用等級識別符(classid)標記網絡數據包,可允許 Linux 流量控制程序(tc)識別從具體 cgroup 中生成的數據包。

CGroup 應用架構

圖 2. CGroup 典型應用架構圖
圖 2. CGroup 典型應用架構圖

如圖 2 所示,CGroup 技術可以被用來在操作系統底層限制物理資源,起到 Container 的作用。圖中每一個 JVM 進程對應一個 Container Cgroup 層級,通過 CGroup 提供的各類子系統,可以對每一個 JVM 進程對應的線程級別進行物理限制,這些限制包括 CPU、內存等等許多種類的資源。下一部分會具體對應用程序進行 CPU 資源隔離進行演示。

cgroup的安裝

其實安裝很簡單,最佳實踐就是yum直接安裝(centos下)

配置文件

/etc/cgconfig.conf  

 
 
 
         
  1. mount {          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;              
                            }  

cgroup section的語法格式如下

  1. group <name> {  
  2.     [<permissions>]  
  3.     <controller> {  
  4.         <param name> = <param value>;  
  5.         …  
  6.     }  
  7.     …}  

name: 指定cgroup的名稱
permissions:可選項,指定cgroup對應的掛載點文件系統的權限,root用戶擁有所有權限。
controller:子系統的名稱
param name 和 param value:子系統的屬性及其屬性值



7.1 配置對mysql實例的資源限制

    前提:MySQL數據庫已在機器上安裝

    7.1.1 修改cgconfig.conf文件

[plain]  view plain  copy
  1. mount {  
  2.     cpuset  = /cgroup/cpuset;  
  3.     cpu = /cgroup/cpu;  
  4.     cpuacct = /cgroup/cpuacct;  
  5.     memory  = /cgroup/memory;  
  6.         blkio   = /cgroup/blkio;  
  7. }  
  8.   
  9. group mysql_g1 {    
  10.     cpu {  
  11.             cpu.cfs_quota_us = 50000;  
  12.             cpu.cfs_period_us = 100000;  
  13.     }  
  14.     cpuset {    
  15.             cpuset.cpus = "3";    
  16.             cpuset.mems = "0";    
  17.     }    
  18.     cpuacct{  
  19.   
  20.     }  
  21.     memory {    
  22.             memory.limit_in_bytes=104857600;  
  23.             memory.swappiness=0;  
  24.             # memory.max_usage_in_bytes=104857600;  
  25.             # memory.oom_control=0;  
  26.     }   
  27.     blkio  {  
  28.            blkio.throttle.read_bps_device="8:0 524288";  
  29.            blkio.throttle.write_bps_device="8:0 524288";  
  30.     }   
  31. }   

    7.1.2 配置文件的部分解釋。

    cpu:cpu使用時間限額。

    cpu.cfs_period_us和cpu.cfs_quota_us來限制該組中的所有進程在單位時間里可以使用的cpu時間。這里的cfs是完全公平調度器的縮寫。cpu.cfs_period_us就是時間周期(微秒),默認為100000,即百毫秒。cpu.cfs_quota_us就是在這期間內可使用的cpu時間(微秒),默認-1,即無限制。(cfs_quota_us是cfs_period_us的兩倍即可限定在雙核上完全使用)。

    cpuset:cpu綁定

    我們限制該組只能在0一共1個超線程上運行。cpuset.mems是用來設置內存節點的。

    本例限制使用超線程0上的第四個cpu線程。

    其實cgconfig也就是幫你把配置文件中的配置整理到/cgroup/cpuset這個目錄里面,比如你需要動態設置mysql_group1/ cpuset.cpus的CPU超線程號,可以采用如下的辦法。

[plain]  view plain  copy
  1. [root@localhost ~]# echo "0" > mysql_group1/ cpuset.cpus  

    cpuacct:cpu資源報告


    memory:內存限制 

    內存限制我們主要限制了MySQL可以使用的內存最大大小memory.limit_in_bytes=256M。而設置swappiness為0是為了讓操作系統不會將MySQL的內存匿名頁交換出去。

    blkio:BLOCK IO限額

    blkio.throttle.read_bps_device="8:0 524288"; #每秒讀數據上限
    blkio.throttle.write_bps_device="8:0 524288"; #每秒寫數據上限

    其中8:0對應主設備號和副設備號,可以通過ls -l /dev/sda查看

[plain]  view plain  copy
  1. [root@localhost /]# ls -l /dev/sda  
  2. brw-rw----. 1 root disk 8, 0 Sep 15 04:19 /dev/sda  

    7.1.3 拓展知識

    現在較新的服務器CPU都是numa結構<非一致內存訪問結構(NUMA:Non-Uniform Memory Access)>,使用numactl --hardware可以看到numa各個節點的CPU超線程號,以及對應的節點號。

    本例結果如下:

[plain]  view plain  copy
  1. [root@localhost /]# numactl --hardware   
  2. available: 1 nodes (0)  
  3. node 0 cpus: 0 1 2 3  
  4. node 0 size: 1023 MB  
  5. node 0 free: 68 MB  
  6. node distances:  
  7. node   0   
  8.   0:  10   

    以下是較高端服務器的numa信息,僅作參考。

[plain]  view plain  copy
  1. [root@localhost ~]# numactl --hardware     
  2. available: 4 nodes (0-3)  
  3. node 0 cpus: 0 4 8 12 16 20 24 28 32 36 40 44 48 52 56 60  
  4. node 0 size: 16338 MB  
  5. node 0 free: 391 MB  
  6. node 1 cpus: 1 5 9 13 17 21 25 29 33 37 41 45 49 53 57 61  
  7. node 1 size: 16384 MB  
  8. node 1 free: 133 MB  
  9. node 2 cpus: 2 6 10 14 18 22 26 30 34 38 42 46 50 54 58 62  
  10. node 2 size: 16384 MB  
  11. node 2 free: 137 MB  
  12. node 3 cpus: 3 7 11 15 19 23 27 31 35 39 43 47 51 55 59 63  
  13. node 3 size: 16384 MB  
  14. node 3 free: 186 MB  
  15. node distances:  
  16. node   0   1   2   3   
  17.   0:  10  20  30  20   
  18.   1:  20  10  20  30   
  19.   2:  30  20  10  20   
  20.   3:  20  30  20  10  

    7.1.4 修改cgrules.conf文件

[plain]  view plain  copy
  1. [root@localhost ~]# vi /etc/cgrules.conf  
  2. # /etc/cgrules.conf  
  3. #The format of this file is described in cgrules.conf(5)  
  4. #manual page.  
  5. #  
  6. # Example:  
  7. #<user>         <controllers>   <destination>  
  8. #@student       cpu,memory      usergroup/student/  
  9. #peter          cpu             test1/  
  10. #%              memory          test2/  
  11. *:/usr/local/mysql/bin/mysqld * mysql_g1  

    注:共分為3個部分,分別為需要限制的實例,限制的內容(如cpu,memory),掛載目標。

    7.2 使配置生效

[plain]  view plain  copy
  1. [root@localhost ~]# /etc/init.d/cgconfig restart  
  2. Stopping cgconfig service:                                 [  OK  ]  
  3. Starting cgconfig service:                                 [  OK  ]  
  4. [root@localhost ~]# /etc/init.d/cgred restart  
  5. Stopping CGroup Rules Engine Daemon...                     [  OK  ]  
  6. Starting CGroup Rules Engine Daemon:                       [  OK  ]  

    注:重啟順序為cgconfig -> cgred ,更改配置文件后兩個服務需要重啟,且順序不能錯。

    7.3 啟動MySQL,查看MySQL是否處於cgroup的限制中

[plain]  view plain  copy
  1. [root@localhost ~]# ps -eo pid,cgroup,cmd | grep -i mysqld  
  2. 29871 blkio:/;net_cls:/;freezer:/;devices:/;memory:/;cpuacct:/;cpu:/;cpuset:/ /bin/sh ./bin/mysqld_safe --defaults-file=/etc/my.cnf --basedir=/usr/local/mysql/ --datadir=/usr/local/mysql/data/  
  3. 30219 blkio:/;net_cls:/;freezer:/;devices:/;memory:/;cpuacct:/;cpu:/;cpuset:/mysql_g1 /usr/local/mysql/bin/mysqld --defaults-file=/etc/my.cnf --basedir=/usr/local/mysql/ --datadir=/usr/local/mysql/data/ --plugin-dir=/usr/local/mysql//lib/plugin --user=mysql --log-error=/usr/local/mysql/data//localhost.localdomain.err --pid-file=/usr/local/mysql/data//localhost.localdomain.pid --socket=/tmp/mysql.sock --port=3306  
  4. 30311 blkio:/;net_cls:/;freezer:/;devices:/;memory:/;cpuacct:/;cpu:/;cpuset:/ grep -i mysqld  

    7.4 資源限制驗證

    使用mysqlslap對mysql進行壓力測試,看mysql使用資源是否超過限制。

    7.4.1 在shell窗口1用mysqlslap對mysql進行壓力測試。

[plain]  view plain  copy
  1. [root@localhost /]# /usr/local/mysql/bin/mysqlslap --defaults-file=/etc/my.cnf --concurrency=150 --iterations=1 --number-int-cols=8 --auto-generate-sql --auto-generate-sql-load-type=mixed --engine=innodb --number-of-queries=100000 -ujesse -pjesse --number-char-cols=35 --auto-generate-sql-add-autoincrement --debug-info -P3306 -h127.0.0.1  

    7.4.2 在shell窗口2查看mysql對cpu,內存的使用

    可見:cpu限制在了第四個核心上,且對第四個核心的使用限制在50%。

    7.4.3 在shell窗口3查看io的消耗


    可見:mysql對io的讀及寫消耗均限制在2M每秒以內。

8 cgroup實例分析(手工動態驗證)

    還原配置文件/etc/cgconfig.conf及/etc/cgrules.conf 為默認配置。測試實例依然為mysql,測試工具為mysqlslap。

    開啟cgconfig及cgrules 服務。

[plain]  view plain  copy
  1. [root@localhost /]# /etc/init.d/cgconfig restart  
  2. Stopping cgconfig service:                                 [  OK  ]  
  3. Starting cgconfig service:                                 [  OK  ]  
  4. [root@localhost /]# /etc/init.d/cgred restart  
  5. Stopping CGroup Rules Engine Daemon...                     [  OK  ]  
  6. Starting CGroup Rules Engine Daemon:                       [  OK  ]  

    開啟mysqlslap壓力測試程序。

[plain]  view plain  copy
  1. [root@localhost /]# /usr/local/mysql/bin/mysqlslap --defaults-file=/etc/my.cnf --concurrency=150 --iterations=1 --number-int-cols=8 --auto-generate-sql --auto-generate-sql-load-type=mixed --engine=innodb --number-of-queries=100000 -ujesse -pjesse --number-char-cols=35 --auto-generate-sql-add-autoincrement --debug-info -P3306 -h127.0.0.1  

    通過htop查看資源消耗。


    8.1 cpu限制實例

    限制mysql使用一個核,如第2個核,且對該核的使用不超過50%

[plain]  view plain  copy
  1. [root@localhost /]# mkdir -p /cgroup/cpu/foo/  
  2. [root@localhost /]# mkdir -p /cgroup/cpuset/foo/  
  3. [root@localhost /]# echo 50000 > /cgroup/cpu/foo/cpu.cfs_quota_us  
  4. [root@localhost /]# echo 100000 > /cgroup/cpu/foo/cpu.cfs_period_us  
  5. [root@localhost /]# echo "0" > /cgroup/cpuset/foo/cpuset.mems  
  6. [root@localhost /]# echo "1" > /cgroup/cpuset/foo/cpuset.cpus  
  7. [root@localhost /]# echo 28819 > /cgroup/cpu/foo/tasks   

    其中:28819為mysqld的進程號。


    8.2 內存限制實例

    限制mysql使用內存為不超過512M

    跑一個消耗內存腳本

[plain]  view plain  copy
  1. x='a'  
  2. while [ True ];do  
  3.     x=$x$x  
  4. done;  


    內存的消耗在不斷增加,對其進行限制,使其使用內存在500M以內

[plain]  view plain  copy
  1. [root@localhost /]# mkdir -p /cgroup/memory/foo  
  2. [root@localhost /]# echo 524288000 >  /cgroup/memory/foo/memory.limit_in_bytes  
  3. [root@localhost /]# echo 44476 > /cgroup/memory/foo/tasks   


    內存使用得到了有效控制。

    8.3 IO限制實例

    跑一個消耗IO的測試

[plain]  view plain  copy
  1. [root@localhost ~]# dd if=/dev/sda of=/dev/null   

    通過iotop看io占用情況,磁盤讀取速度到了50M/s

 
    限制讀取速度為10M/S

[plain]  view plain  copy
  1. [root@localhost ~]# mkdir -p /cgroup/blkio/foo  
  2. [root@localhost ~]# echo '8:0   10485760' >  /cgroup/blkio/foo/blkio.throttle.read_bps_device  
  3. [root@localhost ~]# echo 45033 > /cgroup/blkio/foo/tasks  

    注1:45033為dd的進程號

    注2:8:0對應主設備號和副設備號,可以通過ls -l /dev/sda查看

[plain]  view plain  copy
  1. [root@localhost ~]# ls -l /dev/sda  
  2. brw-rw----. 1 root disk 8, 0 Sep 15 04:19 /dev/sda  

9 cgroup小結

    使用cgroup臨時對進程進行調整,直接通過命令即可,如果要持久化對進程進行控制,即重啟后依然有效,需要寫進配置文件/etc/cgconfig.conf及/etc/cgrules.conf 

   

****************************************************************************************
    原文地址:http://blog.csdn.net/jesseyoung/article/details/39077829
    博客主頁:http://blog.csdn.net/jesseyoung







免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM