談談k8s1.12新特性–Mountpropagation(掛載名稱空間的傳播)

店家小二發表於2018-12-17

Mount propagation

掛載傳播允許將Container掛載的卷共享到同一Pod中的其他Container,甚至可以共 享到同一節點上的其他Pod。
一個卷的掛載傳播由Container.volumeMounts中的mountPropagation欄位控制。它的值是:

  • None 此卷掛載不會接收到任何後續掛載到該卷或是掛載到該卷的子目錄下的掛載。以類似的方式,在主機上不會顯示Container建立的裝載。這是預設模式。

此模式等同於Linux核心文件中所述的 private 傳播。

  • HostToContainer 此卷掛載將會接收到任何後續掛載到該卷或是掛載到該卷的子目錄下的掛載。

換句話說,如果主機在卷掛載中掛載任何內容,則Container將看到它掛載在那裡。
類似地,如果任何具有 Bidirectional 掛載傳播設定的Pod掛載到同一個卷中,那麼具有HostToContainer掛載傳播的Container將會看到它。
此模式等同於Linux核心文件中描述的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(掛載名稱空間的傳播)


相關文章