好的,各位观众老爷,大家好!我是你们的老朋友,人称“代码诗人”的程序猿小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 成功“牵手”,需要满足以下几个条件:
- 容量匹配: PV 的容量必须大于或等于 PVC 请求的容量。
- 访问模式匹配: PV 的访问模式必须包含 PVC 请求的访问模式。
- 存储类匹配: 如果 PVC 指定了存储类,PV 也必须指定相同的存储类。
- 选择器匹配: 如果 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
)进行处理。常用的回收策略有三种:
- Retain(保留): PV 不会被自动删除,数据会保留。需要手动清理 PV 和底层存储资源。这种策略适用于需要保留数据的场景。
- Recycle(回收): PV 会被简单擦除数据,然后可以被新的 PVC 使用。这种策略适用于需要重复利用存储资源的场景。
- 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会尽力解答。下次再见!👋