K8s存储解耦PVC和PV

Kubernetes高级概念和应用 之K8s存储解耦PVC和PV

Kubernetes PV和PVC的区别?

在Kubernetes中,PV(Persistent Volume)和PVC(Persistent Volume Claim)是用于持久化存储的两个核心概念。它们之间的区别如下:

Persistent Volume(PV):

  • PV 是一种集群级别的资源对象,它代表着集群中的一个持久化存储卷。
  • PV 独立于任何特定的Pod,可以在多个Pod之间共享使用。
  • PV 需要由集群管理员预先创建和配置,以供用户使用。
  • PV 定义了持久化存储的属性,如存储容量、访问模式(ReadWriteOnce、ReadOnlyMany、ReadWriteMany)、存储类别等。

Persistent Volume Claim(PVC):

  • PVC 是Pod对PV的请求,它声明了Pod需要的持久化存储资源。
  • PVC 是在Pod级别定义的,并与特定的Pod相关联。
  • PVC 可以根据应用程序的需要灵活地创建和删除,无需干预集群管理员。
  • PVC 指定了对存储资源的需求,如存储容量、访问模式等。

PV 和 PVC 之间的关系:

  • 用户通过创建 PVC 来请求一定数量和类型的存储资源。
  • Kubernetes 调度器会寻找匹配这些要求的 PV,并将其绑定到 PVC 上。
  • 一旦 PV 和 PVC 绑定成功,PVC 就可以在 Pod 的配置中引用它,从而将持久化存储挂载到 Pod 中。

简而言之,PV 是一种集群级别的资源,由管理员配置,而 PVC 是在Pod级别定义的资源请求。PV 和 PVC 之间的绑定为Pod提供了持久化存储,并允许多个Pod共享同一个PV,提供了灵活且可伸缩的存储解决方案。


PVC的引入实现了Volume和持久化存储的具体实现 达到了解耦,另外还实现了职责分离,Volume和PVC由Pod的开发来定义,提出存储的需求,而不关心存储的具体实现; PV或Storange Class由K8s管理员负责

Pod可以关联Volume(Pod中的容器可以挂载Volume),Volume可以对接引用PVC,PVC可以绑定PV,PV可以对接具体的物理存储。


k8s_动态卷和静态卷

这节课我们讲一下K8S里的动态卷和静态卷的概念,这两个概念容易搞混。在讲之前,我们先说一下学习的基本套路,一般打开官方文档,特别是Tasks部分写的比较好,可直接实操验证特性。当然在此之前需要有环境,可以用minikube在本地跑一个K8S集群。

一般我们不会在应用程序的配置文件中使用ConfigMap,因为ConfigMap在更新后应用不会自动获取新配置。我们通常使用Apollo、Consul等集中式配置系统。ConfigMap和Secret我们一般只在一些基础组件如EFK、Prometheus等场景下使用。

对于无状态应用,我们可以用emptyDir这种临时共享存储目录。对于有状态应用,就需要用到PV和PVC了。PV可以理解为一块盘,通过NFS等后端存储系统挂载到节点上的一个目录。PVC用于管理和使用PV,可通过名字或标签绑定所需PV。

先看静态卷的例子。我们需要先创建一个PV,指定存储capability、path等,用storageClassName作为标识。然后创建PVC,通过storageClassName绑定所需的PV。如果没有对应的StorageClass,PVC会一直处于Pending状态报错。创建好后Pod中就可以通过Volume挂载该PVC从而使用对应存储了。

在这个示例中,我们先创建了一个PV,然后创建PVC绑定该PV。发现PVC报错是因为我们的StorageClass名称不正确,修复后就可以了。

接下来讲动态卷。与静态不同,动态不需要预先创建PV,而是通过StorageClass动态创建所需的PV。PVC在指定StorageClass后,会动态创建对应的PV,PV名称是随机的。每次删除PVC后,对应的动态PV也会根据策略被删除或保留。

