1. 程式人生 > >Kubernetes之持久化儲存

Kubernetes之持久化儲存

ConfigMap、Secret、emptyDir、hostPath等屬於臨時性儲存,當pod被排程到某個節點上時,它們隨pod的建立而建立,臨時佔用節點儲存資源,當pod離開節點時,儲存資源被交還給節點,pod一旦離開它們就失效,不具備持久化儲存資料的能力。與此相反,持久化儲存擁有獨立的生命週期,具備持久化儲存能力,其後端一般是獨立的儲存系統如NFS、iSCSI、cephfs、glusterfs等。

PV與PVC

Kubernetes中的node代表計算資源,而PersistentVolume(PC)則代表儲存資源,它是對各種諸如NFS、iSCSI、雲端儲存等各種儲存後端所提供儲存塊的統一抽象,通過它遮蔽低層實現細節。與普通volume不同,PC擁有完全獨立的生命週期。

因為PC表示的是叢集能力,它是一種叢集資源,所以使用者不能直接使用PC,就像不能直接使用記憶體一樣,需要先向系統申請。Kubernetes通過PersistentVolumeClaim(PVC)代理使用者行為,使用者通過對PVC的操作實現對PC申請、使用、釋放等操作,PVC是使用者層面的資源。

靜態PV與動態PV

靜態PV由系統管理員負責建立、提供、維護,系統管理員為使用者遮蔽真正提供儲存的後端及其實現細節,普通使用者作為消費者,只需通過PVC申請、使用此類資源。

當用戶通過PVC申請PV時,如果系統無法從靜態PV為使用者分配資源,則嘗試建立動態PV。前提條件是使用者需要在PVC中給出“storage class”名稱,指示系統建立動態PV的具體方式。“storage class”可以理解成某種具體的後端儲存,它也是Kubernetes叢集中的一種資源,當然在使用之前,需要先由叢集管理員負責建立、配置。如果使用者的PVC中“storage class”的值為"",則表示不能為此PVC動態建立PV。

想要開啟基於“storage class”的動態儲存供應功能,需要為apiServer啟用"DefaultStorageClass"入口控制器,具體方法為在apiServer選項--enable-admission-plugins中包含"DefaultStorageClass"字串。

PV與PVC繫結

使用者建立包含容量、訪問模式等資訊的PVC,向系統請求儲存資源。系統查詢已存在PV或者監控新建立PV,如果與PVC匹配則將兩者繫結。如果PVC建立動態PV,則系統將一直將兩者繫結。PV與PVC的繫結是一一對應關係,不能重複繫結與被繫結。如果系統一直沒有為PVC找到匹配PV,則PVC無限期維持在"unbound"狀態,直到系統找到匹配PV。實際繫結的PV容量可能大於PVC中申請的容量。

在POD中使用PVC

當系統為使用者建立的PVC繫結PV後,表明使用者成功申請了儲存資源。使用者在pod中定義PVC型別的volume,當建立POD例項時系統將與PVC繫結的PV掛載到POD例項。如果PV支援多種訪問模式,使用者需要pod的PVC volume中指定期望的型別。注意,pod與PVC必需位於相同namespace之下。

儲存物件使用中保護

如果啟用了儲存物件使用中保護特性,則不允許將正在被pod使用的活動PVC或者繫結到PVC的PV從系統中移除,防止資料丟失。活動PVC指使用PVC的pod處於pending狀態並且已經被指派節點或者處於running狀態。

如果已經啟用儲存物件使用中保護特性,且使用者刪除正在被pod使用的活動PVC,不會立即刪除PVC,而是延後到其狀態變成非活動。同樣如果使用者刪除已經繫結的PV,則刪除動作延後到PV解除繫結後。

當PVC處於保護中時,其狀態為"Terminating"並且其"Finalizers"包含"kubernetes.io/pvc-protection":

kubectl describe pvc hostpath
Name:          hostpath
Namespace:     default
StorageClass:  example-hostpath
Status:        Terminating
Volume:        
Labels:        <none>
Annotations:   volume.beta.kubernetes.io/storage-class=example-hostpath
               volume.beta.kubernetes.io/storage-provisioner=example.com/hostpath
Finalizers:    [kubernetes.io/pvc-protection]
...

 正處在保護中的PV,其狀態為"Terminating"且"Finalizers"包含"kubernetes.io/pv-protection":

