1. 程式人生 > >Docker基礎: Linux核心名稱空間之(1) mnt namespace

Docker基礎: Linux核心名稱空間之(1) mnt namespace

作為開源Container技術代表的Docker,它跟Linux核心的Namespace和Cgroup兩大特性密不可分。物有本末,事有終始。知所先後,則近道矣。理解Linux的這兩大特性將有助於我們更深入的理解Docker。在前面的文章中,我們曾經體驗過如何使用chroot和LXC,在本文中我們將會使用unshare命令來演示Linux核心的MNT Namespace是如何動作的。

Namespace的歷史

Namespace並不是Linux才推出的東西,早在很久之前,Unix上就有類似的東西,而HPUX和Solaris商用的Conatiner更是以前就有推出。而在Linux的2.6之後的版本Namespace就逐步的被加了進來。

Linux Namespace的6大型別

項番 型別 功能說明
No.1 MNT Namespace 提供磁碟掛載點和檔案系統的隔離能力
No.2 IPC Namespace 提供程序間通訊的隔離能力
No.3 Net Namespace 提供網路隔離能力
No.4 UTS Namespace 提供主機名隔離能力
No.5 PID Namespace 提供程序隔離能力
No.6 User Namespace 提供使用者隔離能力

Ubuntu版本

root@ubuntu
:~# uname -a Linux ubuntu 4.4.0-31-generic #50-Ubuntu SMP Wed Jul 13 00:07:12 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux root@ubuntu:~#

事前確認

確認當前程序PID

root@ubuntu:~# echo $$
32968
root@ubuntu:~#

確認當前程序的各個namespace

root@ubuntu:~# ls -l /proc/$$/ns
total 0
lrwxrwxrwx 1 root root 0 Sep 15 10:23 cgroup ->
cgroup:[4026531835] lrwxrwxrwx 1 root root 0 Sep 15 10:23 ipc -> ipc:[4026531839] lrwxrwxrwx 1 root root 0 Sep 15 10:23 mnt -> mnt:[4026531840] lrwxrwxrwx 1 root root 0 Sep 15 10:23 net -> net:[4026531957] lrwxrwxrwx 1 root root 0 Sep 15 10:23 pid -> pid:[4026531836] lrwxrwxrwx 1 root root 0 Sep 15 10:23 user -> user:[4026531837] lrwxrwxrwx 1 root root 0 Sep 15 10:23 uts -> uts:[4026531838] root@ubuntu:~#

內容說明

項番 內容說明
No.1 linux會在/proc下建立所對應的程序相關的資訊,ns則為Namespace的資訊
No.2 $$為當前程序PID,/proc/$$/ns下的Namespace的個數回隨著Linux核心的高低不同顯示的個數不同,因為Linux所支援的Namespace不是一次到位的
No.3 mnt:[4026531840],不同的Namespace都有不同的編號,比如32968的mnt的namespace的編號就是4026531840
No.4 關於Cgroup會單獨在後面進行說明

沒有隔離的mount

首先我們來看一下沒有隔離的mount是怎樣動作的,為了簡單起見使用tmpfs這種基於記憶體的檔案系統來模擬。

事前準備

root@ubuntu:~# mkdir /tmp/testnoisolation

mount tmpfs

root@ubuntu:~# mount -t tmpfs tmpfs /tmp/testnoisolation
root@ubuntu:~# cd /tmp/testnoisolation
root@ubuntu:/tmp/testnoisolation# 

建立檔案

root@ubuntu:/tmp/testnoisolation# touch aaa bbb ccc ddd
root@ubuntu:/tmp/testnoisolation# ll
total 4
drwxrwxrwt  2 root root  120 Sep 15 10:56 ./
drwxrwxrwt 13 root root 4096 Sep 15 10:55 ../
-rw-r--r--  1 root root    0 Sep 15 10:56 aaa
-rw-r--r--  1 root root    0 Sep 15 10:56 bbb
-rw-r--r--  1 root root    0 Sep 15 10:56 ccc
-rw-r--r--  1 root root    0 Sep 15 10:56 ddd
root@ubuntu:/tmp/testnoisolation#

確認

在新起一個終端來確認目錄/tmp/testnoisolation的資訊

admin01@ubuntu:~$ echo $$
33414
admin01@ubuntu:~$ ls -l /tmp/testnoisolation
total 0
-rw-r--r-- 1 root root 0 Sep 15 10:56 aaa
-rw-r--r-- 1 root root 0 Sep 15 10:56 bbb
-rw-r--r-- 1 root root 0 Sep 15 10:56 ccc
-rw-r--r-- 1 root root 0 Sep 15 10:56 ddd
admin01@ubuntu:~$

