k8s之PV、PVC、StorageClass詳解

上古偽神發表於2021-01-27

導讀

上一篇寫了共享儲存的概述以及一個簡單的案例演示。這一篇就寫一下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的生命週期

k8s之PV、PVC、StorageClass詳解

 

將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使用的儲存管理機制

k8s之PV、PVC、StorageClass詳解

 

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

k8s之PV、PVC、StorageClass詳解

 

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儲存外掛的關鍵元件和部署架構

k8s之PV、PVC、StorageClass詳解

 

主要包括兩個元件: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,一個喜歡健身的程式設計師。

獲取更多幹貨以及最新訊息,請關注公眾號:上古偽神

如果對您有幫助,點個關注就是對我最大的支援!!!

相關文章