容器核心技術--CGroup
接上一個小節,我們來試想這樣一個場景:
一臺宿主機的容器中運行了一個監控服務,但監控服務佔用了宿主機全部的 CPU 和記憶體等資源,導致宿主機上的其他服務和容器都被卡死,無法正常執行。
監控類服務不應占用大量資源,無論是什麼原因引起的問題,都不應該影響宿主機的正常使用,否則容器的隔離就沒有意義。Namespace 只能做到系統資源維度的隔離,無法做到硬體資源的控制。我們需要使用一種機制 Cgroup,指定容器應用最大佔用多少資源。
Linux cgroups 的全稱是 Linux Control Groups,它是 Linux 核心的特性,主要作用是限制、記錄和隔離程序組(process groups)使用的物理資源(CPU、Memory、IO 等)。
1. CGroup 核心概念
前面說過 CGroup 是用來對程序進行資源管理的,因此 CGroup 需要考慮如何抽象這兩種概念:程序和資源,同時如何組織自己的結構。CGroup 機制中有以下幾個基本概念:
- task:任務,對應於系統中執行的一個實體,下文統稱程序;
- subsystem:子系統,具體的資源控制器(resource class 或者 resource controller),控制某個特定的資源使用;
- cgroup:控制組,一組任務和子系統的關聯關係,表示對這些任務進行怎樣的資源管理策略;
- hierarchy:層級樹,由一系列 CGroup 組成的樹形結構。每個節點都是一個 CGroup ,CGroup 可以有多個子節點,子節點預設會繼承父節點的屬性。系統中可以有多個 hierarchy。
Cgroup 機制非常複雜,上面的名詞瞭解就好,學習 Docker 暫時還不需要深入研究它。
在 Linux 環境中,我們可以執行 ls -al /sys/fs/cgroup/
檢視當前系統的 Cgroup:
我們看到目錄中有若干個子目錄,除了 systemd 目錄,其他的一個子目錄對應一個子系統,子系統功能如下所示。
子系統 | 功能 |
---|---|
blkio | 為塊裝置,如硬碟等裝置,設定輸入輸出限制 |
cpu | 設定 cgroup 中程序的 CPU 被排程的策略 |
cpuacct | 統計 cgroup 中程序的 CPU 佔用 |
cpuset | 設定 cgroup 中程序可以使用的 CPU 和記憶體 |
devices | 控制 cgroup 中程序對裝置的訪問 |
freezer | 掛起或者恢復 cgroup 中的程序 |
hugetlb | 用於控制 cgroup 中程序的記憶體佔用,這是一個大頁檔案系統。 |
memory | 控制 cgroup 中程序的記憶體佔用,並統計記憶體資源使用情況。 |
net_cls | 將 cgroup 中程序產生的網路包分類,允許 Linux 流量控制系統識別從具體 cgroup 中生成的資料包。 |
net_prio | 控制 cgroup 中程序的網路流量的優先順序 |
perf_event | 識別任務的 cgroup 成員,可以用來做效能分析 |
pids | 限制 cgroup 及其所有子孫 cgroup 裡面能建立的總的程序數量 |
rdma | 限制 RDMA/IB 資源 |
3. 演示:使用 Cgroup 限制程序 CPU 資源佔用
在上面的表格中, 你會發現大量出現Cgroup 中的程序這個描述,原因在於我們必須先掛載子系統,將程序納入 Cgroup 組規則中,然後 Cgroup 機制才能控制這個程序。
我們馬上上手嘗試一下,先安裝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 的軟體進行壓力負載測試,stress 會根據設定,執行一系列消耗系統資源的操作,使得系統在一定的負載下執行。
啟動一個壓力負載測試的程序:
# 產生 1個程序,每個程序都反覆不停地計算隨機數的平方根
stress -c 1 > /dev/null &
使用top
命令檢視資源佔用情況
圖中兩個紅框從左到右分別代表壓力測試的程序號是 1816,CPU 佔用百分比 99%,說明壓力測試程序正常生效了。
切換到 root 使用者:
sudo su - root
進入 /sys/fs/cgroup/cpu
這個目錄:
cd /sys/fs/cgroup/cpu
建立一個 Cgroup 組,即在當前目錄下建立一個子目錄:
mkdir testcpu
進入 testcpu 目錄:
cd testcpu
檢視 cpu.cfs_period_us
代表時間週期總長度:
cat cpu.cfs_period_us # 100000
將 cpu.cfs_quota_us
設為當前 cgroup 在設定的週期長度內所能使用的 CPU 時間 10000,即總週期100000的 10%:
echo 10000 > cpu.cfs_quota_us
將壓力測試的程序新增到 Cgroup 組的規則中,1816 是stress程序 id:
echo 1816 > tasks
top
檢視資源佔用,發現 stress 程序的 CPU 佔用率被壓到了 10%,說明 Cgroups 對於 CPU 的控制起了效果。
3. 思考
試想一下,我們將本節限制 CPU 資源的操作物件,從 stress 這個程式,改換成前一節的 container,就獲得了一個同時限制了硬體資源和系統資源的容器。
4. 小結
通過本節的介紹,我們對 Cgroup 有了直觀的認知。Cgroup 是個非常強大的系統,容器技術需要使用它進行資源的限制,但這不代表著 Cgroup 只能用於容器技術,比如在雲服務商的計費系統中,也有它的身影。
或許你會感覺這一節與上一節 Namespace 的內容有些生僻,別擔心,我們介紹 Namespace 和 CGroup 的目的不是去精通他們的底層原理和使用方法,而是要真正認識到:容器的本質就是一個特殊的程序。