Persistent Volume(持久卷)
PersistentVolume(持久卷)
https://kubernetes.io/docs/concepts/storage/persistent-volumes/ kubernetes 的 volume 有一个问题就是不够灵活,且使用 volume 的用户必须要明确知道要使用的 volume 后端是用的什么类型的存储系统(例如 NFS 就需要配置 IP 和 PATH)。这与 kubernetes 的向用户和开发隐藏底层架构的目的有所背离,对存储资源最好的使用方式是能向计算资源一样,用户和开发人员无需了解 pod 资源究竟运行于哪个节点,也无需了解存储系统是什么类型的设备以及位于何处。他们只需要提出容量大小的需求(i.e.PVC),k8s 管理员可以为其分配所需的空间。这就是 PV 与 PVC 的作用,抽象了底层的存储,使得存储系统的使用和管理两个职能互相解耦。这就好比创建一台虚拟机,并需求 20G 的存储空间,然后虚拟机管理系统就会自动创建出来,而不用去手动指定使用哪个存储空间了。
PersistentVolume(持久卷,简称 PV) 与 PersistentVolumeClaims(持久卷申请,简称 PVC) 是 kubernetes 中的一个 Resource(资源),PVC 与 volume 不同,volume 的定义需要写进 Pod 的 manifest 中。而 PVC 对于 volume 来说就是一种 “volume 的类型”。
- PV 就相当于虚拟机中的存储卷,虚拟了宿主机或者远程存储的存储资源。PVC 就相当于虚拟机里的一个物理磁盘。虚拟机里的磁盘其实就是通过存储卷来实现的,这与 PV 与 PVC 的关系基本一致。而下文讲的 StorageClass(存储类) 则相当于虚拟机中的存储池的概念了。
- PV 与 PVC 为用户和管理员提供了一个 API 接口,抽象定义了存储的消费者-生产者模型(即从 k8s 系统来说,管理员使用 PV 生产一个 storage 资源,用户使用 PVC 消费一个 storage 资源)
PV 与 PVC 的生命周期
PV 是集群中的资源。 PVC 是对这些资源的请求,并且还充当对资源的声明检查。 PV 和 PVC 之间的交互遵循以下生命周期:
- Provisioning(供应)
- Binding(绑定)
- Using(使用)
- Storage Object in User(保护使用中存储对象)
- Protection(回收)
- Reserving a PersistentVolume(预留 PV)
- Expanding Persistent Volumes Claims(扩充 PVC 申领)
PV、PVC 在 Pod 中实现方式简述:
PV 与 PVC 的工作流程:Container—Volume—PVC—PV—StorageResource
- 创建 PV 资源类型的对象,每个 PV 包括几个属性:名字、capacity(容量)、reclaim policy(回收策略) 等等
- 创建 PVC 资源类型的对象,每个 PVC 中包括几个属性:会话模式、名字、所需求的容量的大小等等
- 当 PVC 创建后,会自动选择一个满足 PVC 所需求容量的最小 PV 来与 PVC 进行绑定,此时 PV 的状态变为 bond
- 创建 Pod,在 Pod 中定义 Volume 类型为 PVC,并指定 PVC 名字以选择一个 PVC 挂载上来,然后在 container 中指定要挂载的 volume 名以及在 container 中的挂载路径
Provisioning(供应)
Provisioning(供应) 就是指供应 PV,也就是创建 PV 的意思
可以通过两种方式创建 PV:statically(静态地) 或 dynamically(动态地)
- Static(静态) # 手动编写 PV 的 manifest,并 apply 到集群中。
- Dynamic(动态) # 当管理员创建的所有 Statci PV(静态 PV) 都不匹配用户的 PVC 时,集群将会尝试为 PVC 动态地提供一个卷
- 这种动态供应必须基于 StorageClasses:PVC 必须配置指定的 StorageClass,并且集群必须存在与 PVC 配置的同名的 StorageClass,才能进行动态供应。
- 在声明一个 PVC 对象时,如果 manifest 中 storageClassName 字段为空,则该声明会禁用动态供应。除非集群中有一个默认的 StorageClass。
Binding(绑定)
Using(使用)
Storage Object in User Protection(保护使用中存储对象)
Reclaiming(回收)
当删除 PVC 后,与之关联的 PV 会变为 Released(已释放) 状态。此时,控制器根据一个**Reclaim Policy(回收策略)**来处理已释放的 PV。目前, 回收策略包括三种:
- Retained(保留)
- Recycled(回收)
- Deleted(删除)。
也就是说,PV 可以进行这三种处理方式。
Reserving a PersistentVolume(预留 PV)
Expanding Persistent Volumes Claims(扩充 PVC 申领)
动态 PV 交互流程

