Kubernetes 上的持久卷(PV)与持久卷声明(PVC)

好的,各位观众老爷,大家好!我是你们的老朋友,人称“代码诗人”的程序猿小P。今天,咱们不聊风花雪月,不谈人生理想,就来聊聊 Kubernetes 里面那些“持久”的家伙们——Persistent Volume (PV) 和 Persistent Volume Claim (PVC)。

相信很多小伙伴刚接触 Kubernetes 的时候,都被 PV 和 PVC 搞得晕头转向,感觉就像在绕口令。别担心,今天小P就来用最通俗易懂的语言,把这两个概念给彻底掰开了、揉碎了,让你们彻底明白它们之间的爱恨情仇。

开场白:数据的爱情故事

想象一下,你的 Kubernetes 集群就是一个热闹非凡的“云上公寓”。每个 Pod 都是一个住户,他们需要地方存放自己的数据,就像我们住户需要衣柜、书架一样。

但是,问题来了!Pod 们都是“游牧民族”,随时可能被 Kubernetes 调度到不同的节点上,甚至被直接“踢出公寓”。如果 Pod 的数据直接存在节点本地,那 Pod 搬家后,数据岂不就丢了?这简直就是数据界的“海王行为”啊!

为了解决这个问题,Kubernetes 就引入了 PV 和 PVC 这对“神仙眷侣”,专门负责管理 Pod 的持久化数据。它们就像是公寓里的“公共储物柜”,可以被多个 Pod 共享,而且即使 Pod 搬家或者被“踢出公寓”,储物柜里的东西依然安全无恙。

第一幕:持久卷(PV)——“财大气粗”的储物柜

PV,全称 Persistent Volume,翻译过来就是“持久卷”。它代表着集群中一块已经预置好的存储资源。你可以把它想象成一个“财大气粗”的储物柜,里面装满了各种各样的存储介质,比如硬盘、SSD、网络存储等等。

PV 的特点是:

  • 资源提供者: PV 是由集群管理员或者云平台提前创建好的,它代表着实际的存储资源。
  • 资源描述: PV 描述了存储的容量、访问模式、存储类型等信息,就像储物柜的“使用说明书”。
  • 独立存在: PV 的生命周期独立于 Pod,即使 Pod 被删除,PV 依然存在,数据不会丢失。

PV 的定义通常包含以下几个关键字段:

  • apiVersion: Kubernetes API 版本。
  • kind: 资源类型,这里是 PersistentVolume
  • metadata: PV 的元数据,比如名称(name)。
  • spec: PV 的规格,定义了 PV 的容量、访问模式、存储类型等。
apiVersion: v1
kind: PersistentVolume
metadata:
  name: my-pv
spec:
  capacity:
    storage: 10Gi  # 存储容量为 10GB
  accessModes:
    - ReadWriteOnce  # 访问模式为 ReadWriteOnce,表示只能被一个节点以读写模式挂载
  persistentVolumeReclaimPolicy: Retain  # 回收策略为 Retain,表示删除 PVC 后,PV 不会被自动删除,数据会保留
  storageClassName: standard  # 存储类为 standard
  nfs:  # 使用 NFS 作为存储后端
    path: /data/nfs/my-pv  # NFS 服务器上的路径
    server: nfs-server.example.com  # NFS 服务器的地址

表格:PV 的关键属性

属性 描述
capacity 存储容量,可以使用 Gi、Mi 等单位表示。
accessModes 访问模式,定义了 PV 如何被 Pod 访问。常用的访问模式有:ReadWriteOnce(只能被一个节点以读写模式挂载)、ReadOnlyMany(可以被多个节点以只读模式挂载)、ReadWriteMany(可以被多个节点以读写模式挂载)。
persistentVolumeReclaimPolicy 回收策略,定义了当 PVC 被删除后,PV 如何处理。常用的回收策略有:Retain(保留数据,需要手动清理)、Recycle(简单擦除数据)、Delete(删除 PV,同时删除底层存储资源)。
storageClassName 存储类,用于动态 Provisioning(动态供应),后面会详细介绍。
nfs 如果使用 NFS 作为存储后端,需要指定 NFS 服务器的地址和路径。
hostPath 仅用于开发和测试环境,不建议在生产环境中使用。指定主机上的一个目录作为存储后端。
gcePersistentDisk 如果使用 Google Compute Engine Persistent Disk 作为存储后端,需要指定磁盘的名称。
awsElasticBlockStore 如果使用 Amazon Elastic Block Store 作为存储后端,需要指定 EBS 卷的 ID。

