PV

概述

PV 的全称是:PersistentVolume(持久化卷),是对底层的共享存储的一种抽象,PV 由管理员进行创建和配置,它和具体的底层的共享存储技术的实现方式有关,比如 Ceph、GlusterFS、NFS 等,都是通过插件机制完成与共享存储的对接。

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:本地存储设备,从Kubernetes 1.7版本引入,到1.14版本时更新为稳定版,目前可以通过指定块(Block)设备提供LocalPV,或通过社区开发的sig-storage-local-static-provisioner插件(https://github.com/kubernetes-sigs/sigstorage-local-static-provisioner)来管理LocalPV的生命周期。
◎ NFS:网络文件系统。
◎ Portworx Volumes:Portworx提供的存储服务。
◎ Quobyte Volumes:Quobyte提供的存储服务。
◎ RBD(Ceph Block Device):Ceph块存储。
◎ ScaleIO Volumes:DellEMC的存储设备。
◎ StorageOS:StorageOS提供的存储服务。
◎ VsphereVolume:VMWare提供的存储系统。

配置参数

存储能力(Capacity)

描述存储设备具备的能力,目前仅支持对存储空间的设置(storage=xx)

存储卷模式(Volume Mode)

Kubernetes从1.13版本开始引入存储卷类型的设置(volumeMode=xxx),存储卷的模式有两种:Filesystem(文件系统) 和 Block(块设备),默认为 Filesystem。
支持块类型的存储卷有:
AWSElasticBlockStore、AzureDisk、FC、GCEPersistentDisk、iSCSI、Local volume、RBD(Ceph Block Device)、VsphereVolume

访问模式(Access Modes)

设置 PV 的访问模式,描述应用对存储资源的访问权限,现在的访问模式有如下 3 类:

访问模式 说明

- ReadWriteOnce(RWO):读写权限
只能被单个 Node 挂载

- ReadWriteOnce(RWO):读写权限
可以被多个 Node 挂载

- ReadWriteOnce(RWO):读写权限
可以被多个 Node 挂载

某些 PV 可以支持多种访问模式(比如:NFS 可以支持多个应用的读写操作),但是在挂载的时候只能支持一种访问模式,多种访问模式并不能同时生效。
下面的表格展示了不同卷类型所支持的访问模式:

Volume Plugin ReadWriteOnce ReadOnlyMany ReadWriteMany
AWSElasticBlockStore ✔️ - -
AzureFile ✔️ ✔️ ✔️
AzureDisk ✔️ - -
CephFS ✔️ ✔️ ✔️
Cinder ✔️ - -
CSI 视驱动而定 视驱动而定 视驱动而定
FC ✔️ ✔️ -
FlexVolume ✔️ ✔️ 视驱动而定
Flocker ✔️ - -
GCEPersistentDisk ✔️ ✔️ -
Glusterfs ✔️ ✔️ ✔️
HostPath ✔️ - -
iSCSI ✔️ ✔️ -
Quobyte ✔️ ✔️ ✔️
NFS ✔️ ✔️ ✔️
RBD ✔️ ✔️ -
VsphereVolume ✔️ - -
PortworxVolume ✔️ - ✔️
ScaleIO ✔️ ✔️ -
StorageOS ✔️ - -

PV 回收策略(persistentVolumeReclaimPolicy)

当前的回收策略有 3 种:

回收策略 说明
Retain(保留) 保留数据,需要手工处理。回收策略 Retain 使得用户可以手动回收资源。当 PersistentVolumeClaim 对象 被删除时,PersistentVolume 卷仍然存在,对应的数据卷被视为”已释放(released)”。 由于卷上仍然存在这前一申领人的数据,该卷还不能用于其他申领。 管理员可以通过下面的步骤来手动回收该卷:删除 PersistentVolume 对象。与之相关的、位于外部基础设施中的存储资产 (例如 AWS EBS、GCE PD、Azure Disk 或 Cinder 卷)在 PV 删除之后仍然存在。根据情况,手动清除所关联的存储资产上的数据。手动删除所关联的存储资产;如果你希望重用该存储资产,可以基于存储资产的 定义创建新的 PersistentVolume 卷对象。
Recycle(回收空间) 简单清除文件的操作(执行 rm -rf /thevolume/* 命令)。
Delete(删除) 与 PV 相连的后端存储完成 Volume 的删除操作(比如:AWS EBS、GCE PD、Azure Disk 和 OpenStack Cinder 等设备内部的 Volume 清理)。

支持对应策略的卷分别有:

  • Recycle 策略:NFS、HostPath
  • Delete 策略:AWS EBS、GCE PD、Azure Disk 和 OpenStack Cinder

    存储类别(storageClassName)

    如果需要支持动态存储的话,需要配置这个字段选项,通过storageClassName参数指定一个StorageClass资源对象的名称。具有特定类别的PV只能与请求了该类别的PVC进行绑定。未设定类别的PV则只能与不请求任何类别的PVC进行绑定。

    挂载参数(mountOptions)

    当 PV 挂载到 Node 上时,根据不同卷的特点可以设置额外的挂载参数。
    现在支持挂载参数的卷有:AWSElasticBlockStore、AzureDisk、AzureFile、CephFS、Cinder、GCEPersistentDisk、Glusterfs、NFS、Quobyte Volumes、RBD(Ceph Block Device)、StorageOS、VsphereVolume、iSCSI。
    由于挂载参数没有验证,所以如果其中的一个参数是无效的,那么挂载就会失败。

    节点亲和性(nodeAffinity)

    使用这个字段可以限制只有符合条件的 Node 才能访问存储卷,而使用这些存储卷的 Pod 也只会被调度到满足条件的 Node 上。
    这个参数只能用于 Local 存储卷。对于公有云提供的存储卷(比如:AWS EBS、GCE PD、Azure Disk 等)是公有云自动完成节点亲和性设置,不需要手工设置。

PV生命周期

  • Available: 可用状态,表示还没有与 PVC 绑定
  • Bound: 已经 PVC 绑定
  • Released: 绑定的 PVC 已经删除,资源已经释放,但没有被集群回收
  • Failed: 自动资源回收失败

PVC(持久化卷声明)

PVC 是对 PV 的声明使用。PVC 和 Pod 比较类似,Pod 消耗的是节点,PVC 消耗的是 PV 资源,Pod 可以请求 CPU 和内存,而 PVC 可以请求特定的存储空间和访问模式

生命周期

  • Pending: 等待状态,还没有与 PV 绑定
  • Bound: 绑定状态,已经与 PV 绑定
  • Lost: 丢失状态,与 PV 失去了绑定关系

参数设置

accessModes(访问模式)

这个字段,PVC 与 PV 相同,也可以设置访问模式,作用也是描述应用对存储资源的访问权限。

volumeMode(存储卷模式)

这个字段,PVC 与 PV 也是相同的,描述的是希望使用的 PV 存储卷模式,可以配置的模式为文件系统和块设备。

resources(资源请求)

这个字段用于描述对存储资源的请求,目前仅支持设置 requests.storage,也就是对存储空间的设置。

storageClassName(绑定的 StorageClass 的名称,即:存储类别)

这个字段用于设置后端存储类别(即:绑定 StorageClass),可以减少对后端存储特性详细信息的依赖。分为两种情况:

  • 如果设置这个字段为某个 StorageClass,那么只有设置了相同 Class 的 PV 才会被选中,然后与 PVC 绑定。
  • 如果设置这个字段为空 storageClassName="",即不设置 Class。这时取决于系统是否启用名为 DefaultStorageClass 的 admission controller:

    • 没有启动 DefaultStorageClass:将选择没有设定 Class 的 PV 进行匹配和绑定。
    • 启用 DefaultStorageClass:管理员定义默认的 StorageClass,系统将使用默认 StorageClass 的后端存储创建一个 PV 并自动与 PVC 绑定。设置的具体方法为:在 StorageClass 的定义中添加一个 annotation “storageclass.kubernetes.io/is-default-class=true”。需要注意的是:只能定义一个默认的 StorageClass。

      selector(选择条件)

      这个字段可以对系统中已经存在的各种 PV 进行筛选,根据筛选条件选出最符合条件的 PV 进行绑定。这下面包含两个字段:
  • matchLabels:PV 必须有这个标签值

  • matchExpressions:通过键值对和操作符指定标签选择器列表,操作符包括:In、Notln、Exists 和 DoesNotExist

如果两个字段都设置了,就必须满足所有的条件才能完成匹配。
最后需要注意的是:Pod、PV 和 PVC 都必须在同一命名空间下才起作用。
另外,如果使用动态存储管理,即不预先定义 PV,只通过 StorageClass 交给系统自动完成 PV 的动态创建,那么 PVC 设置的 selector 就是无效的。如果用户删除了 PVC,与它绑定的 PV(默认回收策略为 Delete)也会被删除,可以在绑定成功后手动将 Delete 策略修改为 Retain

HelloWorld

pv-hostpath.yaml

  1. apiVersion: v1
  2. kind: PersistentVolume
  3. metadata:
  4. name: pv-hostpath
  5. labels:
  6. type: local
  7. spec:
  8. capacity:
  9. storage: 2Gi
  10. volumeMode: Filesystem
  11. accessModes:
  12. - ReadWriteOnce
  13. persistentVolumeReclaimPolicy: Recycle
  14. storageClassName: local-sc
  15. hostPath:
  16. path: /data/k8s/local/hostpath

执行

  1. $ kubectl apply -f pv-hostpath.yaml
  2. persistentvolume/pv-hostpath created
  3. $ kubectl get pv pv-hostpath
  4. NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
  5. pv-hostpath 2Gi RWO Recycle Available local-sc 28s

创建 pvc-hostpath.yaml

  1. apiVersion: v1
  2. kind: PersistentVolumeClaim
  3. metadata:
  4. name: pvc-hostpath
  5. spec:
  6. storageClassName: local-sc
  7. resources:
  8. requests:
  9. storage: 2Gi
  10. volumeMode: Filesystem
  11. accessModes:
  12. - ReadWriteOnce

执行

  1. $ kubectl apply -f pvc-hostpath.yaml
  2. persistentvolumeclaim/pvc-hostpath created
  3. $ kubectl get pvc
  4. NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
  5. pvc-hostpath Bound pv-hostpath 2Gi RWO local-sc 93s

创建pv-hostpath-pod.yaml

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: pv-hostpath-pod
  5. labels:
  6. name: myapp
  7. spec:
  8. nodeSelector:
  9. kubernetes.io/hostname: k8s-node1
  10. volumes:
  11. - name: pvc-hostpath
  12. persistentVolumeClaim:
  13. claimName: pvc-hostpath
  14. containers:
  15. - name: nginx
  16. image: nginx:1.14
  17. resources:
  18. limits:
  19. memory: "128Mi"
  20. cpu: "500m"
  21. ports:
  22. - containerPort: 80
  23. volumeMounts:
  24. - mountPath: /usr/share/nginx/html
  25. name: pvc-hostpath

在k8s-node1 执行

  1. echo "hello k8s" >> /data/k8s/local/hostpath/index.html

执行

  1. kubectl get pod -o wide
  2. NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
  3. pv-hostpath-pod 1/1 Running 0 28s 100.111.156.110 k8s-node1 <none> <none>

在集群内部执行

  1. curl 100.111.156.110
  2. hello k8s