名字空間是 Linux 內(nèi)核一個(gè)強(qiáng)大的特性。每個(gè)容器都有自己單獨(dú)的名字空間,運(yùn)行在其中的應(yīng)用都像是在獨(dú)立的操作系統(tǒng)中運(yùn)行一樣。名字空間保證了容器之間彼此互不影響。
不同用戶的進(jìn)程就是通過 pid 名字空間隔離開的,且不同名字空間中可以有相同 pid。所有的 LXC 進(jìn)程在 Docker 中的父進(jìn)程為Docker進(jìn)程,每個(gè) LXC 進(jìn)程具有不同的名字空間。同時(shí)由于允許嵌套,因此可以很方便的實(shí)現(xiàn)嵌套的 Docker 容器。
有了 pid 名字空間, 每個(gè)名字空間中的 pid 能夠相互隔離,但是網(wǎng)絡(luò)端口還是共享 host 的端口。網(wǎng)絡(luò)隔離是通過 net 名字空間實(shí)現(xiàn)的, 每個(gè) net 名字空間有獨(dú)立的 網(wǎng)絡(luò)設(shè)備, IP 地址, 路由表, /proc/net 目錄。這樣每個(gè)容器的網(wǎng)絡(luò)就能隔離開來。Docker 默認(rèn)采用 veth 的方式,將容器中的虛擬網(wǎng)卡同 host 上的一 個(gè)Docker 網(wǎng)橋 docker0 連接在一起。
容器中進(jìn)程交互還是采用了 Linux 常見的進(jìn)程間交互方法(interprocess communication - IPC), 包括信號(hào)量、消息隊(duì)列和共享內(nèi)存等。然而同 VM 不同的是,容器的進(jìn)程間交互實(shí)際上還是 host 上具有相同 pid 名字空間中的進(jìn)程間交互,因此需要在 IPC 資源申請(qǐng)時(shí)加入名字空間信息,每個(gè) IPC 資源有一個(gè)唯一的 32 位 id。
類似 chroot,將一個(gè)進(jìn)程放到一個(gè)特定的目錄執(zhí)行。mnt 名字空間允許不同名字空間的進(jìn)程看到的文件結(jié)構(gòu)不同,這樣每個(gè)名字空間 中的進(jìn)程所看到的文件目錄就被隔離開了。同 chroot 不同,每個(gè)名字空間中的容器在 /proc/mounts 的信息只包含所在名字空間的 mount point。
UTS("UNIX Time-sharing System") 名字空間允許每個(gè)容器擁有獨(dú)立的 hostname 和 domain name, 使其在網(wǎng)絡(luò)上可以被視作一個(gè)獨(dú)立的節(jié)點(diǎn)而非 主機(jī)上的一個(gè)進(jìn)程。
每個(gè)容器可以有不同的用戶和組 id, 也就是說可以在容器內(nèi)用容器內(nèi)部的用戶執(zhí)行程序而非主機(jī)上的用戶。
注:關(guān)于 Linux 上的名字空間,這篇文章 介紹的很好。