1. 程式人生 > Docker入門教學 >容器核心技術--CGroup

容器核心技術--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 的目的不是去精通他們的底層原理和使用方法,而是要真正認識到:容器的本質就是一個特殊的程序