導讀
上一篇寫了共享存儲的概述以及一個簡單的案例演示。這一篇就寫一下PV和PVC。
PV是對底層網絡共享存儲的抽象,將共享存儲定義為一種“資源”,比如Node也是容器應用可以消費的資源。PV由管理員創建和配置,與共享存儲的具體實現直接相關。
PVC則是用戶對存儲資源的一個“申請”,就像Pod消費Node資源一樣,PVC能夠消費PV資源。PVC可以申請特定的存儲空間和訪問模式。
StorageClass,用於標記存儲資源的特性和性能,管理員可以將存儲資源定義為某種類別,正如存儲設備對於自身的配置描述(Profile)。根據StorageClass的描述可以直觀的得知各種存儲資源的特性,就可以根據應用對存儲資源的需求去申請存儲資源了。存儲卷可以按需創建。
PV
PV作為存儲資源,主要包括存儲能力、訪問模式、存儲類型、回收策略、后端存儲類型等關鍵信息的設置。
apiVersion: v1 kind: PersistentVolume metadata: name: pv1 spec: capacity: #容量 storage: 5Gi accessModes: #訪問模式 - ReadWriteOnce persistentVolumeReclaimPolicy: Recycle #回收策略 storageClassName: slow nfs: path: / server: 172.17.0.2
kubernetes支持的PV類型如下:
◎ AWSElasticBlockStore:AWS公有雲提供的ElasticBlockStore。
◎ AzureFile:Azure公有雲提供的File。
◎ AzureDisk:Azure公有雲提供的Disk。
◎ CephFS:一種開源共享存儲系統。
◎ FC(Fibre Channel):光纖存儲設備。
◎ FlexVolume:一種插件式的存儲機制。
◎ Flocker:一種開源共享存儲系統。
◎ GCEPersistentDisk:GCE公有雲提供的PersistentDisk。
◎ Glusterfs:一種開源共享存儲系統。
◎ HostPath:宿主機目錄,僅用於單機測試。
◎ iSCSI:iSCSI存儲設備。
◎ Local:本地存儲設備,目前可以通過指定塊(Block)設備提供Local PV,或通過社區開發的sig-storage-local-static-provisioner插件( https://github.com/kubernetes-sigs/sig-storage-local-static-provisioner )來管理Local PV的生命周期。
◎ NFS:網絡文件系統。
◎ Portworx Volumes:Portworx提供的存儲服務。
◎ Quobyte Volumes:Quobyte提供的存儲服務。
◎ RBD(Ceph Block Device):Ceph塊存儲。
◎ ScaleIO Volumes:DellEMC的存儲設備。
◎ StorageOS:StorageOS提供的存儲服務。
◎ VsphereVolume:VMWare提供的存儲系統。
關鍵配置參數
1、存儲能力(Capacity)
描述存儲設備具備的能力,支持對存儲空間的設置(storage=xx)
2、存儲卷模式(Volume Mode)
volumeMode=xx,可選項包括Filesystem(文件系統)和Block(塊設備),默認值是FileSystem。
目前有以下PV類型支持塊設備類型:
AWSElasticBlockStore、AzureDisk、FC、GCEPersistentDisk、iSCSI、Local volume、RBD(Ceph Block Device)、VsphereVolume(alpha)
apiVersion: v1 kind: PersistentVolume metadata: name: pv spec: capacity: storage: 5Gi accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Retain volumeMode: Block fc: targetWWNs: ["url"] lun: 0 readOnly: false
3、訪問模式(Access Modes)
用於描述應用對存儲資源的訪問權限。
◎ ReadWriteOnce(RWO):讀寫權限,並且只能被單個Node掛載。
◎ ReadOnlyMany(ROX):只讀權限,允許被多個Node掛載。
◎ ReadWriteMany(RWX):讀寫權限,允許被多個Node掛載。
4、存儲類別(Class)
設定存儲的類別,通過storageClassName參數指定給一個StorageClass資源對象的名稱,具有特定類別的PV只能與請求了該類別的PVC進行綁定。未綁定類別的PV則只能與不請求任何類別的PVC進行綁定。
5、回收策略(Reclaim Policy)
通過persistentVolumeReclaimPolicy字段設置,
◎ Retain 保留:保留數據,需要手工處理。
◎ Recycle 回收空間:簡單清除文件的操作(例如執行rm -rf /thevolume/* 命令)。
◎ Delete 刪除:與PV相連的后端存儲完成Volume的刪除操作
EBS、GCE PD、Azure Disk、OpenStack Cinder等設備的內部Volume清理)。
6、掛載參數(Mount Options)
在將PV掛載到一個Node上時,根據后端存儲的特點,可能需要設置額外的掛載參數,可根據PV定義中的mountOptions字段進行設置。
apiVersion: v1 kind: PersistentVolume metadata: name: pv spec: capacity: storage: 5Gi accessModes: - ReadWriteOnce mountOptions: - hard - nolock - nfsvers=3 gcePersistentDisk: fsType: ext4 pdName: gce-disk-1
目前,以下PV類型支持設置掛載參數:
AWSElasticBlockStore、AzureDisk、AzureFile、CephFS、Cinder (OpenStack block storage)、GCEPersistentDisk、Glusterfs、NFS、Quobyte Volumes、RBD (Ceph Block Device)、StorageOS、VsphereVolume、iSCSI
7、節點親和性(Node Affinity)
限制只能通過某些Node來訪問Volume,可在nodeAffinity字段中設置。使用這些Volume的Pod將被調度到滿足條件的Node上。
此參數僅用於Local存儲卷上。
apiVersion: v1 kind: PersistentVolume metadata: name: pv spec: capacity: storage: 5Gi accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Delete storageClassName: local-storage local: path: /mnt/disks/ssd1 nodeAffinity: required: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/hostname operator: In values: - my-node
PV生命周期的各個階段
◎ Available:可用狀態,還未與某個PVC綁定。
◎ Bound:已與某個PVC綁定。
◎ Released:綁定的PVC已經刪除,資源已釋放,但沒有被集群回收。
◎ Failed:自動資源回收失敗。
PVC
PVC作為用戶對存儲資源的需求申請,主要包括存儲空間請求、訪問模式、PV選擇條件和存儲類別等信息的設置。
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: pvc spec: accessModes: #訪問模式 - ReadWriteOnce resources: #申請資源,8Gi存儲空間 requests: storage: 8Gi storageClassName: slow #存儲類別 selector: matchLabels: release: "stable" matchExpressions: - {key: environment, operator: In, values: [dev]}
關鍵配置
1、資源請求(Resources)
描述對存儲資源的請求,目前僅支持request.storage的設置,即是存儲空間的大小
2、訪問模式(AccessModes)
用於描述對存儲資源的訪問權限,與PV設置相同
3、存儲卷模式(Volume Modes)
用於描述希望使用的PV存儲卷模式,包括文件系統和塊設備。
4、PV選擇條件(Selector)
通過對Label Selector的設置,可使PVC對於系統中已存在的各種PV進行篩選。
選擇條件可以使用matchLabels和matchExpressions進行設置,如果兩個字段都設置了,則Selector的邏輯將是兩組條件同時滿足才能完成匹配
5、存儲類別(Class)
PVC 在定義時可以設定需要的后端存儲的類別(通過storageClassName字段指定),以減少對后端存儲特性的詳細信息的依賴。只有設置了該Class的PV才能被系統選出,並與該PVC進行綁定
PVC也可以不設置Class需求。如果storageClassName字段的值被設置為空(storageClassName=""),則表示該PVC不要求特定的Class,系統將只選擇未設定Class的PV與之匹配和綁定。PVC也可以完全不設置storageClassName字段,此時將根據系統是否啟用了名為DefaultStorageClass的admission controller進行相應的操作
6、未啟用DefaultStorageClass
等效於PVC設置storageClassName的值為空(storageClassName=""),即只能選擇未設定Class的PV與之匹配和綁定。
7、啟用DefaultStorageClass
要求集群管理員已定義默認的StorageClass。如果在系統中不存在默認StorageClass,則等效於不啟用DefaultStorageClass的情況。如果存在默認的StorageClass,則系統將自動為PVC創建一個PV(使用默認StorageClass的后端存儲),並將它們進行綁定。集群管理員設置默認StorageClass的方法為,在StorageClass的定義中加上一個annotation“storageclass.kubernetes.io/is-default-class= true”。如果管理員將多個StorageClass都定義為default,則由於不唯一,系統將無法為PVC創建相應的PV。
PVC和PV都受限於Namespace,PVC在選擇PV時受到Namespace的限制,只有相同Namespace中的PV才可能與PVC綁定。Pod在引用PVC時同樣受Namespace的限制,只有相同Namespace中的PVC才能掛載到Pod內。
當Selector和Class都進行了設置時,系統將選擇兩個條件同時滿足的PV與之匹配。
另外,如果資源供應使用的是動態模式,即管理員沒有預先定義PV,僅通過StorageClass交給系統自動完成PV的動態創建,那么PVC再設定Selector時,系統將無法為其供應任何存儲資源。
在啟用動態供應模式的情況下,一旦用戶刪除了PVC,與之綁定的PV也將根據其默認的回收策略“Delete”被刪除。如果需要保留PV(用戶數據),則在動態綁定成功后,用戶需要將系統自動生成PV的回收策略從“Delete”改成“Retain”。
PV和PVC的生命周期

將PV看作可用的存儲資源,PVC則是對存儲資源的需求。
(1)資源供應
k8s支持兩種資源的供應模式:靜態模式(Static)和動態模式(Dynamic)。資源供應的結果就是創建好的PV。
靜態模式:集群管理員手工創建許多PV,在定義PV時需要將后端存儲的特性進行設置。
動態模式:集群管理員無需手工創建PV,而是通過StorageClass的設置對后端存儲進行描述,標記為某種類型。此時要求PVC對存儲的類型進行聲明,系統將自動完成PV的創建及與PVC的綁定。PVC可以聲明Class為"",說明該PVC禁止使用動態模式。
(2)資源綁定
在定義好PVC之后,系統將根據PVC對存儲資源的要求(存儲空間和訪問模式)在已存在的PV中選擇一個滿足PVC要求的PV,一旦找到,就將該PV與定義的PVC進行綁定,應用就可以使用這個PVC了。如果系統中沒有這個PV,則PVC則會一直處理Pending狀態,直到系統中有符合條件的PV。PV一旦綁定到PVC上,就會被PVC獨占,不能再與其他PVC進行綁定。當PVC申請的存儲空間比PV的少時,整個PV的空間就都能夠為PVC所用,可能會造成資源的浪費。如果資源供應使用的是動態模式,則系統在為PVC找到合適的StorageClass后,將自動創建一個PV並完成與PVC的綁定。
(3)資源使用
Pod使用Volume定義,將PVC掛載到容器內的某個路徑進行使用。Volume的類型為Persistent VolumeClaim,在容器掛載了一個PVC后,就能被持續獨占使用。多個Pod可以掛載到同一個PVC上。
volumes: - name: pv persistentVolumeClaim: claimName: pvc
(4)資源釋放
當存儲資源使用完畢后,可以刪除PVC,與該PVC綁定的PV會被標記為“已釋放”,但還不能立刻與其他PVC進行綁定。通過之前PVC寫入的數據可能還被保留在存儲設備上,只有在清除之后該PV才能被再次使用。
(5)資源回收
對於PV,管理員可以設定回收策略,用於設置與之綁定的PVC釋放資源之后如何處理遺留數據的問題。只有PV的存儲空間完成回收,才能供新的PVC綁定和使用。
通過兩張圖分別對在靜態資源供應模式和動態資源供應模式下,PV、PVC、StorageClass及Pod使用PVC的原理進行說明。
在靜態資源供應模式下,通過PV和PVC完成綁定,並供Pod使用的存儲管理機制

在動態資源供應模式下,通過StorageClass和PVC完成資源動態綁定(系統自動生成PV),並供Pod使用的存儲管理機制

StorageClass
StorageClass作為對存儲資源的抽象定義,對用戶設置的PVC申請屏蔽后端存儲的細節,一方面減少了用戶對存儲資源細節的關注,另一方面減少了管理員手工管理PV的工作,由系統自動完成PV的創建和綁定,實現了動態的資源供應。
StorageClass的定義主要包括名稱、后端存儲的提供者(privisioner)和后端存儲的相關參數配置。StorageClass一旦被創建,就無法修改,如需修改,只能刪除重建。
下例定義了一個名為standard的StorageClass,提供者為aws-ebs,其參數設置了一個type,值為gp2:
apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: standard privisioner: kubernetes.io/aws-ebs parameters: type: gp2
關鍵配置
1、提供者(Privisioner)
描述存儲資源的提供者,也可以看作后端存儲驅動。
2、參數(Parameters)
后端存儲資源提供者的參數設置,不同的Provisioner包括不同的參數設置。某些參數可以不顯示設定,Provisioner將使用其默認值。
設置默認的StorageClass
首先需要啟用名為DefaultStorageClass的admission controller,即在kube-apiserver的命令行參數--admission-control中增加
--admission-control=...,DefaultStorageClass
然后,在StorageClass的定義中設置一個annotation:
apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: slow annotations: storageclass.beta.kubernetes.io/is-default-class="true" privisioner: kubernetes.io/gce-pd parameters: type: pd-ssd
通過kubectl create命令創建成功后,查看StorageClass列表,可以看到名為gold的StorageClass被標記為default:
kubectl get sc
CSI存儲機制
Container Storage Interface(CSI)機制,用於在kubenetes和外部存儲系統之間建立一套標准的存儲管理接口,通過該接口為容器提供存儲服務。
CSI存儲插件的關鍵組件和部署架構

主要包括兩個組件:CSI Controller和CSI Node
1、CSI Controller
提供存儲服務視角對存儲資源和存儲進行管理和操作,在k8s中建議部署為單實例Pod,可以使用StatefulSet和Deployment控制器進行部署,設置副本數為1,保證為一種存儲插件只運行一個控制器實例。
在此Pod內部署兩個容器:
(1)與Master(kubernetes Controller Manager)通信的輔助sidecar容器,
在sidecar容器內又可以包含extenal-attacher和extenal-privisioner兩個容器,功能如下:
◎ external-attacher:監控VolumeAttachment資源對象的變更,觸發針對CSI端點的ControllerPublish和ControllerUnpublish操作。
◎ external-provisioner:監控PersistentVolumeClaim資源對象的變更,觸發針對CSI端點的CreateVolume和DeleteVolume操作
(2)CSI Driver存儲驅動容器,第三方提供,需實現上述接口
這兩個容器使用本地Socket(Unix Domain Socket,UDS),並使用gPRC協議進行通信,sidecar容器通過socket調用CSI Driver容器的CSI接口,CSI Driver容器負責具體的存儲卷操作。
2、CSI Node
對主機(Node)上的Volume進行管理和操作,建議使用DaemonSet,每個Node上都運行一個Pod。
在此Pod上部署如下兩個容器:
(1)與kubelet通信的輔助sidecar容器node-driver-register,主要功能是將存儲驅動注冊到kubelet中。
(2)CSI Driver存儲驅動容器,由第三方存儲提供商提供,主要功能是接收kubelet的調用,需要實現一系列與Node相關的CSI接口,例如NodePublishVolume接口(用於將Volume掛載到容器內的目標路徑)、NodeUnpublishVolume接口(用於從容器中卸載Volume),等等。
node-driver-register容器與kubelet通過Node主機的一個hostPath目錄下的unix Socket進行通信,CSI Driver容器與kubelet通過Node主機的另一個hostPath目錄下的unix Socket進行通信,同時需要將kubelet的工作目錄(/var/lib/kubelet)掛載到CSI Driver容器,用於為Pod進行Volume的管理操作(包括mount,unmount等)。
===============================
我是Liusy,一個喜歡健身的程序員。
獲取更多干貨以及最新消息,請關注公眾號:上古偽神
如果對您有幫助,點個關注就是對我最大的支持!!!