Docker Namespce 隔離

如果我們想像 Docker 一樣實現(xiàn)一個簡陋的資源隔離的容器祝迂,我們需要隔離文件系統(tǒng)、需要隔離網(wǎng)絡缺狠、需要隔離主機名问慎、需要隔離進程間的通信,需要隔離PID挤茄,需要隔離用戶和用戶組如叼。

Namespace 是 Linux 提供的資源隔離機制。只有在同一個 Namespace 下的進程可以相互聯(lián)系穷劈,但無法感受到外部進程的存在笼恰,營造出處于一個獨立的系統(tǒng)環(huán)境中的錯覺,從而實現(xiàn)了隔離囚衔。

Linux內(nèi)核中就提供了這六種 namespace 隔離的系統(tǒng)調(diào)用挖腰,如下表所示雕沿。

image.png

Linux提供的操作 namespace 相關 API 介紹如下:
API包括 clone()练湿、setns( )以及 unshare(),還有 /proc 下的部分文件审轮。為了確定隔離的到底是哪種 namespace肥哎,在使用這些 API 時,通常需要指定上面圖中的參數(shù)的六個常數(shù)的一個或多個疾渣,通過 |(位或)操作來實現(xiàn)篡诽。

  1. clone()
    clone()是fork()的一種實現(xiàn)方式。調(diào)用fork()函數(shù)時系統(tǒng)會創(chuàng)建新進程榴捡,為其分配資源杈女,并把原來進程中的值復制到新進程中,可通過 fpid 區(qū)分新進程和父進程
int clone(int (*child_func)(void *), void *child_stack, int flags, void *arg);

參數(shù):
child_func 傳入子進程運行的程序主函數(shù)吊圾。
child_stack 傳入子進程使用的棿镆空間
flags 表示使用哪些 CLONE_* 標志位
args 則可用于傳入用戶參數(shù)

  1. setns()
    setns()用于加入已存在的namespace
int setns(int fd, int nstype);

參數(shù):
fd:要加入namespace的文件描述符(指向/proc/[pid]/ns目錄)。
nstype:要加入namespace的類型项乒,用于檢查啰劲,0表示不檢查。

  1. unshare()
    unshare()在原進程上進行namespace隔離檀何。
int unshare(int flags)

unshare()不啟動新進程蝇裤,但是跳出了原來的namespace廷支。

UTS(UNIX Time-sharing System)namespace

分時系統(tǒng)(Time-sharing System)中一臺主機連接了若干個終端,每個終端有一個用戶在使用栓辜。

用戶交互式地向系統(tǒng)提出命令請求恋拍,系統(tǒng)接受每個用戶的命令,采用時間片輪轉方式處理服務請求藕甩,并通過交互方式在終端上向用戶顯示結果芝囤。用戶根據(jù)上步結果發(fā)出下道命令。

分時操作系統(tǒng)將CPU的時間劃分成若干個片段,稱為時間片扮匠。操作系統(tǒng)以時間片為單位池颈,輪流為每個終端用戶服務。每個用戶輪流使用一個時間片而使每個用戶并不感到有別的用戶存在悯许。

UTS(Unix Time-sharing System) namespace提供了主機名和域名的隔離,使每個Docker容器可以擁有獨立的主機名和域名辉阶,在網(wǎng)絡上可以視為獨立的節(jié)點先壕。
下面通過 go 來簡單實現(xiàn) UTS 隔離

package main

import (
    "log"
    "os"
    "os/exec"
    "syscall"
)

func main() {
    cmd := exec.Command("sh")
    cmd.SysProcAttr = &syscall.SysProcAttr{
        Cloneflags: syscall.CLONE_NEWUTS,
    }
    cmd.Stdin = os.Stdin
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr
    if err := cmd.Run(); err != nil {
        log.Fatal(err)
    }
}

在 Linux 環(huán)境下執(zhí)行

go run uts.go

此時在一個新的進程中執(zhí)行了sh命令,由于指定了 flag syscall.CLONE_NEWUTS, 此時已經(jīng)與之前的進程不在同一個 UTS namespace中了谆甜。在新 sh 和原 sh 中分別執(zhí)行 ls -l /proc/$$/ns 進行驗證,可以看到這里兩個只有 uts 所指向的 ID 不同,說明已經(jīng)隔離成功


image.png

IPC(Interprocess Communication)namespace

容器中進程間通信采用的方法包括常見的信號量垃僚、消息隊列和共享內(nèi)存。然而與虛擬機不同的是规辱,容器內(nèi)部進程間通信對宿主機來說谆棺,實際上是具有相同 PID namespace 中的進程間通信,因此需要一個唯一的標識符來進行區(qū)別罕袋。申請 IPC 資源就申請了這樣一個全局唯一的 32 位 ID改淑,所以 IPC namespace 中實際上包含了系統(tǒng) IPC 標識符以及實現(xiàn)POSIX消息隊列的文件系統(tǒng)。在同一個 IPC namespace下的進程彼此可見浴讯,而與其他的IPC namespace下的進程則互相不可見朵夏。
IPC namespace在代碼上的變化與UTS namespace相似,只是標識位有所變化榆纽,需要加上 CLONE_NEWIPC 參數(shù)仰猖。
我們首先在 shell 中使用 ipcmk -Q 命令創(chuàng)建一個message queue。
使用 ipcs -q 查看已經(jīng)有一個 id 為 0 message queue
我們可以運行 ipd.go 新建的子進程中執(zhí)行 ipcs -q 查看 message queue奈籽。