第二幕:持久卷声明(PVC)——“精打细算”的需求清单

PVC,全称 Persistent Volume Claim,翻译过来就是“持久卷声明”。它代表着 Pod 对存储资源的需求。你可以把它想象成一份“精打细算”的需求清单,Pod 通过 PVC 向 Kubernetes 集群声明自己需要多大的存储空间、什么样的访问模式等等。

PVC 的特点是:

  • 资源请求者: PVC 是由 Pod 创建的,它代表着 Pod 对存储资源的需求。
  • 资源描述: PVC 描述了 Pod 需要的存储容量、访问模式、存储类型等信息,就像 Pod 的“购物清单”。
  • 资源绑定: PVC 会和符合条件的 PV 进行绑定,Pod 就可以通过 PVC 来访问 PV 提供的存储资源。

PVC 的定义通常包含以下几个关键字段:

  • apiVersion: Kubernetes API 版本。
  • kind: 资源类型,这里是 PersistentVolumeClaim
  • metadata: PVC 的元数据,比如名称(name)。
  • spec: PVC 的规格,定义了 PVC 请求的存储容量、访问模式、存储类等。
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-pvc
spec:
  accessModes:
    - ReadWriteOnce  # 请求的访问模式为 ReadWriteOnce
  resources:
    requests:
      storage: 5Gi  # 请求的存储容量为 5GB
  storageClassName: standard  # 请求的存储类为 standard

表格:PVC 的关键属性

属性 描述
accessModes 请求的访问模式,必须与 PV 的 accessModes 兼容。
resources.requests.storage 请求的存储容量,可以使用 Gi、Mi 等单位表示。
storageClassName 请求的存储类,用于动态 Provisioning,后面会详细介绍。
selector 用于选择特定的 PV,通常在没有使用存储类的情况下使用。

第三幕:PV 和 PVC 的“一见钟情”

当 PVC 被创建后,Kubernetes 会自动寻找符合 PVC 要求的 PV,并将它们“撮合”在一起,这个过程叫做“绑定”(Binding)。

要让 PV 和 PVC 成功“牵手”,需要满足以下几个条件:

  1. 容量匹配: PV 的容量必须大于或等于 PVC 请求的容量。
  2. 访问模式匹配: PV 的访问模式必须包含 PVC 请求的访问模式。
  3. 存储类匹配: 如果 PVC 指定了存储类,PV 也必须指定相同的存储类。
  4. 选择器匹配: 如果 PVC 指定了选择器,PV 必须满足选择器的条件。

一旦 PV 和 PVC 成功绑定,Pod 就可以通过 PVC 来访问 PV 提供的存储资源了。Pod 只需要在自己的 Volume 定义中指定 PVC 的名称,就可以像访问本地目录一样访问 PV 上的数据。

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
    - name: my-container
      image: nginx
      volumeMounts:
        - name: my-volume
          mountPath: /usr/share/nginx/html  # 将 PV 挂载到容器的 /usr/share/nginx/html 目录下
  volumes:
    - name: my-volume
      persistentVolumeClaim:
        claimName: my-pvc  # 指定使用的 PVC 的名称为 my-pvc

第四幕:动态 Provisioning——“私人订制”的储物柜

前面我们讲的都是静态 Provisioning,也就是集群管理员提前创建好 PV,然后 Pod 通过 PVC 来申请使用这些 PV。但是,这种方式有一个缺点:管理员需要提前预估 Pod 的存储需求,手动创建大量的 PV,非常麻烦。

为了解决这个问题,Kubernetes 引入了动态 Provisioning 的概念。简单来说,就是当 Pod 需要存储资源的时候,Kubernetes 可以自动创建 PV,而不需要管理员手动干预。

