type
status
date
slug
summary
tags
category
password

1、存储简介

Kubernetes 存储的核心设计理念是:应用程序与存储基础设施解耦。开发者无需关心底层存储的具体细节(如是 NFS、云盘还是 Ceph),而是通过抽象的 API 对象来声明自己需要的存储资源。
为什么需要存储?
这主要是由容器本身的性质决定的:
  1. 非持久化存储:容器中的文件是临时性的。当容器崩溃、重启或终止时,容器内部的文件系统会被清除,数据会丢失。
  1. 容器间共享:一个 Pod 中的多个容器可能需要共享文件(比如一个 Web 服务器容器和一个日志处理容器)。
存储就是为了解决这两个核心问题,它抽象了底层的存储设备,提供了持久化、共享数据的能力。
Kubernetes 存储的核心概念如下:
  • Volume:存储的最基本概念。它是一个目录,可以被 Pod 中的一个或多个容器访问。
  • PersistentVolume(PV):集群中的一块物理存储资源(如 NFS、云存储、本地磁盘等),由管理员预先配置或通过 StorageClass 动态供给。
  • PersistentVolumeClaim(PVC):用户(或 Pod)对存储资源的请求,通过绑定 PV 来获取实际存储。
  • StorageClass(SC):实现 PV 的动态供给,根据用户的需求(PVC)动态创建 PV 资源,而不需要提前手动创建一批 PV 资源。

2、Volumn

Volumn 是一个抽象概念,它是一个可以被 Pod 中容器访问的目录,可以挂载到 Pod 中的一个或多个容器的指定路径上。当 Pod 重启时,Volumn 中的数据不会丢失。
Volumn 的特点:
  1. 生命周期与 Pod 绑定:Volume 的生命周期不与单个容器绑定,而是与 Pod 绑定。这意味着即使 Pod 中的容器终止重启,Volume 中的数据依然存在。但是,当整个 Pod 被删除时,Volume 通常也会随之被销毁(除非使用了特定类型的持久化卷)。
  1. 数据共享:一个 Volume 可以被挂载到 Pod 中的一个或多个容器的指定路径上,从而实现容器间的数据共享。
  1. 多种类型支持:Kubernetes 支持众多 Volume 类型,对应不同的存储后端和用途:
      • 本地存储emptyDir(临时空目录)、hostPath(挂载节点上的文件系统)【不推荐用于生产】
      • 网络存储nfscephfsglusterfs
      • 云提供商存储awsElasticBlockStoreazureDiskgcePersistentDisk
      • 特殊用途secretconfigMap(用于向Pod注入敏感信息或配置)
以下是一些常见 Volumn 类型示例。

2.1 emptyDir - 临时存储

emptyDir 卷首先是一个空的目录,其生命周期与 Pod 完全相同。当 Pod 被删除时,其中的数据也会被永久清除。适用于 Pod 中容器之间的临时数据交换或作为缓存空间。
  • emptyDir: {} 指定了 Volume 的类型。
  • 本例中,名为 cache-volume 的 emptyDir 卷被挂载到了容器的 /cache 目录,容器可以直接访问 /cache 目录。
  • 默认情况下,emptyDir 存储在承载 Pod 的节点所使用的介质上(可能是磁盘或 SSD)。你也可以通过设置 emptyDir.medium 字段为 "Memory" 来使用 RAM 作为存储介质(tmpfs),但这需要谨慎考虑内存容量。

2.2 hostPath - 本地节点存储

hostPath 将节点上的一个实际目录挂载到 Pod 中供容器使用。即使 Pod 被销毁,只要节点还在,数据就会保留在节点上。但是如果 Pod 被重新调度到其他节点,则无法访问原节点上的数据。适用于需要访问节点特定文件(如节点日志、Docker 内部数据)的场景。
hostPath 的 type 常用值:
Type
行为
DirectoryOrCreate
如果给定路径下目录不存在,则创建权限为 0755 的空目录,与 Kubelet 具有相同的组和所有权。
Directory
给定路径下必须已经存在目录。
FileOrCreate
如果给定路径下文件不存在,则创建权限为 0644 的空文件,与 Kubelet 具有相同的组和所有权。
File
给定路径下必须已经存在文件。

2.3 nfs - 跨节点存储

nfs 允许将网络文件系统挂载到 Pod,数据持久化保存在 NFS 服务器上,不受 Pod 调度节点的影响,支持多节点 Pod 共享数据
使用 nfs 需要先搭建 NFS 服务器并确保 Kubernetes 集群节点可以访问该服务器

3、PVC和PV

Volume 的概念很好,但有一个问题:开发者需要知道后端存储的技术细节(如 NFS 服务器的地址、路径)。这违背了 Kubernetes 屏蔽底层基础设施的初衷。
为了将存储管理(管理员职责)与存储使用(开发者职责)分离,Kubernetes 引入了两个重要的 API 资源:
  • PersistentVolume(PV):实际的物理存储资源。
  • PersistentVolumeClaim(PVC):定义了需求的存储规格,Kubernetes 根据 PVC 的需求绑定合适的 PV。
