5分鐘了解Docker原理之二,最簡單的Cgroups介紹!
本文轉(zhuǎn)載自微信公眾號「小姐姐味道」,作者小姐姐養(yǎng)的狗 。轉(zhuǎn)載本文請聯(lián)系小姐姐味道公眾號。
很多接觸Docker的同學(xué),都接觸過cgroup這個名詞。它是Linux上的一項古老的技術(shù),用來實現(xiàn)資源限制,比如CPU、內(nèi)存等。但有很多同學(xué)反映,這項技術(shù)有點晦澀,不太好懂。
這就是本篇文章存在的目的,會讓你以最簡單直觀的方式,了解cgroups到底是個什么東西。
cgroups,是實現(xiàn)docker功能的重要底層設(shè)施。如上圖,使用cgroups,能夠把操作系統(tǒng)的各項資源變成池子,然后通過配置獲取相應(yīng)的資源。
那它是怎么實現(xiàn)的呢?
要注意cgroups這個名詞,它有兩個特性。首先是c,就是Control的意思,是個動詞;第二部分,就是groups,證明它是個組。
1. 動詞的目標
control,用來限制什么呢?除了CPU、內(nèi)存,還有啥?
使用mount命令,查看當(dāng)前系統(tǒng)支持的限制目標,它有個專用的名詞,叫做子系統(tǒng)。
- # mount | grep cgroup
- tmpfs 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)
不同的系統(tǒng)版本,會有一些細微的區(qū)別,大體上,子系統(tǒng)的分類包含下面這些:
- cpu,cpuacct cpu主要限制進程的 cpu 使用率,cpuacct可以統(tǒng)計 cgroups 中的進程的 cpu 使用報告
- cpuset 可以為 cgroups 中的進程分配單獨的 cpu 節(jié)點或者內(nèi)存節(jié)點,就像Numa做的那些事情一樣
- blkio 可以限制進程的塊設(shè)備 io,比如物理設(shè)備(磁盤,固態(tài)硬盤,USB 等等)
- devices 控制進程能夠訪問某些設(shè)備
- net_cls 標記 cgroups 中進程的網(wǎng)絡(luò)數(shù)據(jù)包,然后可以使用 tc 模塊(traffic control)對數(shù)據(jù)包進行控制
- net_prio — 這個子系統(tǒng)用來設(shè)計網(wǎng)絡(luò)流量的優(yōu)先級
- freezer 可以掛起或者恢復(fù) cgroups 中的進程。
- ns 可以使不同 cgroups 下面的進程使用不同的 namespace
- hugetlb 主要針對于HugeTLB系統(tǒng)進行限制,這是一個大頁文件系統(tǒng)。
內(nèi)容很多,但我們平常關(guān)注的大多數(shù)就是內(nèi)存和CPU,這些繁雜的細節(jié),不影響我們理解它的設(shè)計原則。
下面就以CPU為例,來看一下子系統(tǒng)的實際表現(xiàn)。
2. CPU使用限制的例子
首先,我們進入cpu子系統(tǒng)目錄。
- cd /sys/fs/cgroup/cpu
然后,創(chuàng)建一個組名為xjjdog的cgroups,這個名字,就叫做控制組。
- mkdir xjjdog
這時候,神奇的事情發(fā)生了。我們使用ll命令,查看xjjdog目錄中的內(nèi)容,發(fā)現(xiàn)系統(tǒng)已經(jīng)為我們默認生成了一堆文件。
- # 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
通過控制這些文件里面的數(shù)值,就可以對資源進行限制。比如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
我們把當(dāng)前shell的pid,加入被受控進程列表。
- echo $$ > xjjdog/tasks
執(zhí)行完畢之后,再啟動一個死循環(huán)。
- while true;do ;done;
重新打開一個shell,使用top觀察CPU的使用率。可以發(fā)現(xiàn),我們的死循環(huán),最多只使用了20%的CPU。us保持在20%以下,且不間斷的在各個cpu之間切換。
依次試驗以下的命令,可以發(fā)現(xiàn)CPU的使用,會逐步增加,大體上和我們的限額是相等的。
- sudo echo 40000 > xjjdog/cpu.cfs_quota_us
- sudo echo 60000 > xjjdog/cpu.cfs_quota_us
- sudo echo 100000 > xjjdog/cpu.cfs_quota_us
其他的資源限制,都是類似的思路。那么最重要的工作,就是需要知道cpu.cfs_quota_us這樣的字眼,代表的是什么意思,這些對著手冊來看是很容易掌握的。比如quota是配額的意思,很明顯就是限制資源的使用。
如上圖,子系統(tǒng)可以控制多個tasks,把它納入到控制組之內(nèi)。我們上篇文章講到,可以將bash進程,作為docker系統(tǒng)的1號進程,那么同樣的,這個1號進程的子進程,都會共享同樣的限額配置。
3. group的意思
淺顯的來講,group就是指的對各種資源進行分組。不同名字的資源,有不同的隔離配置。但它有更多的特性。
比較重要的,是它的層級關(guān)系(hierarchy)。這個也比較好理解,它主要是為了簡化配置而存在的。
比如我上面的xjjdog目錄,對cpu的限制限制在0.5核。這時候,我想要有另外一個應(yīng)用,對cpu的使用限制在0.5核,同時限制內(nèi)存1gb,那么就可以直接在xjjdog目錄下創(chuàng)建xjjdog0目錄,在xjjdog0目錄下只配置內(nèi)存方面的就可以了。
另外,如果你在外層的cpu限額限制了2core,然后在繼承的目錄里限制了1/5核,那它就只能使用操作系統(tǒng)的2/5核。這也是繼承的一個特性。
End
cgroups是2006年誕生的,發(fā)起人是Google 的工程師(Rohit Seth 和 Paul Menage )。在 2008 年成功合入 Linux 2.6.24 版本中,可以說這項技術(shù)是很古老的。cgroups目前已經(jīng)成為 systemd、Docker、Linux Containers(LXC) 等技術(shù)的基礎(chǔ)。
像Windows平臺的WSL,是沒有cgroups功能的,使用mount命令可以驗證,這證明了它是不能把docker跑起來的,因為缺乏基礎(chǔ)。不過,WSL2已經(jīng)可以了。
有些同學(xué)對docker目前的發(fā)展現(xiàn)狀有些擔(dān)心,但當(dāng)你熟悉了這幾個常見的底層原理,讀完容器的標準之后,就會發(fā)現(xiàn),上層的實現(xiàn)無論是換成docker也好,換成containerd也罷,都一樣!
作者簡介:小姐姐味道 (xjjdog),一個不允許程序員走彎路的公眾號。聚焦基礎(chǔ)架構(gòu)和Linux。十年架構(gòu),日百億流量,與你探討高并發(fā)世界,給你不一樣的味道。我的個人微信xjjdog0,歡迎添加好友,進一步交流。