Docker 入門筆記 10 - Control groups

Linux上的Docker Engine也依賴於另一種稱爲CGroup的技術。CGroups 最初叫Process Container,顧名思義就是將進程放到一個組裏進行統一控制。後來改名叫Control Groups。CGroups 是 Control Groups 的縮寫,它爲資源管理提供了一個統一框架,可以把系統任務及其子任務整合到按資源等級劃分的不同任務組內。並且對這些任務組實施不同的資源分配方案。CGroups可以限制、記錄、隔離進程組所使用的物理資源(包括CPU、memory、I/O等)。

cgroups有如下四個有趣的特點:

  • cgroups的API以一個僞文件系統的方式實現,即用戶可以通過文件操作實現cgroups的組織管理。
  • cgroups的組織管理操作單元可以細粒度到線程級別,用戶態代碼也可以針對系統分配的資源創建和銷燬cgroups,從而實現資源再分配和管理。
  • 所有資源管理的功能都以“subsystem(子系統)”的方式實現,接口統一。
  • 子進程創建之初與其父進程處於同一個cgroups的控制組。

相關概念

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

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

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

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

子系統

cgroups提供了subsystem(resource controllers)作爲資源的控制器

  1. cpu (since Linux 2.6.24; CONFIG_CGROUP_SCHED)
    用來限制cgroup的CPU使用率。
  2. cpuacct (since Linux 2.6.24; CONFIG_CGROUP_CPUACCT)
    統計cgroup的CPU的使用率。
  3. cpuset (since Linux 2.6.24; CONFIG_CPUSETS)
    綁定cgroup到指定CPUs和NUMA節點。
  4. memory (since Linux 2.6.25; CONFIG_MEMCG)
    統計和限制cgroup的內存的使用率,包括process memory, kernel memory, 和swap。
  5. devices (since Linux 2.6.26; CONFIG_CGROUP_DEVICE)
    限制cgroup創建(mknod)和訪問設備的權限。
  6. freezer (since Linux 2.6.28; CONFIG_CGROUP_FREEZER)
    suspend和restore一個cgroup中的所有進程。
  7. net_cls (since Linux 2.6.29; CONFIG_CGROUP_NET_CLASSID)
    將一個cgroup中進程創建的所有網絡包加上一個classid標記,用於tc和iptables。 只對發出去的網絡包生效,對收到的網絡包不起作用。
  8. blkio (since Linux 2.6.33; CONFIG_BLK_CGROUP)
    限制cgroup訪問塊設備的IO速度。
  9. perf_event (since Linux 2.6.39; CONFIG_CGROUP_PERF)
    對cgroup進行性能監控
  10. net_prio (since Linux 3.3; CONFIG_CGROUP_NET_PRIO)
    針對每個網絡接口設置cgroup的訪問優先級。
  11. hugetlb (since Linux 3.5; CONFIG_CGROUP_HUGETLB)
    限制cgroup的huge pages的使用量。
  12. pids (since Linux 4.3; CONFIG_CGROUP_PIDS)
    限制一個cgroup及其子孫cgroup中的總進程數。

概念相互關係及基本規則

傳統的Unix進程管理,實際上是先啓動init進程作爲根節點,再由init節點創建子進程作爲子節點,而每個子節點由可以創建新的子節點,如此往復,形成一個樹狀結構。

Cgroup 與進程在以下方面類似:
- 它們是分級的,且
- 子 cgroup 會繼承父 cgroup 的某些屬性。

根本的不同是在某個系統中可同時存在不同的分級 cgroup。如果 Linux 進程模式是進程的單一樹模式,那麼 cgroup 模式是一個或者更多任務的獨立、未連接樹(例如:進程)。
需要多個獨立 cgroup 分級,因爲每個分級都會附加到一個或者多個子系統中。子系統代表單一資源,比如 CPU 時間或者內存。

基於虛擬文件系統的CGroup管理

