Persistent Volume

PersistentVolume (PV) 和 PersistentVolumeClaim (PVC) 提供了方便的持久化卷:PV 提供网络存储资源,而 PVC 请求存储资源。这样,设置持久化的工作流包括配置底层文件系统或者云数据卷、创建持久性数据卷、最后创建 PVC 来将 Pod 跟数据卷关联起来。PV 和 PVC 可以将 pod 和数据卷解耦,pod 不需要知道确切的文件系统或者支持它的持久化引擎。

Volume 生命周期

Volume 的生命周期包括 5 个阶段

  1. Provisioning,即 PV 的创建,可以直接创建 PV(静态方式),也可以使用 StorageClass 动态创建
  2. Binding,将 PV 分配给 PVC
  3. Using,Pod 通过 PVC 使用该 Volume,并可以通过准入控制 StorageProtection(1.9及以前版本为PVCProtection)阻止删除正在使用的 PVC
  4. Releasing,Pod 释放 Volume 并删除 PVC
  5. Reclaiming,回收 PV,可以保留 PV 以便下次使用,也可以直接从云存储中删除
  6. Deleting,删除 PV 并从云存储中删除后段存储

根据这 5 个阶段,Volume 的状态有以下 4 种

  • Available:可用
  • Bound:已经分配给 PVC
  • Released:PVC 解绑但还未执行回收策略
  • Failed:发生错误

API 版本对照表

Kubernetes 版本 PV/PVC 版本 StorageClass 版本
v1.5-v1.6 core/v1 storage.k8s.io/v1beta1
v1.7+ core/v1 storage.k8s.io/v1

PV

PersistentVolume(PV)是集群之中的一块网络存储。跟 Node 一样,也是集群的资源。PV 跟 Volume (卷) 类似,不过会有独立于 Pod 的生命周期。比如一个 NFS 的 PV 可以定义为

  1. apiVersion: v1
  2. kind: PersistentVolume
  3. metadata:
  4. name: pv0003
  5. spec:
  6. capacity:
  7. storage: 5Gi
  8. accessModes:
  9. - ReadWriteOnce
  10. persistentVolumeReclaimPolicy: Recycle
  11. nfs:
  12. path: /tmp
  13. server: 172.17.0.2

PV 的访问模式(accessModes)有三种:

  • ReadWriteOnce(RWO):是最基本的方式,可读可写,但只支持被单个 Pod 挂载。
  • ReadOnlyMany(ROX):可以以只读的方式被多个 Pod 挂载。
  • ReadWriteMany(RWX):这种存储可以以读写的方式被多个 Pod 共享。不是每一种存储都支持这三种方式,像共享方式,目前支持的还比较少,比较常用的是 NFS。在 PVC 绑定 PV 时通常根据两个条件来绑定,一个是存储的大小,另一个就是访问模式。

