容器核心技術(shù)–CGroup
接上一個小節(jié),我們來試想這樣一個場景:
一臺宿主機(jī)的容器中運行了一個監(jiān)控服務(wù),但監(jiān)控服務(wù)占用了宿主機(jī)全部的 CPU 和內(nèi)存等資源,導(dǎo)致宿主機(jī)上的其他服務(wù)和容器都被卡死,無法正常運行。
監(jiān)控類服務(wù)不應(yīng)占用大量資源,無論是什么原因引起的問題,都不應(yīng)該影響宿主機(jī)的正常使用,否則容器的隔離就沒有意義。Namespace 只能做到系統(tǒng)資源維度的隔離,無法做到硬件資源的控制。我們需要使用一種機(jī)制 Cgroup,指定容器應(yīng)用最大占用多少資源。
Linux cgroups 的全稱是 Linux Control Groups,它是 Linux 內(nèi)核的特性,主要作用是限制、記錄和隔離進(jìn)程組(process groups)使用的物理資源(CPU、Memory、IO 等)。
1. CGroup 核心概念
前面說過 CGroup 是用來對進(jìn)程進(jìn)行資源管理的,因此 CGroup 需要考慮如何抽象這兩種概念:進(jìn)程和資源,同時如何組織自己的結(jié)構(gòu)。CGroup 機(jī)制中有以下幾個基本概念:
- task:任務(wù),對應(yīng)于系統(tǒng)中運行的一個實體,下文統(tǒng)稱進(jìn)程;
- subsystem:子系統(tǒng),具體的資源控制器(resource class 或者 resource controller),控制某個特定的資源使用;
- cgroup:控制組,一組任務(wù)和子系統(tǒng)的關(guān)聯(lián)關(guān)系,表示對這些任務(wù)進(jìn)行怎樣的資源管理策略;
- hierarchy:層級樹,由一系列 CGroup 組成的樹形結(jié)構(gòu)。每個節(jié)點都是一個 CGroup ,CGroup 可以有多個子節(jié)點,子節(jié)點默認(rèn)會繼承父節(jié)點的屬性。系統(tǒng)中可以有多個 hierarchy。
Cgroup 機(jī)制非常復(fù)雜,上面的名詞了解就好,學(xué)習(xí) Docker 暫時還不需要深入研究它。
在 Linux 環(huán)境中,我們可以執(zhí)行 ls -al /sys/fs/cgroup/
查看當(dāng)前系統(tǒng)的 Cgroup:
我們看到目錄中有若干個子目錄,除了 systemd 目錄,其他的一個子目錄對應(yīng)一個子系統(tǒng),子系統(tǒng)功能如下所示。
子系統(tǒng) | 功能 |
---|---|
blkio | 為塊設(shè)備,如硬盤等設(shè)備,設(shè)定輸入輸出限制 |
cpu | 設(shè)置 cgroup 中進(jìn)程的 CPU 被調(diào)度的策略 |
cpuacct | 統(tǒng)計 cgroup 中進(jìn)程的 CPU 占用 |
cpuset | 設(shè)置 cgroup 中進(jìn)程可以使用的 CPU 和內(nèi)存 |
devices | 控制 cgroup 中進(jìn)程對設(shè)備的訪問 |
freezer | 掛起或者恢復(fù) cgroup 中的進(jìn)程 |
hugetlb | 用于控制 cgroup 中進(jìn)程的內(nèi)存占用,這是一個大頁文件系統(tǒng)。 |
memory | 控制 cgroup 中進(jìn)程的內(nèi)存占用,并統(tǒng)計內(nèi)存資源使用情況。 |
net_cls | 將 cgroup 中進(jìn)程產(chǎn)生的網(wǎng)絡(luò)包分類,允許 Linux 流量控制系統(tǒng)識別從具體 cgroup 中生成的數(shù)據(jù)包。 |
net_prio | 控制 cgroup 中進(jìn)程的網(wǎng)絡(luò)流量的優(yōu)先級 |
perf_event | 識別任務(wù)的 cgroup 成員,可以用來做性能分析 |
pids | 限制 cgroup 及其所有子孫 cgroup 里面能創(chuàng)建的總的進(jìn)程數(shù)量 |
rdma | 限制 RDMA/IB 資源 |
3. 演示:使用 Cgroup 限制進(jìn)程 CPU 資源占用
在上面的表格中, 你會發(fā)現(xiàn)大量出現(xiàn)Cgroup 中的進(jìn)程這個描述,原因在于我們必須先掛載子系統(tǒng),將進(jìn)程納入 Cgroup 組規(guī)則中,然后 Cgroup 機(jī)制才能控制這個進(jìn)程。
我們馬上上手嘗試一下,先安裝stress
sudo dnf install https://download-ib01.fedoraproject.org/pub/epel/7/x86_64/Packages/s/stress-1.0.4-16
.el7.x86_64.rpm
Tips:我們使用stress 的軟件進(jìn)行壓力負(fù)載測試,stress 會根據(jù)設(shè)定,執(zhí)行一系列消耗系統(tǒng)資源的操作,使得系統(tǒng)在一定的負(fù)載下運行。
啟動一個壓力負(fù)載測試的進(jìn)程:
# 產(chǎn)生 1個進(jìn)程,每個進(jìn)程都反復(fù)不停地計算隨機(jī)數(shù)的平方根
stress -c 1 > /dev/null &
使用top
命令查看資源占用情況
圖中兩個紅框從左到右分別代表壓力測試的進(jìn)程號是 1816,CPU 占用百分比 99%,說明壓力測試進(jìn)程正常生效了。
切換到 root 用戶:
sudo su - root
進(jìn)入 /sys/fs/cgroup/cpu
這個目錄:
cd /sys/fs/cgroup/cpu
創(chuàng)建一個 Cgroup 組,即在當(dāng)前目錄下創(chuàng)建一個子目錄:
mkdir testcpu
進(jìn)入 testcpu 目錄:
cd testcpu
查看 cpu.cfs_period_us
代表時間周期總長度:
cat cpu.cfs_period_us # 100000
將 cpu.cfs_quota_us
設(shè)為當(dāng)前 cgroup 在設(shè)置的周期長度內(nèi)所能使用的 CPU 時間 10000,即總周期100000的 10%:
echo 10000 > cpu.cfs_quota_us
將壓力測試的進(jìn)程添加到 Cgroup 組的規(guī)則中,1816 是stress進(jìn)程 id:
echo 1816 > tasks
top
查看資源占用,發(fā)現(xiàn) stress 進(jìn)程的 CPU 占用率被壓到了 10%,說明 Cgroups 對于 CPU 的控制起了效果。
3. 思考
試想一下,我們將本節(jié)限制 CPU 資源的操作對象,從 stress 這個程序,改換成前一節(jié)的 container,就獲得了一個同時限制了硬件資源和系統(tǒng)資源的容器。
4. 小結(jié)
通過本節(jié)的介紹,我們對 Cgroup 有了直觀的認(rèn)知。Cgroup 是個非常強(qiáng)大的系統(tǒng),容器技術(shù)需要使用它進(jìn)行資源的限制,但這不代表著 Cgroup 只能用于容器技術(shù),比如在云服務(wù)商的計費系統(tǒng)中,也有它的身影。
或許你會感覺這一節(jié)與上一節(jié) Namespace 的內(nèi)容有些生僻,別擔(dān)心,我們介紹 Namespace 和 CGroup 的目的不是去精通他們的底層原理和使用方法,而是要真正認(rèn)識到:容器的本質(zhì)就是一個特殊的進(jìn)程。