type
status
date
slug
summary
tags
category
password
1、存储简介
Kubernetes 存储的核心设计理念是:应用程序与存储基础设施解耦。开发者无需关心底层存储的具体细节(如是 NFS、云盘还是 Ceph),而是通过抽象的 API 对象来声明自己需要的存储资源。
为什么需要存储?
这主要是由容器本身的性质决定的:
- 非持久化存储:容器中的文件是临时性的。当容器崩溃、重启或终止时,容器内部的文件系统会被清除,数据会丢失。
- 容器间共享:一个 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 的特点:
- 生命周期与 Pod 绑定:Volume 的生命周期不与单个容器绑定,而是与 Pod 绑定。这意味着即使 Pod 中的容器终止重启,Volume 中的数据依然存在。但是,当整个 Pod 被删除时,Volume 通常也会随之被销毁(除非使用了特定类型的持久化卷)。
- 数据共享:一个 Volume 可以被挂载到 Pod 中的一个或多个容器的指定路径上,从而实现容器间的数据共享。
- 多种类型支持:Kubernetes 支持众多 Volume 类型,对应不同的存储后端和用途:
- 本地存储:
emptyDir
(临时空目录)、hostPath
(挂载节点上的文件系统)【不推荐用于生产】 - 网络存储:
nfs
、cephfs
、glusterfs
- 云提供商存储:
awsElasticBlockStore
、azureDisk
、gcePersistentDisk
- 特殊用途:
secret
、configMap
(用于向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)以只读模式挂载(不可写入)。
注意:
- 存储后端支持:不是所有存储类型都支持 RWX,具体取决于 PV 的底层存储系统(如 AWS EBS 仅支持 RWO,而 EFS 支持 RWX)。
- 性能影响:RWX 在多节点写入时可能需要考虑文件锁或冲突问题。
- 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 删除而释放)。 |
工作流程(静态制备):
- 管理员创建多个 PV。
- 用户创建 PVC,指定所需存储的要求。
- Kubernetes 控制平面为 PVC 寻找一个匹配的 PV。PVC 和 PV 关联基于以下条件的匹配:
- 存储容量:PVC 请求的容量 ≤ PV 的容量
- 访问模式:PVC 的访问模式必须被 PV 支持(ReadWriteOnce, ReadOnlyMany, ReadWriteMany)
- StorageClass:
- 如果 PVC 指定了 StorageClass,则只会匹配相同 StorageClass 的 PV
- 如果 PVC 没有指定 StorageClass,则只会匹配没有 StorageClass 的 PV
- 标签选择器:PVC 可以通过 selector 指定更详细的匹配条件
- PVC 与 PV 绑定(一对一关系)。
- 用户创建 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-ebs
,ceph.com/rbd
)。
- 参数化:可以传递特定的参数给后端存储系统(如磁盘类型、IOPS、文件系统类型等)。
4.1 StorageClass使用示例
1、StorageClass 配置示例:
关键字段解析:
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 标准的第三方存储驱动)
parameters
:这些参数传递给provisioner
,用于指定存储的具体属性。不同的 provisioner 支持的参数完全不同。例如,对于 AWS EBS,可以指定磁盘类型 (gp3
,io2
)、IOPS、吞吐量等。
reclaimPolicy
:回收策略Delete
:当用户删除 PVC 时,自动删除对应的后端存储卷和 PV。这是默认策略。Retain
:当用户删除 PVC 时,保留 PV 和后端存储卷。数据会被保留,需要管理员手动清理。
allowVolumeExpansion
:允许卷扩展,设置为true
时,允许用户之后编辑 PVC,申请更大的存储空间。是否真的能扩容成功,取决于底层存储系统是否支持。
volumeBindingMode
:卷绑定模式Immediate
:立即绑定。一旦创建 PVC,就立即触发 PV 的创建和绑定流程。WaitForFirstConsumer
:延迟绑定。直到真正使用这个 PVC 的 Pod 被调度到某个节点上之后,才在那个节点上创建 PV 并完成绑定。这对于拓扑受限的存储(如本地存储)或需要考虑节点区域的云存储非常有用,可以确保存储创建在 Pod 所在的节点或可用区。
2、创建 PVC 时引用定义好的 StorageClass:
3、最后在 Pod 中挂载这个 PVC:
工作流程(动态制备):
- 管理员创建 StorageClass(通常云提供商已经内置了若干SC)。
- 用户创建 PVC,并在
storageClassName
字段指定所需的 StorageClass 名称。
- Kubernetes 看到这个 PVC 请求后,不会去寻找现有的 PV,而是直接调用 StorageClass 指定的
provisioner
。
provisioner
根据 StorageClass 的配置,去后端存储系统(如 AWS)自动创建一块磁盘,并同时创建一个 PV 对象与之对应。
- 新创建的 PV 自动与 PVC 绑定。
- 用户创建 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、最佳实践
- 优先使用动态制备: 对于大多数工作负载,尤其是云环境,使用 StorageClass 进行动态存储配置更高效、更灵活。
- 命名要有明确意义:例如 StorageClass 的名称应能清晰体现其用途,如
fast-ssd
、shared-nfs
、archive-hdd
等。
- 显式指定 StorageClass:即使在集群中设置了默认的 StorageClass,也建议在 PVC 中显式指定
storageClassName
,防止误用高成本存储。
- 理解回收策略的影响:
Delete
策略在 PVC 删除后会自动删除后端存储资源,适用于临时数据。Retain
策略在 PVC 删除后会保留后端存储资源,需要手动清理,适用于重要数据。
- 延迟绑定用于拓扑限制:对于有区域(Zone)限制的云存储(如 AWS EBS、GCE PD),建议使用
volumeBindingMode: WaitForFirstConsumer
,这样可以确保 PV 在 Pod 调度的可用区创建,避免跨区挂载失败。
- 关注扩展性:在创建 StorageClass 时,如果后端存储支持扩容,建议设置
allowVolumeExpansion: true
,以便后续无需重建即可扩容 PVC。
- 定期清理保留的 PV:如果使用
Retain
策略,需建立流程定期检查和清理已释放的 PV,避免存储资源浪费。
- Author:mcbilla
- URL:http://mcbilla.com/article/26585c7d-7c1d-8096-b71f-e101dcb382cf
- Copyright:All articles in this blog, except for special statements, adopt BY-NC-SA agreement. Please indicate the source!
Relate Posts