1. 程式人生 > 實用技巧 >k8s pv與pvc

k8s pv與pvc

一、儲存卷的概念和型別

為了保證資料的永續性,必須保證資料在外部儲存在docker容器中,為了實現資料的永續性儲存,在宿主機和容器內做對映,可以保證在容器的生命週期結束,資料依舊可以實現永續性儲存。但是在k8s中,由於pod分佈在各個不同的節點之上,並不能實現不同節點之間永續性資料的共享,並且,在節點故障時,可能會導致資料的永久性丟失。為此,k8s就引入了外部儲存卷的功能。
k8s的儲存卷型別:

[root@k8s-master ~]# kubectl explain pod.spec.volumes #檢視k8s支援的儲存型別
KIND:     Pod
VERSION:  v1

常用分類:
emptyDir(臨時目錄):Pod刪除,資料也會被清除,這種儲存成為emptyDir,用於資料的臨時儲存。
hostPath(宿主機目錄對映):
本地的SAN(iSCSI,FC)、NAS(nfs,cifs,http)儲存
分散式儲存(glusterfs,rbd,cephfs)
雲端儲存(EBS,Azure Disk)

persistentVolumeClaim -->PVC(儲存卷建立申請)
當你需要建立一個儲存卷時,只需要進行申請對應的儲存空間即可使用,這就是PVC。其關聯關係如圖:

上圖解析:在Pod上定義一個PVC,該PVC要關聯到當前名稱空間的PVC資源,該PVC只是一個申請,PVC需要和PV進行關聯。PV屬於儲存上的一部分儲存空間。但是該方案存在的問題是,我們無法知道使用者是什麼時候去建立Pod,也不知道建立Pod時定義多大的PVC,那麼如何實現按需建立呢???

不需要PV層,把所有儲存空間抽象出來,這一個抽象層稱為儲存類,當用戶建立PVC需要用到PV時,可以向儲存類申請對應的儲存空間,儲存類會按照需求建立對應的儲存空間,這就是PV的動態供給,如圖:

那麼PV的動態供給,其重點是在儲存類的定義,其分類大概是對儲存的效能進行分類的,如圖:金儲存類、銀儲存類、銅儲存類等。

總結:
k8s要使用儲存卷,需要2步:
1、在pod定義volume,並指明關聯到哪個儲存裝置
2、在容器使用volume mount進行掛載

二、emptyDir儲存卷演示

一個emptyDir 第一次建立是在一個pod被指定到具體node的時候,並且會一直存在在pod的生命週期當中,正如它的名字一樣,它初始化是一個空的目錄,pod中的容器都可以讀寫這個目錄,這個目錄可以被掛在到各個容器相同或者不相同的的路徑下。當一個pod因為任何原因被移除的時候,這些資料會被永久刪除。注意:一個容器崩潰了不會導致資料的丟失,因為容器的崩潰並不移除pod.

emptyDir 磁碟的作用:
(1)普通空間,基於磁碟的資料儲存
(2)作為從崩潰中恢復的備份點
(3)儲存那些那些需要長久儲存的資料,例web服務中的資料
預設的,emptyDir 磁碟會儲存在主機所使用的媒介上,可能是SSD,或者網路硬碟,這主要取決於你的環境。當然,我們也可以將emptyDir.medium的值設定為Memory來告訴Kubernetes 來掛在一個基於記憶體的目錄tmpfs,因為
tmpfs速度會比硬碟塊度了,但是,當主機重啟的時候所有的資料都會丟失。

[root@k8s-master ~]# kubectl explain pods.spec.volumes.emptyDir  #檢視emptyDir儲存定義
[root@k8s-master ~]# kubectl explain pods.spec.containers.volumeMounts  #檢視容器掛載方式
[root@k8s-master ~]# cd mainfests && mkdir volumes && cd volumes
[root@k8s-master volumes]# cp ../pod-demo.yaml ./
[root@k8s-master volumes]# mv pod-demo.yaml pod-vol-demo.yaml
[root@k8s-master volumes]# vim pod-vol-demo.yaml   #建立emptyDir的清單
apiVersion: v1
kind: Pod
metadata:
  name: pod-demo
  namespace: default
  labels:
    app: myapp
    tier: frontend
  annotations:
    magedu.com/create-by:"cluster admin"
