Kubernetes-基於StorageClass的動態儲存供應
1、儲存類介紹
Kubernetes叢集管理員通過提供不同的儲存類,可以滿足使用者不同的服務質量級別、備份策略和任意策略要求的儲存需求。動態儲存卷供應使用StorageClass進行實現,其允許儲存卷按需被建立。如果沒有動態儲存供應,Kubernetes叢集的管理員將不得不通過手工的方式類建立新的儲存卷。通過動態儲存卷,Kubernetes將能夠按照使用者的需要,自動建立其需要的儲存。
基於StorageClass的動態儲存供應整體過程如下圖所示:
1)叢集管理員預先建立儲存類(StorageClass);
2)使用者建立使用儲存類的持久化儲存宣告(PVC:PersistentVolumeClaim);
3)儲存持久化宣告通知系統,它需要一個持久化儲存(PV: PersistentVolume);
4)系統讀取儲存類的資訊;
5)系統基於儲存類的資訊,在後臺自動建立PVC需要的PV;
6)使用者建立一個使用PVC的Pod;
7)Pod中的應用通過PVC進行資料的持久化;
8)而PVC使用PV進行資料的最終持久化處理。
2、定義儲存類
每一個儲存類都包含provisioner、parameters和reclaimPolicy這三個引數域,當一個屬於某個類的PersistentVolume需要被動態提供時,將會使用上述的引數域。
儲存類物件的名稱非常重要,使用者通過名稱類請求特定的儲存類。管理員建立儲存類物件時,會設定類的名稱和其它的引數,儲存類的物件一旦被建立,將不能被更新。管理員能夠為PVC指定一個預設的儲存類。
kind: StorageClass apiVersion: storage.k8s.io/v1 metadata: name: standard # 指定儲存類的供應者 provisioner: kubernetes.io/aws-ebs parameters: type: gp2 # 指定回收策略 reclaimPolicy: Retain mountOptions: - debug
2.1 供應者
儲存類有一個供應者的引數域,此引數域決定PV使用什麼儲存卷外掛。引數必需進行設定:
儲存卷 | 內建供應者 | 配置例子 |
AWSElasticBlockStore | ✓ | |
CephFS | – | – |
FC | – | – |
FlexVolume | – | – |
Flocker | ✓ | – |
GCEPersistentDisk | ✓ | GCE |
iSCSI | – | – |
PhotonPersistentDisk | ✓ | – |
NFS | – | – |
VsphereVolume | ✓ | |
Local | – | Local |
Kubernetes的儲存類並不侷限於表中的“interneal”供應者,“interneal”供應者的名稱帶有“kubernetes.io”字首;也可以允許和指定外部的供應者,外部供應者通過獨立的程式進行實現。外部供應者的作者對程式碼在何處生存、如何供應、如何執行、使用什麼卷外掛(包括Flex)等有充分的判斷權,kubernetes-incubator/external-storage倉庫中存在編寫外部提供者的類庫。例如,NFS不是內部的供應者,但也是可以使用。在kubernetes-incubator/external-storage倉庫中以列表的形式展示了一些外部的供應者,一些第三方供應商也提供了他們自己的外部供應者。
2.2 提供者的引數
儲存類存在很多描述儲存卷的引數,依賴不同的提供者可能有不同的引數。例如,對於type引數,它的值可能為io1。當一個引數被省略,則使用預設的值。
2.3 回收策略
通過儲存類建立的持久化儲存卷通過reclaimPolicy引數來指定,它的值可以是Delete或者Retain,預設為Delete。對於通過手工建立的,並使用儲存類進行管理的持久化儲存卷,將使用任何在建立時指定的儲存卷。
2.4 掛接選項
通過儲存類動態建立的持久化儲存卷,會存在一個通過mountOptions引數指定的掛接選擇。如果儲存卷外掛不支援指定的掛接選項,這提供儲存供應就會失敗,在儲存類或者PV中都不會對掛接選項進行驗證,因此需要在設定時進行確認。
3、使用儲存類
動態儲存卷供應基於StorageClass的API物件的來實現,叢集管理員能夠按需定義StorageClass物件,每一個StorageClass物件能夠指定一個儲存卷外掛(即供應者)。叢集管理員能夠在一個叢集中定義各種儲存卷供應,使用者不需要了解儲存的細節和複雜性,就能夠選擇符合自己要求的儲存。
3.1 啟用動態供應
為了啟用動態供應,叢集管理員需要預先為使用者建立一個或者多個儲存類物件。儲存類物件定義了使用哪個供應者,以及供應者相關的引數。下面是儲存類的一個示例,它建立一個名稱為slow的儲存類,使用gce供應者:
apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: slow provisioner: kubernetes.io/gce-pd parameters: type: pd-standard
下面建立了一個名為“fast”的儲存類,其提供類似固態磁碟的儲存卷磁碟:
apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: fast provisioner: kubernetes.io/gce-pd parameters: type: pd-ssd
3.2 使用動態供應
使用者通過在PersistentVolumeClaim中包含一個儲存類,來請求動態供應儲存。在Kubernetes v1.6之前的版本,通過volume.beta.kubernetes.io/storage-class註釋類請求動態供應儲存;在v1.6版本之後,使用者應該使用PersistentVolumeClaim物件的storageClassName引數來請求動態儲存。
下面是請求fast儲存類的持久化儲存卷宣告的YAML配置檔案示例:
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: claim1 spec: accessModes: - ReadWriteOnce # 指定所使用的儲存類,此儲存類將會自動建立符合要求的PV storageClassName: fast resources: requests: storage: 30Gi
此宣告將使用類似於固態儲存磁碟,當持久化儲存卷宣告被刪除後,儲存卷也將會被銷燬。
3.3 預設行為
如果Kubernetes的叢集中沒有指定儲存類,叢集管理員可以通過執行下面的設定,啟用預設的儲存類:
- 標記一個預設的StorageClass物件;
- 確定API server中DefaultStorage接入控制器已被啟用
管理員能夠通過新增storageclass.kubernetes.io/is-default-class註釋,標記一個特定的StorageClass作為預設的儲存類。在叢集中,如果存在一個預設的StorageClass,系統將能夠在不指定storageClassName 的情況下建立一個PersistentVolume,DefaultStorageClass接入控制器會自動將storageClassName指向預設的儲存類。注意:在一個叢集中,最多隻能有一個預設的儲存類,如果沒有預設的儲存類,那麼如果在PersistentVolumeClaim中沒有顯示指定storageClassName,則將無法建立PersistentVolume。
4、NFS儲存類示例
4.1 部署nfs-provisioner
為nfs-provisioner例項選擇儲存狀態和資料的儲存卷,並將儲存卷掛接到容器的/export 命令。
... volumeMounts: - name: export-volume mountPath: /export volumes: - name: export-volume hostPath: path: /tmp/nfs-provisioner ...
為StorageClass選擇一個供應者名稱,並在deploy/kubernetes/deployment.yaml進行設定。
args: - "-provisioner=example.com/nfs" ...
完整的deployment.yaml檔案內容如下:
kind: Service apiVersion: v1 metadata: name: nfs-provisioner labels: app: nfs-provisioner spec: ports: - name: nfs port: 2049 - name: mountd port: 20048 - name: rpcbind port: 111 - name: rpcbind-udp port: 111 protocol: UDP selector: app: nfs-provisioner --- apiVersion: extensions/v1beta1 kind: Deployment metadata: name: nfs-provisioner spec: replicas: 1 strategy: type: Recreate template: metadata: labels: app: nfs-provisioner spec: containers: - name: nfs-provisioner image: quay.io/kubernetes_incubator/nfs-provisioner:v1.0.8 ports: - name: nfs containerPort: 2049 - name: mountd containerPort: 20048 - name: rpcbind containerPort: 111 - name: rpcbind-udp containerPort: 111 protocol: UDP securityContext: capabilities: add: - DAC_READ_SEARCH - SYS_RESOURCE args: # 定義提供者的名稱,儲存類通過此名稱指定提供者 - "-provisioner=nfs-provisioner" env: - name: POD_IP valueFrom: fieldRef: fieldPath: status.podIP - name: SERVICE_NAME value: nfs-provisioner - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace imagePullPolicy: "IfNotPresent" volumeMounts: - name: export-volume mountPath: /export volumes: - name: export-volume hostPath: path: /srv
在設定好deploy/kubernetes/deployment.yaml檔案後,通過kubectl create命令在Kubernetes叢集中部署nfs-provisioner。
$ kubectl create -f {path}/deployment.yaml
4.2 建立StorageClass
下面是example-nfs的StorageClass配置檔案,此配置檔案定義了一個名稱為nfs-storageclass的儲存類,此儲存類的提供者為nfs-provisioner。
apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: nfs-storageclass provisioner: nfs-provisioner
通過kubectl create -f命令使用上面的配置檔案建立:
$ kubectl create -f deploy/kubernetes/class.yaml
storageclass “example-nfs” created
在儲存類被正確建立後,就可以建立PersistenetVolumeClaim來請求StorageClass,而StorageClass將會為PersistenetVolumeClaim自動建立一個可用PersistentVolume。
4.3 建立PersistenetVolumeClaim
PersistenetVolumeClaim是對PersistenetVolume的宣告,即PersistenetVolume為儲存的提供者,而PersistenetVolumeClaim為儲存的消費者。下面是PersistentVolumeClaim的YAML配置檔案,此配置檔案通過spec.storageClassName欄位指定所使用的儲存儲類。
在此配置檔案中,使用nfs-storageclass儲存類為PersistenetVolumeClaim建立PersistenetVolume,所要求的PersistenetVolume儲存空間大小為1Mi,可以被多個容器進行讀取和寫入操作。
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: nfs-pvc spec: accessModes: - ReadWriteMany storageClassName: nfs-storageclass resources: requests: storage: 1Mi
通過kubectl create命令建立上述的持久化儲存卷宣告:
$ kubectl create -f {path}/claim.yaml
4.4 建立使用PersistenVolumeClaim的部署
在這裡定義名為busybox-deployment的部署YAML配置檔案,使用的映象為busybox。基於busybox映象的容器需要對/mnt目錄下的資料進行持久化,在YAML檔案指定使用名稱為nfs的PersistenVolumeClaim對容器的資料進行持久化。
# This mounts the nfs volume claim into /mnt and continuously # overwrites /mnt/index.html with the time and hostname of the pod. apiVersion: v1 kind: Deployment metadata: name: busybox-deployment spec: replicas: 2 selector: name: busybox-deployment template: metadata: labels: name: busybox-deployment spec: containers: - image: busybox command: - sh - -c - 'while true; do date > /mnt/index.html; hostname >> /mnt/index.html; sleep $(($RANDOM % 5 + 5)); done' imagePullPolicy: IfNotPresent name: busybox volumeMounts: # name must match the volume name below - name: nfs mountPath: "/mnt" # volumes: - name: nfs persistentVolumeClaim: claimName: nfs-pvc
通過kubectl create建立busy-deployment部署:
$ kubectl create -f {path}/nfs-busybox-deployment.yaml
參考資料
作者簡介: 季向遠,北京神舟航天軟體技術有限公司產品經理。本文版權歸原作者所有。