在动态卷的示例中,我们直接创建PVC指定StorageClass,就会动态创建出随机命名的PV,而不需要预先创建PV资源。

关于PV,我们还需要注意status、reclaim policy和access mode等参数的作用。Status表示PV当前状态;access mode分为单节点读写、多节点读写和多节点只读等;reclaim policy包括Retain、Recycle和Delete等,控制PV删除后数据是否被保留。

如果需要固定存储位置的应用,如CI/CD构件、数据库等,需要使用静态PV,预先准备好存储资源。而对于通用应用,使用动态PV就更灵活方便了。

最后以AWS EBS为例,讲解了如何使用CSI驱动通过动态或静态方式将EBS卷挂载为PV的用法。

总之,对有状态应用的数据持久化,我们需要合理选择静态PV还是动态PV,并正确设置相关参数,以满足不同需求,这是管理有状态应用的关键。

emptyDir和PV/PVC有什么联系和区别?各用于什么场景?

emptyDir和PV/PVC虽然都是Kubernetes中用于存储的资源对象,但它们有一些区别和不同的使用场景:

emptyDir:

  • 是一种临时存储卷,生命周期与Pod相同
  • 可以用作临时目录存放一些临时数据,供同一Pod内的容器共享
  • 当Pod被删除时,emptyDir卷中的数据也会被一起删除
  • 常用于一些临时缓存、磁盘临时存放等场景
  • 不适合持久化数据存储

PV/PVC:

  • PV(Persistent Volume)表示一块外部的存储设备
  • PVC(Persistent Volume Claim)是用户对存储资源的请求
  • PVC通过绑定合适的PV来满足存储需求
  • PV和PVC可以在Pod重启或者调度到其他节点时,实现数据持久化
  • 适用于有状态应用需要持久化数据的场景

两者的主要区别:

  1. 生命周期不同

    • emptyDir生命周期与Pod一致,临时性的
    • PV/PVC的生命周期独立于Pod,属于集群资源
  2. 数据持久性不同

    • emptyDir在Pod删除时会一起删除,不能持久化数据
    • PV/PVC数据可以持久化,即使Pod被删除/迁移也不会丢失
  3. 存储性质不同

    • emptyDir适合一些临时缓存、数据共享等
    • PV/PVC更多用于持久化数据存储,如数据库、文件系统等

因此:

  • 如果只是临时需要在同一Pod内的容器之间共享一些数据,可以用emptyDir
  • 如果需要持久化数据,为有状态应用提供持久数据存储,应该使用PV/PVC

k8s中动态卷和静态卷是什么?

K8s中的动态卷和静态卷指的是使用PV/PVC资源对象实现持久化存储的两种方式:

静态卷(Static Provisioning):

  • 集群管理员需要预先手动创建一些PV资源对象
  • 创建PV时需要指定存储的详细信息,如存储类型、容量、访问模式等
  • 创建PVC时,需要指定绑定哪个具体的PV
  • 优点是PV的创建细节可控,但需要预先配置存储资源

动态卷(Dynamic Provisioning):

  • 无需预先创建PV资源对象
  • 集群管理员需要预先创建好”StorageClass”对象,定义存储的类型和配置
  • 创建PVC时,直接指定StorageClass即可
  • K8s会自动调用相应的存储插件(StorageProvisionor)动态创建PV,并绑定给PVC
  • 优点是使用更加自动化,不需要预先创建PV资源

两者的区别主要在于PV对象的创建方式:

  • 静态卷需要集群管理员预先手动创建PV
  • 动态卷由K8s根据PVC请求动态自动创建PV

使用场景:

  • 静态卷适用于存储资源有限并且需要细致控制的场景
  • 动态卷则更加自动化,适用于公有云或灵活分配存储资源的环境

总的来说,动态卷的使用更加方便自动化,是推荐的做法;但在某些场景下静态卷仍然有其存在的价值和用途。






20250226


20250422

