一、Linux CGroup
Cgroups是control groups的縮寫,是Linux內核提供的一種可以限制,記錄,隔離進程組(process groups)所使用物理資源的機制
二、作用
1、Resource limitation: 限制資源使用,比如內存使用上限以及文件系統的緩存限制
2、Prioritization: 優先級控制,比如:CPU利用和磁盤IO吞吐
3、Accounting: 一些審計或一些統計,主要目的是為了計費
4、Control: 掛起進程,恢復執行進程
三、基本概念
Cgroups主要由task,cgroup,subsystem及hierarchy構成
1、task:在Cgroups中,task就是系統的一個進程
2、cgroup
Cgroups中的資源控制都以cgroup為單位實現的。
cgroup表示按照某種資源控制標准划分而成的任務組,包含一個或多個子系統。
一個任務可以加入某個cgroup,也可以從某個cgroup遷移到另外一個cgroup
3、subsystem
Cgroups中的subsystem就是一個資源調度控制器(Resource Controller)。
比如CPU子系統可以控制CPU時間分配,內存子系統可以限制cgroup內存使用量
4、hierarchy
hierarchy由一系列cgroup以一個樹狀結構排列而成,每個hierarchy通過綁定對應的subsystem進行資源調度。
hierarchy中的cgroup節點可以包含零或多個子節點,子節點繼承父節點的屬性。整個系統可以有多個hierarchy
四、組件之間的關系
1、同一個hierarchy能夠附加一個或多個subsystem
cpu和memory subsystems(或者任意多個subsystems)附加到同一個hierarchy

2、cpu subsystem已經附加到了hierarchy A,並且memory subsystem已經附加到了hierarchy B,此時cpu subsystem不能在附加到hierarchy B

3、一個task不能存在於同一個hierarchy的不同cgroup,但可以存在在不同hierarchy中的多個cgroup
系統每次新建一個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 hierarchy。並且httpd進程被同時加到了cpu_mem_cg hierarchy的cg1 cgroup中和net hierarchy的cg3 cgroup中。並通過兩個hierarchy的subsystem分別對httpd進程進行cpu,memory及網絡帶寬的限制。
4、子task繼承父task cgroup的關系
系統中的任何一個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中。

五、Cgroup使用
1、創建hierarchy
# mkdir /cgroup/cpuset # mount -t cgroup -o cpuset cpuset /cgroup/cpuset # mount -t cgroup|grep cpuset cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,cpuset) cpuset on /cgroup/cpuset type cgroup (rw,relatime,cpuset)
2、卸載hierarchy
# umount /cgroup/cpuset
3、創建Cgroup
# mkdir /cgroup/cpuset/group1 # ls /cgroup/cpuset/group1/ cgroup.clone_children cpuset.cpu_exclusive cpuset.effective_mems cpuset.memory_migrate cpuset.memory_spread_slab cpuset.sched_relax_domain_level cgroup.event_control cpuset.cpus cpuset.mem_exclusive cpuset.memory_pressure cpuset.mems notify_on_release cgroup.procs cpuset.effective_cpus cpuset.mem_hardwall cpuset.memory_spread_page cpuset.sched_load_balance tasks # ls /sys/fs/cgroup/cpuset/group1/ cgroup.clone_children cpuset.cpu_exclusive cpuset.effective_mems cpuset.memory_migrate cpuset.memory_spread_slab cpuset.sched_relax_domain_level cgroup.event_control cpuset.cpus cpuset.mem_exclusive cpuset.memory_pressure cpuset.mems notify_on_release cgroup.procs cpuset.effective_cpus cpuset.mem_hardwall cpuset.memory_spread_page cpuset.sched_load_balance tasks
可以看到cpuset子系統同時掛載到cgroup/cpuset和/sys/fs/cgroup/cpuset,其實底層是連接到同一個inode,相當於硬連接
4、設置參數
# echo 0-1 >/cgroup/cpuset/group1/cpuset.cpus # echo 0 >/cgroup/cpuset/group1/cpuset.mems
5、限制進程
# echo 1024 > /sys/fs/cgroup/cpuset/group1/tasks
六、subsystem
1、當前系統支持的子系統
# more /proc/cgroups #subsys_name hierarchy num_cgroups enabled cpuset 9 1 1 cpu 10 2 1 cpuacct 10 2 1 memory 7 2 1 devices 4 1 1 freezer 11 1 1 net_cls 3 1 1 blkio 5 1 1 perf_event 6 1 1 hugetlb 8 1 1 pids 2 2 1 net_prio 3 1 1
- subsys_name:subsystem的名字
- hierarchy:subsystem所關聯到的cgroup樹的ID,如果多個subsystem關聯到同一顆cgroup樹,那么他們的這個字段將一樣
- num_cgroups:subsystem所關聯的cgroup樹中進程組的個數,也即樹上節點的個數
- enabled:是否開啟開子系統,1表示開啟,0表示沒有被開啟
2、子系統介紹
- cpu:用來限制cgroup的CPU使用率。
- cpuacct:統計cgroup的CPU的使用率。
- cpuset:綁定cgroup到指定CPUs和NUMA節點。
- memory:統計和限制cgroup的內存的使用率,包括process memory, kernel memory, 和swap。
- devices:限制cgroup創建(mknod)和訪問設備的權限。
- freezer:suspend和restore一個cgroup中的所有進程。
- net_cls:將一個cgroup中進程創建的所有網絡包加上一個classid標記,用於tc和iptables。 只對發出去的網絡包生效,對收到的網絡包不起作用。
- blkio:限制cgroup訪問塊設備的IO速度。
- perf_event:對cgroup進行性能監控
- net_prio:針對每個網絡接口設置cgroup的訪問優先級。
- hugetlb:限制cgroup的huge pages的使用量。
- pids:限制一個cgroup及其子孫cgroup中的總進程數。
3、查看進程所屬的cgroup
# more /proc/{PID}/cgroup 11:freezer:/ 10:cpuacct,cpu:/ 9:cpuset:/ 8:hugetlb:/ 7:memory:/ 6:perf_event:/ 5:blkio:/ 4:devices:/ 3:net_prio,net_cls:/ 2:pids:/ 1:name=systemd:/system.slice/filebeat.service
第一列:cgroup樹的ID
第二列:和cgroup樹綁定的所有subsystem,多個subsystem之間用逗號隔開。這里name=systemd表示沒有和任何subsystem綁定,只是給他起了個名字叫systemd
第三列:進程在cgroup樹中的路徑,這個路徑是相對於掛載點的相對路徑