kubectl describe pv task-pv-volume
Name:            task-pv-volume
Labels:          type=local
Annotations:     <none>
Finalizers:      [kubernetes.io/pv-protection]
StorageClass:    standard
Status:          Available
Claim:           
Reclaim Policy:  Delete
Access Modes:    RWO
Capacity:        1Gi
Message:         
Source:
    Type:          HostPath (bare host directory volume)
    Path:          /tmp/data
    HostPathType:  
Events:            <none>

 Reclaiming

使用者刪除PVC釋放對PV的佔用後,系統根據PV的"reclaim policy"決定對PV執行何種回收操作。 目前,"reclaim policy"有三種方式:Retained、Recycled、Deleted。

Retained

保護被PVC釋放的PV及其上資料,並將PV狀態改成"released",不將被其它PVC繫結。叢集管理員手動通過如下步驟釋放儲存資源:

  1. 手動刪除PV,但與其相關的後端儲存資源如(AWS EBS, GCE PD, Azure Disk, or Cinder volume)仍然存在。
  2. 手動清空後端儲存volume上的資料。
  3. 手動刪除後端儲存volume,或者重複使用後端volume,為其建立新的PV。

Delete

刪除被PVC釋放的PV及其後端儲存volume。對於動態PV其"reclaim policy"繼承自其"storage class",預設是Delete。叢集管理員負責將"storage class"的"reclaim policy"設定成使用者期望的形式,否則需要使用者手動為建立後的動態PV編輯"reclaim policy"。

Recycle 

保留PV,但清空其上資料,已廢棄

RESIZING

PVC

FEATURE STATE: Kubernetes v1.8 alpha

FEATURE STATE: Kubernetes v1.11 beta

此特性預設啟用。支援PVC擴容的的volume型別:

  • gcePersistentDisk
  • awsElasticBlockStore
  • Cinder
  • glusterfs
  • rbd
  • Azure File
  • Azure Disk
  • Portworx

如果對PVC擴容,則其對應的"storage class"中allowVolumeExpansion欄位需要設定成true:

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: gluster-vol-default
provisioner: kubernetes.io/glusterfs
parameters:
  resturl: "http://192.168.10.100:8080"
  restuser: ""
  secretNamespace: ""
  secretName: ""
allowVolumeExpansion: true

編輯PVC為其指定更大容量,自動觸發與其繫結的PV的擴容,不是建立新的PV,而是在原有基礎上resize。

PV

只能對包含XFS, Ext3, or Ext4檔案系統的PV執行resize操作,並且resize操作不會立即生效,只有當新pod通過ReadWrite模式的PVC使用PV,真正的resize才會生效。所以當為雲端儲存供應商提供的PV執行resize後,必需刪除舊pod並建立新pod後,resize才會生效。檢視PVC是否正在等待resize:

kubectl describe pvc <pvc_name>

當PVC的狀態為"FileSystemResizePending"時,刪除舊的pod並用PVC建立新pod是安全的,也就是不會丟失資料。

PV型別

Kubernetes通過外掛支援各種PV型別,目前支援的外掛有:

  • GCEPersistentDisk
  • AWSElasticBlockStore
  • AzureFile
  • AzureDisk
  • FC (Fibre Channel)
  • FlexVolume
  • Flocker
  • NFS
  • iSCSI
  • RBD (Ceph Block Device)
  • CephFS
  • Cinder (OpenStack block storage)
  • Glusterfs
  • VsphereVolume
  • Quobyte Volumes
  • HostPath (Single node testing only – local storage is not supported in any way and WILL NOT WORK in a multi-node cluster)
  • Portworx Volumes
  • ScaleIO Volumes
  • StorageOS

PV物件

PV物件與POD物件類似,包含spec與status兩部分:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv0003
spec:
  capacity:
    storage: 5Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: slow
  mountOptions:
    - hard
    - nfsvers=4.1
  nfs:
    path: /tmp
    server: 172.17.0.2

Capacity

.spec.capacity欄位,目前只包含表示PV容量的storage欄位,未來可能增加IOPS、throughput等。

Volume Mode

在1.9及之前的版本中,所有的volume外掛都會在PV上建立檔案系統(什麼型別的檔案系統?)。1.9以後的版本,此欄位可以設定成"raw",則此時建立的PV為raw型別的儲存塊裝置。如果此欄位省略,預設為"Filesystem"。

Access Modes

不同儲存後端支援的訪問模式不同,同一種儲存後端的不同PV也可以各自設定訪問模式。如NFS支援多客端read/write,但其某一個具體PV的訪問模式可能是read-only。每個PV的訪問模式取決於其PV物件中accessModes欄位設定。

