Persistent 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 版本对照表

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

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

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

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

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

StorageClass

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
AzureFile Azure File
AzureDisk
CephFS - -
Cinder OpenStack Cinder
FC - -
FlexVolume - -
Flocker -
GCEPersistentDisk
Glusterfs Glusterfs
iSCSI - -
PhotonPersistentDisk -
Quobyte
NFS - -
RBD Ceph RBD
VsphereVolume
PortworxVolume Portworx Volume
ScaleIO
StorageOS StorageOS
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 示例

OpenStack Cinder 示例

  1. apiVersion: storage.k8s.io/v1
  2. metadata:
  3. name: gold
  4. provisioner: kubernetes.io/cinder
  5. parameters:
  6. type: fast
  7. 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. adminSecretName: ceph-secret
  9. adminSecretNamespace: kube-system
  10. pool: kube
  11. userId: kube
  12. 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

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

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
  • rbd

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

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

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

  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

参考文档