Linux 使用了多種數據結構在內核中實現了 cgroups 的配置,關聯了進程和 cgroups 節點,那麼 Linux 又是如何讓用戶態的進程使用到 cgroups 的功能呢? Linux內核有一個很強大的模塊叫 VFS (Virtual File System)。 VFS 能夠把具體文件系統的細節隱藏起來,給用戶態進程提供一個統一的文件系統 API 接口。 cgroups 也是通過 VFS 把功能暴露給用戶態的,cgroups 與 VFS 之間的銜接部分稱之爲 cgroups 虛擬文件系統。使用cgroup很簡單,掛載這個文件系統就可以了。這時通過掛載選項指定使用哪個子系統。
默認情況都是掛載到/sys/fs/cgroup目錄下,當然掛載到其它任何目錄都沒關係。

//掛載一顆和所有subsystem關聯的cgroup樹到/sys/fs/cgroup
mount -t cgroup <cgroup name> /sys/fs/cgroup

//掛載一顆和cpuset subsystem關聯的cgroup樹到/sys/fs/cgroup/cpuset
mkdir /sys/fs/cgroup/cpuset
mount -t cgroup -o cpuset <cgroup name> /sys/fs/cgroup/cpuset


//掛載一顆與cpu和cpuacct subsystem關聯的cgroup樹到/sys/fs/cgroup/cpu,cpuacct
mkdir /sys/fs/cgroup/cpu,cpuacct
mount -t cgroup -o cpu,cpuacct <cgroup name> /sys/fs/cgroup/cpu,cpuacct

//掛載一棵cgroup樹,但不關聯任何subsystem,下面就是systemd所用到的方式
mkdir /sys/fs/cgroup/systemd
mount -t cgroup -o none,name=systemd <cgroup name> /sys/fs/cgroup/systemd

規則 1: 多個subsystem可附着到同一個hierarchy

image 1

例如在ubuntu中,systemd就是將和cpu,cpuacct兩個subsystem掛載到了/sys/fs/cgroup/cpu,cpuacct 這個hierarchy

# mount |grep cpu,cpuacct
cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpu,cpuacct)

規則2: 一個subsystem不能同時附加到多個hierarchy,除非那個hierarchy不包含其他subsystem。

image 2

//嘗試將cpu subsystem重新關聯cpu_cg hierarchy 並且將這棵樹mount到./cpu目錄
# mkdir -p /mnt/cgroup/cpu_cg
# mount -t cgroup -o cpu cpu_cg /mnt/cgroup/cpu_cg
mount: cpu_cg is already mounted or /mnt/cgroup/cpu_cg busy

//但是將memory subsystem 關聯到另一個Cgroup hierarchy是可以的
# mkdir -p /mnt/cgroup/mem_cg
# mount -t cgroup -o memory mem_cg /mnt/cgroup/mem_cg 
# mount|grep memory
cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,memory)
mem_cg on /mnt/cgroup/mem_cg type cgroup (rw,relatime,memory)


//實際上,用同樣的參數掛載時,會重用現有的cgroup hierarchy,也即兩個掛載點看到的內容是一樣的
# mkdir -p /mnt/cgroup/cpu,cpuacct && cd /mnt/cgroup
# mount -t cgroup -o cpu,cpuacct new-cpu-cpuacct ./cpu,cpuacct

# mount |grep cpu,cpuacct
cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpu,cpuacct)
new-cpu-cpuacct on /mnt/cgroup/cpu,cpuacct type cgroup (rw,relatime,cpu,cpuacct)

# mkdir -p /sys/fs/cgroup/cpu,cpuacct/test; ls -l /mnt/cgroup/cpu,cpuacct|grep test
drwxr-xr-x   2 root root 0 123 18:18 test

//clean
# umount new-cpu-cpuacct
# umount mem_cg
# cgdelete cpu,cpuacct:test

本質上將,一個subsystem只能關聯到一顆cgroup hierarchy ,一旦關聯並在這個hierarchy上創建了子cgroup,subsystems和這棵cgroup hierarchy就成了一個整體,不能再重新組合。

規則3:同一個task不能同時作爲同一個hierarchy的不同cgroup的成員

image 3

每次在系統中創建新hierarchy時,該系統中的所有task都是那個hierarchy的默認 cgroup(我們稱之爲 root cgroup)的初始成員。

這樣,單一task可以是在多個 cgroup 中。前提是這些cgroup不能同時位於同一個hierarchy。