具體的訪問模式有:

  • ReadWriteOnce – volume可以被單節點以read-write模式掛開。
  • ReadOnlyMany – volume可以被多節點以read-only模式掛載。
  • ReadWriteMany – volume可以被多個節點以read-write模式掛載。

Volume可以同時支援多種訪問模式,但是在具體掛載時只能使用一種,這一點需要在pod中定義PVC型別的volume時說明。命令列支援縮寫:

  • RWO - ReadWriteOnce
  • ROX - ReadOnlyMany
  • RWX - ReadWriteMany

不同儲存後端對訪問模式的支援:

Volume Plugin ReadWriteOnce ReadOnlyMany ReadWriteMany
AWSElasticBlockStore - -
AzureFile
AzureDisk - -
CephFS
Cinder - -
FC -
FlexVolume -
Flocker - -
GCEPersistentDisk -
Glusterfs
HostPath - -
iSCSI -
Quobyte
NFS
RBD -
VsphereVolume - - (works when pods are collocated)
PortworxVolume -
ScaleIO -
StorageOS - -

 Class

"storageClassName"的值為某個"storage class"的名稱,表示PV由那個具體的儲存後端提供。特定"storage class"的PV只能被繫結給具有相同"storage class"的PVC。如果PV不包含"storage class",則這種型別的PV只能被繫結給同樣不包含"storage class"的PVC。

以前,使用註解"volume.beta.kubernetes.io/storage-class"儲存"storage class"而非"storageClassName",目前前一種方式仍然可以工作,但在將來的Kubernetes版本中將會完全廢棄。

Reclaim Policy

前文提到過,有三種:

  • Retain – manual reclamation
  • Recycle – basic scrub (rm -rf /thevolume/*)
  • Delete – associated storage asset such as AWS EBS, GCE PD, Azure Disk, or OpenStack Cinder volume is deleted

目前只有NFS與hostPath支援Recycle, AWS EBS, GCE PD, Azure Disk, and Cinder支援Delete。

Mount Options

由叢集管理員為PV指定的,當PV掛載到node的選項(動態PV如何指定?從storage class繼承嗎?)

支援掛載選項的後端儲存型別:

  • GCEPersistentDisk
  • AWSElasticBlockStore
  • AzureFile
  • AzureDisk
  • NFS
  • iSCSI
  • RBD (Ceph Block Device)
  • CephFS
  • Cinder (OpenStack block storage)
  • Glusterfs
  • VsphereVolume
  • Quobyte Volumes

系統不驗證掛載選項的可用性,如果設定錯誤,則僅僅返回掛載失敗。
以前,用註解volume.beta.kubernetes.io/mount-options表示掛載選項,目前仍然工作,但在將來版本中會被完全廢棄。

Phase

PV可能的phase:

  • Available – 沒有繫結的free資源。
  • Bound – 已經被PVC繫結。
  • Released – PVC被刪除,但PV被保留,並且不可以被新PVC繫結。
  • Failed – reclaim policy執行失敗。

可以通過命令列檢視繫結PV的PVC。

PVC物件

同樣,一個PVC物件也包括spec與status兩部分:

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: myclaim
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 8Gi
  storageClassName: slow
  selector:
    matchLabels:
      release: "stable"
    matchExpressions:
      - {key: environment, operator: In, values: [dev]}

 Access Modes

與PV含義相同,應該是PV與PVC相匹配才可以繫結。

Volume Modes

與PV含義相同,應該是PV與PVC相匹配才可以繫結。

Resources

指明所請求PV的大小。

Selector

選擇器PVC通過選擇器進一步過濾可選PV,支援matchLabels與matchExpressions兩種匹配表示式。

Class

含義與PV相同,只有此欄位相同的PV與PVC可以相互繫結。但是如果PVC中完全沒有出現此欄位,結果取決於:
DefaultStorageClass入口管理器是否被開啟:

如果此入口管理器被管理員開啟並指定了預設的storage class,則為PVC指定此預設storage class,如果開啟入口控制器但沒有設定預設storage則與沒有開啟效果相同。如果有多個預設storage class,禁止所有PVC建立。

如果沒有開啟此入口控制器,則PVC中完此欄位與將此欄位設定成""等效。

後續問題:如何在副本控制器中為每個pod例項指定PVC,持久化儲存與StatefulSet什麼關係?