謹記一點,pod中的每個容器都有自己的隔離的檔案系統,因為檔案系統來自容器映像檔。
每個新容器都是透過在建構映像檔時加入的詳細設定檔案來起動的。將此與pod中容器重新起動的現象結合起來(也許是因為程序崩潰,也許是存活探針向k8s發送了容器狀態異常的信號),你就會意識到新容器並不會認得前一個容器寫入檔案系統的任何內容。既使新起動的容器運行在同一個pod。
某些場景下,可能希望新的容器可以在上一個容器結束的位置繼續運行,就像在實體機上重啟程序。可能不需要(或者不想要)整個檔案系統被持久化,但又希望能保存實際資料的目錄。
k8s透過定義storage volume滿足這個需求,它們不像pod這樣的頂級(top-level)資源,而是被定義為pod的一部分,並和pod分享相同的生命週期。這表示在pod起動時建立volume,並在刪除pod時銷毀volume。另外,如果有一個pod包含多個容器,那個volume可以同時被所有容器使用。
k8s的volume是pod的一個組成部分,因此像容器一樣在pod規範中定義。它們不是獨立的k8s物件,也不能單獨建立或刪除。pod中的所有容器都可以使用volume,但必須先將volume掛載在每個需要存取它的容器中。在每個容器中,都可以在其檔案系統任意位置掛載volume
有一個帶著 3 個容器的pod
第1個容器:運行web服務,該web服務的HTML頁面放在 /var/htdocs ,並且將access log寫到 /var/logs 第2個容器:執行一個agent來建立HTML檔案,並將它們放在 /var/html 第3個容器:處理在 /var/logs 目錄中找到log (轉換、壓縮、分析或者做其他處理)
每個容器都有用途,但是每個容器單獨使用就沒有用處了,在沒有共享磁碟的情況下,這三個容器建立的pod沒有任何意義,因為它們之間的檔案系統都是隔離,互不相干無法共用。
但是,如果將兩個volume加入到pod中,並在這三個容器的適當路徑上掛載它們,進能建立出比單獨使用更完善的系統了。 Linux允許在檔案樹階層中的任何位置掛載檔案系統,當這樣做的時候,掛載的檔案系統內容在目錄中是可以訪問的。透過將相同的volume掛載到兩個容器中,它們就可以對相同的檔案進行操作。另外既使容器跟volume在同一個pod中,在pod的規範中定義volume是不夠的。如果我們希望容器能夠訪問volume,還需要在容器的規範中定義一個volumeMount。
在這個例子中,兩個volume一開始都是空的,因此可以使用一種名稱為 emptyDir 的volume。 k8s還支援其他類型的volume,這些volume通常從外部來源初始化時填充的,不然就是volume內掛載現有的目錄。這個填充的程序或掛載volume執行是在pod內的容器起動之前執行的。
volume被綁定到pod的lifecycle(生命週期)中,只有在pod存在時才會存在,但取決於volume的類型,既使在pod跟volume消失之後,volume的檔案也可能保持原狀,並可以掛載到新的volume中。
有多種volume可以提供選擇,其中一些是通用的。而另一些則相對於當前常用的儲存技術有較大的差別。
.emptyDir —— 用於儲存臨時資料的簡單空目錄 .hostPath —— 將目錄從工作節點的檔案系統掛載到pod中 .gitRepo —— 透過 Git repo 的內容來初始化的volume .nfs —— 將NFS共享volume掛載到pod中 .gcePerststentDisk(Google高性能型儲存磁碟)、awsElasticBlockStore(AWS服務彈性快存儲)、azureDisk(微軟Azure磁碟) —— 掛載雲端廠商提供的特定儲存類型 .cindr、cephfs、iscsi、flocker、glusterfs、quobyte、rbd、flexVolume、vsphere-volume、photonPersistentDisk、scaleIO —— 掛載其他類型的網路儲存 .configMap、secret、downwardAPI —— 用於將k8s部分資源和叢集資訊公開給pod的特殊類型volume .persistentVolumeClaim —— 一種使用預先或者動態提供(provisioned)的持久化儲存類型。
單個容器可以同時使用不同類型的多個volume,每個容器都可以掛載或者不掛載volume。