Docker:Namespace和Cgroups

一. 簡介

開篇,先給出一個結(jié)論:容器是一個“單進(jìn)程”模型。一個正在運(yùn)行的 Docker 容器,其實(shí)就是一個啟用了多個 Linux Namespace 的應(yīng)用進(jìn)程,而這個進(jìn)程能夠使用的資源量,則受 Cgroups 配置的限制。
關(guān)于Namespace和Cgroups這倆功能的聯(lián)合使用,實(shí)現(xiàn)了Docker所謂的 偽“虛擬化”。

二. Namespace

Namespace是Linux內(nèi)核的功能之一,也是Linux上容器的基本方面。另一方面,Namespace提供了一層隔離。Docker使用各種Namespace來提供容器所需的隔離,以便保持可移植性并避免影響主機(jī)系統(tǒng)的其余部分。容器的每個方面都在單獨(dú)的Namespace中運(yùn)行,并且對其的訪問僅限于該Namespace。

2.1 clone()函數(shù)

Namespace 的使用方式也特別:它其實(shí)只是 Linux 創(chuàng)建新進(jìn)程的一個可選參數(shù)。
在 Linux 系統(tǒng)中創(chuàng)建線程的系統(tǒng)調(diào)用是 clone(),比如:

int pid = clone(main_function, stack_size, SIGCHLD, NULL); 

這個系統(tǒng)調(diào)用就會為我們創(chuàng)建一個新的進(jìn)程,并且返回它的進(jìn)程號 pid。而當(dāng)我們用 clone() 系統(tǒng)調(diào)用創(chuàng)建一個新進(jìn)程時,就可以在參數(shù)中指定 CLONE_NEWPID參數(shù),比如:

int pid = clone(main_function, stack_size, CLONE_NEWPID | SIGCHLD, NULL); 

2.2 原理

例如上面案例,新創(chuàng)建的這個進(jìn)程將會“看到”一個全新的進(jìn)程空間,在這個進(jìn)程空間里,它的 PID 是 1。之所以說“看到”,是因?yàn)檫@只是一個“障眼法”,在宿主機(jī)真實(shí)的進(jìn)程空間里,這個進(jìn)程的 PID 還是真實(shí)的數(shù)值,比如 100。

2.3 Namespace分類

Namespace類型如下:

  • Process ID
  • Mount
  • IPC (Interprocess communication)
  • User (currently experimental support for)
  • Network

2.4 小結(jié)

實(shí)際上在創(chuàng)建容器進(jìn)程時,Docker指定了這個進(jìn)程所需要啟用的一組 Namespace 參數(shù)。這樣,容器就只能“看”到當(dāng)前 Namespace 所限定的資源、文件、設(shè)備、狀態(tài),或者配置。而對于宿主機(jī)以及其他不相關(guān)的程序,它就完全看不到了。

三. Cgroups

Linux Cgroups的全稱是 Linux Control Group。它最主要的作用,就是限制一個進(jìn)程組能夠使用的資源上限,包括 CPU、內(nèi)存、磁盤、網(wǎng)絡(luò)帶寬等等,Cgroups 還能夠?qū)M(jìn)程進(jìn)行優(yōu)先級設(shè)置、審計,以及將進(jìn)程掛起和恢復(fù)等操作。

3.1 查看cgroup文件

在 Linux 中,Cgroups 給用戶暴露出來的操作接口是文件系統(tǒng),即它以文件和目錄的方式組織在操作系統(tǒng)的 /sys/fs/cgroup路徑下。
我們可以通過如下指令查看

mount -t cgroup

/sys/fs/cgroup下面有很多諸如cpuset、cpu、 memory這樣的子目錄,也叫子系統(tǒng)。這些都是當(dāng)前機(jī)器當(dāng)前可以被 Cgroups 進(jìn)行限制的資源種類。

3.2 限制資源

在子系統(tǒng)對應(yīng)的資源種類下,我們就可以看到該類資源具體可以被限制的方法。

  1. 查看配置文件
    對 CPU 子系統(tǒng)來說,使用如下指令查看對應(yīng)的配置文件:
ls /sys/fs/cgroup/cpu

(由于暫無對應(yīng)展示系統(tǒng),所以此處是引用自網(wǎng)上指令結(jié)果)我們會查看到這些文件:

cgroup.clone_children cpu.cfs_period_us cpu.rt_period_us cpu.shares notify_on_releasecgroup.procs cpu.cfs_quota_us cpu.rt_runtime_us cpu.stat tasks
  1. 目標(biāo)參數(shù)
    關(guān)于上面內(nèi)容,cfs_period 和 cfs_quota 這兩個參數(shù)需要組合使用,可以用來限制進(jìn)程在長度為 cfs_period 的一段時間內(nèi),只能被分配到總量為 cfs_quota 的 CPU 時間。

  2. 配置限制參數(shù)
    我們已經(jīng)找到了目標(biāo)配置,此刻我們可以向?qū)?yīng)的配置文件寫入限制參數(shù)即可。
    指令如下:

echo 30000 > /sys/fs/cgroup/cpu/container/cpu.cfs_quota_us

在每 100 ms 的時間里,被該控制組限制的進(jìn)程只能使用 30 ms 的 CPU 時間,也就是說這個進(jìn)程只能使用到 30% 的 CPU 帶寬。

  1. 配置tasks
    我們把被限制的進(jìn)程的 PID(task-id) 寫入 container 組里的 tasks 文件,上面的設(shè)置就會對該進(jìn)程生效了:
echo task-id > /sys/fs/cgroup/cpu/container/tasks 

task-id就是我們填寫我們被限制的進(jìn)程號。

Cgroup在容器空間內(nèi)提供資源限制和報告功能。它們允許對哪些主機(jī)資源分配給容器以及何時分配容器進(jìn)行精細(xì)控制。

3.3 Cgroups類型

常見的Cgroups管理的資源類型如下:

  • CPU
  • Memory
  • Network Bandwidth
  • Disk
  • Priority

3.4 小結(jié)

Linux Cgroups就是一個子系統(tǒng)目錄加上一組資源限制文件的組合。它們只需要在每個子系統(tǒng)下面,為每個容器創(chuàng)建一個控制組(即創(chuàng)建一個新目錄),然后在啟動容器進(jìn)程之后,把這個進(jìn)程的PID填寫到對應(yīng)控制組的tasks文件中就可以了。

四. 總結(jié)

容器,其實(shí)是一種特殊的進(jìn)程而已。所以,Docker其實(shí)沒有那么神話,也沒有那么的高門檻。對比虛擬機(jī),“敏捷”和“高性能”是容器最大的優(yōu)勢。
本文關(guān)于Namespace和Cgroups的講解非常粗淺,Linux相關(guān)基礎(chǔ)還是非常深的,終于明白Linux為啥這么優(yōu)秀。
換句話說,容器本身沒有價值,有價值的是“容器編排”,這將是后面文章關(guān)于Kubernetes的開始。

最后,歡迎關(guān)注我的博客:https://blog.wyatt.plus

Reference

https://medium.com/@kasunmaduraeng/docker-namespace-and-cgroups-dece27c209c7
https://coolshell.cn/articles/17010.html

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容