PV 和 PVC 的工作流程:

3.1 PersistentVolume(PV)

  • 定义:集群中的一块物理存储资源(如 NFS、云存储、本地磁盘等),由管理员预先配置或通过 StorageClass 动态供给。
  • 特点:
    • 是集群级别的资源,不属于任何命名空间。
    • 定义了存储的详细信息(如容量、访问模式、存储类型等)。
    • 生命周期独立于 Pod,即使 Pod 被删除,PV 仍然存在。
配置示例:

3.1.1 PV的访问模式

  • ReadWriteOnce(RWO):存储卷只能被单个节点的一个 Pod读写模式挂载,即使同一个节点上的多个 Pod 也无法共享。适用于单 Pod 需要独占存储的场景(如 MySQL 数据库的数据目录)。
    • ReadWriteMany(RWX):存储卷可以被 多个节点(多个 Pod)同时以读写模式挂载。适用于需要共享存储的场景(如文件共享、分布式日志收集)。
      • ReadOnlyMany(ROX):允许多个节点(多个 Pod)只读模式挂载(不可写入)。
        注意:
        1. 存储后端支持:不是所有存储类型都支持 RWX,具体取决于 PV 的底层存储系统(如 AWS EBS 仅支持 RWO,而 EFS 支持 RWX)。
        1. 性能影响:RWX 在多节点写入时可能需要考虑文件锁或冲突问题。
        1. StatefulSets:通常使用 RWO 模式,因为每个 Pod 需要独立存储。正常情况下,StatefulSet 通过 volumeClaimTemplates 自动为每个 Pod 创建 PVC。

          3.1.2 PV的回收策略

          • Retain:删除 PVC 后保留 PV 和数据,PV 变为 Released 状态,数据仍在,但需要管理员手动清理和重新绑定。
          • Delete:删除 PVC 后,后端的存储资源(如云硬盘)也会被自动删除。
          • Recycle(已废弃):数据擦除后重新使用 PV,基本被 Dynamic Provisioning 取代。

          3.2 PersistentVolumeClaim(PVC)

          • 定义:PVC 是用户(或 Pod)对存储资源的请求,类似于 Pod 对 CPU/内存的请求。它通过绑定 PV 来获取实际存储。
          • 特点:
            • 属于某个命名空间(Namespace)。
            • 开发者不需要关心底层存储细节,只需要声明所需的存储大小、访问模式等。Kubernetes 会根据 PVC 的请求(容量、访问模式、StorageClass)匹配符合条件的 PV,并与之绑定。
          示例配置:
          在 Pod 中引用

          3.3 PV和PVC的关联

          特性
          PV (PersistentVolume)
          PVC (PersistentVolumeClaim)
          角色
          存储资源(如磁盘、NFS 等)的抽象。
          用户对存储资源的请求。
          作用范围
          集群级别,不属于任何 Namespace。
          属于特定 Namespace。
          创建者
          通常由管理员或 StorageClass 动态创建。
          由用户或开发者创建。
          绑定关系
          可被多个 PVC 绑定(取决于访问模式)。
          只能绑定一个 PV(一对一)。
          生命周期
          独立于 Pod 和 PVC(需手动或通过策略回收)。
          与 Pod 的生命周期关联(通常随 Pod 删除而释放)。
          工作流程(静态制备):
          1. 管理员创建多个 PV。
          1. 用户创建 PVC,指定所需存储的要求。
          1. Kubernetes 控制平面为 PVC 寻找一个匹配的 PV。PVC 和 PV 关联基于以下条件的匹配:
            1. 存储容量:PVC 请求的容量 ≤ PV 的容量
            2. 访问模式:PVC 的访问模式必须被 PV 支持(ReadWriteOnce, ReadOnlyMany, ReadWriteMany)
            3. StorageClass:
                • 如果 PVC 指定了 StorageClass,则只会匹配相同 StorageClass 的 PV
                • 如果 PVC 没有指定 StorageClass,则只会匹配没有 StorageClass 的 PV
            4. 标签选择器:PVC 可以通过 selector 指定更详细的匹配条件
          1. PVC 与 PV 绑定(一对一关系)。
          1. 用户创建 Pod,并通过 PVC 名称使用该存储。
          静态制备需要管理员预先创建好足够容量和数量的 PV,非常不灵活。如果没有任何现成的 PV 满足 PVC 的请求,PVC 就会一直处于 Pending 状态。这就需要动态制备,也就是 StorageClass 的作用。

          4、StorageClass

          StorageClass 是描述存储类型的抽象,它定义了如何动态制备(Dynamic Provisioning) 一个 PV。
          核心特点:
          • 动态制备:当用户创建 PVC 并指定了 StorageClass 时,Kubernetes 会自动(动态地)按 StorageClass 的配置创建出对应的 PV,并立即与 PVC 绑定。
          • 存储供应商:每个 StorageClass 都有一个 provisioner 字段,用于决定使用哪个卷插件来制备 PV(如 kubernetes.io/aws-ebsceph.com/rbd)。
          • 参数化:可以传递特定的参数给后端存储系统(如磁盘类型、IOPS、文件系统类型等)。

          4.1 StorageClass使用示例

          1、StorageClass 配置示例:
          关键字段解析:
          1. provisioner:这是最关键的字段,决定了 Kubernetes 去调用哪个存储插件的 API 来创建存储。例如:
              • kubernetes.io/aws-ebs (AWS EBS)
              • kubernetes.io/gce-pd (GCP Persistent Disk)
              • kubernetes.io/azure-disk (Azure Disk)
              • csi.example.com (任何符合 CSI 标准的第三方存储驱动)
          1. parameters:这些参数传递给 provisioner,用于指定存储的具体属性。不同的 provisioner 支持的参数完全不同。例如,对于 AWS EBS,可以指定磁盘类型 (gp3io2)、IOPS、吞吐量等。
          1. reclaimPolicy:回收策略
              • Delete:当用户删除 PVC 时,自动删除对应的后端存储卷和 PV。这是默认策略。
              • Retain:当用户删除 PVC 时,保留 PV 和后端存储卷。数据会被保留,需要管理员手动清理。
          1. allowVolumeExpansion:允许卷扩展,设置为 true 时,允许用户之后编辑 PVC,申请更大的存储空间。是否真的能扩容成功,取决于底层存储系统是否支持。
          1. volumeBindingMode:卷绑定模式
              • Immediate:立即绑定。一旦创建 PVC,就立即触发 PV 的创建和绑定流程。
              • WaitForFirstConsumer:延迟绑定。直到真正使用这个 PVC 的 Pod 被调度到某个节点上之后,才在那个节点上创建 PV 并完成绑定。这对于拓扑受限的存储(如本地存储)或需要考虑节点区域的云存储非常有用,可以确保存储创建在 Pod 所在的节点或可用区。
          2、创建 PVC 时引用定义好的 StorageClass:
          3、最后在 Pod 中挂载这个 PVC:
          工作流程(动态制备):
          1. 管理员创建 StorageClass(通常云提供商已经内置了若干SC)。
          1. 用户创建 PVC,并在 storageClassName 字段指定所需的 StorageClass 名称。
          1. Kubernetes 看到这个 PVC 请求后,不会去寻找现有的 PV,而是直接调用 StorageClass 指定的 provisioner
          1. provisioner 根据 StorageClass 的配置,去后端存储系统(如 AWS)自动创建一块磁盘,并同时创建一个 PV 对象与之对应。
          1. 新创建的 PV 自动与 PVC 绑定。
          1. 用户创建 Pod,并在 volumeMounts 中引用上述 PVC。Pod 成功运行并使用了动态创建的存储。

          4.2 常用StorageClass示例

          4.2.1 AWS EBS 存储类

          适用于在 AWS EKS 环境中使用弹性块存储:

          4.2.2 NFS 存储类

          适用于网络文件存储,需要先部署 NFS Client Provisioner:

          4.2.3 Ceph RBD 存储类

          适用于 Ceph 分布式存储系统:

          5、最佳实践

          1. 优先使用动态制备: 对于大多数工作负载,尤其是云环境,使用 StorageClass 进行动态存储配置更高效、更灵活。
          1. 命名要有明确意义:例如 StorageClass 的名称应能清晰体现其用途,如 fast-ssdshared-nfsarchive-hdd 等。
          1. 显式指定 StorageClass:即使在集群中设置了默认的 StorageClass,也建议在 PVC 中显式指定 storageClassName,防止误用高成本存储。
          1. 理解回收策略的影响
              • Delete 策略在 PVC 删除后会自动删除后端存储资源,适用于临时数据。
              • Retain 策略在 PVC 删除后会保留后端存储资源,需要手动清理,适用于重要数据。
          1. 延迟绑定用于拓扑限制:对于有区域(Zone)限制的云存储(如 AWS EBS、GCE PD),建议使用 volumeBindingMode: WaitForFirstConsumer,这样可以确保 PV 在 Pod 调度的可用区创建,避免跨区挂载失败。
          1. 关注扩展性:在创建 StorageClass 时,如果后端存储支持扩容,建议设置 allowVolumeExpansion: true,以便后续无需重建即可扩容 PVC。
          1. 定期清理保留的 PV:如果使用 Retain 策略,需建立流程定期检查和清理已释放的 PV,避免存储资源浪费。
          Kubernetes系列:配置管理(ConfigMap、Secret)Kubernetes系列:容器网络(CNI、Service、DNS、Ingress)
          Loading...