有隔離的mount

事前準備

root@ubuntu:~# mkdir /tmp/testisolation

使用unshare隔離mnt namespace

雖然也可以使用Linux核心提供的系統函式寫簡單的程式來實現,但是多少有點喧賓奪主的感覺。linux已經提供了非常貼心的unshare命令,只需要下面一行語句我們就能重新啟動一個bash的程序,而在其中的mnt namespace是被隔離的。

root@ubuntu:~# echo $$
32968
root@ubuntu:~# unshare --mount /bin/bash
root@ubuntu:~#

好像沒有任何變化,其實這個已經不是剛才我們的32968程序了,而是一個新的程序,通過確認$$就能確認

root@ubuntu:~# echo $$
33447
root@ubuntu:~#

再來確認一下,33447和32968兩個程序的關係,我們能清楚地看到這是父子關係的兩個程序,雖然都是bash

admin01@ubuntu:~$ ps -ef |grep 32968 |grep -v grep
root      32968  32967  0 10:16 pts/0    00:00:00 -su
root      33447  32968  0 11:09 pts/0    00:00:00 /bin/bash
admin01@ubuntu:~$ pstree 32968
bashqqqbash
admin01@ubuntu:~$

mount tmpfs

root@ubuntu:~# echo $$
33447
root@ubuntu:~# mount -t tmpfs tmpfs /tmp/testisolation
root@ubuntu:~# cd /tmp/testisolation
root@ubuntu:/tmp/testisolation#

建立檔案

root@ubuntu:/tmp/testisolation# touch aaa bbb ccc ddd
root@ubuntu:/tmp/testisolation# ll
total 4
drwxrwxrwt  2 root root  120 Sep 15 11:15 ./
drwxrwxrwt 14 root root 4096 Sep 15 11:02 ../
-rw-r--r--  1 root root    0 Sep 15 11:15 aaa
-rw-r--r--  1 root root    0 Sep 15 11:15 bbb
-rw-r--r--  1 root root    0 Sep 15 11:15 ccc
-rw-r--r--  1 root root    0 Sep 15 11:15 ddd
root@ubuntu:/tmp/testisolation#

確認

在新起一個終端來確認目錄/tmp/testisolation的資訊,沒有任何資訊。

admin01@ubuntu:~$ ll /tmp/testisolation
total 8
drwxr-xr-x  2 root root 4096 Sep 15 11:02 ./
drwxrwxrwt 14 root root 4096 Sep 15 11:02 ../
admin01@ubuntu:~$

新mnt Namespace編號

/proc/$$/ns下面會列出當前的namespace資訊,我們來看看一下這個使用unshare隔離了mnt namespace的資訊

root@ubuntu:~# ls -l /proc/33447/ns
total 0
lrwxrwxrwx 1 root root 0 Sep 15 11:25 cgroup -> cgroup:[4026531835]
lrwxrwxrwx 1 root root 0 Sep 15 11:11 ipc -> ipc:[4026531839]
lrwxrwxrwx 1 root root 0 Sep 15 11:11 mnt -> mnt:[4026532506]
lrwxrwxrwx 1 root root 0 Sep 15 11:11 net -> net:[4026531957]
lrwxrwxrwx 1 root root 0 Sep 15 11:11 pid -> pid:[4026531836]
lrwxrwxrwx 1 root root 0 Sep 15 11:11 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 Sep 15 11:11 uts -> uts:[4026531838]
root@ubuntu:~#

與之前進行比較,我們可以清晰地發現,除了mnt的namespace編號從4026531840變為4026532506之外,其餘都沒有改變。這也是使用unshare -m或者unshare –mnt所實現的隔離,建立了新的namespace。

和chroot的比較

在比較原始的chroot中,畫地為牢之後,是無法掙脫其所指定的根的,雖然有效但是略顯粗暴。而namespace則自由的多,起碼可以自由的動作,當然不只是這一點區別,但是這一點是最為直觀能看出來的

root@ubuntu:/tmp/testisolation# pwd
/tmp/testisolation
root@ubuntu:/tmp/testisolation# cd ../testnoisolation/
root@ubuntu:/tmp/testnoisolation# ll
total 4
drwxrwxrwt  2 root root  120 Sep 15 10:56 ./
drwxrwxrwt 14 root root 4096 Sep 15 11:17 ../
-rw-r--r--  1 root root    0 Sep 15 10:56 aaa
-rw-r--r--  1 root root    0 Sep 15 10:56 bbb
-rw-r--r--  1 root root    0 Sep 15 10:56 ccc
-rw-r--r--  1 root root    0 Sep 15 10:56 ddd
root@ubuntu:/tmp/testnoisolation#

其他相關