首先我們嘗試創建一個root cgroup, 在系統中可以創建任意多個不和任何subsystem關聯的cgroup樹,name是這棵樹的唯一標記,當name指定的是一個新的名字時,將創建一顆新的cgroup樹,但如果內核中已經存在一顆一樣name的cgroup樹,那麼將mount已存在的這顆cgroup樹

// 由於name=test的cgroup樹在系統中不存在,所以這裏會創建一顆新的name=test的cgroup樹
# mkdir -p /mnt/cgroup/test && cd /mnt/cgroup
# mount -t cgroup -o none,name=test test ./test

// 系統爲新創建的cgroup樹的root cgroup生成了默認文件
# ls /mnt/cgroup/test
cgroup.clone_children  cgroup.procs  cgroup.sane_behavior  notify_on_release  release_agent  tasks

// 新創建的cgroup樹的root cgroup裏包含系統中的所有進程
# wc -l ./test/cgroup.procs
188 ./test/cgroup.procs


// 創建子cgroup
# cd test && mkdir subcg

// 系統已經爲新的子cgroup生成了默認文件
# ls subcg
cgroup.clone_children  cgroup.procs  notify_on_release  tasks

//新創建的子cgroup中沒有任何進程
# wc -l subcg/cgroup.procs
0 subcg/cgroup.procs

//重新掛載這棵樹到test1,由於mount的時候指定的name=test,所以和上面掛載的是同一顆cgroup樹,於是test1目錄下的內容和test目錄下的內容一樣
# mkdir -p /mnt/cgroup/test1 && cd /mnt/cgroup
# mount -t cgroup -o none,name=test test ./test1
# ls ./test1
cgroup.clone_children  cgroup.procs  cgroup.sane_behavior  notify_on_release  release_agent  subcg  tasks

#清理
# umount /mnt/cgroup/test1
# umount /mnt/cgroup/test
# rm -rf /mnt/cgroup/test /mnt/cgroup/test1

再試一個例子:

// 換一個console 啓動一個bash
$ ps -ef|grep $$
chic      1944  1939  0 09:56 pts/1    00:00:00 -bash

//查看這個bash所屬的cgroup
$ cat /proc/1944/cgroup 
11:blkio:/user.slice
10:freezer:/
9:memory:/user.slice
8:cpuset:/
7:devices:/user.slice
6:net_cls,net_prio:/
5:hugetlb:/
4:pids:/user.slice/user-1000.slice
3:perf_event:/
2:cpu,cpuacct:/user.slice
1:name=systemd:/user.slice/user-1000.slice/session-2.scope

每一行包含用冒號隔開的三列,他們的意思分別是

  • cgroup樹的ID, 和/proc/cgroups文件中的ID一一對應。
  • 和cgroup樹綁定的所有subsystem,多個subsystem之間用逗號隔開。這裏name=systemd表示沒有和任何subsystem綁定,只是給他起了個名字叫systemd。
  • 進程在cgroup樹中的路徑,即進程所屬的cgroup,這個路徑是相對於掛載點的相對路徑。
# mount -t cgroup -o none,name=cgroup cgroup /mnt/cgroup
# mkdir -p /mnt/cgroup/child1
# mkdir -p /mnt/cgroup/child2

//檢查之前的bash現在也屬於這個cgroup
/mnt/cgroup# cat cgroup.procs |grep 1944
1944

//將bash移入 child1 cgroup
# cd child1
# echo 1944 > cgroup.procs
# cat /proc/1944/cgroup 
13:name=cgroup:/child1
11:blkio:/user.slice
10:freezer:/
9:memory:/user.slice
8:cpuset:/
7:devices:/user.slice
6:net_cls,net_prio:/
5:hugetlb:/
4:pids:/user.slice/user-1000.slice
3:perf_event:/
2:cpu,cpuacct:/user.slice
1:name=systemd:/user.slice/user-1000.slice/session-2.scope

//再試着將bash放入 child2 cgroup
# echo 1944 > /mnt/cgroup/child2/cgroup.procs
# cat /proc/1944/cgroup 
13:name=cgroup:/child2
11:blkio:/user.slice
10:freezer:/
9:memory:/user.slice
8:cpuset:/
7:devices:/user.slice
6:net_cls,net_prio:/
5:hugetlb:/
4:pids:/user.slice/user-1000.slice
3:perf_event:/
2:cpu,cpuacct:/user.slice
1:name=systemd:/user.slice/user-1000.slice/session-2.scope
//可以看見bash現在屬於child2 而從child1 移除了,一個task不會同時屬於同一hierarchy的不同cgroup

