文章

kubernetes持久化存储(一)| PV和PVC的使用

Kubernetes提供了可靠的存储来保存应用的持久化数据,这样容器在重建后,依然可以使用之前的数据。但是显然存储资源和 CPU 资源以及内存资源有很大不同,为了屏蔽底层的技术实现细节,让用户更加方便的使用,Kubernetes 便引入了 PVPVC 两个重要的资源对象来实现对存储的管理。

Kuberntes Volume

Kubernetes 和 Docker 类似,也是通过 Volume 的方式提供对存储的支持。Volume 被定义在 Pod 上,可以被 Pod 里的多个容器挂载到相同或不同的路径下。Kubernetes 中 Volume 的 概念与Docker 中的 Volume 类似,但不完全相同。具体区别如下:

  • Kubernetes 中的 Volume 与 Pod 的生命周期相同,但与容器的生命周期不相关。当容器终止或重启时,Volume 中的数据也不会丢失。

  • 当 Pod 被删除时,Volume 才会被清理。并且数据是否丢失取决于 Volume 的具体类型,比如:emptyDir 类型的 Volume 数据会丢失,而 PV 类型的数据则不会丢失。

Kubernetes 卷具有明确的生命周期——与包裹它的 Pod 相同。 因此,卷比 Pod 中运行的任何容器的存活期都长,在容器重新启动时数据也会得到保留。 当然,当一个 Pod 不再存在时,卷也将不再存在。 也许更重要的是,Kubernetes 可以支持许多类型的卷,Pod 也能同时使用任意数量的卷。

卷的核心是包含一些数据的目录,Pod 中的容器可以访问该目录。 特定的卷类型可以决定这个目录如何形成的,并能决定它支持何种介质,以及目录中存放什么内容。

使用卷时, Pod 声明中需要提供卷的类型 (.spec.volumes 字段)和卷挂载的位置 (.spec.containers.volumeMounts 字段).

Kubernetes 目前支持多种 Volume 类型,最新数据可以查看官网,大致如下:

注:这些 Volume 并非全部都是持久化的,比如: emptyDir 等,就会随着 Pod 的消亡而消失。

概念

PV

PV 的全称是:PersistentVolume(持久化卷)。PersistentVolume 是 Volume 的一种类型,是对底层的共享存储的一种抽象。PV 由集群管理员进行创建和配置,就像节点 (Node) 是集群中的资源一样,PV 也是集群资源的一种。PV 包含存储类型、存储大小和访问模式。PV 的生命周期独立于 Pod,例如:当使用它的 Pod 销毁时对 PV 没有影响。

PersistentVolume 通过插件机制实现与共享存储的对接。Kubernetes 目前支持以下插件类型:

  • GCEPersistentDisk

  • AWSElasticBlockStore

  • AzureFile

  • AzureDisk

  • CSI

  • 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

PVC

PVC 的全称是:PersistentVolumeClaim(持久化卷声明),PVC 是用户对存储资源的一种请求。PVC 和 Pod 比较类似,Pod 消耗的是节点资源,PVC 消耗的是 PV 资源。Pod 可以请求 CPU 和内存,而 PVC 可以请求特定的存储空间和访问模式。对于真正使用存储的用户不需要关心底层的存储实现细节,只需要直接使用 PVC 即可。

但是通过 PVC 请求到一定的存储空间也很有可能不足以满足应用对于存储设备的各种需求,而且不同的应用程序对于存储性能的要求可能也不尽相同,比如读写速度、并发性能等,为了解决这一问题,Kubernetes 又为我们引入了一个新的资源对象:StorageClass,通过 StorageClass 的定义,管理员可以将存储资源定义为某种类型的资源,比如快速存储、慢速存储等,用户根据 StorageClass 的描述就可以非常直观的知道各种存储资源的具体特性了,这样就可以根据应用的特性去申请合适的存储资源了。关于StorageClass我们将会在下节讲述。

PV的使用

以NFS文件存储为例,IP地址为:100.0.0.50。

PV 作为存储资源,主要包括存储能力、访问模式、存储类型、回收策略等关键信息,下面我们来新建一个 PV 对象,使用 nfs 类型的后端存储,10G 的存储空间,访问模式为 ReadWriteOnce,回收策略为 Recycle,对应的 YAML 文件如下:

 apiVersion: v1
 kind: PersistentVolume
 metadata:
   name:  nfs-pv
 spec:
   capacity:
     storage: 10Gi
   accessModes:
   - ReadWriteOnce
   persistentVolumeReclaimPolicy: Recycle
   nfs:
     path: /
     server: 100.0.0.50