spec:
  containers:
  - name: myapp
    image: ikubernetes/myapp:v1
    imagePullPolicy: IfNotPresent
    ports:
    - name: http
      containerPort: 80
    volumeMounts:    #在容器內定義掛載儲存名稱和掛載路徑
    - name: html
      mountPath: /usr/share/nginx/html/
  - name: busybox
    image: busybox:latest
    imagePullPolicy: IfNotPresent
    volumeMounts:
    - name: html
      mountPath: /data/    #在容器內定義掛載儲存名稱和掛載路徑
    command: ['/bin/sh','-c','while true;do echo $(date) >> /data/index.html;sleep 2;done']
  volumes:  #定義儲存卷
  - name: html    #定義儲存卷名稱  
    emptyDir: {}  #定義儲存卷型別
[root@k8s-master volumes]# kubectl apply -f pod-vol-demo.yaml 
pod/pod-vol-demo created 
[root@k8s-master volumes]# kubectl get pods
NAME                                 READY     STATUS    RESTARTS   AGE
pod-vol-demo                         2/2       Running   0          27s
[root@k8s-master volumes]# kubectl get pods -o wide
NAME                      READY     STATUS    RESTARTS   AGE       IP            NODE
......
pod-vol-demo              2/2       Running   0          16s       10.244.2.34   k8s-node02
......

在上面,我們定義了2個容器,其中一個容器是輸入日期到index.html中,然後驗證訪問nginx的html是否可以獲取日期。以驗證兩個容器之間掛載的emptyDir實現共享。如下訪問驗證:
[root@k8s-master volumes]# curl 10.244.2.34  #訪問驗證
Tue Oct 9 03:56:53 UTC 2018
Tue Oct 9 03:56:55 UTC 2018
Tue Oct 9 03:56:57 UTC 2018
Tue Oct 9 03:56:59 UTC 2018
Tue Oct 9 03:57:01 UTC 2018
Tue Oct 9 03:57:03 UTC 2018
Tue Oct 9 03:57:05 UTC 2018
Tue Oct 9 03:57:07 UTC 2018
Tue Oct 9 03:57:09 UTC 2018
Tue Oct 9 03:57:11 UTC 2018
Tue Oct 9 03:57:13 UTC 2018
Tue Oct 9 03:57:15 UTC 2018

三、hostPath儲存卷演示

hostPath宿主機路徑,就是把pod所在的宿主機之上的脫離pod中的容器名稱空間的之外的宿主機的檔案系統的某一目錄和pod建立關聯關係,在pod刪除時,儲存資料不會丟失。

(1)檢視hostPath儲存型別定義
[root@k8s-master volumes]# kubectl explain pods.spec.volumes.hostPath  
KIND:     Pod
VERSION:  v1

RESOURCE: hostPath <Object>

DESCRIPTION:
     HostPath represents a pre-existing file or directory on the host machine
     that is directly exposed to the container. This is generally used for
     system agents or other privileged things that are allowed to see the host
     machine. Most containers will NOT need this. More info:
     https://kubernetes.io/docs/concepts/storage/volumes#hostpath

     Represents a host path mapped into a pod. Host path volumes do not support
     ownership management or SELinux relabeling.

FIELDS:
   path	<string> -required-  #指定宿主機的路徑
     Path of the directory on the host. If the path is a symlink, it will follow
     the link to the real path. More info:
     https://kubernetes.io/docs/concepts/storage/volumes#hostpath

   type	<string>
     Type for HostPath Volume Defaults to "" More info:
     https://kubernetes.io/docs/concepts/storage/volumes#hostpath

type:
DirectoryOrCreate  宿主機上不存在建立此目錄  
Directory 必須存在掛載目錄  
FileOrCreate 宿主機上不存在掛載檔案就建立  
File 必須存在檔案  

(2)清單定義
[root@k8s-master volumes]# vim pod-hostpath-vol.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-vol-hostpath
  namespace: default
spec:
  containers:
  - name: myapp
    image: ikubernetes/myapp:v1
    volumeMounts:
    - name: html
      mountPath: /usr/share/nginx/html
  volumes:
    - name: html
      hostPath:
        path: /data/pod/volume1
        type: DirectoryOrCreate

(3)在node節點上建立掛載目錄
[root@k8s-node01 ~]# mkdir -p /data/pod/volume1
[root@k8s-node01 ~]# vim /data/pod/volume1/index.html
node01.magedu.com
[root@k8s-node02 ~]# mkdir -p /data/pod/volume1
[root@k8s-node02 ~]# vim /data/pod/volume1/index.html
node02.magedu.com
[root@k8s-master volumes]# kubectl apply -f pod-hostpath-vol.yaml 
pod/pod-vol-hostpath created

