首頁>技術>

很多接觸Docker的同學,都接觸過cgroup這個名詞。它是Linux上的一項古老的技術,用來實現資源限制,比如CPU、記憶體等。但有很多同學反映,這項技術有點晦澀,不太好懂。

這就是本篇文章存在的目的,會讓你以最簡單直觀的方式,瞭解cgroups到底是個什麼東西。

接上上篇文章:《5分鐘快速瞭解Docker的底層原理 | namespace篇》

cgroups,是實現docker功能的重要底層設施。如上圖,使用cgroups,能夠把作業系統的各項資源變成池子,然後透過配置獲取相應的資源。

那它是怎麼實現的呢?

要注意cgroups這個名詞,它有兩個特性。首先是c,就是Control的意思,是個動詞;第二部分,就是groups,證明它是個組。

1. 動詞的目標

control,用來限制什麼呢?除了CPU、記憶體,還有啥?

使用mount命令,檢視當前系統支援的限制目標,它有個專用的名詞,叫做子系統。

# mount  | grep cgrouptmpfs on /sys/fs/cgroup type tmpfs (ro,nosuid,nodev,noexec,mode=755)cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,xattr,release_agent=/usr/lib/systemd/systemd-cgroups-agent,name=systemd)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/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpuacct,cpu)cgroup on /sys/fs/cgroup/net_cls,net_prio type cgroup (rw,nosuid,nodev,noexec,relatime,net_prio,net_cls)cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,cpuset)cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,memory)cgroup on /sys/fs/cgroup/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,freezer)cgroup on /sys/fs/cgroup/pids type cgroup (rw,nosuid,nodev,noexec,relatime,pids)cgroup on /sys/fs/cgroup/hugetlb type cgroup (rw,nosuid,nodev,noexec,relatime,hugetlb)cgroup on /sys/fs/cgroup/perf_event type cgroup (rw,nosuid,nodev,noexec,relatime,perf_event)複製程式碼

不同的系統版本,會有一些細微的區別,大體上,子系統的分類包含下面這些:

cpu,cpuacct cpu主要限制程序的 cpu 使用率,cpuacct可以統計 cgroups 中的程序的 cpu 使用報告cpuset 可以為 cgroups 中的程序分配單獨的 cpu 節點或者記憶體節點,就像Numa做的那些事情一樣blkio 可以限制程序的塊裝置 io,比如物理裝置(磁碟,固態硬碟,USB 等等)devices 控制程序能夠訪問某些裝置net_cls 標記 cgroups 中程序的網路資料包,然後可以使用 tc 模組(traffic control)對資料包進行控制net_prio — 這個子系統用來設計網路流量的優先順序freezer 可以掛起或者恢復 cgroups 中的程序。ns 可以使不同 cgroups 下面的程序使用不同的 namespacehugetlb 主要針對於HugeTLB系統進行限制,這是一個大頁檔案系統。

內容很多,但我們平常關注的大多數就是記憶體和CPU,這些繁雜的細節,不影響我們理解它的設計原則。

下面就以CPU為例,來看一下子系統的實際表現。

2. CPU使用限制的例子

首先,我們進入cpu子系統目錄。

cd /sys/fs/cgroup/cpu複製程式碼

然後,建立一個組名為xjjdog的cgroups,這個名字,就叫做控制組。

mkdir xjjdog複製程式碼

這時候,神奇的事情發生了。我們使用ll命令,檢視xjjdog目錄中的內容,發現系統已經為我們預設生成了一堆檔案。

