1. 程式人生 > >Kubernetes-基於StorageClass的動態儲存供應

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
AWS
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。

4NFS儲存類示例

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

參考資料

作者簡介: 季向遠,北京神舟航天軟體技術有限公司產品經理。本文版權歸原作者所有。