(4)訪問測試
[root@k8s-master volumes]# kubectl get pods -o wide
NAME                                 READY     STATUS    RESTARTS   AGE       IP            NODE
......
pod-vol-hostpath                     1/1       Running   0          37s       10.244.2.35   k8s-node02
......
[root@k8s-master volumes]# curl 10.244.2.35
node02.magedu.com
[root@k8s-master volumes]# kubectl delete -f pod-hostpath-vol.yaml  #刪除pod,再重建,驗證是否依舊可以訪問原來的內容
[root@k8s-master volumes]# kubectl apply -f pod-hostpath-vol.yaml 
pod/pod-vol-hostpath created
[root@k8s-master volumes]# curl  10.244.2.37 
node02.magedu.com

hostPath可以實現持久儲存,但是在node節點故障時,也會導致資料的丟失

四、nfs共享儲存卷演示

nfs使的我們可以掛在已經存在的共享到的我們的Pod中,和emptyDir不同的是,emptyDir會被刪除當我們的Pod被刪除的時候,但是nfs不會被刪除,僅僅是解除掛在狀態而已,這就意味著NFS能夠允許我們提前對資料進行處理,而且這些資料可以在Pod之間相互傳遞.並且,nfs可以同時被多個pod掛在並進行讀寫

注意:必須先報紙NFS伺服器正常執行在我們進行掛在nfs的時候

(1)在stor01節點上安裝nfs,並配置nfs服務
[root@stor01 ~]# yum install -y nfs-utils  ==》192.168.56.14
[root@stor01 ~]# mkdir /data/volumes -pv
[root@stor01 ~]# vim /etc/exports
/data/volumes 192.168.56.0/24(rw,no_root_squash)
[root@stor01 ~]# systemctl start nfs
[root@stor01 ~]# showmount -e
Export list for stor01:
/data/volumes 192.168.56.0/24

(2)在node01和node02節點上安裝nfs-utils,並測試掛載
[root@k8s-node01 ~]# yum install -y nfs-utils
[root@k8s-node02 ~]# yum install -y nfs-utils
[root@k8s-node02 ~]# mount -t nfs stor01:/data/volumes /mnt
[root@k8s-node02 ~]# mount
......
stor01:/data/volumes on /mnt type nfs4 (rw,relatime,vers=4.1,rsize=131072,wsize=131072,namlen=255,hard,proto=tcp,port=0,timeo=600,retrans=2,sec=sys,clientaddr=192.168.56.13,local_lock=none,addr=192.168.56.14)
[root@k8s-node02 ~]# umount /mnt/

(3)建立nfs儲存卷的使用清單
[root@k8s-master volumes]# cp pod-hostpath-vol.yaml pod-nfs-vol.yaml
[root@k8s-master volumes]# vim pod-nfs-vol.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-vol-nfs
  namespace: default
spec:
  containers:
  - name: myapp
    image: ikubernetes/myapp:v1
    volumeMounts:
    - name: html
      mountPath: /usr/share/nginx/html
  volumes:
    - name: html
      nfs:
        path: /data/volumes
        server: stor01
[root@k8s-master volumes]# kubectl apply -f pod-nfs-vol.yaml 
pod/pod-vol-nfs created
[root@k8s-master volumes]# kubectl get pods -o wide
NAME                     READY     STATUS    RESTARTS   AGE       IP            NODE
pod-vol-nfs              1/1       Running   0          21s       10.244.2.38   k8s-node02

(3)在nfs伺服器上建立index.html
[root@stor01 ~]# cd /data/volumes
[root@stor01 volumes ~]# vim index.html
<h1> nfs stor01</h1>
[root@k8s-master volumes]# curl 10.244.2.38
<h1> nfs stor01</h1>
[root@k8s-master volumes]# kubectl delete -f pod-nfs-vol.yaml   #刪除nfs相關pod,再重新建立,可以得到資料的持久化儲存
pod "pod-vol-nfs" deleted
[root@k8s-master volumes]# kubectl apply -f pod-nfs-vol.yaml 

五、PVC和PV的概念

我們前面提到kubernetes提供那麼多儲存介面,但是首先kubernetes的各個Node節點能管理這些儲存,但是各種儲存引數也需要專業的儲存工程師才能瞭解,由此我們的kubernetes管理變的更加複雜的。由此kubernetes提出了PV和PVC的概念,這樣開發人員和使用者就不需要關注後端儲存是什麼,使用什麼引數等問題。如下圖:

