Linux
下的cgroups
,全稱叫Control Groups
,最初由Google工程師提出并實現,linux從2.6開始將這個特性納入內核。cgroups主要對進程按組(Group
)進行資源配額的控制,包括CPU、內存、IO等,相比古老的ulimit
,cgroups更為平滑和易用,成為容器技術(比如docker
)的基礎。
cgroups的形態
-
hierarchy
:cgroups從用戶態看,提供了一種叫cgroup
類型的文件系統(Filesystem)
,這是一種虛擬的文件系統,并不真正保存文件,類似/proc
。通過對這個文件系統的操作(讀,寫,創建子目錄),告訴內核,你希望內核如何控制進程對資源的使用。文件系統本身是層級的,所以構成了hierarchy
。 -
task
:進程(process
)在cgroups中稱為task,taskid
就是pid
。 -
subsystem
:cgroups支持的所有可配置的資源稱為subsystem。例如cpu
是一種subsystem,memory
也是一種subsystem。linux內核在演進過程中subsystem是不斷增加的。 -
libcgroup
:一個開源軟件,提供了一組支持cgroups的應用程序和庫,方便用戶配置和使用cgroups。目前許多發行版都附帶這個軟件。
事實上,使用cgroups是非常簡單的,幾行shell命令就可以。下面以CPU子系統為例,來嘗試控制一個進程的CPU利用率。
掛載cgroup文件系統
首先掛載cgroup文件系統:
# mkdir -p /cgroup/mave
# mount -t cgroup -o cpu mave /cgroup/mave
# cat /proc/mounts
...
mave /cgroup/mave cgroup rw,relatime,cpu 0 0
上面的命令掛載了一個cpu
子系統,目錄為/cgroup/mave
,名字叫mave
。cpu子系統用于控制進程的cpu總體占用率,是最常用的子系統。內核會根據配額的設置在調度進程上做出相應的調整。
觀察/cgroup/mave
目錄:
# ls /cgroup/mave
cgroup.event_control
cpu.cfs_period_us
cpu.rt_period_us
cpu.shares
notify_on_release
cgroup.procs
cpu.cfs_quota_us
cpu.rt_runtime_us
cpu.stat
release_agent
tasks
這些文件是自動創建出來的,且都跟cpu這個子系統有關。不同的子系統會創建出不同的文件。我們重點關注:
- cpu.cfs_period_us
- cpu.cfs_quota_us
- tasks
tasks
這個文件里面可以寫入一個或多個taskid
(pid),/cgroup/mave
這個組中的配額設置將影響這些task。
cpu.cfs_period_us
# cat /cgroup/mave/cpu.cfs_period_us
100000
表示將cpu時間片分成100000
份。
cpu.cfs_quota_us
# cat /cgroup/mave/cpu.cfs_period_us
200000
表示當前這個組中的task(/cgroup/mave/tasks
中的taskid
)將分配多少比例的cpu時間片。由于是雙核cpu,這里就表示最多可以用到200%
的CPU。
創建一個控制組
盡管根目錄(/cgroup/mave
)也可以設置配額,但是習慣上,我們在這個目錄下創建一個目錄,作為一個控制組
,這個控制組可以單獨設置配額,而不影響其他控制組
:
# mkdir /cgroup/mave/steam
# ls /cgroup/mave/steam
cgroup.event_control
cpu.cfs_period_us
cpu.rt_period_us
cpu.shares
notify_on_release
cgroup.procs
cpu.cfs_quota_us
cpu.rt_runtime_us
cpu.stat
tasks
可以看到,創建的steam
目錄下也會自動創建出一堆cpu子系統相關的文件,幾乎和根目錄(/cgroup/mave
)完全一樣。現在我們再來理解一下什么是hierarchy
:
hierarchy
就是一個帶有繼承關系的目錄層次,每一層形成一個控制組
,單獨控制其中的task。
一個文件系統可以同時掛載多種子系統
手動設置配額
采集器進程在不受限制的情況下全速采集,CPU占用率達到50%
:
將5000寫入cpu.cfs_quota_us
,表示希望CPU占用率控制在(5000/100000=5%)以內:
# echo 5000 > /cgroup/mave/steam/cpu.cfs_quota_us
然后將進程號30126
寫入tasks
:
# echo 30126 >> /cgroup/mave/steam/tasks
觀察cpu占用率,瞬間降到4%
。
自動設置
可以看到,使用cgroups十分簡單,效果很好。然而,進程id并不是每次都保持不變。我們需要一些自動化的機制。上文提到過libcgroup,這個庫提供了掛載、配置和運行的程序和庫。
附:cgroups中的子系統
- blkio 設置限制每個塊設備的輸入輸出控制。例如:磁盤,光盤以及usb等等。
- cpu 使用調度程序為cgroup任務提供cpu的訪問。
- cpuacct 產生cgroup任務的cpu資源報告。
- cpuset 如果是多核心的cpu,這個子系統會為cgroup任務分配單獨的cpu和內存。
- devices 允許或拒絕cgroup任務對設備的訪問。
- freezer 暫停和恢復cgroup任務。
- memory 設置每個cgroup的內存限制以及產生內存資源報告。
- net_cls 標記每個網絡包以供cgroup方便使用。
- ns 名稱空間子系統。
- perf_event 增加了對每group的監測跟蹤的能力,即可以監測屬于某個特定的group的所有線程以及運行在特定CPU上的線程,此功能對于監測整個group非常有用。