,容器里面每個(gè)容器都可以單獨掛載存儲,這就需要掛載隔離。Mount Namespace是Linux最早支持的命名空間,支持在不同的Namespace中可以看到不同的掛載視圖。
我們可以通過(guò)unshare分離出一個(gè)新的掛載空間,然后在這個(gè)新的mount空間內將/usr/bin目錄掛載到/mnt目錄下面,當exit退回后,mount失效了。如下所示。
- # unshare --mount
- # mount --bind /usr/bin/ /mnt/
- # ls /mnt/cp
- /mnt/cp
- # exit
- # ls /mnt/cp
- ls: 無(wú)法訪(fǎng)問(wèn)'/mnt/cp': 沒(méi)有那個(gè)文件或目錄
其實(shí),unshare --mount的本質(zhì)就是clone的時(shí)候指定flag為CLONE_NEWNS,后續Demo原理類(lèi)似。
要理解Mount Namespace必須先了解mount原理,mount可以將一個(gè)文件系統掛載到另外一個(gè)文件系統下面。下圖是將一個(gè)文件系統掛載到根文件系統的”/home“路徑下面,mount的關(guān)系通過(guò)一個(gè)內核結構體 mount標識,mount結構體中核心的就是mnt_mountpoint指向掛載的目標路徑,在圖中就是根文件系統的/home路徑。
上圖中home有兩個(gè)dentry,一個(gè)是根文件系統下的dentry,它是目標掛載點(diǎn),另外一個(gè)dentry是被掛載文件系統的dentry。譬如將一個(gè)掛載盤(pán)格式EXT4文件系統,那么這個(gè)dentry就掛載盤(pán)的根文件系統dentry。通過(guò)mount struct就可以將外部文件系統掛載到根文件系統上面。
每個(gè)mount struct里面都有一個(gè)mnt_namespace,它是一個(gè)指向掛載命令空間的指針,之前命名空間概述文章中介紹的ns_proxy也是指向這個(gè)mnt_namespace。這樣進(jìn)程和它的掛載空間就可以關(guān)聯(lián)起來(lái)了。
Mount Namespace還有一個(gè)特殊的地方就是掛載傳播(mount propagation),掛載傳播是指由一個(gè)掛載對象的狀態(tài)變化導致的其它掛載對象的掛載與解除掛載動(dòng)作的事件。針對容器這個(gè)場(chǎng)景就是,如果Docker內執行了一次掛載后,宿主機上是否能看到這個(gè)掛載,反過(guò)來(lái),如果宿主機執行了某個(gè)掛載,容器內是否能看見(jiàn)。常見(jiàn)的有三種掛載方式:
共享關(guān)系(share relationship),如果兩個(gè)掛載對象具有共享關(guān)系,那么一個(gè)掛載對象中的掛載事件會(huì )傳播到另一個(gè)掛載對象,反之亦然。也就是說(shuō)容器和宿主機的掛載會(huì )互相可見(jiàn)。
從屬關(guān)系(slave relationship),如果兩個(gè)掛載對象形成從屬關(guān)系,那么一個(gè)掛載對象中的掛載事件會(huì )傳播到另一個(gè)掛載對象,但是反過(guò)來(lái)不行;在這種關(guān)系中,從屬對象是事件的接收者。也就是說(shuō)主機掛載容器可見(jiàn),反過(guò)來(lái)不行。
私有關(guān)系(private relationship),之間互相不傳播,相互獨立。也就是說(shuō)相互不可見(jiàn)。
在上面的程序中添加CLONE_NEWNS便可以創(chuàng )建一個(gè)新的Mount Namespace。代碼還是基于之前PID的代碼,加上CLONE_NEWNS。
- package main
- import (
- "fmt"
- "os"
- "os/exec"
- "syscall"
- )
- func main() {
- cmd := exec.Command("/bin/sh")
- cmd.Stdin = os.Stdin
- cmd.Stdout = os.Stdout
- cmd.Stderr = os.Stderr
- cmd.Env = []string{"PS1=-[ns-process]- # "}
- cmd.SysProcAttr = &syscall.SysProcAttr{
- Cloneflags: syscall.CLONE_NEWUTS | syscall.CLONE_NEWPID | syscall.CLONE_NEWNS,
- }
- if err := cmd.Run(); err != nil {
- fmt.Printf("Error running the /bin/sh command - %s\n", err)
- os.Exit(1)
- }
- }
通過(guò)go run 直接運行后,執行文章最開(kāi)始unshare的Demo。你會(huì )發(fā)現
因為默認情況下掛載傳播是share共享,所以當我們在新的Mount Namespace執行掛載后,也會(huì )傳播到主機上面。我們可以在主機上面先將根目錄調整到私有掛載,這樣容器內的掛載就不會(huì )傳播到主機上面了。
- # mount --make-rprivate /
上面的Demo也可以正常運行了。
【編輯推薦】
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自本網(wǎng)站內容采集于網(wǎng)絡(luò )互聯(lián)網(wǎng)轉載等其它媒體和分享為主,內容觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如侵犯了原作者的版權,請告知一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容,聯(lián)系我們QQ:712375056,同時(shí)歡迎投稿傳遞力量。
Copyright ? 2009-2022 56dr.com. All Rights Reserved. 特網(wǎng)科技 特網(wǎng)云 版權所有 特網(wǎng)科技 粵ICP備16109289號
域名注冊服務(wù)機構:阿里云計算有限公司(萬(wàn)網(wǎng)) 域名服務(wù)機構:煙臺帝思普網(wǎng)絡(luò )科技有限公司(DNSPod) CDN服務(wù):阿里云計算有限公司 百度云 中國互聯(lián)網(wǎng)舉報中心 增值電信業(yè)務(wù)經(jīng)營(yíng)許可證B2
建議您使用Chrome、Firefox、Edge、IE10及以上版本和360等主流瀏覽器瀏覽本網(wǎng)站