Blog:博客园 个人
参考:Volumes | Kubernetes、Persistent Volumes | Kubernetes、Kubernetes 基础入门实战
简单来说,存储卷是定义在Pod资源之上可被其内部的所有容器挂载的共享目录,该目录关联至宿主机或某外部的存储设备之上的存储空间,可由Pod内的多个容器同时挂载使用。Pod存储卷独立于容器自身的文件系统,因而也独立于容器的生命周期,它存储的数据可于容器重启或重建后继续使用。
存储卷并非Kubernetes上一种独立的API资源类型,它隶属于Pod资源,且与所属的特定Pod对象有着相同的生命周期。
PV(PersistentVolume)与PVC(PersistentVolumeClaim)就是在用户与存储服务之间添加的一个中间层,管理员事先根据PV支持的存储卷插件及适配的存储方案(目标存储系统)细节定义好可以支撑存储卷的底层存储空间,而后由用户通过PVC声明要使用的存储特性来绑定符合条件的最佳PV定义存储卷,从而实现存储系统的使用与管理职能的解耦,大大简化了用户使用存储的方式。
前置知识
关于卷(Volume)
Container 中的文件在磁盘上是临时存放的,这给 Container 中运行的较重要的应用程序带来一些问题。 问题之一是当容器崩溃时文件丢失。 kubelet 会重新启动容器,但容器会以干净的状态(clean state)重启。 第二个问题会在同一 Pod 中运行多个容器并共享文件时出现。 Kubernetes 卷(Volume)这一抽象概念能够解决这两个问题。
Docker 也有卷(Volume) 的概念,但对它只有少量且松散的管理。 Docker 卷是磁盘上或者另外一个容器内的一个目录。 Docker 提供卷驱动程序,但是其功能非常有限。
Kubernetes 支持很多类型的卷。 Pod 可以同时使用任意数目的卷类型。 临时卷类型的生命周期与 Pod 相同,但持久卷可以比 Pod 的存活期长。 当 Pod 不再存在时,Kubernetes 也会销毁临时卷;不过 Kubernetes 不会销毁持久卷。 对于给定 Pod 中任何类型的卷,在容器重启期间数据都不会丢失。
卷的核心是一个目录,其中可能存有数据,Pod 中的容器可以访问该目录中的数据。 所采用的特定的卷类型将决定该目录如何形成的、使用何种介质保存数据以及目录中存放的内容。
概述
kubernetes 抽象出来了几个 Resource 概念:
-
PersistentVolumeClaim:简称 PVC,用于描述应用对存储资源的需求,比如大小等。 -
PersistentVolume:简称 PV,提供具体的存储,跟具体环境有关。比如 Hostpath、GCE PD、Azure Disk、AWS EBS 等资源。 -
StorageClass:存储类。PV 是静态创建好的存储资源,StorageClass 是描述了生成 PV 的方法,可以用于动态地创建 PV,也与具体环境有关。
可以看到,Kubernetes 的 Volume 架构是分层的,将存储的使用者与提供者解耦。这样更贴合一般的使用场景,因为一般的环境中,会有不同的使用者存在,主要有以下两类:
- 管理者:比如运维人员、系统管理员,负责具体的底层设施的维护。
- 使用者:普通的开发测试人员等,是这些资源的使用者。
角色的分工就对应着资源的分工。前者管理比较重量级的 PV / StorageClass 等资源,配置参数,调整大小等,后者只需提出存储需求。
同时要注意的是,PersistentVolume / StorageClass 是一个 cluster 级别的资源,不属于任何的 namespace,而 PVC 属于对应的 namespace。这也对应着上面的分工,比较重量级的、与环境关系密切的,属于 cluster 级别的资源,而与环境关系不大,轻量级的则属于 namespace 级别的资源,也方便迁移。
配合这种 Volume 架构的最常见的 Workload 是 StatefulSet,与 DaemonSet 和 Deployment 不同的是,StatefulSet 在设计之初就是面向有状态服务的,它有以下特点:
- Pod 的启动和停止都是有序的,不是并行的。
- 每个 Pod 有自己的标示。像 DaemonSet 和 Deployment 管理的 Pod 都以随机数做后缀,但 StatefulSet 是以 -0,-1 为后缀。
- 搭配 Headless Service,每个 Pod 也有自己的固定的域名,可以单独访问。
有状态服务大多都是不对称架构(不同的实例的角色不一样),StatefulSet 的特性就是为了解决此问题而生。
PV
PV(PersistentVolume)是由集群管理员于全局级别配置的预挂载存储空间,它通过支持的存储卷插件及给定的配置参数关联至某个存储系统上可用数据存储的一段空间,这段存储空间可能是Ceph存储系统上的一个存储映像、一个文件系统(CephFS)或其子目录,也可能是NFS存储系统上的一个导出目录等。PV将存储系统之上的存储空间抽象为Kubernetes系统全局级别的API资源,由集群管理员负责管理和维护。
目前,存储大小是可以设置和请求的唯一资源。 未来可能会包含 IOPS、吞吐量等属性。
类型
PV 持久卷是用插件的形式来实现的。Kubernetes 目前支持以下插件:
- awsElasticBlockStore - AWS 弹性块存储(EBS)
- azureDisk - Azure Disk
- azureFile - Azure File
- cephfs - CephFS volume
- csi - 容器存储接口 (CSI)
- fc - Fibre Channel (FC) 存储
- gcePersistentDisk - GCE 持久化盘
- glusterfs - Glusterfs 卷
- hostPath - HostPath 卷 (仅供单节点测试使用;不适用于多节点集群; 请尝试使用 local 卷作为替代)
- iscsi - iSCSI (SCSI over IP) 存储
- local - 节点上挂载的本地存储设备
- nfs - 网络文件系统 (NFS) 存储
- portworxVolume - Portworx 卷
- rbd - Rados 块设备 (RBD) 卷
- vsphereVolume - vSphere VMDK 卷
Volume Mode
针对 PV 持久卷,Kubernetes 支持两种卷模式(volumeModes):Filesystem(文件系统) 和 Block(块)。 volumeMode 是一个可选的 API 参数。 如果该参数被省略,默认的卷模式是 Filesystem。
volumeMode 属性设置为 Filesystem 的卷会被 Pod 挂载(Mount) 到某个目录。 如果卷的存储来自某块设备而该设备目前为空,Kuberneretes 会在第一次挂载卷之前 在设备上创建文件系统。
你可以将 volumeMode 设置为 Block,以便将卷作为原始块设备来使用。 这类卷以块设备的方式交给 Pod 使用,其上没有任何文件系统。 这种模式对于为 Pod 提供一种使用最快可能方式来访问卷而言很有帮助,Pod 和 卷之间不存在文件系统层。
访问模式
PersistentVolume 卷可以用资源提供者所支持的任何方式挂载到宿主系统上。 如下表所示,提供者(驱动)的能力不同,每个 PV 卷的访问模式都会设置为 对应卷所支持的模式值。 例如,NFS 可以支持多个读写客户,但是某个特定的 NFS PV 卷可能在服务器 上以只读的方式导出。每个 PV 卷都会获得自身的访问模式集合,描述的是 特定 PV 卷的能力。
访问模式有:
-
ReadWriteOnce:卷可以被一个节点以读写方式挂载。 ReadWriteOnce 访问模式也允许运行在同一节点上的多个 Pod 访问卷。 -
ReadOnlyMany:卷可以被多个节点以只读方式挂载。 -
ReadWriteMany:卷可以被多个节点以读写方式挂载。 -
ReadWriteOncePod:卷可以被单个 Pod 以读写方式挂载。 如果你想确保整个集群中只有一个 Pod 可以读取或写入该 PVC, 请使用ReadWriteOncePod 访问模式。这只支持 CSI 卷以及需要 Kubernetes 1.22 以上版本。
在命令行接口(CLI)中,访问模式也使用以下缩写形式:
- RWO - ReadWriteOnce
- ROX - ReadOnlyMany
- RWX - ReadWriteMany
- RWOP - ReadWriteOncePod