动态 Provisioning 的核心是 StorageClass(存储类)。StorageClass 定义了存储资源的类型、Provisioner(存储驱动)以及其他参数。当 PVC 指定了 StorageClass 时,Kubernetes 就会使用 StorageClass 中定义的 Provisioner 来自动创建 PV。

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: my-storage-class
provisioner: kubernetes.io/aws-ebs  # 使用 AWS EBS 作为存储驱动
parameters:
  type: gp2  # EBS 卷的类型为 gp2
  fsType: ext4  # 文件系统类型为 ext4

表格:StorageClass 的关键属性

属性 描述
provisioner 存储驱动,用于创建 PV。Kubernetes 内置了一些常用的存储驱动,比如 kubernetes.io/aws-ebs(AWS EBS)、kubernetes.io/gce-pd(Google Compute Engine Persistent Disk)、kubernetes.io/azure-file(Azure File)等等。
parameters 存储驱动的参数,不同的存储驱动有不同的参数。
reclaimPolicy 回收策略,定义了当 PVC 被删除后,PV 如何处理。可以覆盖 PV 的 persistentVolumeReclaimPolicy 属性。
volumeBindingMode 卷绑定模式,定义了 PV 何时被绑定到 PVC。常用的模式有:Immediate(立即绑定,在 PVC 创建时立即绑定)和 WaitForFirstConsumer(等待第一个消费者,在第一个 Pod 使用 PVC 时才绑定)。

第五幕:回收策略——“好聚好散”的艺术

当 PVC 被删除后,PV 会根据其回收策略(persistentVolumeReclaimPolicy)进行处理。常用的回收策略有三种:

  1. Retain(保留): PV 不会被自动删除,数据会保留。需要手动清理 PV 和底层存储资源。这种策略适用于需要保留数据的场景。
  2. Recycle(回收): PV 会被简单擦除数据,然后可以被新的 PVC 使用。这种策略适用于需要重复利用存储资源的场景。
  3. Delete(删除): PV 会被删除,同时删除底层存储资源。这种策略适用于不需要保留数据的场景。

PV 和 PVC 的状态

  • PV 的状态:
    • Available: PV 可用,可以被 PVC 绑定。
    • Bound: PV 已经和 PVC 绑定。
    • Released: PVC 已经被删除,PV 已经释放,等待回收。
    • Failed: PV 出现错误。
  • PVC 的状态:
    • Pending: PVC 正在等待 PV 绑定。
    • Bound: PVC 已经和 PV 绑定。
    • Lost: PVC 找不到对应的 PV。

总结:PV 和 PVC 的“爱情结晶”

好了,各位观众老爷,说了这么多,相信大家对 PV 和 PVC 已经有了更深入的了解。总结一下,PV 和 PVC 的关系就像这样:

  • PV 是“财大气粗”的储物柜,代表着集群中已经预置好的存储资源。
  • PVC 是“精打细算”的需求清单,代表着 Pod 对存储资源的需求。
  • Kubernetes 负责将符合 PVC 要求的 PV “撮合”在一起,让 Pod 可以通过 PVC 来访问 PV 提供的存储资源。
  • StorageClass 实现了动态 Provisioning,让 Kubernetes 可以自动创建 PV,而不需要管理员手动干预。
  • 回收策略定义了当 PVC 被删除后,PV 如何处理,实现了“好聚好散”的艺术。

代码示例:完整的 PV 和 PVC 示例

# PV
apiVersion: v1
kind: PersistentVolume
metadata:
  name: my-pv
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: standard
  nfs:
    path: /data/nfs/my-pv
    server: nfs-server.example.com

# PVC
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi
  storageClassName: standard

# Pod
apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
    - name: my-container
      image: nginx
      volumeMounts:
        - name: my-volume
          mountPath: /usr/share/nginx/html
  volumes:
    - name: my-volume
      persistentVolumeClaim:
        claimName: my-pvc

结束语:愿数据永存!

希望通过今天的讲解,大家能够彻底掌握 PV 和 PVC 的使用方法,让你的 Kubernetes 集群的数据永存不灭!记住,数据是无价的,保护数据就是保护未来!

如果大家还有什么疑问,欢迎在评论区留言,小P会尽力解答。下次再见!👋

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注