一文帶你搞懂 Docker 容器的核心基石 Cgroups
Cgroups 是 Linux 系統內核提供的一種機制,這種機制可以根據需求將一些列系統任務機器子任務整合或分離到按資源劃分登記的不同組內,從而爲系統資源管理提供一個的框架。簡單地說,cgroups 可以限制、記錄任務組所使用的物理組員(比如 CPU、Memory、IO 等),爲容器實現虛擬化提供了基本保證,是構建 Docker 等一些列虛擬化管理工具的基石。今天我們就來詳細介紹一下 cgroups 相關的內容。
- 爲什麼要了解 Cgroups
從 2013 年開源的 Docker 推出、2014 年開源的 Kubernetes 出現,到現在的雲原生技術與生態的全面普及與火熱化,容器技術已經逐步成爲主流的基礎雲原生技術之一。使用容器技術,可以很好地實現資源層面上的限制和隔離,這都依賴於 Linux 系統內核所提供的 Cgroups 和 Namespace 技術。
Cgroups
主要用來管理資源的分配、限制;Namespace
主要用來封裝抽象、限制、隔離資源,使命名空間內的進程擁有它們自己的全局資源。
Linux 內核提供的 Cgroups 和 Namespace 技術,爲容器實現虛擬化提供了基本保證,是構建 Docker 等一些列虛擬化管理工具的基石。下面我們就來詳細介紹一下 Cgroups 相關的內容。
- Cgroups 簡介
Cgroups 是 control groups 的縮寫,是 Linux 內核提供的一種可以限制、記錄、隔離進程組(process groups)所使用的物理資源(如 CPU、Memory、IO 等等)的機制。
通過使用 Cgroups,系統管理員在分配、排序、拒絕、管理和監控系統資源等方面,可以進行精細化控制。硬件資源可以在應用程序和用戶間智能分配,從而增加整體效率。最初由 google 的工程師提出,後來被整合進 Linux 內核。也是目前輕量級虛擬化技術 XC(Linux Container)的基礎之一。
Cgroups 和 Namespace 類似,也是將進程進行分組,但它的目的和 Namespace 不一 樣,Namespace 是爲了隔離進程組之間的資源,而 Cgroups 是爲了對一組進程進行統一的資源監控和限制。
Cgroups 分 v1 和 v2 兩個版本,v1 實現較早,功能比較多,但是由於它裏面的功能都是零零散散的實現的,所以規劃的不是很好,導致了一些使用和維護上的不便,v2 的出現 就是爲了解決 v1 中這方面的問題,在最新的 4.5 內核中,Cgroups v2 聲稱已經可以用於生產環境了,但它所支持的功能還很有限,隨着 v2 一起引入內核的還有 Cgroups、Namespace,v1 和 v2 可以混合使用,但是這樣會更復雜,所以一般沒人會這樣用。
- 什麼是 Cgroups?
Cgroups 是 Linux 下的一種將進程按組進行管理的機制,在用戶層看來,Cgroups 技術就是把系統中的所有進程組織成一顆一顆獨立的樹,每棵樹都包含系統的所有進程,樹的每個節點是一個進程組,而每顆樹又和一個或者多個 subsystem 關聯,樹的作用是將進程分組,而 subsystem 的作用就是對這些組進行操作,Cgroups 的主體架構提如下:
Cgroups 主要包括下面兩部分:
-
subsystem: 一個 subsystem 就是一個內核模塊,他被關聯到一顆 cgroup 樹之後, 就會在樹的每個節點(進程組)上做具體的操作。subsystem 經常被稱作 resource controller,因爲它主要被用來調度或者限制每個進程組的資源,但是這個說法不完全準 確,因爲有時我們將進程分組只是爲了做一些監控,觀察一下他們的狀態,比如 perf_event subsystem。到目前爲止,Linux 支持 12 種 subsystem,比如限制 CPU 的使 用時間,限制使用的內存,統計 CPU 的使用情況,凍結和恢復一組進程等,後續會對它們一一進行介紹。
-
hierarchy: 一個 hierarchy 可以理解爲一棵 cgroup 樹,樹的每個節點就是一個進程 組,每棵樹都會與零到多個 subsystem 關聯。在一顆樹裏面,會包含 Linux 系統中的所有 進程,但每個進程只能屬於一個節點(進程組)。系統中可以有很多顆 cgroup 樹,每棵樹 都和不同的 subsystem 關聯,一個進程可以屬於多顆樹,即一個進程可以屬於多個進程 組,只是這些進程組和不同的 subsystem 關聯。
目前 Linux 支持 12 種 subsystem,如果不考慮不與任何 subsystem 關聯的情況(systemd 就屬於這種情況),Linux 裏面最多可以建 12 顆 cgroup 樹,每棵樹關聯一個 subsystem,當然也可以只建一棵樹,然後讓這 棵樹關聯所有的 subsystem。當一顆 cgroup 樹不和任何 subsystem 關聯的時候,意味着這棵樹只是將進程進行分組,至於要在分組的基礎上做些什麼,將由應用程序自己決定, systemd 就是一個這樣的例子。
- 爲什麼需要 Cgroups?
在 Linux 裏,一直以來就有對進程進行分組的概念和需求,比如 session group, progress group 等,後來隨着人們對這方面的需求越來越多,比如需要追蹤一組進程的內存和 IO 使用情況等,於是出現了 cgroup,用來統一將進程進行分組,並在分組的基礎上對進程進行監控和資源控制管理等。
舉個例子,Linux 系統中安裝了殺毒軟件 ESET 或者 ClamAV,殺毒時佔用系統資源過高,影響系統承載業務運行,怎麼辦?單個虛擬機進程或者 docker 進程使用過高的資源,怎麼辦?單個 Java 進行佔用系統過多的內存的資源,怎麼辦?
cgroup 就是能夠控制並解決上述問題的工具,cgroup 在 linux 內核實現、用於控制 linux 系統資源。
- Cgroups 是如何實現的?
在 CentOS 7 系統中(包括 Red Hat Enterprise Linux 7),通過將 cgroup 層級系統與 systemd 單位樹捆綁,可以把資源管理設置從進程級別移至應用程序級別。默認情況下 systemd 會自動創建 slice、scope 和 service 單位的層級(具體的意思稍後再解釋),來爲 cgroup 樹提供統一結構。
可以通過 systemctl 命令創建自定義 slice 進一步修改此結構。如果我們將系統的資源看成一塊餡餅,那麼所有資源默認會被劃分爲 3 個 cgroup:System, User 和 Machine。每一個 cgroup 都是一個 slice,每個 slice 都可以有自己的子 slice,如下圖所示:
下面我們以 CPU 資源爲例,來解釋一下上圖中出現的一些關鍵詞。如上圖所示,系統默認創建了 3 個頂級 slice(System, User 和 Machine),每個 slice 都會獲得相同的 CPU 使用時間(僅在 CPU 繁忙時生效),如果 user.slice 想獲得 100% 的 CPU 使用時間,而此時 CPU 比較空閒,那麼 user.slice 就能夠如願以償。這三種頂級 slice 的含義如下:
-
1)system.slice:所有系統 service 的默認位置。
-
2)user.slice:所有用戶會話的默認位置。每個用戶會話都會在該 slice 下面創建一個子 slice,如果同一個用戶多次登錄該系統,仍然會使用相同的子 slice。
-
3)machine.slice:所有虛擬機和 Linux 容器的默認位置 控制 CPU 資源使用的其中一種方法是 shares。shares 用來設置 CPU 的相對值(你可以理解爲權 重),並且是針對所有的 CPU(內核),默認值是 1024。因此在上圖中,httpd, sshd, crond 和 gdm 的 CPU shares 均爲 1024,System, User 和 Machine 的 CPU shares 也是 1024。
假設該系統上運行了 4 個 service,登錄了兩個用戶,還運行了一個虛擬機。同時假設 每個進程都要求使用盡可能多的 CPU 資源(每個進程都很繁忙),則:
-
1)system.slice 會獲得 33.333% 的 CPU 使用時間,其中每個 service 都會從 system.slice 分配的 資源中獲得 1/4 的 CPU 使用時間,即 8.25% 的 CPU 使用時間。
-
2)user.slice 會獲得 33.333% 的 CPU 使用時間,其中每個登錄的用戶都會獲得 16.5% 的 CPU 使 用時間。假設有兩個用戶:tom 和 jack,如果 tom 註銷登錄或者殺死該用戶會話下的所有進程, jack 就能夠使用 33.333% 的 CPU 使用時間。
-
3)machine.slice 會獲得 33.333% 的 CPU 使用時間,如果虛擬機被關閉或處於 idle 狀態,那麼 system.slice 和 user.slice 就會從這 33.333% 的 CPU 資源裏分別獲得 50% 的 CPU 資源,然後 均分給它們的子 slice。
- Cgroups 的作用
Cgroups 最初的目標是爲資源管理提供的一個統一的框架,既整合現有的 cpuset 等子系統,也爲未來開發新的子系統提供接口。現在的 cgroups 適用於多種應用場景,從單個進程的資源控制,到實現操作系統層次的虛擬化(OS Level Virtualization),框架圖如下:
Cgroups 提供了以下功能:
-
1)限制進程組可以使用的資源數量(Resource limiting )。比如:memory 子系統可以爲進程 組設定一個 memory 使用上限,一旦進程組使用的內存達到限額再申請內存,就會出發 OOM(out of memory)。
-
2)進程組的優先級控制(Prioritization )。比如:可以使用 cpu 子系統爲某個進程組分配特定 cpu share。
-
3)記錄進程組使用的資源數量(Accounting )。比如:可以使用 cpuacct 子系統記錄某個進程 組使用的 cpu 時間。
-
4)進程組隔離(Isolation)。比如:使用 ns 子系統可以使不同的進程組使用不同的 namespace,以達到隔離的目的,不同的進程組有各自的進程、網絡、文件系統掛載空間。
-
5)進程組控制(Control)。比如:使用 freezer 子系統可以將進程組掛起和恢復。
- Cgroups 相關概念及相互關係
7.1 相關概念
1)任務(task):在 cgroups 中,任務就是系統的一個進程。
2)控制族羣(control group):控制族羣就是一組按照某種標準劃分的進程。Cgroups 中的資源控制都是以控制族羣爲單位實現。一個進程可以加入到某個控制族羣,也從一個進程組遷移到另 一個控制族羣。一個進程組的進程可以使用 cgroups 以控制族羣爲單位分配的資源,同時受到 cgroups 以控制族羣爲單位設定的限制。
3)層級(hierarchy):控制族羣可以組織成 hierarchical 的形式,既一顆控制族羣樹。控制族 羣樹上的子節點控制族羣是父節點控制族羣的孩子,繼承父控制族羣的特定的屬性。
4)子系統(subsystem):一個子系統就是一個資源控制器,比如 cpu 子系統就是控制 cpu 時間分配的一個控制器。子系統必須附加(attach)到一個層級上才能起作用,一個子系統附加到某個 層級以後,這個層級上的所有控制族羣都受到這個子系統的控制。
7.2 相互關係
-
1)每次在系統中創建新層級時,該系統中的所有任務都是那個層級的默認 cgroup(我們稱之爲 root cgroup ,此 cgroup 在創建層級時自動創建,後面在該層級中創建的 cgroup 都是此 cgroup 的後代)的初始成員。
-
2)一個子系統最多隻能附加到一個層級。
-
3)一個層級可以附加多個子系統
-
4)一個任務可以是多個 cgroup 的成員,但是這些 cgroup 必須在不同的層級。
-
5)系統中的進程(任務)創建子進程(任務)時,該子任務自動成爲其父進程所在 cgroup 的成員。然後可根據需要將該子任務移動到不同的 cgroup 中,但開始時它總是繼承其父任務的 cgroup。
- Cgroups 子系統介紹
可以看到,在 /sys/fs/cgroup
下面有很多 cpu、memory 這樣的子目錄,也就稱爲子系統 subsystem:
它是一組資源控制模塊,一般包含如下幾項:
-
1)net_cls:將 cgroup 中進程產生的網絡包分類,以便 Linux 的 tc(traffic controller) 可以根據分類區分出來自某個 cgroup 的包並做限流或監控。這個子系統使用等級識別符(classid)標記網絡數據包,可允許 Linux 流量控制程序 (tc)識別從具體 cgroup 中生成的數據包。
-
2)net_prio:設置 cgroup 中進程產生的網絡流量的優先級。
-
3)memory:控制 cgroup 中進程的內存佔用。
-
4)cpuset:在多核機器上設置 cgroup 中進程可以使用的 cpu 和內存。這個子系統爲 cgroup 中的任務分配獨立 CPU(在多核系統)和內存節點。
-
5)freezer:掛起 (suspend) 和恢復(resume) cgroup 中的進程。這個子系統掛起或者恢復 cgroup 中的任務。
-
6)blkio:設置對塊設備 (如硬盤) 輸入輸出的訪問控制。這個子系統爲塊設備設定輸入 / 輸出限制,比如物理設備(磁盤,固態硬盤,USB 等等)。
-
7)cpu:設置 cgroup 中進程的 CPU 佔用。這個子系統使用調度程序提供對 CPU 的 cgroup 任務訪問。
-
8)cpuacct:統計 cgroup 中進程的 CPU 佔用。這個子系統自動生成 cgroup 中任務所使用的 CPU 報告。
-
9)devices:控制 cgroup 中進程對設備的訪問 16 這個子系統可允許或者拒絕 cgroup 中的任務訪問設備。
8.1 如何查看當前系統支持哪些 subsystem?
可以通過查看 /proc/cgroups
(since Linux 2.6.24) 知道當前系統支持哪些 subsystem,下面 是一個例子:
#subsys_name hierarchy num_cgroups enabled
cpuset 11 1 1
cpu 3 64 1
cpuacct 3 64 1
blkio 8 64 1
memory 9 104 1
devices 5 64 1
freezer 10 4 1
net_cls 6 1 1
perf_event 7 1 1
net_prio 6 1 1
hugetlb 4 1 1
pids 2 68 1
每一列的說明:
-
1)subsys_name:subsystem 的名字
-
2)hierarchy:subsystem 所關聯到的 cgroup 樹的 ID,如果多個 subsystem 關聯到同一顆 cgroup 樹,那麼他們的這個字段將一樣,比如這裏的 cpu 和 cpuacct 就一樣,表示他們綁定到了同一顆樹。如果出現下面的情況,這個字段將爲 0:
-
當前 subsystem 沒有和任何 cgroup 樹綁定
-
當前 subsystem 已經和 cgroup v2 的樹綁定
-
當前 subsystem 沒有被內核開啓
-
3)num_cgroups:subsystem 所關聯的 cgroup 樹中進程組的個數,也即樹上節點的個數
-
4)enabled:1 表示開啓,0 表示沒有被開啓 (可以通過設置內核的啓動參數
cgroup_disable
來控制 subsystem 的開啓)。
8.2 Cgroups 下的 CPU 子系統
cpu 子系統用於控制 cgroup 中所有進程可以使用的 cpu 時間片。cpu subsystem 主要涉及 5 接口:cpu.cfs_period_us
、cpu.cfs_quota_us
、cpu.shares
、cpu.rt_period_us
、cpu.rt_runtime_us.cpu
。
-
1)cfs_period_us:cfs_period_us 表示一個 cpu 帶寬,單位爲微秒。系統總 CPU 帶寬:
cpu核心數 * cfs_period_us cpu
。 -
2)cfs_quota_us:cfs_quota_us 表示 Cgroup 可以使用的 cpu 的帶寬,單位爲微秒。cfs_quota_us 爲 - 1,表示使用的 CPU 不受 cgroup 限制。cfs_quota_us 的最小值爲 1ms(1000),最大值爲 1s。結合 cfs_period_us,就可以限制進程使用的 cpu。例如配置 cfs_period_us=10000,而 cfs_quota_us=2000。那麼該進程就可以可以用 2 個 cpu core。
-
3)cpu.shares:通過 cfs_period_us 和 cfs_quota_us 可以以絕對比例限制 cgroup 的 cpu 使用,即
cfs_quota_us/cfs_period_us
等於進程可以利用的 cpu cores,不能超過這個數值。而 cpu.shares 以相對比例限制 cgroup 的 cpu。例如:在兩個 cgroup 中都將 cpu.shares 設定爲 1 的任務將有相同的 CPU 時間,但在 cgroup 中將 cpu.shares 設定爲 2 的任務可使用的 CPU 時間 是在 cgroup 中將 cpu.shares 設定爲 1 的任務可使用的 CPU 時間的兩倍。 -
4)cpu.rt_runtime_us:以微秒(µs,這裏以 “us” 代表)爲單位指定在某個時間段中 cgroup 中的任務對 CPU 資源的最長連續訪問時間。建立這個限制是爲了防止一個 cgroup 中的任務獨佔 CPU 時間。如果 cgroup 中的任務應該可以每 5 秒中可有 4 秒時間訪問 CPU 資源,請將 cpu.rt_runtime_us 設定爲 4000000,並將 cpu.rt_period_us 設定爲 5000000。
-
5)cpu.rt_period_us:以微秒(µs,這裏以 “us” 代表)爲單位指定在某個時間段中 cgroup 對 CPU 資源訪問重新分配的頻率。如果某個 cgroup 中的任務應該每 5 秒鐘有 4 秒時間可訪問 CPU 資源,則請將 cpu.rt_runtime_us 設定爲 4000000,並將 cpu.rt_period_us 設定爲 5000000。注意
sched_rt_runtime_us
是實時任務的保證時間和最高佔用時間,如果實時任務沒有使用,可以分配給非實時任務,並且實時任務最終佔用的時間不能超過這個數值,參考 Linux-85 關於sched_rt_runtime_us
和sched_rt_period_us
。對cpu.rt_period_us
參數的限制是必須小於父目錄中的同名參數值。對cpu.rt_runtime_us
的限制是:Sum_{i} runtime_{i} / global_period <= global_runtime / global_period
即:
Sum_{i} runtime_{i} <= global_runtime
當前的實時進程調度算法可能導致部分實時進程被餓死,如下 A 和 B 是並列的,A 的運行時時長正好覆蓋了 B 的運行時間:
* group A: period=100000us, runtime=50000us - this runs for 0.05s once every 0.1s * group B: period= 50000us, runtime=25000us - this runs for 0.025s twice every 0.1s (or once every 0.05 sec).
Real-Time group scheduling 中提出正在開發 SCHED_EDF (Earliest Deadline First scheduling),優先調度最先結束的實時進程。
8.3 在 CentOS 中安裝 Cgroups
#若系統未安裝則進行安裝,若已安裝則進行更新。
yum install libcgroup
#查看運行狀態,並啓動服務
[root@localhost ~] service cgconfig status
Stopped
[root@localhost ~] service cgconfig start
Starting cgconfig service: [ OK ]
service cgconfig status 9 Running 1011
#查看是否安裝cgroup
[root@localhost ~] grep cgroup /proc/filesystems
8.4 查看 service 服務在哪個 cgroup 組
systemctl status [pid] | grep CGroup 23
cat /proc/[pid]/cgroup
cd /sys/fs/ && find * ‐name "*.procs" ‐exec grep [pid] {} /dev/null \; 2> /dev/null
#查看進程cgroup的最快方法是使用以下bash腳本按進程名:
#!/bin/bash
THISPID=`ps ‐eo pid,comm | grep $1 | awk '{print $1}'`
cat /proc/$THISPID/cgroup
- 如何使用 Cgroups
9.1 通過 systemctl 設置 cgroup
在使用命令 systemctl set-property
時,可以使用 tab 補全:
$ systemctl set‐property user‐1000.slice
AccuracySec= CPUAccounting= Environment= LimitCPU= LimitNICE= LimitSIGPEN DING= SendSIGKILL=
BlockIOAccounting= CPUQuota= Group= LimitDATA= LimitNOFILE= LimitSTACK= U ser=
BlockIODeviceWeight= CPUShares= KillMode= LimitFSIZE= LimitNPROC= MemoryA ccounting= WakeSystem=
BlockIOReadBandwidth= DefaultDependencies= KillSignal= LimitLOCKS= LimitR SS= MemoryLimit=
BlockIOWeight= DeviceAllow= LimitAS= LimitMEMLOCK= LimitRTPRIO= Nice=
BlockIOWriteBandwidth= DevicePolicy= LimitCORE= LimitMSGQUEUE= LimitRTTIM E= SendSIGHUP=
這裏有很多屬性可以設置,但並不是所有的屬性都是用來設置 cgroup 的,我們只需要關注 Block, CPU 和 Memory。
如果你想通過配置文件來設置 cgroup,service 可以直接在 /etc/systemd/system/xxx.service.d
目錄下面創建相應的配置文件,slice 可以直接在 /run/systemd/system/xxx.slice.d
目錄下面創建相應的配置文件。事實上通過 systemctl 命令行工具設置 cgroup 也會寫到該目錄下的配置文件中:
$ cat /run/systemd/system/user‐1000.slice.d/50‐CPUQuota.conf
[Slice]
CPUQuota=20%
9.2 設置 CPU 資源的使用上限
如果想嚴格控制 CPU 資源,設置 CPU 資源的使用上限,即不管 CPU 是否繁忙,對 CPU 資源的使用都不能超過這個上限。可以通過以下兩個參數來設置:
-
1)cpu.cfs_period_us = 統計 CPU 使用時間的週期,單位是微秒(us)
-
2)cpu.cfs_quota_us = 週期內允許佔用的 CPU 時間 (指單核的時間,多核則需要在設置時累加)
systemctl 可以通過 CPUQuota 參數來設置 CPU 資源的使用上限。例如,如果你想將用戶 tom 的 CPU 資源使用上限設置爲 20%,可以執行以下命令:
$ systemctl set‐property user‐1000.slice CPUQuota=20%
9.3 通過配置文件設置 cgroup(/etc/cgconfig.conf)
cgroup 配置文件所在位置 /etc/cgconfig.conf,其默認配置文件內容
mount {
cpuset = / cgroup / cpuset ;
cpu = / cgroup / cpu ;
cpuacct = / cgroup / cpuacct ;
memory = / cgroup / memory ;
devices = / cgroup / devices ;
freezer = / cgroup / freezer ;
net_cls = / cgroup / net_cls ;
blkio = / cgroup / blkio ;
}
相當於執行命令:
mkdir /cgroup/cpuset
mount ‐t cgroup ‐o cpuset red /cgroup/cpuset
……
mkdir /cgroup/blkio
[root@localhost ~] vi /etc/cgrules.conf
[root@localhost ~] echo 524288000 > /cgroup/memory/foo/memory.limit_in_b ytes
使用 cgroup 臨時對進程進行調整,直接通過命令即可,如果要持久化對進程進行控制,即重啓後依然有效,需要寫進配置文件 /etc/cgconfig.conf
及 /etc/cgrules.conf
。
- 查看 Cgroup
10.1 通過 systemd 查看 cgroup
1)systemd-cgls 命令:通過 systemd-cgls 命令來查看,它會返回系統的整體 cgroup 層級,cgroup 樹的最高層 由 slice 構成,如下所示:
$ systemd‐cgls ‐‐no‐page
├─1 /usr/lib/systemd/systemd ‐‐switched‐root ‐‐system ‐‐deserialize 22
├─user.slice
│ ├─user‐1000.slice
│ │ └─session‐11.scope
│ │ ├─9507 sshd: tom [priv]
│ │ ├─9509 sshd: tom@pts/3
│ │ └─9510 ‐bash
│ └─user‐0.slice
│ └─session‐1.scope
│ ├─ 6239 sshd: root@pts/0
│ ├─ 6241 ‐zsh
│ └─11537 systemd‐cgls ‐‐no‐page
└─system.slice 15 ├─rsyslog.service
│ └─5831 /usr/sbin/rsyslogd ‐n
├─sshd.service 18 │ └─5828 /usr/sbin/sshd ‐D
├─tuned.service
│ └─5827 /usr/bin/python2 ‐Es /usr/sbin/tuned ‐l ‐P 21 ├─crond.service
│ └─5546 /usr/sbin/crond ‐n
可以看到系統 cgroup 層級的最高層由 user.slice 和 system.slice 組成。因爲系統中沒有 運行虛擬機和容器,所以沒有 machine.slice,所以當 CPU 繁忙時,user.slice 和 system.slice 會各獲得 50% 的 CPU 使用時間。
user.slice 下面有兩個子 slice:user-1000.slice 和 user-0.slice,每個子 slice 都用 User ID (UID) 來命名,因此我們很容易識別出哪個 slice 屬於哪個用戶。例如從上面的輸出信息中可以看出 user-1000.slice 屬於用戶 tom,user-0.slice 屬於用戶 root。
2)systemd-cgtop 命令:systemd-cgls 命令提供的只是 cgroup 層級的靜態信息快照,要想查看 cgroup 層級的動 態信息,可以通過 systemd-cgtop 命令查看:
$ systemd‐cgtop
Path Tasks %CPU Memory Input/s Output/s
/ 161 1.2 161.0M ‐ ‐ 5 /system.slice ‐ 0.1 ‐ ‐ ‐
/system.slice/vmtoolsd.service 1 0.1 ‐ ‐ ‐
/system.slice/tuned.service 1 0.0 ‐ ‐ ‐
/system.slice/rsyslog.service 1 0.0 ‐ ‐ ‐
/system.slice/auditd.service 1 ‐ ‐ ‐ ‐
/system.slice/chronyd.service 1 ‐ ‐ ‐ ‐
/system.slice/crond.service 1 ‐ ‐ ‐ ‐
/system.slice/dbus.service 1 ‐ ‐ ‐ ‐
/system.slice/gssproxy.service 1 ‐ ‐ ‐ ‐
/system.slice/lvm2‐lvmetad.service 1 ‐ ‐ ‐ ‐
/system.slice/network.service 1 ‐ ‐ ‐ ‐
/system.slice/polkit.service 1 ‐ ‐ ‐ ‐
/system.slice/rpcbind.service 1 ‐ ‐ ‐ ‐
/system.slice/sshd.service 1 ‐ ‐ ‐ ‐
/system.slice/system‐getty.slice/getty@tty1.service 1 ‐ ‐ ‐ ‐
/system.slice/systemd‐journald.service 1 ‐ ‐ ‐ ‐
/system.slice/systemd‐logind.service 1 ‐ ‐ ‐ ‐
/system.slice/systemd‐udevd.service 1 ‐ ‐ ‐ ‐
/system.slice/vgauthd.service 1 ‐ ‐ ‐ ‐
/user.slice 3 ‐ ‐ ‐ ‐
/user.slice/user‐0.slice/session‐1.scope 3 ‐ ‐ ‐ ‐
/user.slice/user‐1000.slice 3 ‐ ‐ ‐ ‐
/user.slice/user‐1000.slice/session‐11.scope 3 ‐ ‐ ‐ ‐
/user.slice/user‐1001.slice/session‐8.scope
scope systemd-cgtop 提供的統計數據和控制選項與 top 命令類似,但該命令只顯示那些開啓了 資源統計功能的 service 和 slice。
如果你想開啓 sshd.service
的資源統計功能,可以進行如下操作:
$ systemctl set‐property sshd.service CPUAccounting=true MemoryAccounting=true
#該命令會在 /etc/systemd/system/sshd.service.d/ 目錄下創建相應的配置文件:
$ ll /etc/systemd/system/sshd.service.d/
總用量 8
4 ‐rw‐r‐‐r‐‐ 1 root root 28 5月 31 02:24 50‐CPUAccounting.conf
4 ‐rw‐r‐‐r‐‐ 1 root root 31 5月 31 02:24 50‐MemoryAccounting.conf
$ cat /etc/systemd/system/sshd.service.d/50‐CPUAccounting.conf
[Service]
CPUAccounting=yes 1415
$ cat /etc/systemd/system/sshd.service.d/50‐MemoryAccounting.conf
[Service]
MemoryAccounting=yes 1819
#配置完成之後,再重啓 sshd 服務:
$ systemctl daemon‐reload 21 $ systemctl restart sshd
這時再重新運行 systemd‐cgtop
命令,就能看到 sshd 的資源使用統計了。
10.2 通過 proc 查看 cgroup
如何查看當前進程屬於哪些 cgroup 可以通過查看 /proc/[pid]/cgroup
(since Linux 2.6.24) 知道指定進程屬於哪些 cgroup,如下:
$ cat /proc/777/cgroup
11:cpuset:/
10:freezer:/
9:memory:/system.slice/cron.service
8:blkio:/system.slice/cron.service
7:perf_event:/ 7 6:net_cls,net_prio:/
5:devices:/system.slice/cron.service
4:hugetlb:/
3:cpu,cpuacct:/system.slice/cron.service
2:pids:/system.slice/cron.service
1:name=systemd:/system.slice/cron.service
每一行包含用冒號隔開的三列,他們的意思分別是:
cgroup樹的ID :和cgroup樹綁定的所有subsystem :進程在cgroup樹中的路徑
-
1)cgroup 樹的 ID,和
/proc/cgroups
文件中的 ID 一一對應。 -
2)和 cgroup 樹綁定的所有 subsystem,多個 subsystem 之間用逗號隔開。這裏
name=systemd
表示沒有和任何 subsystem 綁定,只是給他起了個名字叫 systemd。 -
3)進程在 cgroup 樹中的路徑,即進程所屬的 cgroup,這個路徑是相對於掛載點的相對路徑。
10.3 通過 /sys
查看 cgroup
查看 cgroup 下 CPU 資源的使用上限:
$ cat /sys/fs/cgroup/cpu,cpuacct/user.slice/user‐1000.slice/cpu.cfs_perio d_us
100000
$ cat /sys/fs/cgroup/cpu,cpuacct/user.slice/user‐1000.slice/cpu.cfs_quota _us
20000
這表示用戶 tom 在一個使用週期內(100 毫秒)可以使用 20 毫秒的 CPU 時間。不管 CPU 是否空閒,該用戶使用的 CPU 資源都不會超過這個限制。
CPUQuota 的值可以超過 100%,例如:如果系統的 CPU 是多核,且 CPUQuota 的值爲 200%,那麼該 slice 就能夠使用 2 核的 CPU 時間。
作者丨 dvlinker
來源丨網址:https://blog.csdn.net/chenlycly/article/details/125956805
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/uvtuaXIDoCyy7-JO4qYY8Q