Kubernetes 持久化存储解密:PV 和 PVC 的工作原理与实践
我们都知道,在 Kubernetes 这个动态环境中,Pods 可以被创建、销毁并在多个节点之间移动。这引出了一个问题:如何在这种动态环境中处理存储呢?答案就在 Kubernetes 的 PV(Persistent Volume)和 PVC(Persistent Volume Claim)。
PV 和 PVC 的重要性
在 Kubernetes 中,PV 是在集群中提供给用户使用的存储资源的抽象,就像一种云上的硬盘。而 PVC 则是用户对这些资源的请求或申请,就像租赁一块硬盘。
这种设计策略是一种很明智的区分:PV 是供应方的角色,是管理员的事情,管理集群内的实际存储资源。而 PVC 则是消费方的角色,是用户或开发者的事情,他们只需要关心如何消费这些存储资源。
PV 和 PVC 的工作原理
PV 在 Kubernetes 中是集群级别的资源,具有以下特性:
PV 不受 Pod 生命周期限制:当删除与 PV 对象关联的 Pod 时,PV 仍然存在。
PV 在故障中仍然存在:当 Pod 崩溃时,PV 仍然在集群中存在。
PV 是集群范围的:PV 可以附加到在集群中运行的任何 Pod。
PV 支持三种访问模式:
ReadWriteOnce(单节点读写)
ReadOnlyMany(多节点只读)
ReadWriteMany(多节点读写)
PV 和 PVC 的交互过程可以分为两部分:静态供应和动态供应。
静态供应:
对于 PVC,开发者在其应用的配置文件中创建一个 PVC,其中指定了所需的存储大小和访问模式。Kubernetes 会查找符合这些要求的 PV 并将其与 PVC 绑定。这被称为静态供应。静态供应需要管理员先创建 PV,然后用户通过 PVC 来申请使用 PV。这个过程就像管理员为用户准备了一系列的储物柜(PV),用户则通过储物柜钥匙(PVC)来申请使用这些储物柜。
然而,当集群规模扩大,手动创建 PV 和 PVC 可能变得复杂和繁琐。为了解决这个问题,Kubernetes 提供了动态供应。动态供应中,PV 的创建将被自动化。当创建 PVC 时,PV 将自动在后台创建。Kubernetes 使用另一个叫做 Storage Class 的对象来实现这一点。
动态供应:
动态供应则更为方便,它不需要管理员事先创建 PV。当用户创建 PVC 时,Kubernetes 会自动为这个 PVC 创建一个满足其请求的 PV。这就好比你走到一个储物柜前,自动售货机会根据你的需求,为你现场制造一个储物柜。
Kubernetes PV 和 PVC 的源码实现
Kubernetes 的源代码在 GitHub 上开源,你可以在 pkg/controller/volume
目录下找到 PV 和 PVC 的实现。其中,persistentvolume
子目录是 PV 和 PVC 的核心实现。
源码中的 pv_controller.go
是 PV 和 PVC 控制器的主要实现,它监听 PVC 和 PV 的事件,并根据事件类型执行相应的操作。这种事件驱动的设计是 Kubernetes 控制器的典型模式,也是其能够自动化管理资源的关键。
对于静态供应,PV 和 PVC 控制器会在 PVC 创建时寻找满足其要求的 PV。如果找到了,则会将 PVC 和 PV 绑定,否则 PVC 将一直处于等待状态。
对于动态供应,PV 和 PVC 控制器会在 PVC 创建时,检查是否存在满足其要求的 PV,如果没有,并且 PVC 定义了 Storage Class,则会根据 Storage Class 动态创建一个 PV。
PV 和 PVC 的实践使用
那么,如何在实际中使用 PV 和 PVC 呢?让我们通过一个例子来看。
假设我们要创建一个名为 my-pv
的 PV,存储大小为 10Gi,访问模式为 ReadWriteOnce。我们可以创建以下 PV 资源:
apiVersion: v1
kind: PersistentVolume
metadata:
name: my-pv
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
hostPath:
path: /data/my-pv
然后,我们要创建一个 PVC 来申请这个 PV:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-pvc
spec:
resources:
requests:
storage: 10Gi
accessModes:
- ReadWriteOnce
创建这两个资源后,Kubernetes 就会自动将 PVC my-pvc
和 PV my-pv
绑定。现在,我们就可以在 Pod 中通过这个 PVC 来使用存储空间了。
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
volumes:
- name: my-storage
persistentVolumeClaim:
claimName: my-pvc
containers:
- name: my-container
image: nginx
volumeMounts:
- mountPath: /data
name: my-storage
结论
通过使用 PV 和 PVC,Kubernetes 提供了一种简单且灵活的方法来在动态环境中处理存储问题。而且,通过查看 Kubernetes 的源码,我们可以深入理解其工作原理,进一步提升我们的 Kubernetes 技能。
参考资料: