PersistentVolume(PV)和PersistentVolumeClaim(PVC)
这两个概念用于pod和volume之间解耦。Pod根据自己的需要提出数据卷的申请,k8s系统将符合条件的数据卷返回给pod。这样一来pod就无需直接和数据卷本身强绑定了。Pod无需知道数据卷的细节信息,比如具体用的是什么存储。
Pod中对数据卷的申请为PVC,用来和PVC绑定的数据卷称为PV。
PV可以有多种存储方式,比如NFS,iSCSI等。
PVC是使用PV资源的声明。
PVC和PV的关系是一对一的, 不能将多个PVC绑定到同一个PV上.PV和PVC的生命周期
供应阶段
PV有两种供应方式
- static 静态方式由系统管理员创建PV
- dynamic 如果没有静态的PV。系统会动态创建出PV来满足PVC。PV的提供者为StorageClass。要使用动态供应,PVC必须要指定一个StorageClass。如果StorageClass设置为空,那么针对这个PVC的动态供应特性会被禁用。
绑定阶段
这个阶段指的是PV和PVC绑定的过程。系统有一个机制,循环检查新创建的PVC,然后找到一个符合条件的PV,把他们绑定到一起。如果有多个满足要求的PV可以绑定,会使用消耗资源最小的那个。PV和PVC之间是一对一的关系。如果找不到符合条件的PV,PVC会一致保持未绑定状态。
使用阶段
PVC绑定合适的PV之后,Pod使用这个PV。和PVC绑定并处于使用状态的PV不会被系统删除,防止数据丢失。
如果用户删除了Pod正在使用的PVC,这个PVC不会被立即移除。直到这个PVC不被任何Pod时候的时候,才会被真正的删除。
重新声明阶段
当PV不再使用的时候,k8s根据不同的策略来回收这些PV。
Retain
Retain策略在volume不再使用的时候,不删除旧的数据,等待管理员处理。
Delete
Delete策略会删除不再使用的PV,同时删除这些PV对应真实存储的资源。
Recycle(已废弃)
删除volume内的内容,使得volume可供下次使用。
PV描述文件
1 | apiVersion: v1 |
PV的属性
Capacity
PV的容量
VolumeMode
可以使用Filesystem或者Block。Filesystem为默认值。
AccessModes
具有如下可选值:
- ReadWriteOnce:可以被一个node读写。缩写为RWO。
- ReadOnlyMany:可以被多个node读取。缩写为ROX。
- ReadWriteMany:可以摆多个node读写。缩写为RWX。
Class
配置storageClassName。
storage class, 如果使用k3s, rancher lab默认为我们提供了一个local-path, 如果不填写storageClassName, 则默认就是它
1 | [root@VM-33-122-centos ~]# kubectl get storageclasses.storage.k8s.io |
Reclaim Policy
可以使用如下回收策略:
- Retain 手工回收
- Recycle (rm -rf /thevolume/*)
- Delete 删除相关Volume
Mount Options
可以指定存储的类型。
Node Affinity
Local volume必须要设定这个属性。该属性规定了volume可以通过哪些node访问。
PV的阶段(Phase)
- Available:可用状态,没有被任何PVC绑定。
- Bound:已绑定到了PVC。
- Released:PVC已删除,但是资源没有被集群回收。
- Failed:PV自动回收失败。
PVC的描述文件
pv和pvc的绑定规则
当 PVC 绑定 PV 时,需考虑以下参数来筛选当前集群内是否存在满足条件的 PV
| 参数 | 描述 |
|---|---|
| VolumeMode | 主要定义 volume 是文件系统(FileSystem)类型还是块(Block)类型,PV 与 PVC 的 VolumeMode 标签必须相匹配。 |
| Storageclass | PV 与 PVC 的 storageclass 类名必须相同(或同时为空)。 |
| AccessMode | 主要定义 volume 的访问模式,PV 与 PVC 的 AccessMode 必须相同。 |
| Size | 主要定义 volume 的存储容量,PVC 中声明的容量必须小于等于 PV,如果存在多个满足条件的 PV,则选择最小的 PV 与 PVC 绑定。 |
1 | apiVersion: v1 |
PVC的配置参数
AccessModes
访问模式。和PV相同。
VolumeMode
volume的挂载模式,可以为Filesystem或block。
Resources
约定声明PV的大小等参数。
Selector
用于限制volume,只有label匹配的volume才能绑定到PVC上。可以使用matchLabels或者matchExpressions来约束。
Class
用于实现动态供给。只有StorageClassName相同的PV和PVC才能够绑定到一起。如果PVC的StorageClassName设置为"",那么它只会和StorageClassName也为""的PV绑定到一起。
创建StorageClass的时候如果将它的storageclass.kubernetes.io/is-default-class annotation设置为true,那么此StorageClass会成为默认的StorageClass。如果PVC没有指定StorageClassName,那么它会和StorageClassName为默认StorageClass的PV绑定到一起。当然,使用这个特性必须要开启DefaultStorageClass的admission plugin。
如果没有启动这个admission plugin。没有指定StorageClass的PVC只能和没有指定StorageClass的PV绑定在一起。没有指定StorageClass和设置StorageClass的值为"",含义是相同的。
在Pod中使用PVC
1 | apiVersion: v1 |
LocalPersistentVolume
这种类型的PV把数据储存在集群中某个节点上。
1 | apiVersion: v1 |
注意:nodeAffinity属性是必须要指定的,因为local模式一定要确定数据保存在哪个机器。
对应StorageClass如下:
1 | kind: StorageClass |
StorageClass
样例
- 以下创建一个使用 hostpath 的底层存储的 StorageClass
1 | apiVersion: storage.k8s.io/v1 |
- 之后就可以在 PVC(PersistentVolumeClaim)中使用它
1 | apiVersion: v1 |
当 PVC 创建成功后,Kubernetes 将会自动为其创建一个 PV(PersistentVolume)。PV 是集群中的实际存储资源,用于满足 PVC 的请求。Kubernetes 会根据 storageClass 的配置,选择一个满足 PVC 要求的 PV。如果没有可用的 PV,则 Kubernetes 将会自动创建一个 PV。如果在创建 PVC 后,Kubernetes 没有自动创建 PV,可能原因如下
没有配置动态存储卷。如果集群中没有配置动态存储卷,Kubernetes 就无法根据 PVC 的需求自动创建 PV。在这种情况下,需要手动创建 PV,并将其绑定到 PVC 上。
没有合适的 PV 可用。如果没有已经存在的 PV 能够满足 PVC 的需求,并且也没有配置动态存储卷,Kubernetes 就无法自动创建 PV。在这种情况下,可以手动创建一个 PV,并将其绑定到 PVC 上。如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15apiVersion: v1
kind: PersistentVolume
metadata:
name: prometheus-pv
spec:
accessModes:
- ReadWriteOnce
capacity:
storage: 50Gi
hostPath:
path: /var/data/prometheus
type: DirectoryOrCreate
persistentVolumeReclaimPolicy: Retain
storageClassName: prometheus-store
volumeMode: Filesystem
将创建的 PVC 绑定到 Pod 中。可以通过在 Pod 的 YAML 文件中指定
volumes和volumeMounts字段来完成。例如,以下 YAML 文件创建了一个 Pod,并将prometheus-pvcPVC 挂载到了容器的/data目录:
1 | yamlCopy codeapiVersion: v1 |
需要注意的是,使用 hostpath 存储有一些限制,因为它仅在单个节点上工作,并且不能在 Pod 迁移时保留数据。如果需要在生产环境中使用持久化存储,建议考虑使用更稳定和可靠的解决方案,例如 NFS 或 AWS EBS 等。
Provisioner(供应者)
Kubernetes 中自带的 Provisioner有以下类型
kubernetes.io/aws-ebs:用于提供 AWS Elastic Block Store(EBS)存储。kubernetes.io/gce-pd:用于提供 Google Compute Engine(GCE)Persistent Disk(PD)存储。kubernetes.io/glusterfs:用于提供 GlusterFS 存储。kubernetes.io/nfs:用于提供 NFS 存储。kubernetes.io/rbd:用于提供 Ceph RBD 存储。kubernetes.io/cinder:用于提供 OpenStack Cinder 存储。kubernetes.io/azure-disk:用于提供 Azure Disk 存储。kubernetes.io/azure-file:用于提供 Azure File 存储。
使用这些自带的 Provisioner,可以轻松地将不同类型的存储资源集成到 Kubernetes 集群中,从而为应用程序提供持久化存储支持。需要注意的是,不同的 Provisioner 支持的存储类型和功能也不同,应该选择最适合您的应用程序和环境的 Provisioner。
K3s
如果使用k3s, rancher lab默认为我们提供了一个local-path(local-path只有ReadWriteOnce的权限)
1 | [root@VM-33-122-centos ~]# kubectl get storageclasses.storage.k8s.io |
rancher.io/local-path 和 kubernetes.io/host-path的区别
rancher.io/local-path 和 kubernetes.io/host-path 都是 Kubernetes 中用于提供基于主机路径的存储的 Provisioner,它们的原理和功能类似,都是在宿主机上创建一个目录,用于提供持久化存储。
不过,rancher.io/local-path 和 kubernetes.io/host-path 在实现细节和特性上有一些不同,具体如下:
- 实现方式:
kubernetes.io/host-path是 Kubernetes 原生的 Provisioner,由 Kubernetes 组件直接实现;而rancher.io/local-path则是 Rancher 自己开发的 Provisioner,基于 hostPath 的 PVC Controller 实现。 - 特性支持:相较于
kubernetes.io/host-path,rancher.io/local-path支持更多的特性,例如:- 多副本模式:支持在多个节点上创建相同的 PV;
- 动态 PVC 配额:支持为 PVC 动态分配存储空间;
- 数据迁移:支持在 Pod 迁移时将数据迁移到新的宿主机上。
- 安全性:相较于
kubernetes.io/host-path,rancher.io/local-path的安全性更高。由于 Kubernetes 的 hostPath 特性会将宿主机上的目录直接暴露给 Pod,可能存在潜在的安全风险;而rancher.io/local-path则使用了一些安全措施,例如通过 Kubernetes Secret 来存储目录的访问控制信息,从而降低了安全风险。
综上所述,rancher.io/local-path 在实现细节和特性上都比 kubernetes.io/host-path 更为灵活和安全,因此建议在 Rancher 环境中使用 rancher.io/local-path。
StorageClass 的选择和 PV/PVC 的绑定关系
StorageClass 的选择与 PV/PVC 之间的绑定关系见下图:
