PVC-持久卷声明

PVC的出现,可以使得创建Pod时,不用再去管底层的存储类型,只需要声明该Pod需要的存储空间大小即可,即将Pod与底层存储技术解耦。

PVC(持久卷声明)和PV(持久卷)是成对出现的,PV与底层存储技术密切相关。Pod通过挂载PVC资源,令PVC申请满足条件的PV作为Pod的存储卷。

PV资源不属于任何一个命名空间,它是集群层面的资源。

PVC和PV使用时如下:

Pod中的容器挂载PVC,从而间接挂载PV

Tips:

  1. PVC和PV都是需要单独创建的资源对象;

  2. Pod在spec.volumes.persistentVolumeClaim.claimName中指定已经创建好的PVC的名字即可;

使用PVC

Pod使用PVC申请PV,总共需要以下两步:

  1. 集群管理员根据底层存储技术,创建PV资源;

  2. 集群使用者/管理员,根据所需存储卷的读写权限、大小等创建PVC资源;

  3. 集群使用者在Pod中挂载PVC资源,间接挂载PV卷;

创建PV

PV与底层的存储技术是息息相关的,因此在创建PV资源时,需要在spec中确定底层的存储技术。

PV资源不属于任何一个命名空间,是集群层面的资源。

spec.accessModes中可以指定PV卷的访问模式,共有以下三种:

  • ReadWriteOnce(RWO):PV能以read-write模式挂载到单个Node

  • ReadWriteMany(RWX):PV能以read-write模式挂载到多个Node

  • ReadOnlyMany(ROX):PV能以read-only模式挂载到多个Node

spec.persistentVolumeReclaimPolicy中可以指定PV卷被PVC资源释放时的回收操作,即当PVC释放PV时,该PV卷的操作:

  • Retain:删除PVC时,PV和底层数据都不会被删除,需要管理员手工回收;当删除PVC后,PV仅呈现为Released状态,尝试使用PVC重新绑定也不行,需要重新部署PV才行,且数据不会被清除;(因为PV中可能包含前一个Pod留下的数据,为了安全,所以暂时不能被使用)

  • Recycle:删除PVC时,PV不会被删除,但底层数据被删除,效果相当于执行rm -rf /thevolume/*;k8s会启动一个容器负责清除数据的操作。通过这种方式,PV可以被不同的PVC绑定,和不同的Pod反复使用。

  • Delete:删除PVC时,PV被删除,但底层数据不被删除;

例如,在下面这个例子中,创建一个名为mypv1的nfs类型的PV,其存储容量为1Gi,其访问模式有被单个Node挂载为读写模式被多个Node挂载为只读模式两种,并且该PV的回收模式为Recycle,其所属的StorageClass为nfsStorageClass是被用来动态创建PV的):

apiVersion: v1
kind: PersistentVolume    # 资源类型为PV
metadata:
  name: mypv1
spec:    # PV的规格
  capacity:    # PV的容量
    storage: 1Gi
  accessModes:    # 访问模式(下面两个合起来的意思是:可以被单个Node挂载为读写模式或者被多个Node挂载为只读模式)
  - ReadWriteOnce
  - ReadOnlyMany
  persistentVolumeReclaimPolicy: Recycle    # PV的回收策略,一般有Retain、Recycle和Delete三种
  storageClassName: nfs    # PV所属的storageClass的名字(这里根据是否需要定义在动态供给中会具体解释),注意这里即使写了,如果nfs这个SC不存在,也不会创建nfs这个SC
  nfs:    # 创建nfs类型的持久卷
    path: /nfsdata/pv1
    server: 192.168.56.105

Tips: spec.storageClassName不指定的话,则该PV资源对象不属于任何一个StorageClass资源。

创建PVC

PVC资源需要先创建,然后才能被挂载至Pod中。

在创建PVC时,需要指定申请的PV卷的容量大小、访问模式等,相当于筛选条件,进而从StorageClass中申请PV资源。

Tips: 若StorageClass中没有手动创建的PV卷资源,则会依靠StorageClass资源动态创建PV卷,这个在对应章节中另外仔细介绍。

下面介绍一个创建PVC资源的例子,

apiVersion: v1
kind: PersistentVolumeClaim    # 资源类型为PVC
metadata:
  name: mongodb-pvc    # PVC资源名字,之后需要在Pod中的spec.volumes.persistentVolumeClaim.claimName中指定,然后在spec.containers.volumeMounts中挂载
spec:
  resources:    # 申请的资源规格,包括卷大小等
    requests:
      storage: 1Gi
  accessModes:    # 申请的资源的访问模式
  - ReadWriteOnce
  storageClassName: nfs    # 申请的卷所属的StorageClass名

Tips:

  1. storageClassName="",则不会从任何的StorageClass中申请PV资源,因此若集群在任何StorageClass外都没有PV资源的话(即不指定PV资源的spec.storageClassName),则这里会申请失败;

  2. 若没有指定storageClassName,则会从集群的默认的StorageClass中申请PV资源;

  3. 若名为nfs的StorageClass中没有符合的预创建的PV卷,则该StorageClass资源会动态创建PV卷;

在Pod中挂载PVC

在Pod中挂载PVC,同样需要两步:

  1. 定义卷:此处定义的是PVC资源,即在spec.volumes.persistentVolumeClaim中指定claimName为预先创建好的PVC资源的名字,即与PVC相关联;

  2. 挂载卷:在Pod的spec.container.volumeMounts中指定挂载点和挂载卷名;

下面举一个例子,创建一个名为mongodb的Pod,其在内部的名为mongodb的容器的/data/db下挂载一个名为mongodb-data的PVC卷,该卷与名为mongodb-pvc的PVC资源关联:

apiVersion: v1
kind: Pod
metadata:
  name: mongodb 
spec:
  containers:
  - image: mongo
    name: mongodb
    volumeMounts:    # 定义挂载点
    - name: mongodb-data    # (必须)需要挂载的卷名
      mountPath: /data/db    # (必须)挂载至容器的文件系统中的路径
    ports:
    - containerPort: 27017
      protocol: TCP
  volumes:    # 定义卷
  - name: mongodb-data    # (必须)卷名
    persistentVolumeClaim:    # 定义一个PVC卷
      claimName: mongodb-pvc    # 与预先创建好的PVC资源名一致

Last updated

Was this helpful?