談談k8s1.12新特性--Mount propagation(掛載名稱空間的傳播)
Mount propagation
掛載傳播允許將Container掛載的卷共享到同一Pod中的其他Container,甚至可以共享到同一節點上的其他Pod。
一個卷的掛載傳播由Container.volumeMounts中的mountPropagation欄位控制。它的值是:
- None此卷掛載不會接收到任何後續掛載到該卷或是掛載到該卷的子目錄下的掛載。以類似的方式,在主機上不會顯示Container建立的裝載。這是預設模式。
此模式等同於ofollow,noindex" target="_blank">Linux核心文件 中所述的private 傳播。
- HostToContainer 此卷掛載將會接收到任何後續掛載到該卷或是掛載到該卷的子目錄下的掛載。
換句話說,如果主機在卷掛載中掛載任何內容,則Container將看到它掛載在那裡。
類似地,如果任何具有Bidirectional 掛載傳播設定的Pod掛載到同一個卷中,那麼具有HostToContainer 掛載傳播的Container將會看到它。
此模式等同於Linux核心文件 中描述的rslave掛載傳播。
- Bidirectional 此卷掛載的行為與HostToContainer掛載相同。此外,Container建立的所有卷掛載都將傳播回主機和所有使用相同卷的Pod的所有容器。
此模式的典型用例是具有Flexvolume或CSI驅動程式的Pod需要使用hostPath 卷模式 在主機上掛載內容。
此模式等同於Linux核心文件中描述的rshared 安裝傳播。
PS:
Bidirectional 掛載傳播可能很危險。它可能會損壞主機作業系統,因此只允許在特權容器中使用它。強烈建議您熟悉Linux核心行為。此外,容器在容器中建立的任何卷裝入必須在終止時由容器銷燬(解除安裝)。
配置
在掛載傳播可以在某些部署(CoreOS,RedHat / Centos,Ubuntu)上正常工作之前,必須在Docker中正確配置掛載共享,如下所示。
編輯Docker的systemd service 檔案。設定MountFlags 如下:
MountFlags=shared
或者,如果存在,則刪除MountFlags = slave。然後重啟Docker守護程序:
$ sudo systemctl daemon-reload $ sudo systemctl restart docker
刨根問底
究其深層次分析,該特性並不是k8s或是docker實現的。本質上是mount namespace 的特性。
mount namespace通過隔離檔案系統掛載點對隔離檔案系統提供支援,它是歷史上第一個Linux namespace,所以它的標識位比較特殊,就是CLONE_NEWNS。隔離後,不同mount namespace中的檔案結構發生變化也互不影響。你可以通過/proc/[pid]/mounts檢視到所有掛載在當前namespace中的檔案系統,還可以通過/proc/[pid]/mountstats看到mount namespace中檔案裝置的統計資訊,包括掛載檔案的名字、檔案系統型別、掛載位置等等。
程序在建立mount namespace時,會把當前的檔案結構複製給新的namespace。新namespace中的所有mount操作都隻影響自身的檔案系統,而對外界不會產生任何影響。這樣做非常嚴格地實現了隔離,但是某些情況可能並不適用。比如父節點namespace中的程序掛載了一張CD-ROM,這時子節點namespace拷貝的目錄結構就無法自動掛載上這張CD-ROM,因為這種操作會影響到父節點的檔案系統。
2006 年引入的掛載傳播(mount propagation)解決了這個問題,掛載傳播定義了掛載物件(mount object)之間的關係,系統用這些關係決定任何掛載物件中的掛載事件如何傳播到其他掛載物件(參考自:http://www.ibm.com/developerw... )。所謂傳播事件,是指由一個掛載物件的狀態變化導致的其它掛載物件的掛載與解除掛載動作的事件。
- 共享關係(share relationship)。如果兩個掛載物件具有共享關係,那麼一個掛載物件中的掛載事件會傳播到另一個掛載物件,反之亦然。
- 從屬關係(slave relationship)。如果兩個掛載物件形成從屬關係,那麼一個掛載物件中的掛載事件會傳播到另一個掛載物件,但是反過來不行;在這種關係中,從屬物件是事件的接收者。
一個掛載狀態可能為如下的其中一種:
- 共享掛載(shared)
- 從屬掛載(slave)
- 共享/從屬掛載(shared and slave)
- 私有掛載(private)
- 不可繫結掛載(unbindable)
在預設情況下,所有掛載都是私有的。可以用以下命令將掛載物件顯式地標為共享掛載:
mount --make-shared <mount-object>
例如,如果 / 上的掛載必須是共享的,那麼執行以下命令:
mount --make-shared /
從共享掛載克隆的掛載物件也是共享的掛載;它們相互傳播掛載事件。
通過執行以下命令,可以顯式地將一個共享掛載轉換為從屬掛載:
mount --make-slave <shared-mount-object>
從從屬掛載克隆的掛載物件也是從屬的掛載,它也從屬於原來的從屬掛載的主掛載物件。
通過執行以下命令,可以將掛載物件標為私有的:
mount --make-private <mount-object>
通過執行以下命令,可以將掛載物件標為不可繫結的:
mount --make-unbindable <mount-object>
最後,這些設定都可以遞迴地應用,這意味著它們將應用於目標掛載之下的所有掛載。
mount --make-rshared /
將 / 之下的所有掛載轉換為共享掛載。