PV 的回收策略(persistentVolumeReclaimPolicy,即 PVC 释放卷的时候 PV 该如何操作)也有三种

  • Retain,不清理, 保留 Volume(需要手动清理)
  • Recycle,删除数据,即 rm -rf /thevolume/*(只有 NFS 和 HostPath 支持)
  • Delete,删除存储资源,比如删除 AWS EBS 卷(只有 AWS EBS, GCE PD, Azure Disk 和 Cinder 支持)

StorageClass

上面通过手动的方式创建了一个 NFS Volume,这在管理很多 Volume 的时候不太方便。Kubernetes 还提供了 StorageClass 来动态创建 PV,不仅节省了管理员的时间,还可以封装不同类型的存储供 PVC 选用。

StorageClass 包括四个部分

  • provisioner:指定 Volume 插件的类型,包括内置插件(如 kubernetes.io/glusterfs)和外部插件(如 external-storage 提供的 ceph.com/cephfs)。
  • mountOptions:指定挂载选项,当 PV 不支持指定的选项时会直接失败。比如 NFS 支持 hardnfsvers=4.1 等选项。
  • parameters:指定 provisioner 的选项,比如 kubernetes.io/aws-ebs 支持 typezoneiopsPerGB 等参数。
  • reclaimPolicy:指定回收策略,同 PV 的回收策略。

在使用 PVC 时,可以通过 DefaultStorageClass 准入控制设置默认 StorageClass, 即给未设置 storageClassName 的 PVC 自动添加默认的 StorageClass。而默认的 StorageClass 带有 annotation storageclass.kubernetes.io/is-default-class=true

Volume Plugin Internal Provisioner Config Example
AWSElasticBlockStore AWS
AzureFile Azure File
AzureDisk Azure Disk
CephFS - -
Cinder OpenStack Cinder
FC - -
FlexVolume - -
Flocker -
GCEPersistentDisk GCE
Glusterfs Glusterfs
iSCSI - -
PhotonPersistentDisk -
Quobyte Quobyte
NFS - -
RBD Ceph RBD
VsphereVolume vSphere
PortworxVolume Portworx Volume
ScaleIO ScaleIO
StorageOS StorageOS
Local - Local

修改默认 StorageClass

取消原来的默认 StorageClass

  1. kubectl patch storageclass <default-class-name> -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"false"}}}'

标记新的默认 StorageClass

  1. kubectl patch storageclass <your-class-name> -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'

GCE 示例

  1. kind: StorageClass
  2. apiVersion: storage.k8s.io/v1
  3. metadata:
  4. name: slow
  5. provisioner: kubernetes.io/gce-pd
  6. parameters:
  7. type: pd-standard
  8. zone: us-central1-a

Glusterfs 示例

  1. apiVersion: storage.k8s.io/v1
  2. kind: StorageClass
  3. metadata:
  4. name: slow
  5. provisioner: kubernetes.io/glusterfs
  6. parameters:
  7. resturl: "http://127.0.0.1:8081"
  8. clusterid: "630372ccdc720a92c681fb928f27b53f"
  9. restauthenabled: "true"
  10. restuser: "admin"
  11. secretNamespace: "default"
  12. secretName: "heketi-secret"
  13. gidMin: "40000"
  14. gidMax: "50000"
  15. volumetype: "replicate:3"

OpenStack Cinder 示例

  1. kind: StorageClass
  2. apiVersion: storage.k8s.io/v1
  3. metadata:
  4. name: gold
  5. provisioner: kubernetes.io/cinder
  6. parameters:
  7. type: fast
  8. availability: nova

Ceph RBD 示例

  1. apiVersion: storage.k8s.io/v1
  2. kind: StorageClass
  3. metadata:
  4. name: fast
  5. provisioner: kubernetes.io/rbd
  6. parameters:
  7. monitors: 10.16.153.105:6789
  8. adminId: kube
  9. adminSecretName: ceph-secret
  10. adminSecretNamespace: kube-system
  11. pool: kube
  12. userId: kube
  13. userSecretName: ceph-secret-user

Local Volume 示例

Local Volume 需要开启 VolumeScheduling 特性(--feature-gates=VolumeScheduling):

  1. kind: StorageClass
  2. apiVersion: storage.k8s.io/v1
  3. metadata:
  4. name: local-fast
  5. provisioner: kubernetes.io/no-provisioner
  6. volumeBindingMode: WaitForFirstConsumer

注意:Local Volume 在首次被容器引用时才会创建。

PVC

PV 是存储资源,而 PersistentVolumeClaim (PVC) 是对 PV 的请求。PVC 跟 Pod 类似:Pod 消费 Node 资源,而 PVC 消费 PV 资源;Pod 能够请求 CPU 和内存资源,而 PVC 请求特定大小和访问模式的数据卷。

  1. kind: PersistentVolumeClaim
  2. apiVersion: v1
  3. metadata:
  4. name: myclaim
  5. spec:
  6. accessModes:
  7. - ReadWriteOnce
  8. resources:
  9. requests:
  10. storage: 8Gi
  11. storageClassName: slow
  12. selector:
  13. matchLabels:
  14. release: "stable"
  15. matchExpressions:
  16. - {key: environment, operator: In, values: [dev]}

PVC 可以直接挂载到 Pod 中:

  1. kind: Pod
  2. apiVersion: v1
  3. metadata:
  4. name: mypod
  5. spec:
  6. containers:
  7. - name: myfrontend
  8. image: dockerfile/nginx
  9. volumeMounts:
  10. - mountPath: "/var/www/html"
  11. name: mypd
  12. volumes:
  13. - name: mypd
  14. persistentVolumeClaim:
  15. claimName: myclaim

扩展 PV 空间

v1.8 开始支持扩展 PV 空间,支持在不丢失数据和重启容器的情况下扩展 PV 的大小。注意, 当前的实现仅支持不需要调整文件系统大小(XFS、Ext3、Ext4)的 PV,并且只支持以下几种存储插件

  • gcePersistentDisk
  • awsElasticBlockStore
  • Cinder
  • glusterfs
  • rbd

开启扩展 PV 空间的功能需要配置

  • 开启 ExpandPersistentVolumes 功能,即配置 --feature-gates=ExpandPersistentVolumes=true
  • 开启准入控制插件 PersistentVolumeClaimResize,它只允许扩展明确配置 allowVolumeExpansion=true 的 StorageClass,比如
  1. kind: StorageClass
  2. apiVersion: storage.k8s.io/v1
  3. metadata:
  4. name: gluster-vol-default
  5. provisioner: kubernetes.io/glusterfs
  6. parameters:
  7. resturl: "http://192.168.10.100:8080"
  8. restuser: ""
  9. secretNamespace: ""
  10. secretName: ""
  11. allowVolumeExpansion: true

这样,用户就可以修改 PVC 中请求存储的大小(如通过 kubectl edit 命令)请求更大的存储空间。

Raw Block Volume

Kubernetes v1.9 还新增了 Alpha 版的 Raw Block Volume。目前仅 Fibre Channel 支持以 Block Volume 的形式挂载。

  1. apiVersion: v1
  2. kind: PersistentVolume
  3. metadata:
  4. name: block-pv
  5. spec:
  6. capacity:
  7. storage: 10Gi
  8. accessModes:
  9. - ReadWriteOnce
  10. volumeMode: Block
  11. persistentVolumeReclaimPolicy: Retain
  12. fc:
  13. targetWWNs: ["50060e801049cfd1"]
  14. lun: 0
  15. readOnly: false
  16. ---
  17. apiVersion: v1
  18. kind: PersistentVolumeClaim
  19. metadata:
  20. name: block-pvc
  21. spec:
  22. accessModes:
  23. - ReadWriteOnce
  24. volumeMode: Block
  25. resources:
  26. requests:
  27. storage: 10Gi

参考文档