# ll xjjdog/total 0-rw-r--r-- 1 root root 0 Jan 28 21:09 cgroup.clone_children--w--w--w- 1 root root 0 Jan 28 21:09 cgroup.event_control-rw-r--r-- 1 root root 0 Jan 28 21:09 cgroup.procs-r--r--r-- 1 root root 0 Jan 28 21:09 cpuacct.stat-rw-r--r-- 1 root root 0 Jan 28 21:09 cpuacct.usage-r--r--r-- 1 root root 0 Jan 28 21:09 cpuacct.usage_percpu-rw-r--r-- 1 root root 0 Jan 28 21:09 cpu.cfs_period_us-rw-r--r-- 1 root root 0 Jan 28 21:09 cpu.cfs_quota_us-rw-r--r-- 1 root root 0 Jan 28 21:09 cpu.rt_period_us-rw-r--r-- 1 root root 0 Jan 28 21:09 cpu.rt_runtime_us-rw-r--r-- 1 root root 0 Jan 28 21:09 cpu.shares-r--r--r-- 1 root root 0 Jan 28 21:09 cpu.stat-rw-r--r-- 1 root root 0 Jan 28 21:09 notify_on_release-rw-r--r-- 1 root root 0 Jan 28 21:09 tasks複製程式碼

透過控制這些檔案裡面的數值,就可以對資源進行限制。比如cpu.cfs_quota_us檔案,如果我們往裡寫入100000(十萬),那麼就證明使用了xjjdog的cgroup,最多能夠使用1核的CPU。寫入20000,證明最多使用使用1/5核的CPU。

這是因為,cpu.cfs_period_us這個配置檔案,預設把1核cpu分成了10萬份。

那我們就寫入20000試一下。

sudo echo 20000 > xjjdog/cpu.cfs_quota_us複製程式碼

我們把當前shell的pid,加入被受控程序列表。

echo $$ > xjjdog/tasks複製程式碼

執行完畢之後,再啟動一個死迴圈。

while true;do ;done;複製程式碼

重新開啟一個shell,使用top觀察CPU的使用率。可以發現,我們的死迴圈,最多隻使用了20%的CPU。us保持在20%以下,且不間斷的在各個cpu之間切換。

依次試驗以下的命令,可以發現CPU的使用,會逐步增加,大體上和我們的限額是相等的。

sudo echo 40000 > xjjdog/cpu.cfs_quota_ussudo echo 60000 > xjjdog/cpu.cfs_quota_ussudo echo 100000 > xjjdog/cpu.cfs_quota_us複製程式碼

其他的資源限制,都是類似的思路。那麼最重要的工作,就是需要知道cpu.cfs_quota_us這樣的字眼,代表的是什麼意思,這些對著手冊來看是很容易掌握的。比如quota是配額的意思,很明顯就是限制資源的使用。

如上圖,子系統可以控制多個tasks,把它納入到控制組之內。我們上篇文章講到,可以將bash程序,作為docker系統的1號程序,那麼同樣的,這個1號程序的子程序,都會共享同樣的限額配置。

3. group的意思

淺顯的來講,group就是指的對各種資源進行分組。不同名字的資源,有不同的隔離配置。但它有更多的特性。

比較重要的,是它的層級關係(hierarchy)。這個也比較好理解,它主要是為了簡化配置而存在的。

比如我上面的xjjdog目錄,對cpu的限制限制在0.5核。這時候,我想要有另外一個應用,對cpu的使用限制在0.5核,同時限制記憶體1gb,那麼就可以直接在xjjdog目錄下建立xjjdog0目錄,在xjjdog0目錄下只配置記憶體方面的就可以了。

另外,如果你在外層的cpu限額限制了2core,然後在繼承的目錄裡限制了1/5核,那它就只能使用作業系統的2/5核。這也是繼承的一個特性。

End

cgroups是2006年誕生的,發起人是Google 的工程師( Rohit Seth 和 Paul Menage )。在 2008 年成功合入 Linux 2.6.24 版本中,可以說這項技術是很古老的。cgroups目前已經成為 systemd、Docker、Linux Containers(LXC) 等技術的基礎。

像Windows平臺的WSL,是沒有cgroups功能的,使用mount命令可以驗證,這證明了它是不能把docker跑起來的,因為缺乏基礎。不過,WSL2已經可以了。

有些同學對docker目前的發展現狀有些擔心,但當你熟悉了這幾個常見的底層原理,讀完容器的標準之後,就會發現,上層的實現無論是換成docker也好,換成containerd也罷,都一樣!

12
最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 一不小心把mysql密碼忘記了,該怎麼辦?