大家好,我是小白。今天給大家講解一下Linux下的資源控制cgroup。
提到cgroup,可能有的同學(xué)一時(shí)不太清楚做什么用的,但大家應(yīng)該都用過(guò)公有云虛擬機(jī)或者容器,套餐1C2G,如何限制資源使用實(shí)現(xiàn)的呢,答案就是cgroup啦~

一、何為cgroup
Linux cgroups 的全稱是 Linux Control Groups,它是 Linux 內(nèi)核的特性,主要作用是限制、記錄和隔離進(jìn)程組(process groups)使用的物理資源(cpu、memory、IO 等)。
cgroups 從設(shè)計(jì)之初使命就很明確,為進(jìn)程提供資源控制,它主要的功能包括:
Resource limitation: 限制資源使用,比如內(nèi)存使用上限以及文件系統(tǒng)的緩存限制。
Prioritization: 優(yōu)先級(jí)控制,比如:CPU利用和磁盤IO吞吐。
Accounting: 一些審計(jì)或一些統(tǒng)計(jì),主要目的是為了計(jì)費(fèi)。
Control: 掛起進(jìn)程,恢復(fù)執(zhí)行進(jìn)程
目前 cgroups 已經(jīng)成為很多技術(shù)的基礎(chǔ),比如 Openstack、LXC、Docker、Kubernetes、systemd等。
二、Cgroup概念
cgroup 全程control group,除了它本身的概念,還有Task(進(jìn)程)、 Hierarchy(層級(jí)結(jié)構(gòu)) 和 subsystem(子系統(tǒng)) 的概念

1. cgroups子系統(tǒng)
cgroups為每種可以控制的資源定義了一個(gè)子系統(tǒng)。典型的子系統(tǒng)介紹如下:
? ? cpu 子系統(tǒng),主要限制進(jìn)程的 cpu 使用率。
? ? cpuacct 子系統(tǒng),可以統(tǒng)計(jì) cgroups 中的進(jìn)程的 cpu 使用報(bào)告。
? ? cpuset 子系統(tǒng),可以為 cgroups 中的進(jìn)程分配單獨(dú)的 cpu 節(jié)點(diǎn)或者內(nèi)存節(jié)點(diǎn)。
? ? memory 子系統(tǒng),可以限制進(jìn)程的 memory 使用量。
? ? blkio 子系統(tǒng),可以限制進(jìn)程的塊設(shè)備 io。
? ? devices 子系統(tǒng),可以控制進(jìn)程能夠訪問(wèn)某些設(shè)備。
? ? net_cls 子系統(tǒng),可以標(biāo)記 cgroups 中進(jìn)程的網(wǎng)絡(luò)數(shù)據(jù)包,然后可以使用 tc 模塊(traffic control)對(duì)數(shù)據(jù)包進(jìn)行控制。
? ? freezer 子系統(tǒng),可以掛起或者恢復(fù) cgroups 中的進(jìn)程。
? ? ns 子系統(tǒng),可以使不同 cgroups 下面的進(jìn)程使用不同的 namespace。
這里面每一個(gè)子系統(tǒng)都需要與內(nèi)核的其他模塊配合來(lái)完成資源的控制,比如對(duì) cpu 資源的限制是通過(guò)進(jìn)程調(diào)度模塊根據(jù) cpu 子系統(tǒng)的配置來(lái)完成的;對(duì)內(nèi)存資源的限制則是內(nèi)存模塊根據(jù) memory 子系統(tǒng)的配置來(lái)完成的,而對(duì)網(wǎng)絡(luò)數(shù)據(jù)包的控制則需要 Traffic Control 子系統(tǒng)來(lái)配合完成。本文不會(huì)討論內(nèi)核是如何使用每一個(gè)子系統(tǒng)來(lái)實(shí)現(xiàn)資源的限制,而是重點(diǎn)放在內(nèi)核是如何把 cgroups 對(duì)資源進(jìn)行限制的配置有效的組織起來(lái)的,和內(nèi)核如何把cgroups 配置和進(jìn)程進(jìn)行關(guān)聯(lián)的,以及內(nèi)核是如何通過(guò) cgroups 文件系統(tǒng)把cgroups的功能暴露給用戶態(tài)的。
2. cgroups 層級(jí)結(jié)構(gòu)(Hierarchy)
內(nèi)核使用 cgroup 結(jié)構(gòu)體來(lái)表示一個(gè) control group 對(duì)某一個(gè)或者某幾個(gè) cgroups 子系統(tǒng)的資源限制。cgroup 結(jié)構(gòu)體可以組織成一顆樹(shù)的形式,每一棵cgroup 結(jié)構(gòu)體組成的樹(shù)稱之為一個(gè) cgroups 層級(jí)結(jié)構(gòu)。cgroups層級(jí)結(jié)構(gòu)可以 attach 一個(gè)或者幾個(gè) cgroups 子系統(tǒng),當(dāng)前層級(jí)結(jié)構(gòu)可以對(duì)其 attach 的 cgroups 子系統(tǒng)進(jìn)行資源的限制。每一個(gè) cgroups 子系統(tǒng)只能被 attach 到一個(gè) cpu 層級(jí)結(jié)構(gòu)中。
3. cgroup概念間的關(guān)系
? ? 系統(tǒng)創(chuàng)建hierarchy 之后,所有的進(jìn)程都會(huì)加入這個(gè)hierarchy的cgroup的根節(jié)點(diǎn)。在這個(gè)cgroup根節(jié)點(diǎn)是hierarchy默認(rèn)創(chuàng)建的。
? ? 一個(gè)subsystem只能附加到一個(gè)hierarchy上面。
? ? 一個(gè)進(jìn)程可以作為多個(gè)cgroup的成員,但是cgroup必須在不同的hierarchy中。
? ? 一個(gè)進(jìn)程fork的子進(jìn)程和父進(jìn)程在同一個(gè)cgroup中也可以根據(jù)需要移到其他cgroup中。
三、容器如何使用cgroup的
1. Docker容器和cgroup
Docker 容器的內(nèi)存限制放在了 /sys/fs/cgroup/memory/docker 目錄下,比如:

2. Kubernetes Pod和cgroup
CRI-O 是被設(shè)計(jì)面向 Kubernetes 的,所以在一些目錄名中就有濃濃的 k8s 風(fēng)格。
CRI-O 容器的內(nèi)存限制放在了 /sys/fs/cgroup/memory/kubepods.slice 目錄下,這一層目錄下,又根據(jù) QoS 創(chuàng)建了三個(gè)子目錄 kubepods-besteffort.slice、kubepods-burstable.slice、kubepods-guaranteed.sice 分別表示三種不同 QoS Class的內(nèi)存限制。
#kubectl -n wcloud get pods
#docker inspect k8s_xxxx-scheduler_xxxx-scheduler-0_wcloud_e9ea0db4-cbbb-4902-99d2-21c9b9b3d20b_0 |grep CgroupParent
"CgroupParent": "/kubepods/besteffort/pode9ea0db4-cbbb-4902-99d2-21c9b9b3d20b",

Kubernete對(duì)資源的限制,靠的是cri-o,cri-o對(duì)資源的限制,靠的是Linux Cgroup 。
Linux Cgroup 限制資源,是限制進(jìn)程,只需要在Cgroup配置目錄的tasks文件中,添加進(jìn)程ID,限制立即生效。
Linux Cgroup 不僅僅可以限制CPU,內(nèi)存,還可以限制磁盤IO等。