規則4:子進程(task)總是自動成爲父進程所在的cgroup的成員,然後可以移動到不同的cgroup中去。

image 4

接着之前的例子:

//在新的bash(1944)中在啓動一個bash(12110)
$ pstree -p 1944
bash(1944)───bash(12110)───pstree(12142)

$ cat /proc/12110/cgroup 
13:name=cgroup:/child2
11:blkio:/user.slice
10:freezer:/
9:memory:/user.slice
8:cpuset:/
7:devices:/user.slice
6:net_cls,net_prio:/
5:hugetlb:/
4:pids:/user.slice/user-1000.slice
3:perf_event:/
2:cpu,cpuacct:/user.slice
1:name=systemd:/user.slice/user-1000.slice/session-2.scope

使用libcgroup工具包

libcgroup工具安裝

  • redhat系統:
    yum install libcgroup
  • ubuntu系統:
    sudo apt-get install cgroup-bin cgroup-lite cgroup-tools cgroupfs-mount libcgroup1

cgroup服務的啓動和停止:

  • redhat系統(Sys V init):
    service cgconfig start|stop
  • ubuntu系統(Systemd):
    systemctl start cgmanager.service
    systemctl start run-cgmanager-fs.mount
    systemctl start cgroupfs-mount.service

CGroups功能測試(基於Ubuntu)

在Ubuntu上安裝完成cgroup工具包後,系統會創建以下文件:

  • /sys/fs/cgroup; 該文件夾包含一堆cgroup類型掛在的虛擬文件用來代表特定的cgroup層級.
  • /etc/init/cgroup-lite.conf. cgroup-lite.conf creates the /sys/fs/cgroup directory, based on the contents of
  • /proc/cgroups, 這個文件指定了cgroup-lite 應該創建哪些Control group.

安裝cgroup-bin後,unbuntu的systemd已經幫我們將各個subsystem和cgroup樹關聯並掛載好了

# mount |grep cgroup
tmpfs on /sys/fs/cgroup type tmpfs (rw,mode=755)
cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,xattr,release_agent=/lib/systemd/systemd-cgroups-agent,name=systemd)
cgroup on /sys/fs/cgroup/net_cls,net_prio type cgroup (rw,nosuid,nodev,noexec,relatime,net_cls,net_prio)
cgroup on /sys/fs/cgroup/pids type cgroup (rw,nosuid,nodev,noexec,relatime,pids,release_agent=/run/cgmanager/agents/cgm-release-agent.pids)
cgroup on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,blkio)
cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,devices)
cgroup on /sys/fs/cgroup/perf_event type cgroup (rw,nosuid,nodev,noexec,relatime,perf_event,release_agent=/run/cgmanager/agents/cgm-release-agent.perf_event)
cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,memory)
cgroup on /sys/fs/cgroup/hugetlb type cgroup (rw,nosuid,nodev,noexec,relatime,hugetlb,release_agent=/run/cgmanager/agents/cgm-release-agent.hugetlb)
cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpu,cpuacct)
cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,cpuset,clone_children)
cgroup on /sys/fs/cgroup/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,freezer)

# ls /sys/fs/cgroup/
blkio  cgmanager  cpu  cpuacct  cpu,cpuacct  cpuset  devices  freezer  hugetlb  memory  net_cls  net_cls,net_prio  net_prio  perf_event  pids  systemd

cgroup-bin 包含的基本命令

  • /usr/bin/cgclassify – cgclassify命令是用來將運行的任務移動到一個或者多個cgroup。
  • /usr/bin/cgcreate – cgcreate在層級中創建新cgroup。
  • /usr/bin/cgdelete – cgdelete命令刪除指定的cgroup。
  • /usr/bin/cgexec – cgexec命令在指定的cgroup中運行任務。
  • /usr/bin/cgget – cgget命令顯示cgroup參數。
  • /usr/bin/cgset – cgset 命令爲 cgroup 設定參數。
  • /usr/bin/lscgroup – lscgroup 命令列出層級中的 cgroup。
  • /usr/bin/lssubsys – lssubsys 命令列出包含指定子系統的層級
  • /usr/sbin/cgclear – cgclear 命令是用來刪除層級中的所有cgroup。
  • /usr/sbin/cgconfigparser – cgconfigparser命令解析cgconfig.conf文件和並掛載層級。
  • /usr/sbin/cgrulesengd – cgrulesengd 在 cgroup 中發佈任務。

