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:        
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:     
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:            

 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的状态为"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中完此字段与将此字段设置成""等效。

参考:https://kubernetes.io/docs/concepts/storage/persistent-volumes/

后续问题:如何在副本控制器中为每个pod实例指定PVC,持久化存储与StatefulSet什么关系?

 

你可能感兴趣的:(kubernetes)