Mount namespace用來隔離文件系統的掛載點, 使得不一樣的mount namespace擁有本身獨立的掛載點信息,不一樣的namespace之間不會相互影響,這對於構建用戶或者容器本身的文件系統目錄很是有用。shell
當前進程所在mount namespace裏的全部掛載信息能夠在/proc/[pid]/mounts、/proc/[pid]/mountinfo和/proc/[pid]/mountstats裏面找到。ubuntu
Mount namespaces是第一個被加入Linux的namespace,因爲當時沒想到還會引入其它的namespace,因此取名爲CLONE_NEWNS,而沒有叫CLONE_NEWMOUNT。segmentfault
每一個mount namespace都擁有一份本身的掛載點列表,當用clone或者unshare函數建立新的mount namespace時,新建立的namespace將拷貝一份老namespace裏的掛載點列表,但從這以後,他們就沒有關係了,經過mount和umount增長和刪除各自namespace裏面的掛載點都不會相互影響。bash
本篇全部例子都在ubuntu-server-x86_64 16.04下執行經過函數
#--------------------------第一個shell窗口---------------------- #先準備兩個iso文件,用於後面的mount測試 dev@ubuntu:~$ mkdir iso dev@ubuntu:~$ cd iso/ dev@ubuntu:~/iso$ mkdir -p iso01/subdir01 dev@ubuntu:~/iso$ mkdir -p iso02/subdir02 dev@ubuntu:~/iso$ mkisofs -o ./001.iso ./iso01 dev@ubuntu:~/iso$ mkisofs -o ./002.iso ./iso02 dev@ubuntu:~/iso$ ls 001.iso 002.iso iso01 iso02 #準備目錄用於mount dev@ubuntu:~/iso$ sudo mkdir /mnt/iso1 /mnt/iso2 #查看當前所在的mount namespace dev@ubuntu:~/iso$ readlink /proc/$$/ns/mnt mnt:[4026531840] #mount 001.iso 到 /mnt/iso1/ dev@ubuntu:~/iso$ sudo mount ./001.iso /mnt/iso1/ mount: /dev/loop1 is write-protected, mounting read-only #mount成功 dev@ubuntu:~/iso$ mount |grep /001.iso /home/dev/iso/001.iso on /mnt/iso1 type iso9660 (ro,relatime) #建立並進入新的mount和uts namespace dev@ubuntu:~/iso$ sudo unshare --mount --uts /bin/bash #更改hostname並從新加載bash root@ubuntu:~/iso# hostname container001 root@ubuntu:~/iso# exec bash root@container001:~/iso# #查看新的mount namespace root@container001:~/iso# readlink /proc/$$/ns/mnt mnt:[4026532455] #老namespace裏的掛載點的信息已經拷貝到新的namespace裏面來了 root@container001:~/iso# mount |grep /001.iso /home/dev/iso/001.iso on /mnt/iso1 type iso9660 (ro,relatime) #在新namespace中mount 002.iso root@container001:~/iso# mount ./002.iso /mnt/iso2/ mount: /dev/loop0 is write-protected, mounting read-only root@container001:~/iso# mount |grep iso /home/dev/iso/001.iso on /mnt/iso1 type iso9660 (ro,relatime) /home/dev/iso/002.iso on /mnt/iso2 type iso9660 (ro,relatime) #umount 001.iso root@container001:~/iso# umount /mnt/iso1 root@container001:~/iso# mount |grep iso /home/dev/iso/002.iso on /mnt/iso2 type iso9660 (ro,relatime) #/mnt/iso1目錄變爲空 root@container001:~/iso# ls /mnt/iso1 root@container001:~/iso# #--------------------------第二個shell窗口---------------------- #打開新的shell窗口,老namespace中001.iso的掛載信息還在 #而在新namespace裏面mount的002.iso這裏看不到 dev@ubuntu:~$ mount |grep iso /home/dev/iso/001.iso on /mnt/iso1 type iso9660 (ro,relatime) #iso1目錄裏面也有內容 dev@ubuntu:~$ ls /mnt/iso1 subdir01 #說明兩個namespace中的mount信息是隔離的
在某些狀況下,好比系統添加了一個新的硬盤,這個時候若是mount namespace是徹底隔離的,想要在各個namespace裏面用這個硬盤,就須要在每一個namespace裏面手動mount這個硬盤,這個是很麻煩的,這時Shared subtrees就能夠幫助咱們解決這個問題。oop
關於Shared subtrees的詳細介紹請參考Linux mount (第二部分),裏面有他的詳細介紹以及bind nount的例子。測試
對Shared subtrees而言,mount namespace和bind mount的狀況差很少,這裏就簡單演示一下shared和private兩種類型spa
#--------------------------第一個shell窗口---------------------- #準備4個虛擬的disk,並在上面建立ext2文件系統,用於後續的mount測試 dev@ubuntu:~/iso$ cd && mkdir disks && cd disks dev@ubuntu:~/disks$ dd if=/dev/zero bs=1M count=32 of=./disk1.img dev@ubuntu:~/disks$ dd if=/dev/zero bs=1M count=32 of=./disk2.img dev@ubuntu:~/disks$ dd if=/dev/zero bs=1M count=32 of=./disk3.img dev@ubuntu:~/disks$ dd if=/dev/zero bs=1M count=32 of=./disk4.img dev@ubuntu:~/disks$ mkfs.ext2 ./disk1.img dev@ubuntu:~/disks$ mkfs.ext2 ./disk2.img dev@ubuntu:~/disks$ mkfs.ext2 ./disk3.img dev@ubuntu:~/disks$ mkfs.ext2 ./disk4.img #準備兩個目錄用於掛載上面建立的disk dev@ubuntu:~/disks$ mkdir disk1 disk2 dev@ubuntu:~/disks$ ls disk1 disk1.img disk2 disk2.img disk3.img disk4.img #顯式的分別以shared和private方式掛載disk1和disk2 dev@ubuntu:~/disks$ sudo mount --make-shared ./disk1.img ./disk1 dev@ubuntu:~/disks$ sudo mount --make-private ./disk2.img ./disk2 dev@ubuntu:~/disks$ cat /proc/self/mountinfo |grep disk| sed 's/ - .*//' 164 24 7:1 / /home/dev/disks/disk1 rw,relatime shared:105 173 24 7:2 / /home/dev/disks/disk2 rw,relatime #查看mount namespace編號 dev@ubuntu:~/disks$ readlink /proc/$$/ns/mnt mnt:[4026531840] #--------------------------第二個shell窗口---------------------- #從新打開一個新的shell窗口 dev@ubuntu:~$ cd ./disks #建立新的mount namespace #默認狀況下,unshare會將新namespace裏面的全部掛載點的類型設置成private, #因此這裏用到了參數--propagation unchanged, #讓新namespace裏的掛載點的類型和老namespace裏保持一致。 #--propagation參數還支持private|shared|slave類型, #和mount命令的那些--make-private參數同樣, #他們的背後都是經過調用mount(...)函數傳入不一樣的參數實現的 dev@ubuntu:~/disks$ sudo unshare --mount --uts --propagation unchanged /bin/bash root@ubuntu:~/disks# hostname container001 root@ubuntu:~/disks# exec bash root@container001:~/disks# #確認已是在新的mount namespace裏面了 root@container001:~/disks# readlink /proc/$$/ns/mnt mnt:[4026532463] #因爲前面指定了--propagation unchanged, #因此新namespace裏面的/home/dev/disks/disk1也是shared, #且和老namespace裏面的/home/dev/disks/disk1屬於同一個peer group 105 #由於在不一樣的namespace裏面,因此這裏掛載點的ID和原來namespace裏的不同了 root@container001:~/disks# cat /proc/self/mountinfo |grep disk| sed 's/ - .*//' 221 177 7:1 / /home/dev/disks/disk1 rw,relatime shared:105 222 177 7:2 / /home/dev/disks/disk2 rw,relatime #分別在disk1和disk2目錄下建立disk3和disk4,而後掛載disk3,disk4到這兩個目錄 root@container001:~/disks# mkdir ./disk1/disk3 ./disk2/disk4 root@container001:~/disks# mount ./disk3.img ./disk1/disk3/ root@container001:~/disks# mount ./disk4.img ./disk2/disk4/ root@container001:~/disks# cat /proc/self/mountinfo |grep disk| sed 's/ - .*//' 221 177 7:1 / /home/dev/disks/disk1 rw,relatime shared:105 222 177 7:2 / /home/dev/disks/disk2 rw,relatime 223 221 7:3 / /home/dev/disks/disk1/disk3 rw,relatime shared:107 227 222 7:4 / /home/dev/disks/disk2/disk4 rw,relatime #--------------------------第一個shell窗口---------------------- #回到第一個shell窗口 #能夠看出因爲/home/dev/disks/disk1是shared,且兩個namespace裏的這個掛載點都屬於peer group 105, #因此在新namespace裏面掛載的disk3,在老的namespace裏面也看的到 #可是看不到disk4的掛載信息,那是由於/home/dev/disks/disk2是private的 dev@ubuntu:~/disks$ cat /proc/self/mountinfo |grep disk| sed 's/ - .*//' 164 24 7:1 / /home/dev/disks/disk1 rw,relatime shared:105 173 24 7:2 / /home/dev/disks/disk2 rw,relatime 224 164 7:3 / /home/dev/disks/disk1/disk3 rw,relatime shared:107 #咱們能夠隨時修改掛載點的propagation type #這裏咱們經過mount命令將disk3改爲了private類型 dev@ubuntu:~/disks$ sudo mount --make-private /home/dev/disks/disk1/disk3 dev@ubuntu:~/disks$ cat /proc/self/mountinfo |grep disk3| sed 's/ - .*//' 224 164 7:3 / /home/dev/disks/disk1/disk3 rw,relatime #--------------------------第二個shell窗口---------------------- #回到第二個shell窗口,disk3的propagation type仍是shared, #代表在老的namespace裏面對propagation type的修改不會影響新namespace裏面的掛載點 root@container001:~/disks# cat /proc/self/mountinfo |grep disk3| sed 's/ - .*//' 223 221 7:3 / /home/dev/disks/disk1/disk3 rw,relatime shared:107
關於mount命令和mount namespace的配合,裏面有不少技巧,後面若是須要用到更復雜的用法,會再作詳細的介紹。.net