Overview
傳統上,容器引擎(Container Engine)不提供比容器壽命更長的存儲。由于容器被認為是瞬態(transient)的,這可能會導致數據丟失或復雜的外部存儲選項。Kubernetes卷共享 Pod 生命周期,而不是其中的容器。如果容器終止,數據將繼續可供新容器使用。
卷(volume)是一個目錄,可能是預先填充的,可供 Pod 中的容器(container)使用。目錄的創建、數據和內容的后端存儲取決于卷類型(volume type)。截至 v1.13,有 27 種不同的卷類型,從用于訪問 Ceph 的 rbd、NFS,到來自 Google 的 gcePersistentDisk 等云提供商的動態卷。每個都有特定的配置選項和依賴性。
容器存儲接口 (CSI-Container Storage Interface) 的采用實現了容器container orchestration行業標準接口的目標,以允許訪問任意存儲系統。目前,卷插件是“樹內 (in-tree)”的,這意味著它們是使用核心 Kubernetes 二進制文件編譯和構建的。這個“樹外(out-of-tree)”對象將允許存儲供應商開發單個驅動程序并允許插件容器化。這將取代現有的 Flex 插件,后者需要提升對主機節點的訪問權限,這是一個很大的安全問題。
如果您希望存儲生命周期與 Pod 不同,則可以使用持久卷(Persistent Volumes)。這些允許 Pod 使用持久卷聲明(Persistent Volume Claim)來聲明空卷或預填充卷,使得這些volume比Pod 的壽命更長。然后,卷內的數據可以被另一個 Pod 使用,或者作為檢索數據的一種方式。
已經存在兩個 API 對象來向 Pod 提供數據。編碼(encoded)數據可以使用 Secret 傳遞,非編碼數據(non-encoded)可以使用 ConfigMap 傳遞。這些可用于傳遞重要數據,例如 SSH 密鑰、密碼,甚至是/etc/hosts等配置文件。
Introducing Volumes
Pod 規范可以聲明一個或多個卷以及它們的可用位置。每個都需要名稱(name)、類型(type)和安裝點(a mount point)。同一卷可以供 Pod 中的多個容器使用,這可以是容器到容器通信的一種方法。一個卷可以供多個 Pod 使用,每個 Pod 都指定一個寫入訪問模式。沒有并發檢查,這意味著數據可能損壞,除非在外部進行鎖定。
特定的訪問模式(access mode)是 Pod 請求的一部分。作為請求,用戶可能會被授予更多但不少于的訪問權限,盡管首先會嘗試直接匹配。集群將具有相同模式的卷分組在一起,然后按大小從最小到最大對卷進行排序。將針對該訪問模式組中的每個卷檢查聲明,直到有足夠大小的卷匹配為止。三種訪問模式是:
ReadWriteOnce,允許單節點(node)讀寫
ReadOnlyMany,允許多個節點只讀
ReadWriteMany,允許多個節點讀寫。
因此,同一節點上的兩個 pod 可以寫入 ReadWriteOnce,但不同節點上的第三個 pod 由于 FailedAttachVolume 錯誤而不會準備就緒。
當請求卷時,本地 kubelet 使用kubelet_pods.go腳本映射原始設備,確定并創建容器的掛載點,然后在主機節點文件系統上創建符號鏈接(symbolic link)以將存儲與容器關聯。API 服務器向StorageClass插件發出存儲請求,但對后端存儲的請求的具體內容取決于所使用的插件。
如果未發出對特定StorageClass 的請求,則使用的唯一參數將是訪問模式和大小。該卷可以來自任何可用的存儲類型,并且沒有配置來確定將使用哪些可用的存儲類型。
Volume Spec
可用的多種存儲類型之一是emptyDir。kubelet 將在容器中創建目錄,但不會掛載任何存儲。創建的任何數據都會寫入共享容器空間。因此,它不會是持久存儲。當 Pod 被銷毀時,該目錄將與容器一起被刪除。
apiVersion: v1
kind: Pod
metadata:name: fordpinto namespace: default
spec:containers:- image: simpleapp name: gastank command:- sleep- "3600"volumeMounts:- mountPath: /scratchname: scratch-volumevolumes:- name: scratch-volumeemptyDir: {}
上面的 YAML 文件將創建一個帶有單個容器的 Pod,并創建一個名為scrap-volume 的卷,這將在容器內創建/scratch目錄。
Volume Types (卷類型)
您可以使用多種類型來定義卷,每種類型都有其優點和缺點。有些是本地的,還有許多利用基于網絡的資源。
在 GCE 或 AWS 中,您可以使用GCEpersistentDisk或awsElasticBlockStore類型的卷,這允許您在 Pod 中掛載 GCE 和 EBS 磁盤(假設您已經設置了帳戶和權限)。
emptyDir和hostPath卷易于使用。如前所述, emptyDir是一個空目錄,當 Pod 終止時該目錄會被刪除,但會在容器重新啟動時重新創建。hostPath卷從主機節點文件系統掛載資源。資源可以是目錄、文件套接字、字符或塊設備。這些資源必須已存在于要使用的主機上。有兩種類型: DirectoryOrCreate和FileOrCreate,它們在主機上創建資源,并在資源不存在時使用它們。
NFS(網絡文件系統)和 iSCSI(互聯網小型計算機系統接口)是多讀卡器場景的直接選擇。
用于塊存儲的 rbd 或 CephFS 和 GlusterFS(如果在 Kubernetes 集群中可用)可以是滿足多個寫入器需求的不錯選擇。
除了我們剛剛提到的卷類型之外,還有許多其他可能的卷類型,并且還會添加更多:azureDisk、azureFile、csi、downwardAPI、fc(光纖通道)、flocker、gitRepo、local、projected、portworxVolume、quobyte、scaleIO、secret、storageos、vsphereVolume、permanentVolumeClaim、CSIPersistentVolumeSource等
CSI 允許更大的靈活性和解耦插件,而無需編輯核心 Kubernetes 代碼。它是作為未來公開任意插件的標準而開發的。
Shared Volume Example (共享卷)
以下 YAML 文件創建一個 pod exampleA,其中包含兩個容器,兩個容器都可以訪問共享卷:
您可以輕松使用emptyDir或hostPath,因為這些類型不需要任何額外的設置,并且可以在您的Kubernetes集群中工作。
請注意,一個容器 ( betacont ) 進行寫入,而另一個容器 ( alphacont ) 可以立即訪問數據。沒有什么可以阻止容器覆蓋對方的數據。鎖定或版本控制注意事項必須成為容器化應用程序的一部分,以避免損壞。