Docker容器本質(zhì)上是宿主機(jī)的進(jìn)程繁调,Docker通過namespace實(shí)現(xiàn)了資源隔離,通過cgroups實(shí)現(xiàn)了資源限制,通過寫時復(fù)制機(jī)制(copy-on-write)實(shí)現(xiàn)了高效的文件操作
六種namespace
六種隔離類型
- MNT Namespace
mount namespace 是用來隔離各個進(jìn)程看到的掛載點(diǎn)視圖。在不同namespace中的進(jìn)程看到的文件系統(tǒng)層次是不一樣的。在mount namespace 中調(diào)用mount()和umount()僅僅只會影響當(dāng)前namespace內(nèi)的文件系統(tǒng)乞巧,而對全局的文件系統(tǒng)是沒有影響的。
看到這里摊鸡,也許就會想到chroot()绽媒。它也是將某一個子目錄變成根節(jié)點(diǎn)蚕冬。但是mount namespace不僅能實(shí)現(xiàn)這個功能,而且能以更加靈活和安全的方式實(shí)現(xiàn)是辕。
- IPC Namespace
進(jìn)程間通信(Inter-Process Communication囤热,IPC)涉及的IPC資源包括常見的信號量、消息隊(duì)列和共享內(nèi)存获三。申請IPC資源就申請了一個全局唯一的32位ID旁蔼,所以IPC namespace中實(shí)際上包含了系統(tǒng)IPC標(biāo)識符以及實(shí)現(xiàn)POSIX消息隊(duì)列的文件系統(tǒng)。在同一個IPC namespace下的進(jìn)程彼此可見疙教,不同IPC namespace下的進(jìn)程則互相不可見棺聊。
目前使用IPC namespace機(jī)制的系統(tǒng)不多,其中比較有名的有PostgreSQL贞谓。Docker當(dāng)前也使用IPC namespace實(shí)現(xiàn)了容器與宿主機(jī)限佩、容器與容器之間的IPC隔離。
- UTS Namespace
UTS namespace 主要隔離nodename(主機(jī)名) 和domainname(域名) 兩個系統(tǒng)標(biāo)識经宏。在UTS namespace里面犀暑,每個 namespace 允許有自己的hostname驯击。
- PID Namespace
PS:在容器中默認(rèn)不能使用systemd作為PID為1的守護(hù)進(jìn)程烁兰,因?yàn)槿萜髦袥]有內(nèi)核
(1)每個PID namespace中的第一個進(jìn)程“PID 1”,都會像全通Linux中的init進(jìn)程一樣擁有特權(quán)徊都,其特殊作用沪斟。
(2)一個namespace中的進(jìn)程,不可能通過kill或ptrace影響父節(jié)點(diǎn)或者兄弟節(jié)點(diǎn)中的進(jìn)程暇矫,因?yàn)槠渌麕c(diǎn)的PID在這個namespace沒有任何意義主之。
(3)如果你在新的PID namespace中重新掛載/proc文件系統(tǒng),會發(fā)現(xiàn)其下只顯示同屬一個PID namespace中的其他進(jìn)程李根。
(4)在root namespace中看到所有的進(jìn)程槽奕,并且遞歸包含所有子節(jié)點(diǎn)中的進(jìn)程。也可以在Docker外部監(jiān)控運(yùn)行程序房轿,就是監(jiān)控Docker daemon所在的PID namespace下的所有進(jìn)程及子進(jìn)程粤攒,在進(jìn)行篩選即可。
dockerd:被client直接訪問囱持,其父進(jìn)程為宿主機(jī)的systemd守護(hù)進(jìn)程
docker-proxy:實(shí)現(xiàn)容器通信夯接,其父進(jìn)程為dockerd
containerd:被dockerd進(jìn)程調(diào)用以實(shí)現(xiàn)與runc交互
containerd-shim:真正運(yùn)行容器的載體,其父進(jìn)程為containerd
宿主機(jī)與容器的進(jìn)程關(guān)系
- Net Namespace
Network namespace 是用來隔離網(wǎng)絡(luò)設(shè)備纷妆,IP地址端口等網(wǎng)絡(luò)棧的namespace盔几。Network namespace 可以讓每個容器擁有自己獨(dú)立的網(wǎng)絡(luò)設(shè)備(虛擬的),而且容器內(nèi)的應(yīng)用可以綁定到自己的端口掩幢,每個 namesapce 內(nèi)的端口都不會互相沖突逊拍。在宿主機(jī)上搭建網(wǎng)橋后上鞠,就能很方便的實(shí)現(xiàn)容器之間的通信,而且每個容器內(nèi)的應(yīng)用都可以使用相同的端口顺献。
安裝bridge-utils旗国,查看網(wǎng)橋:brctl show
容器與宿主機(jī)網(wǎng)絡(luò)環(huán)境
- User Namespace
User namespace 主要是隔離用戶的用戶組ID。也就是說注整,一個進(jìn)程的User ID 和Group ID 在User namespace 內(nèi)外可以是不同的能曾。比較常用的是,在宿主機(jī)上以一個非root用戶運(yùn)行創(chuàng)建一個User namespace肿轨,然后在User namespace里面卻映射成root 用戶寿冕。這樣意味著,這個進(jìn)程在User namespace里面有root權(quán)限椒袍,但是在User namespace外面卻沒有root的權(quán)限驼唱。從Linux kernel 3.8開始,非root進(jìn)程也可以創(chuàng)建User namespace ,并且此進(jìn)程在namespace里面可以被映射成 root并且在 namespace內(nèi)有root權(quán)限驹暑。