image.png

上面的結果顯示中可以發(fā)現(xiàn)饥侵,已經(jīng)找不到原先聲明的message queue,實現(xiàn)了IPC的隔離唠摹。

Process identifier(PID) namespace

PID是大多數(shù)操作系統(tǒng)的內(nèi)核用于唯一標識進程的一個數(shù)值爆捞。
PID為1的進程是init,作為所有進程的父進程勾拉,不會處理來自其他進程的信號(信號屏蔽)煮甥,并維護一張進程表盗温,當有子進程變成孤兒時會回收其資源并結束進程。
PID namespace隔離對進程PID重新編號成肘,兩個不同namespace下的進程沒有關系卖局,因此PID也可以相同。內(nèi)核為所有的PID namespace維護了一個樹狀結構双霍。


image.png

其中:
1)每個PID namespace中的第一個進程擁有特權砚偶。
2)一個namespace中的進程不能影響父節(jié)點或兄弟節(jié)點namespace中的進程。
3)root namespace中可以看到所有的進程洒闸,包括所有后代節(jié)點中的namespace染坯。
4)在外部可以通過監(jiān)控Docker daemon所在的PID namespace中的所有進程和子進程來實現(xiàn)對Docker中運行的程序的監(jiān)控。
同樣修改 flag 運行代碼看 pid 隔離的效果:


image.png

Mount namespace

mount namespace 是歷史上第一個Linux namespace丘逸,通過隔離文件系統(tǒng)掛載點隔離文件系統(tǒng)单鹿,標識位為CLONE_NEWNS。隔離之后不同的mount namespace中的文件結構互不影響深纲。

可以通過/proc/[pid]/mounts查看所有掛載在當前namespace中的文件系統(tǒng)仲锄。進程創(chuàng)建mount namespace時把當前文件結構復制給新的namespace。

掛載傳播(mount propagation)定義了掛載對象之間的關系湃鹊,解決了文件結構復制過程中子節(jié)點namespace影響父節(jié)點namespace文件系統(tǒng)的問題儒喊。

共享關系(share relationship):存在掛載關系的兩個掛載對象中的事件會雙向傳播
從屬關系(slave relationship):掛載對象中的事件只能按指向從屬對象的方向傳播(共享掛載—>從屬掛載)

Network namespace

network namespace提供了關于網(wǎng)絡資源的隔離,包括網(wǎng)絡設備币呵、IPv4和IPv6協(xié)議棧怀愧、IP路由表、防火墻富雅、/proc/net目錄掸驱、/sys/class/net目錄肛搬、套接字(socket)等没佑。

注意:
一個物理的網(wǎng)絡設備最多存在于一個network namespace中
可以通過veth pair在不同的network namespace中創(chuàng)建通道進行通信。
一般情況下温赔,物理網(wǎng)絡設備都分配在最初的root namespace中蛤奢。
User namespace
user namespace主要隔離了安全相關的標識符和屬性(用戶ID、用戶組ID陶贼、root目錄啤贩、key(密鑰)、特殊權限)拜秧。

因此用 clone() 創(chuàng)建的新進程在新的 user namespace 中可以擁有不同的用戶和用戶組痹屹,在新進程創(chuàng)建的容器中,它是超級用戶枉氮,但在容器之外只是普通用戶志衍。

Linux中暖庄,特權用戶的 user ID 是 0,user ID 非 0 的進程啟動 user namespace后 user ID 可以變?yōu)?0

參考:
http://www.sel.zju.edu.cn/?p=556
http://lionheartwang.github.io/blog/2018/03/18/dockerzi-yuan-ge-chi-he-xian-zhi-shi-xian-yuan-li/

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末楼肪,一起剝皮案震驚了整個濱河市培廓,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌春叫,老刑警劉巖肩钠,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異暂殖,居然都是意外死亡价匠,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門呛每,熙熙樓的掌柜王于貴愁眉苦臉地迎上來霞怀,“玉大人,你說我怎么就攤上這事莉给”惺” “怎么了?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵颓遏,是天一觀的道長徐矩。 經(jīng)常有香客問我,道長叁幢,這世上最難降的妖魔是什么滤灯? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮曼玩,結果婚禮上鳞骤,老公的妹妹穿的比我還像新娘。我一直安慰自己黍判,他們只是感情好豫尽,可當我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著顷帖,像睡著了一般美旧。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上贬墩,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天榴嗅,我揣著相機與錄音,去河邊找鬼陶舞。 笑死嗽测,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的肿孵。 我是一名探鬼主播唠粥,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼优炬,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了厅贪?” 一聲冷哼從身側響起蠢护,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎养涮,沒想到半個月后葵硕,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡贯吓,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年懈凹,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片悄谐。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡介评,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出爬舰,到底是詐尸還是另有隱情们陆,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布情屹,位于F島的核電站坪仇,受9級特大地震影響,放射性物質發(fā)生泄漏垃你。R本人自食惡果不足惜椅文,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望惜颇。 院中可真熱鬧皆刺,春花似錦、人聲如沸凌摄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽望伦。三九已至林说,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間屯伞,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工豪直, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留劣摇,地道東北人。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓弓乙,卻偏偏與公主長得像末融,于是被迫代替她去往敵國和親钧惧。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,979評論 2 355

推薦閱讀更多精彩內(nèi)容