Cgroups 是 Linux 系統內核提供的一種機制,這種機制可以根據需求將一些列系統任務機器子任務整合或分離到按資源劃分登記的不同組內,從而為系統資源管理提供一個的框架。簡單地說,cgroups 可以限制、記錄任務組所使用的物理組員(比如 CPU、Memory、IO等),為容器實現虛擬化提供了基本保證,是構建 Docker 等一些列虛擬化管理工具的基石。今天我們就來詳細介紹一下 cgroups 相關的內容。
1. 為什么要了解 Cgroups
從2013年開源的 Docker 推出、2014年開源的 Kubernetes 出現,到現在的云原生技術與生態的全面普及與火熱化,容器技術已經逐步成為主流的基礎云原生技術之一。使用容器技術,可以很好地實現資源層面上的限制和隔離,這都依賴于 Linux 系統內核所提供的Cgroups和 Namespace技術。
Cgroups 主要用來管理資源的分配、限制;Namespace 主要用來封裝抽象、限制、隔離資源,使命名空間內的進程擁有它們自己的全局資源。
Linux內核提供的 Cgroups 和 Namespace 技術,為容器實現虛擬化提供了基本保證,是構建 Docker 等一些列虛擬化管理工具的基石。下面我們就來詳細介紹一下 Cgroups 相關的內容。
2. 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 可以混合使用,但是這樣會更復雜,所以一般沒人會這樣用。
3. 什么是 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 就是一個這樣的例子。
4. 為什么需要 Cgroups?
在 Linux 里,一直以來就有對進程進行分組的概念和需求,比如 session group, progress group 等,后來隨著人們對這方面的需求越來越多,比如需要追蹤一組進程的內存和 IO 使用情況等,于是出現了 cgroup,用來統一將進程進行分組,并在分組的基礎上對進程進行監控和資源控制管理等。
舉個例子,Linux 系統中安裝了殺毒軟件 ESET 或者 ClamAV,殺毒時占用系統資源過高,影響系統承載業務運行,怎么辦?單個虛擬機進程或者 docker 進程使用過高的資源,怎么辦?單個Java進行占用系統過多的內存的資源,怎么辦?
cgroup 就是能夠控制并解決上述問題的工具,cgroup 在 linux 內核實現、用于控制 linux 系統資源。
5. 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。
6. 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子系統可以將進程組掛起和恢復。
7. 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。
8. 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
?
9. 如何使用 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。
10. 查看 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/? 10/? 9/system.slice/cron.service? 8/system.slice/cron.service? 7/?7?6:net_cls,net_prio:/? 5/system.slice/cron.service? 4/? 3:cpu,cpuacct:/system.slice/cron.service? 2/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 時間。
審核編輯:湯梓紅
評論