相關配置文件:
- cgred.conf – cgred.conf是cgred服務的配置文件。
- cgrules.conf – cgrules.conf 包含用來決定何時任務術語某些 cgroup的規則。
- cgconfig.conf – 在cgconfig.conf文件中定義cgroup。

cgconfig.conf

cgconfig.conf是libcgroup用於定義控制組及其參數和掛載點的配置文件。 該文件由mount,group和default部分組成。 這些部分可以是任意的順序,所有這些部分都是可選的。 (refer to “man cgconfig.conf”)

  • mount section
mount {
    <controller> = <path>;
     ...
}
//controller : kernel subsystem 名稱
//path : 與給controller關聯的hierarichy的目錄路徑。
  • group section
group <name> {
       [permissions]
       <controller> {
              <param name> = <param value>;
              ...
       }
       ...
}
//name: Name of the control group
//permissions: 可選項,指定cgroup對應的掛載點文件系統的權限,root用戶擁有所有權限
//param name 和 param value:子系統的屬性及其屬性值
  • default section
default {
       perm {
              task {
                     uid = <task user>;
                     gid = <task group>;
                     fperm = <file permissions>
              }
              admin {
                     uid = <admin name>;
                     gid = <admin group>;
                     dperm = <directory permissions>
                     fperm = <file permissions>
              }
       }
}

例如:

mount {
       cpu = /sys/fs/cgroup/cpu;
       cpuacct = /sys/fs/cgroup/cpu;
}

group daemons/www {
       perm {
              task {
                     uid = root;
                     gid = webmaster;
                     fperm = 770;
              }
              admin {
                     uid = root;
                     gid = root;
                     dperm = 775;
                     fperm = 744;
              }
       }
       cpu {
              cpu.shares = "1000";
       }
}

group daemons/ftp {
       perm {
              task {
                     uid = root;
                     gid = ftpmaster;
                     fperm = 774;
              }
              admin {
                     uid = root;
                     gid = root;
                     dperm = 755;
                     fperm = 700;
              }
       }
       cpu {
              cpu.shares = "500";
       }
}

相當於:

mkdir /sys/fs/cgroup/cpu
mount -t cgroup -o cpu,cpuacct cpu /sys/fs/cgroup/cpu

mkdir /sys/fs/cgroup/cpu/daemons

