作者:燒雞太子爺
背景
最近在給組內(nèi)新人講解一些docker容器化,大家都能夠理解,docker容器實際上就是運行的一個進(jìn)程,只不過由于docker幫助我們包裝了這個進(jìn)程,給這個進(jìn)程加以一個可運行的微linux環(huán)境而已,讓我們感覺看起來"像"虛擬機(jī)而已。那么他是如何做到資源控制的呢,大家也都知道是用了namespace、cgroup。個人也比較好奇,所以也花了一點時間去學(xué)習(xí)了一下,也做一些筆記,可以和大家一起學(xué)習(xí)一下
Linux namespace
Linux namespace 是一種內(nèi)核級別的資源隔離機(jī)制,用來讓運行在同一個操作系統(tǒng)上的進(jìn)程互相不會干擾。
namespace 目的就是隔離,要做到的效果是:如果某個 namespace 中有進(jìn)程在里面運行,它們只能看到該 namespace 的信息,無法看到 namespace 以外的東西。
我們來想一下:一個進(jìn)程在運行的時候,它會知道哪些信息?
- 看到系統(tǒng)的 hostname
- 可用的網(wǎng)絡(luò)資源(bridge、interface、網(wǎng)絡(luò)端口的時候情況……)
- 進(jìn)程的關(guān)系(有哪些進(jìn)程,進(jìn)程之間的父子關(guān)系等)、
- 系統(tǒng)的用戶信息(有哪些用戶、組,它們的權(quán)限是怎么樣的)
- 文件系統(tǒng)(有哪些可用的文件系統(tǒng),使用情況)
- IPC(怎么實現(xiàn)進(jìn)程間通信)
- …… 也就是說,如果要實現(xiàn)隔離,必須保證不同 namespace 中進(jìn)程看到的上面這些東西是不同的。
如果讓我來做,首先的想法是每個 namespace 都實現(xiàn)一整套上述資源的隔離,但是實際上 linux 的實現(xiàn)中,上述的所有資源都是可以多帶帶隔離的。
目前 linux 內(nèi)核主要實現(xiàn)了一下幾種不同的資源 namespace,官網(wǎng)有如下介紹:
名稱 | 宏定義 | 宏定義 |
---|---|---|
IPC | CLONE_NEWIPC | System V IPC, POSIX message queues (since Linux 2.6.19) |
Network | CLONE_NEWNET | network device interfaces, IPv4 and IPv6 protocol stacks, IP routing tables, firewall rules, the /proc/net and /sys/class/net directory trees, sockets, etc (since Linux 2.6.24) |
Mount | CLONE_NEWNS | Mount points (since Linux 2.4.19) |
PID | CLONE_NEWPID | Process IDs (since Linux 2.6.24) |
User | CLONE_NEWUSER | User and group IDs (started in Linux 2.6.23 and completed in Linux 3.8) |
UTS | CLONE_NEWUSER | Hostname and NIS domain name (since Linux 2.6.19) |
Cgroup | CLONE_NEWCGROUP | Cgroup root directory (since Linux 4.6) |
這些 namespace 基本上覆蓋了一個程序運行所需的環(huán)境,保證運行在的隔離的 namespace 中的,會讓程序不會受到其他收到 namespace 程序的干擾。但不是所有的系統(tǒng)資源都能隔離,時間就是個例外,沒有對應(yīng)的 namespace,因此同一臺 Linux 啟動的容器時間都是相同的。
但是Namespace解決的問題主要是環(huán)境隔離的問題,這只是虛擬化中最最基礎(chǔ)的一步,我們還需要解決對計算機(jī)資源使用上的隔離。也就是說,雖然你通過Namespace把我加到一個特定的環(huán)境中去了,但是我在其中的進(jìn)程使用用CPU、內(nèi)存、磁盤等這些計算資源其實還是可以隨心所欲的。所以,我們希望對進(jìn)程進(jìn)行資源利用上的限制或控制。這就是Linux CGroup出來了的原因。
Linux cgroup
Linux CGroup全稱Linux Control Group, 是Linux內(nèi)核的一個功能,用來限制,控制與分離一個進(jìn)程組群的資源(如CPU、內(nèi)存、磁盤輸入輸出等)。
Linux CGroupCgroup 可讓您為系統(tǒng)中所運行任務(wù)(進(jìn)程)的用戶定義組群分配資源 — 比如 CPU 時間、系統(tǒng)內(nèi)存、網(wǎng)絡(luò)帶寬或者這些資源的組合。您可以監(jiān)控您配置的 cgroup,拒絕 cgroup 訪問某些資源,甚至在運行的系統(tǒng)中動態(tài)配置您的 cgroup。
它主要提供了如下功能:
- Resource limitation: 限制資源使用,比如內(nèi)存使用上限以及文件系統(tǒng)的緩存限制。
- Prioritization: 優(yōu)先級控制,比如:CPU利用和磁盤IO吞吐。
- Accounting: 一些審計或一些統(tǒng)計,主要目的是為了計費。
- Control: 掛起進(jìn)程,恢復(fù)執(zhí)行進(jìn)程。 使用 cgroup,系統(tǒng)管理員可更具體地控制對系統(tǒng)資源的分配、優(yōu)先順序、拒絕、管理和監(jiān)控。可更好地根據(jù)任務(wù)和用戶分配硬件資源,提高總體效率。
cgroups 的作用:
- 資源限制
cgroups可以對任務(wù)使用的資源(內(nèi)存,CPU,磁盤等資源)總額進(jìn)行限制。 如 設(shè)定應(yīng)用運行時使用的內(nèi)存上限,一旦超過配額就發(fā)出OOM提示 - 優(yōu)先級分配
通過分配的CPU時間片數(shù)量以及磁盤IO帶寬大小,實際上就相當(dāng)于控制了任務(wù)運行的優(yōu)先級 - 資源統(tǒng)計
cgroups可以統(tǒng)計系統(tǒng)的資源使用量 如CPU使用時長,內(nèi)存用量等,這個功能非常適用于計費 - 任務(wù)控制
cgroups 可以對任務(wù)進(jìn)行掛起、恢復(fù)等操作
總結(jié)
Docker容器的本質(zhì)是宿主機(jī)上的一個進(jìn)程。Docker通過namespace實現(xiàn)了資源隔離,通過cgroups實現(xiàn)了資源限制。 namespace技術(shù)實際上修改了應(yīng)用進(jìn)程看待整個計算機(jī)“視圖”,即它的“視線”被操作系統(tǒng)做了限制,只能“看到”默寫指定的內(nèi)容,而這個進(jìn)程能夠使用的資源量,則受cgroup配置的限制,但對于宿主機(jī)來說,這些被隔離和限制了的進(jìn)程和其他進(jìn)程并沒有太大的區(qū)別。
另外,namespace和cgroup雖然已經(jīng)做的很好了,但是他們還是有很多不完善的地方,比如做不到時間的隔離,比如/proc文件系統(tǒng)的問題,這些后面有時間也可以和大家一起討論一下,本章不做具體的介紹了。