- 用户创建一个包含 PVC 的 Pod
- PV Controller 会观察 ApiServer,如果它发现一个 PVC 已经创建完毕但仍然是未绑定的状态,它就会试图把一个 PV 和 PVC 绑定
- Provision 就是从远端上一个具体的存储介质创建一个 Volume,并且在集群中创建一个 PV 对象,然后将此 PV 和 PVC 进行绑定
- Scheduler 进行多个维度考量完成后,把 Pod 调度到一个合适的 Node
- Kubelet 不断 watch APIServer 是否有 Pod 要调度到当前所在节点
- Pod 调度到某个节点之后,它所定义的 PV 还没有被挂载(Attach),此时 AD Controller 就会调用 VolumePlugin,把远端的 Volume 挂载到目标节点中的设备上(/dev/vdb);当 Volum Manager 发现一个 Pod 调度到自己的节点上并且 Volume 已经完成了挂载,它就会执行 mount 操作,将本地设备(也就是刚才得到的/dev/vdb)挂载到 Pod 在节点上的一个子目录中
- 启动容器,并将已经挂载到本地的 Volume 映射到容器中
PV、PVC 的 manifest 样例
一个简单的创建 PV、PVC,然后 pod 使用 PVC 的实例
https://kubernetes.io/docs/concepts/storage/persistent-volumes/#persistent-volumes 该链接下有 PV 的每个键值对的解释
https://kubernetes.io/docs/concepts/storage/persistent-volumes/#persistentvolumeclaims 该链接下有 PVC 的每个键值对的机制
注意:
- storageClassName 相当于 PV 的一个标签,当 PVC 申请的时候,只会选择具有相同 storageClassName 的 PV 来绑定,如果集群中存在 StorageClass 资源的话,则会在对应的 StorageClass 中创建该 PV。该参数的值可以为空,如果不指定 StorageClass,则 PVC 也不能指定,才会绑定到该 PV 上。此时 PV 不使用任何 StorageClass。StorageClass 概念详见:Storage Classes 存储类
该示例先创建 PV,然后创建 PVC,最后让 pod 使用该 PVC,node-1.tj-test 节点上 /opt/myapp 目录会挂载到容器中的 /persistentVolume 目录上
apiVersion: v1
kind: PersistentVolume
metadata:
labels:
app: myapp
name: myapp-pv
spec:
accessModes:
- ReadWriteOnce
capacity:
storage: 10Gi
local:
path: /opt/myapp
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- node-1.tj-test
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: myapp-pvc
labels:
app: myapp
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
selector:
matchLabels:
app: myapp
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
labels:
name: myapp
spec:
replicas: 1
selector:
matchLabels:
name: myapp
template:
metadata:
name: myapp
labels:
name: myapp
spec:
containers:
- name: myapp
image: lchdzh/network-test
volumeMounts:
- mountPath: "/persistentVolume"
name: myapp-pvc
volumes:
- name: myapp-pvc
persistentVolumeClaim:
claimName: test-claim
反馈
此页是否对你有帮助?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.