mkdir /sys/fs/cgroup/cpu/daemons/www
chown root:root /sys/fs/cgroup/cpu/daemons/www/*
chown root:webmaster /sys/fs/cgroup/cpu/daemons/www/tasks
echo 1000 > /sys/fs/cgroup/cpu/daemons/www/cpu.shares

mkdir /sys/fs/cgroup/cpu/daemons/ftp
chown root:root /sys/fs/cgroup/cpu/daemons/ftp/*
chown root:ftpmaster /sys/fs/cgroup/cpu/daemons/ftp/tasks
echo 500 > /sys/fs/cgroup/cpu/daemons/ftp/cpu.shares
cgroup manager

cgroup manager(cgmanager)提供了一個D-Bus服務,允許程序和用戶管理cgroup,而不需要直接瞭解或訪問cgroup文件系統。 對於來自與管理者相同名稱空間任務的請求,管理者可以直接執行所需的安全檢查,以確保請求是合法的。 對於其他請求(例如來自容器中任務的請求),必須進行增強的D-Bus請求,其中將進程,用戶和組ID作爲SCM_CREDENTIALS傳遞,以便內核將標識符映射到其全局主機值。

爲了便利所有用戶使用簡單的D-Bus呼叫,一個“cgroup管理器代理”(cgproxy)在容器中自動啓動。 代理服務器接受來自相同命名空間中任務的標準D-Bus請求,並將它們轉換爲SCM傳遞給cgmanager的D-Bus請求。

創建一個運行cpu密集編譯的新cgroup的簡單例子如下所示:

cgm create cpuset build1
cgm movepid cpuset build1 $$
cgm setvalue cpuset build1 cpuset.cpus 1
make
cgm

cgm是一個簡化cgroup manager請求的客戶端腳本。 它只是調用dbus-send向運行中的cgmanager或cgproxy發送請求。

下面的例子中,首先創建一個名爲foo的cgroup然後將當前shell移入其中:

sudo cgm create all foo
sudo cgm chown all foo $(id -u) $(id -g)
cgm movepid all foo $$
//then to freeze the cgroup
cgm setvalue freezer foo freezer.state FROZEN
cgproxy

cgproxy是cgmanager的D-Bus代理。 由於非初始pid或user namespace中的進程將引用任務,用戶ID或組ID 在初始名稱空間中是錯亂的。cgproxy將依據內核將它們作爲SCM憑證發送給cgmanager 翻譯標識符。 通過這種方式,容器中的程序和用戶可以使用相同的簡單D-Bus調用通過代理服務器進行cgroup管理請求,就像它們在基本主機上直接與cgmanager交互一樣。

example

創建一個耗CPU的腳本:

$ cat cpu.sh 
#!/bin/bash

tmp=1
while [ True ];do
    tmp=$tmp
done;

運行一下:

#top -p `pidof -x cpu.sh`
  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND 
26855 chic      20   0   14264    912    808 R 100.0  0.0   0:08.70 cpu.sh                                            

創建一個cpu受限的cgroup

# cgcreate -a root -t chic -g cpu:mycpulimitgrp
# ls -l /sys/fs/cgroup/cpu/mycpulimitgrp/
total 0
-rw-r--r-- 1 root root 0 1月  24 17:32 cgroup.clone_children
-rw-r--r-- 1 root root 0 1月  24 17:32 cgroup.procs
-r--r--r-- 1 root root 0 1月  24 17:32 cpuacct.stat
-rw-r--r-- 1 root root 0 1月  24 17:32 cpuacct.usage
-r--r--r-- 1 root root 0 1月  24 17:32 cpuacct.usage_percpu
-rw-r--r-- 1 root root 0 1月  24 17:32 cpu.cfs_period_us
-rw-r--r-- 1 root root 0 1月  24 17:32 cpu.cfs_quota_us
-rw-r--r-- 1 root root 0 1月  24 17:32 cpu.shares
-r--r--r-- 1 root root 0 1月  24 17:32 cpu.stat
-rw-r--r-- 1 root root 0 1月  24 17:32 notify_on_release
-rw-r--r-- 1 chic root 0 1月  24 17:32 tasks

# cat /sys/fs/cgroup/cpu/mycpulimitgrp/cpu.cfs_period_us
100000
# cat /sys/fs/cgroup/cpu/mycpulimitgrp/cpu.cfs_quota_us
-1
//或者
# cgget -g cpu:mycpulimitgrp
mycpulimitgrp:
cpu.shares: 1024
cpu.cfs_quota_us: -1
cpu.stat: nr_periods 0
    nr_throttled 0
    throttled_time 0
cpu.cfs_period_us: 100000
  • cpu.cfs_period_us 表示將每個cpu時間片分成100000份。
  • cpu.cfs_period_us 表示當前這個組中的task(tasks中的taskid)將分配多少比例的cpu時間片。如果是雙核cpu,這裏就表示最多可以用到200%的CPU。

爲我們的cgroup分配 50% cpu的配額

# echo 50000 > /sys/fs/cgroup/cpu/mycpulimitgrp/cpu.cfs_quota_us

//或者
# cgset -r cpu.cfs_quota_us=50000 mycpulimitgrp

$ cgexec -g cpu:mycpulimitgrp ./cpu.sh
$ top -p `pidof -x cpu.sh`
  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND 
29224 chic      20   0   14264    904    800 R  50.0  0.0   0:21.42 cpu.sh

//stop cpu.sh and clean
# cgdelete -r cpu:mycpulimitgrp

參考:
- Resource Management Guide
- Ubuntu 服務器指南(Control Group)
- linux kernel CGroup
- CGroup 介紹、應用實例及原理描述
- Introduction to Linux Control Groups (Cgroups)
- Docker 和 cgroup

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章