Mount propagation
挂載傳播允許将Container挂載的卷共享到同一Pod中的其他Container,甚至可以共 享到同一節點上的其他Pod。
一個卷的挂載傳播由Container.volumeMounts中的mountPropagation字段控制。它的值是:
- None 此卷挂載不會接收到任何後續挂載到該卷或是挂載到該卷的子目錄下的挂載。以類似的方式,在主機上不會顯示Container建立的裝載。這是預設模式。
此模式等同于
Linux核心文檔中所述的 private 傳播。
- HostToContainer 此卷挂載将會接收到任何後續挂載到該卷或是挂載到該卷的子目錄下的挂載。
換句話說,如果主機在卷挂載中挂載任何内容,則Container将看到它挂載在那裡。
類似地,如果任何具有 Bidirectional 挂載傳播設定的Pod挂載到同一個卷中,那麼具有HostToContainer挂載傳播的Container将會看到它。
中描述的rslave挂載傳播。
- Bidirectional 此卷挂載的行為與HostToContainer挂載相同。此外,Container建立的所有卷挂載都将傳播回主機和所有使用相同卷的Pod的所有容器。
此模式的典型用例是具有Flexvolume或CSI驅動程式的Pod需要使用hostPath 卷模式 在主機上挂載内容。
此模式等同于Linux核心文檔中描述的rshared安裝傳播。
PS:
Bidirectional 挂載傳播可能很危險。它可能會損壞主機作業系統,是以隻允許在特權容器中使用它。強烈建議您熟悉Linux核心行為。此外,容器在容器中建立的任何卷裝入必須在終止時由容器銷毀(解除安裝)。
Bidirectional一些使用場景:
- 在不同的pod之間共享裝置,其中挂載發生在pod中,但是在pod之間共享。
- 從容器内部附加裝置。例如,從容器内部附加ISCSI裝置。這時候因為如果容器死掉,主機将不能獲得所需的資訊(除非使用雙向安裝傳播)來正确重新整理寫入和分離裝置。
sample
deployment: containers: - image: gcr.io/google_containers/busybox:1.24 name: reader volume: - mount: /usr/test-pod store: local-vol propagation: bidirectional name: local-test-reader version: extensions/v1beta1 volumes: local-vol: pvc:example-local-claim
配置
在挂載傳播可以在某些部署(CoreOS,RedHat / Centos,Ubuntu)上正常工作之前,必須在Docker中正确配置挂載共享,如下所示。
編輯Docker的systemdservice 檔案。設定MountFlags如下:
MountFlags=shared
或者,如果存在,則删除MountFlags = slave。然後重新開機Docker守護程序:
$ sudo systemctl daemon-reload $ sudo systemctl restart docker
具體案例
之是以關注這塊,是由于我們在實際使用k8s的過程中遇到了相關的問題。
我們容器業務日志的收集有很大一部分通過sidecar的方式,mount日志到主機某個目錄。由于我們的日志量非常大,即使我們每個主機挂載了1T的硬碟,經常會寫滿這張盤。是以我們實作了一個log-tracer的項目,專門用于根據pod的日志挂載資訊clear過期的日志。通過daemonset方式部署。
但是如果設定mount為private的話,缺乏廣播通知。在實際新增pod後,有一部分的日志挂載是無法感測到,因而也無法徹底清理。
刨根問底
究其深層次分析,該特性并不是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 /
将 / 之下的所有挂載轉換為共享挂載。
本文轉自中文社群-
談談k8s1.12新特性--Mount propagation(挂載命名空間的傳播)