五分鐘搞定Docker底層原理
一位同學(xué)曾給我打比方:宿主機(jī)就好比一間大房子,Docker 把它成了 N 個小隔斷。在這些小隔斷之間,有獨立的衛(wèi)生間、小床、電視...
圖片來自 包圖網(wǎng)
麻雀雖小,五臟俱全,這個比喻非常的貼切。Linux 提供了非常全面的隔離機(jī)制,使得每個小隔間互不影響。即使隔壁小間滿室春光,我的小房間一樣的冷清,對我毫無影響。
Docker 能實現(xiàn)這些功能,依賴于 chroot、namespace、cgroup 等三種老技術(shù)。
我們本篇文章,就先聊一下 namespace 方面的東西。畢竟隔離是容器的第一要素。
Linux 的內(nèi)核,提供了多達(dá) 8 種類型的 Namespace。在這些獨立的 Namespace 中,資源互不影響,隔離措施做的非常好。
8 種類型
我們先來看一下,Linux 都支持哪些 Namespace??梢酝ㄟ^ unshare 命令來觀察到這些細(xì)節(jié)。
在終端執(zhí)行 man unshare,將會出現(xiàn)這些 Namespace 的介紹:
- Mount(mnt):隔離掛載點
- Process ID (pid):隔離進(jìn)程 ID
- Network (net):隔離網(wǎng)絡(luò)設(shè)備,端口號等
- Interprocess Communication (ipc):隔離 System V IPC 和 POSIX message queues
- UTS Namespace(uts):隔離主機(jī)名和域名
- User Namespace (user):隔離用戶和用戶組
另外,Linux 在 4.6 版本,5.6 版本,分別加入了 cgroups 和 Time 兩種隔離類型,加起來就有 8 種。
Control group (cgroup) Namespace 隔離 Cgroups 根目錄 (4.6 版本加入);Time Namespace 隔離系統(tǒng)時間 (5.6 版本加入)。
1 個例子
通過 unshare 命令,可以快速建立一些隔離的例子,我們拿最簡單直觀的 pid namespace 來看一下它的效果。
眾所周知,Linux 進(jìn)程號為 1 的,叫做 systemd 進(jìn)程。但在 Docker 中,我們通過執(zhí)行 ps 命令,卻只能看到非常少的進(jìn)程列表。
執(zhí)行下面的命令,進(jìn)入隔離環(huán)境,并將 bash 作為根進(jìn)程:
- unshare --pid --fork --mount-proc /bin/bash
效果如圖所示:
可以看到,我們的 bash,已經(jīng)成為了 1 號進(jìn)程,而宿主機(jī)和其他隔離環(huán)境的進(jìn)程信息,在這里是不可見的。
先在隔離環(huán)境中,執(zhí)行 sleep 1000。再開一個終端,在宿主機(jī)上執(zhí)行 pstree,我們將會看到這個隔離環(huán)境的進(jìn)行信息。
接下來,在宿主機(jī)上,把 sleep 對應(yīng)進(jìn)程的命名空間信息,和宿主機(jī)的命名空間信息作一下對比。
可以看到,它們的 pid namespace,對應(yīng)的數(shù)值是不同的。
下面給出其他 namespace 的實驗性命令,你可以實際操作一下。
試驗一下
- unshare --mount --fork /bin/bash
創(chuàng)建 mount namespace,并在每個不同的環(huán)境中,使用不同的掛載目錄。
- unshare --uts --fork /bin/bash
uts 可以用來隔離主機(jī)名稱,允許每個 namespace 擁有一個獨立的主機(jī)名,你可以通過 hostname 命令進(jìn)行修改。
- unshare --ipc --fork /bin/bash
IPC Namespace 主要是用來隔離進(jìn)程間通信的。Linux 的進(jìn)程間通信,有管道、信號、報文、共享內(nèi)存、信號量、套接口等方式。
使用了 IPC 命名空間,意味著跨 Namespace 的這些通信方式將全部失效!不過,這也正是我們所希望的到的。
- unshare --user -r /bin/bash
用戶命名空間,就非常好理解了。我們可以在一個 Namespace 中建立 xjjdog 賬號,也可以在另外一個 Namespace 中建立 xjjdog 賬號,而且它們是相互不影響的。
- unshare --net --fork /bin/bash
net namespace,這個就非常有用了。它可以用來隔離網(wǎng)絡(luò)設(shè)備、IP 地址和端口等信息。
結(jié)語
可以看到,通過各種 Namespace,Linux 能夠?qū)Ω鞣N資源進(jìn)行精細(xì)化的隔離。
Docker 本身也是一個新瓶裝舊酒的玩具。Docker 的創(chuàng)新之處,在于它加入了一個中央倉庫,并封裝了很多易用的命令。
你可能會發(fā)現(xiàn),到目前為止,我們并沒有對 CPU 和內(nèi)存的資源使用進(jìn)行隔離,也沒有對應(yīng)的 Namespace 來解決這些問題。
資源限制的功能,是使用 Cgroups 進(jìn)行限額配置來完成的,和 Namespace 沒什么關(guān)系。我們將在后面的文章,介紹 Cgroups 這項技術(shù)。
最后,附上 Docker 的一張生命周期圖:
Docker 發(fā)展到現(xiàn)在,應(yīng)用工具鏈已經(jīng)非常成熟了,很多同學(xué)已經(jīng)駕輕就熟,如果你對容器技術(shù)非常感興趣,不如多看一下最底層的原理。這樣,不管是谷歌推自己的容器,還是繼續(xù)使用 Docker,都能快速把它掌握。
作者:小姐姐味道
編輯:陶家龍
來源:轉(zhuǎn)載自公眾號小姐姐味道(ID:xjjdog)