您的分析是正确的。在您提供的部署配置中,Pod 确实只能有一个副本,这主要是因为您使用了 PersistentVolumeClaim (PVC)。

当您的部署使用 PVC 时,是否能够支持多个副本取决于 PVC 的访问模式(accessModes):

  • 如果 PVC 的访问模式是 ReadWriteOnce (RWO),那么它只能被一个节点上的一个 Pod 挂载为读写模式,因此无法支持多个副本。
  • 如果 PVC 的访问模式是 ReadOnlyMany (ROX),则可以被多个节点的多个 Pod 以只读方式挂载。
  • 如果 PVC 的访问模式是 ReadWriteMany (RWX),则可以被多个节点的多个 Pod 以读写方式挂载,这种情况下可以支持多个副本。

在您的配置中,使用了名为 “taskon-test-download” 的 PVC,但没有显示其访问模式。如果它是 RWO 模式(这也是许多存储类型的默认模式),那么确实只能支持单个 Pod。

如果您希望扩展到多个副本,可以考虑以下选项:

  1. 将 PVC 的访问模式更改为 ReadWriteMany(需要存储支持此模式,如 NFS)
  2. 使用共享存储服务如 S3 兼容存储
  3. 根据应用需求,考虑是否可以将状态从应用中分离出来

要查看 PVC 的访问模式,可以运行:

1
kubectl get pvc taskon-test-download -n taskon-test -o yaml

我执行后的返回:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
annotations:
pv.kubernetes.io/bind-completed: "yes"
pv.kubernetes.io/bound-by-controller: "yes"
volume.beta.kubernetes.io/storage-provisioner: com.tencent.cloud.csi.cbs
volume.kubernetes.io/storage-provisioner: com.tencent.cloud.csi.cbs
creationTimestamp: "2025-02-18T02:17:11Z"
finalizers:
- kubernetes.io/pvc-protection
name: taskon-test-download
namespace: taskon-test
resourceVersion: "5052665246"
uid: dd8452c6-2e38-448f-ac3c-8a3e02d23ca3
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
storageClassName: cbs
volumeMode: Filesystem
volumeName: pvc-dd8452c6-2e38-448f-ac3c-8a3e02d23ca3
status:
accessModes:
- ReadWriteOnce
capacity:
storage: 10Gi
phase: Bound

您的分析是完全正确的。从您提供的 PVC 配置可以看到,这个 PVC 的访问模式是 ReadWriteOnce

1
2
3
spec:
accessModes:
- ReadWriteOnce

这意味着这个 PVC 只能被挂载到一个节点上的一个 Pod,所以您的部署确实无法扩展到多个副本。这就是为什么您的部署中 replicas: 1 是必须的限制。

如果您想要扩展部署到多个副本,您有几个选项:

  1. 使用支持 ReadWriteMany 的存储类

    • 如 NFS, GlusterFS, Ceph RBD 等
    • 腾讯云上可能提供一些支持 ReadWriteMany 的存储解决方案
  2. 使用对象存储

    • 如腾讯云 COS(对象存储)
    • 应用程序需要修改为使用对象存储 API 而不是文件系统
  3. 数据分片

    • 每个副本使用自己的 PVC
    • 需要在应用层实现数据分片逻辑
  4. 有状态应用考虑使用 StatefulSet

    • 为每个 Pod 提供独立的存储
    • 适合需要唯一网络标识符的分布式应用

如果您必须保持当前的存储架构,那么确实只能使用单个 Pod。这是云原生应用中常见的限制,特别是在使用块存储(如腾讯云的 CBS)时。

现在使用的腾讯云 云硬盘CBS是只能 单机读写

另外几种可以多机读写

ReadWriteMany

@fliter 如果是多POD/容器的数据共享场景,推荐您使用CFS(文件存储),价格可以根据具体的使用需求使用价格计算器来参考下:https://buy.cloud.tencent.com/price/cfs/calculator

下次可以考虑使用另外两种

但貌似 文件存储需要开通, COS需要在集群里安装插件~