PersistentVolume(PV)是叢集中已由管理員配置的一段網路儲存。 叢集中的資源就像一個節點是一個叢集資源。 PV是諸如卷之類的卷外掛,但是具有獨立於使用PV的任何單個pod的生命週期。 該API物件捕獲儲存的實現細節,即NFS,iSCSI或雲提供商特定的儲存系統。

PersistentVolumeClaim(PVC)是使用者儲存的請求。PVC的使用邏輯:在pod中定義一個儲存卷(該儲存卷型別為PVC),定義的時候直接指定大小,pvc必須與對應的pv建立關係,pvc會根據定義去pv申請,而pv是由儲存空間創建出來的。pv和pvc是kubernetes抽象出來的一種儲存資源。

雖然PersistentVolumeClaims允許使用者使用抽象儲存資源,但是常見的需求是,使用者需要根據不同的需求去建立PV,用於不同的場景。而此時需要叢集管理員提供不同需求的PV,而不僅僅是PV的大小和訪問模式,但又不需要使用者瞭解這些卷的實現細節。 對於這樣的需求,此時可以採用StorageClass資源。這個在前面就已經提到過此方案。

PV是叢集中的資源。 PVC是對這些資源的請求,也是對資源的索賠檢查。 PV和PVC之間的相互作用遵循這個生命週期:

Provisioning(配置)---> Binding(繫結)--->Using(使用)---> Releasing(釋放) ---> Recycling(回收)
Provisioning

這裡有兩種PV的提供方式:靜態或者動態

靜態-->直接固定儲存空間:
    叢集管理員建立一些 PV。它們攜帶可供叢集使用者使用的真實儲存的詳細資訊。 它們存在於Kubernetes API中,可用於消費。

動態-->通過儲存類進行動態建立儲存空間:
    當管理員建立的靜態 PV 都不匹配使用者的 PVC 時,叢集可能會嘗試動態地為 PVC 配置卷。此配置基於 StorageClasses:PVC 必須請求儲存類,並且管理員必須已建立並配置該類才能進行動態配置。 要求該類的宣告有效地為自己禁用動態配置。

Binding

在動態配置的情況下,使用者建立或已經建立了具有特定數量的儲存請求和特定訪問模式的PersistentVolumeClaim。 主機中的控制迴路監視新的PVC,找到匹配的PV(如果可能),並將 PVC 和 PV 繫結在一起。 如果為新的PVC動態配置PV,則迴圈將始終將該PV繫結到PVC。 否則,使用者總是至少得到他們要求的內容,但是卷可能超出了要求。 一旦繫結,PersistentVolumeClaim繫結是排他的,不管用於繫結它們的模式。

如果匹配的卷不存在,PVC將保持無限期。 隨著匹配卷變得可用,PVC將被繫結。 例如,提供許多50Gi PV的叢集將不匹配要求100Gi的PVC。 當叢集中新增100Gi PV時,可以繫結PVC。

Using

Pod使用PVC作為卷。 叢集檢查宣告以找到繫結的卷並掛載該卷的卷。 對於支援多種訪問模式的卷,使用者在將其宣告用作pod中的卷時指定所需的模式。

一旦使用者有宣告並且該宣告被繫結,繫結的PV屬於使用者,只要他們需要它。 使用者通過在其Pod的卷塊中包含PersistentVolumeClaim來安排Pods並訪問其宣告的PV。

Releasing

當用戶完成卷時,他們可以從允許資源回收的API中刪除PVC物件。 當宣告被刪除時,卷被認為是“釋放的”,但是它還不能用於另一個宣告。 以前的索賠人的資料仍然保留在必須根據政策處理的捲上.

Reclaiming

PersistentVolume的回收策略告訴叢集在釋放其聲明後,該卷應該如何處理。 目前,卷可以是保留,回收或刪除。 保留可以手動回收資源。 對於那些支援它的卷外掛,刪除將從Kubernetes中刪除PersistentVolume物件,以及刪除外部基礎架構(如AWS EBS,GCE PD,Azure Disk或Cinder卷)中關聯的儲存資產。 動態配置的卷始終被刪除

Recycling

如果受適當的卷外掛支援,回收將對卷執行基本的擦除(rm -rf / thevolume / *),並使其再次可用於新的宣告。

六、NFS使用PV和PVC

實驗圖如下:

[root@k8s-master ~]# kubectl explain pv    #檢視pv的定義方式
FIELDS:
	apiVersion
	kind
	metadata
	spec