我们来分别对上面的属性进行一些解读。

Capacity(存储能力)

一般来说,一个 PV 对象都要指定一个存储能力,通过 PV 的 capacity属性来设置的,目前只支持存储空间的设置,就是我们这里的 storage=10Gi,不过未来可能会加入 IOPS、吞吐量等指标的配置。

AccessModes(访问模式)

AccessModes 是用来对 PV 进行访问模式的设置,用于描述用户应用对存储资源的访问权限,访问权限包括下面几种方式:

  • ReadWriteOnce(RWO):读写权限,但是只能被单个节点挂载

  • ReadOnlyMany(ROX):只读权限,可以被多个节点挂载

  • ReadWriteMany(RWX):读写权限,可以被多个节点挂载

注意:一些 PV 可能支持多种访问模式,但是在挂载的时候只能使用一种访问模式,多种访问模式是不会生效的。

persistentVolumeReclaimPolicy(回收策略)

我这里指定的 PV 的回收策略为 Recycle,目前 PV 支持的策略有三种:

  • Retain(保留)- 保留数据,需要管理员手工清理数据

  • Recycle(回收)- 清除 PV 中的数据,效果相当于执行 (rm -rf /thevolume/*)

  • Delete(删除)- 与 PV 相连的后端存储完成 volume 的删除操作,当然这常见于云服务商的存储服务,比如 AWS EBS, GCE PD, Azure Disk, and Cinder。

不过需要注意的是,目前只有 NFS 和 HostPath 两种类型支持回收策略。当然一般来说还是设置为 Retain 这种策略保险一点。

状态

一个 PV 的生命周期中,可能会处于4中不同的阶段:

  • Available(可用):表示可用状态,还未被任何 PVC 绑定

  • Bound(已绑定):表示 PV 已经被 PVC 绑定

  • Released(已释放):PVC 被删除,但是资源还未被集群重新声明

  • Failed(失败): 表示该 PV 的自动回收失败

PVC的使用

新建PVC

同样的,我们来新建一个数据卷声明,我们来请求 10Gi 的存储容量,访问模式也是 ReadWriteOnce,YAML 文件如下:(nfs-pvc.yaml)

 kind: PersistentVolumeClaim
 apiVersion: v1
 metadata:
   name: nfs-pvc
 spec:
   accessModes:
     - ReadWriteOnce
   resources:
     requests:
       storage: 10Gi

这时 pvc-nfs 创建成功了,状态是 Bound 状态了,这个时候我们再看下 PV 的状态,也变成 Bound 状态了。

其实这是系统自动帮我们去匹配的,他会根据我们的声明要求去查找处于 Available 状态的 PV,如果没有找到的话那么我们的 PVC 就会一直处于 Pending 状态,找到了的话当然就会把当前的 PVC 和目标 PV 进行绑定,这个时候状态就会变成 Bound 状态了。

这里要注意的一点是,如果PV的容量比PVC的大,是可以绑定的,并且使用的是PV申请的容量,反之不可以。

使用PVC

上面我们已经知道怎么创建 PV 和 PVC 了,现在我们就来使用下我们的 PVC,这里我们同样使用之前的 nginx 的镜像来测试下:(nfs-nginx-deployment.yaml)

 apiVersion: extensions/v1beta1
 kind: Deployment
 metadata:
   name: nginx
 spec:
   replicas: 2
   selector:
     matchLabels:
       app: nginx  
   template:
     metadata:
       labels:
         app: nginx
     spec:
       containers:
       - name: nginx
         image: nginx:latest
         imagePullPolicy: IfNotPresent
         ports:
         - containerPort: 80
           name: web
         volumeMounts:
         - name: www
           mountPath: /usr/share/nginx/html
       volumes:
       - name: www
         persistentVolumeClaim:
           claimName: nfs-pvc

PV和PVC的状态变化

pv_and_pvc_status

注意事项

  1. 如果数据非常重要,不能删除,那么你在删除PVC的时候,需要注意不能自动回收了PV里面的数据。

  2. PVC中的访问模式设置为ReadWriteOnce时,如果有POD关联,则创建 Pod 挂载此 PVC 时会出现失败。

  3. 如果PV的persistentVolumeReclaimPolicy是Retain,那么在PVC删除后,PV的状态为Released。那么可以通过编辑该PV的yaml,将spec.claimRef字段删除,PV的状态就会变成Available,可以被新的PVC重新绑定了。

参考

Kubernetes Volumes

Kubernetes Persistem Volumes

License:  CC BY 4.0