[root@k8s-master ~]# kubectl explain pv.spec    #檢視pv定義的規格
spec:
  nfs(定義儲存型別)
    path(定義掛載卷路徑)
    server(定義伺服器名稱)
  accessModes(定義訪問模型,有以下三種訪問模型,以列表的方式存在,也就是說可以定義多個訪問模式)
    ReadWriteOnce(RWO)  單節點讀寫
	ReadOnlyMany(ROX)  多節點只讀
	ReadWriteMany(RWX)  多節點讀寫
  capacity(定義PV空間的大小)
    storage(指定大小)

[root@k8s-master volumes]# kubectl explain pvc   #檢視PVC的定義方式
KIND:     PersistentVolumeClaim
VERSION:  v1
FIELDS:
   apiVersion	<string>
   kind	<string>  
   metadata	<Object>
   spec	<Object>
[root@k8s-master volumes]# kubectl explain pvc.spec
spec:
  accessModes(定義訪問模式,必須是PV的訪問模式的子集)
  resources(定義申請資源的大小)
    requests:
      storage: 

1、配置nfs儲存

[root@stor01 volumes]# mkdir v{1,2,3,4,5}
[root@stor01 volumes]# vim /etc/exports
/data/volumes/v1 192.168.56.0/24(rw,no_root_squash)
/data/volumes/v2 192.168.56.0/24(rw,no_root_squash)
/data/volumes/v3 192.168.56.0/24(rw,no_root_squash)
/data/volumes/v4 192.168.56.0/24(rw,no_root_squash)
/data/volumes/v5 192.168.56.0/24(rw,no_root_squash)
[root@stor01 volumes]# exportfs -arv
exporting 192.168.56.0/24:/data/volumes/v5
exporting 192.168.56.0/24:/data/volumes/v4
exporting 192.168.56.0/24:/data/volumes/v3
exporting 192.168.56.0/24:/data/volumes/v2
exporting 192.168.56.0/24:/data/volumes/v1
[root@stor01 volumes]# showmount -e
Export list for stor01:
/data/volumes/v5 192.168.56.0/24
/data/volumes/v4 192.168.56.0/24
/data/volumes/v3 192.168.56.0/24
/data/volumes/v2 192.168.56.0/24
/data/volumes/v1 192.168.56.0/24

2、定義PV

這裡定義5個PV,並且定義掛載的路徑以及訪問模式,還有PV劃分的大小。

[root@k8s-master volumes]# kubectl explain pv
[root@k8s-master volumes]# kubectl explain pv.spec.nfs
[root@k8s-master volumes]# vim pv-demo.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv001
  labels:
    name: pv001
spec:
  nfs:
    path: /data/volumes/v1
    server: stor01
  accessModes: ["ReadWriteMany","ReadWriteOnce"]
  capacity:
    storage: 1Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv002
  labels:
    name: pv002
spec:
  nfs:
    path: /data/volumes/v2
    server: stor01
  accessModes: ["ReadWriteOnce"]
  capacity:
    storage: 2Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv003
  labels:
    name: pv003
spec:
  nfs:
    path: /data/volumes/v3
    server: stor01
  accessModes: ["ReadWriteMany","ReadWriteOnce"]
  capacity:
    storage: 2Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv004
  labels:
    name: pv004
spec:
  nfs:
    path: /data/volumes/v4
    server: stor01
  accessModes: ["ReadWriteMany","ReadWriteOnce"]
  capacity:
    storage: 4Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv005
  labels:
    name: pv005
spec:
  nfs:
    path: /data/volumes/v5
    server: stor01
  accessModes: ["ReadWriteMany","ReadWriteOnce"]
  capacity:
    storage: 5Gi
[root@k8s-master volumes]# kubectl apply -f pv-demo.yaml 
persistentvolume/pv001 created
persistentvolume/pv002 created
persistentvolume/pv003 created
persistentvolume/pv004 created
persistentvolume/pv005 created
[root@k8s-master volumes]# kubectl get pv
NAME      CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM     STORAGECLASS   REASON    AGE
pv001     1Gi        RWO,RWX        Retain           Available                                      7s
pv002     2Gi        RWO            Retain           Available                                      7s
pv003     2Gi        RWO,RWX        Retain           Available                                      7s
pv004     4Gi        RWO,RWX        Retain           Available                                      7s
pv005     5Gi        RWO,RWX        Retain           Available                                      7s

3、定義PVC

這裡定義了pvc的訪問模式為多路讀寫,該訪問模式必須在前面pv定義的訪問模式之中。定義PVC申請的大小為2Gi,此時PVC會自動去匹配多路讀寫且大小為2Gi的PV,匹配成功獲取PVC的狀態即為Bound

[root@k8s-master volumes ~]# vim pod-vol-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mypvc
  namespace: default
spec:
  accessModes: ["ReadWriteMany"]
  resources:
    requests:
      storage: 2Gi
---
apiVersion: v1
kind: Pod
metadata:
  name: pod-vol-pvc
  namespace: default
spec:
  containers:
  - name: myapp
    image: ikubernetes/myapp:v1
    volumeMounts:
    - name: html
      mountPath: /usr/share/nginx/html
  volumes:
    - name: html
      persistentVolumeClaim:
        claimName: mypvc
[root@k8s-master volumes]# kubectl apply -f pod-vol-pvc.yaml 
persistentvolumeclaim/mypvc created
pod/pod-vol-pvc created
[root@k8s-master volumes]# kubectl get pv
NAME      CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM           STORAGECLASS   REASON    AGE
pv001     1Gi        RWO,RWX        Retain           Available                                            19m
pv002     2Gi        RWO            Retain           Available                                            19m
pv003     2Gi        RWO,RWX        Retain           Bound       default/mypvc                            19m
pv004     4Gi        RWO,RWX        Retain           Available                                            19m
pv005     5Gi        RWO,RWX        Retain           Available                                            19m
[root@k8s-master volumes]# kubectl get pvc
NAME      STATUS    VOLUME    CAPACITY   ACCESS MODES   STORAGECLASS   AGE
mypvc     Bound     pv003     2Gi        RWO,RWX                       22s

4、測試訪問

在儲存伺服器上建立index.html,並寫入資料,通過訪問Pod進行檢視,可以獲取到相應的頁面。

[root@stor01 volumes]# cd v3/
[root@stor01 v3]# echo "welcome to use pv3" > index.html
[root@k8s-master volumes]# kubectl get pods -o wide
pod-vol-pvc             1/1       Running   0          3m        10.244.2.39   k8s-node02
[root@k8s-master volumes]# curl  10.244.2.39
welcome to use pv3

七、StorageClass

在pv和pvc使用過程中存在的問題,在pvc申請儲存空間時,未必就有現成的pv符合pvc申請的需求,上面nfs在做pvc可以成功的因素是因為我們做了指定的需求處理。那麼當PVC申請的儲存空間不一定有滿足PVC要求的PV事,又該如何處理呢???為此,Kubernetes為管理員提供了描述儲存"class(類)"的方法(StorageClass)。舉個例子,在儲存系統中劃分一個1TB的儲存空間提供給Kubernetes使用,當用戶需要一個10G的PVC時,會立即通過restful傳送請求,從而讓儲存空間建立一個10G的image,之後在我們的叢集中定義成10G的PV供給給當前的PVC作為掛載使用。在此之前我們的儲存系統必須支援restful介面,比如ceph分散式儲存,而glusterfs則需要藉助第三方介面完成這樣的請求。如圖:

[root@k8s-master ~]# kubectl explain storageclass  #storageclass也是k8s上的資源
KIND:     StorageClass
VERSION:  storage.k8s.io/v1
FIELDS:
   allowVolumeExpansion	<boolean>     
   allowedTopologies	<[]Object>   
   apiVersion	<string>   
   kind	<string>     
   metadata	<Object>     
   mountOptions	<[]string>    #掛載選項
   parameters	<map[string]string>  #引數,取決於分配器,可以接受不同的引數。 例如,引數 type 的值 io1 和引數 iopsPerGB 特定於 EBS PV。當引數被省略時,會使用預設值。  
   provisioner	<string> -required-  #儲存分配器,用來決定使用哪個卷外掛分配 PV。該欄位必須指定。
   reclaimPolicy	<string>   #回收策略,可以是 Delete 或者 Retain。如果 StorageClass 物件被建立時沒有指定 reclaimPolicy ,它將預設為 Delete。 
   volumeBindingMode	<string>  #卷的繫結模式

StorageClass 中包含 provisioner、parameters 和 reclaimPolicy 欄位,當 class 需要動態分配 PersistentVolume 時會使用到。由於StorageClass需要一個獨立的儲存系統,此處就不再演示。從其他資料檢視定義StorageClass的方式如下:

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: standard
provisioner: kubernetes.io/aws-ebs
parameters:
  type: gp2
reclaimPolicy: Retain
mountOptions:
  - debug