资讯动态

Kubernetes 存储机制全解析:从核心原理到生态对比

发布时间:2026/9/3 5:09:51 来源:尧图企业网站定制
1. 概述这篇文章的目标是把 Kubernetes简称 K8s的存储机制讲清楚、讲完整。K8s 作为容器编排平台存储是生产环境中绕不开的核心话题Pod 是临时性的容器重启后文件会丢失那么有状态应用数据库、消息队列、文件服务的数据如何持久化多个 Pod 之间如何共享数据存储卷如何动态供给这些问题都指向 K8s 的存储体系。文章会从最基础的 Volume 讲起逐步深入到 PersistentVolumePV、PersistentVolumeClaimPVC、StorageClass、CSI 插件等核心概念再扩展到与 K8s 经常一起使用的兄弟组件和工具的存储机制例如 etcd、Docker、Helm、Prometheus、Harbor、MinIO 等。最后会做横向对比并专门讨论 K8s 存储机制是否随版本迭代发生过变化。2. 为什么需要存储抽象在理解 K8s 存储机制之前先要理解它要解决什么问题。容器本身是无状态的容器被删除后容器内写入的文件随之消失。这在跑无状态服务如 Web 前端时问题不大但数据库、日志系统、文件上传服务等有状态应用必须把数据写到容器之外。K8s 的存储设计围绕三个核心诉求展开持久化Pod 重建后数据不丢失。共享多个 Pod 或多个容器可以读写同一份数据。解耦应用开发者不需要关心底层存储的具体实现是 NFS、云盘还是本地磁盘。为了满足这三个诉求K8s 引入了分层抽象Volume 解决挂载问题PV 和 PVC 解决持久化和解耦问题StorageClass 解决动态供给问题CSI 解决插件扩展问题。3. Volume最基础的存储单元Volume 是 K8s 中最基础的存储抽象直接定义在 Pod 上。一个 Pod 可以挂载多个 VolumePod 内的容器可以共享这些 Volume。Volume 的生命周期与 Pod 绑定Pod 存在Volume 就存在Pod 被删除Volume 也随之销毁除非使用持久化类型的 Volume。Volume 的类型非常多常见的有类型说明持久性emptyDirPod 内临时目录容器重启不丢Pod 删除即丢临时hostPath挂载节点宿主机目录节点级持久configMap以文件形式挂载配置数据随 ConfigMap 存在secret以文件形式挂载敏感数据随 Secret 存在nfs挂载 NFS 共享目录持久persistentVolumeClaim通过 PVC 引用 PV持久emptyDir 是最常用的临时卷适合缓存、临时文件等场景。hostPath 适合需要访问节点文件的场景例如监控 Agent 读取宿主机日志但生产环境不建议作为数据库存储因为 Pod 调度到不同节点后数据不跟随。configMap 和 secret 本质上是把 K8s 对象的内容以文件形式挂载进容器它们解决的是配置注入问题而不是数据持久化问题。4. PV 和 PVC持久化存储的核心抽象PVPersistentVolume是集群级别的存储资源由管理员预先创建或者由 StorageClass 动态创建。PV 独立于 Pod 存在描述的是底层存储的真实信息例如容量、访问模式、回收策略、存储类型等。PVCPersistentVolumeClaim是用户对存储的请求类似于“我要 10Gi 的读写存储”。用户创建 PVC 后K8s 会尝试将 PVC 与满足条件的 PV 绑定。绑定成功后Pod 通过 PVC 挂载存储。这种设计实现了存储供给和存储消费的分离管理员负责准备 PV开发者只关心 PVC不需要知道底层存储是云盘还是 NFS。4.1 PV 的关键属性容量PV 声明的存储大小例如 10Gi。访问模式ReadWriteOnce单节点读写、ReadOnlyMany多节点只读、ReadWriteMany多节点读写。回收策略Retain保留数据、Recycle已废弃、Delete删除底层存储。存储类通过 storageClassName 关联 StorageClass。4.2 PVC 与 PV 的绑定过程PVC 创建后K8s 的 persistentvolume-controller 会扫描集群中的 PV寻找满足以下条件的 PV容量足够、访问模式匹配、storageClassName 匹配。找到后PVC 与 PV 进入 Bound 状态。如果没有现成 PV 匹配且存在默认 StorageClass则触发动态供给。绑定是独占的一个 PV 同一时间只能绑定一个 PVC。PVC 释放后PV 根据回收策略决定数据去留。5. StorageClass动态供给的入口StorageClass 解决了 PV 需要管理员手动创建的问题。通过 StorageClass用户可以声明“我要一块 SSD 云盘”系统自动调用云厂商或存储系统的 API 创建 PV。StorageClass 的核心字段包括provisioner指定存储插件例如 kubernetes.io/aws-ebs、kubernetes.io/gce-pd、nfs.csi.k8s.io。reclaimPolicy动态创建的 PV 被释放后的回收策略默认 Delete。parameters传给 provisioner 的参数例如云盘类型、IOPS、副本数。volumeBindingModeImmediate立即绑定或 WaitForFirstConsumer等待第一个消费者出现再绑定。volumeBindingMode 是生产环境中非常重要的参数。Immediate 模式在 PVC 创建时立即创建 PV但此时 Pod 可能还没调度导致 PV 创建在错误的可用区。WaitForFirstConsumer 模式会等 Pod 调度完成后根据 Pod 所在节点创建 PV避免跨可用区问题。6. CSI存储插件标准CSIContainer Storage Interface是 K8s 与存储系统之间的标准接口。在 CSI 出现之前K8s 的存储插件是内置在 kubelet 和 controller-manager 中的每增加一种存储都要修改 K8s 源码维护成本极高。CSI 将存储插件从 K8s 核心代码中剥离出来以独立组件的形式运行。CSI 插件通常包含三个部分Driver 注册组件负责向 kubelet 注册驱动。Controller 组件负责创建、删除、挂载、卸载卷。Node 组件负责在节点上执行卷挂载操作。CSI 的出现让云厂商和存储厂商可以独立开发和发布存储插件K8s 核心代码不再需要为每种存储单独适配。目前主流的云盘、NFS、Ceph、GlusterFS 等存储都提供了 CSI 驱动。7. 数据面组件kubelet 与卷生命周期存储机制不仅涉及 API 层的 PV、PVC、StorageClass还涉及数据面组件 kubelet 的实际操作。kubelet 负责在节点上执行卷的挂载、格式化、卸载等操作。卷的生命周期大致如下用户创建 PVC触发 PV 绑定或动态供给。Pod 调度到某个节点kubelet 根据 Pod 定义中的 volume 信息准备卷。对于 CSI 卷kubelet 调用 CSI Node 组件执行卷挂载。卷挂载到节点后再绑定到容器内的目标路径。Pod 删除时kubelet 执行卸载操作并根据回收策略处理数据。这里有一个容易混淆的概念卷挂载分为两个层次。第一层是卷挂载到节点NodeStage第二层是卷挂载到 Pod 内的容器路径NodePublish。CSI 规范中明确区分了这两个阶段目的是让卷可以在节点上复用减少重复挂载开销。8. 与 K8s 经常一起使用的兄弟组件和工具的存储机制K8s 本身不直接存储业务数据但围绕 K8s 生态有一批组件和工具承担着不同的存储职责。理解它们的存储机制有助于构建完整的知识体系。8.1 etcdK8s 的元数据存储etcd 是 K8s 的基石所有集群状态Pod、Service、ConfigMap、Secret、PV、PVC 等对象都存储在 etcd 中。etcd 是一个分布式键值存储基于 Raft 协议保证一致性。etcd 的存储机制有几个关键点数据持久化etcd 将数据写入本地磁盘的 WALWrite-Ahead Log和快照文件。高可用生产环境通常部署 3 或 5 节点 etcd 集群Raft 协议保证多数派写入成功才算提交。备份etcd 需要定期备份因为 K8s 的所有状态都在里面一旦丢失整个集群就瘫痪了。存储介质etcd 对磁盘 IO 延迟非常敏感生产环境强烈建议使用 SSD。etcd 存储的是 K8s 的控制面状态而不是业务数据。业务数据由 PV/PVC 体系管理两者职责完全不同。8.2 Docker容器运行时的存储机制Docker 是 K8s 早期最常用的容器运行时。Docker 的存储机制包括镜像层镜像由多层只读层组成基于 UnionFS 技术合并。容器层容器启动后在镜像层之上增加一个可写层容器删除后可写层随之消失。VolumeDocker 的 Volume 由 Docker 管理存储在宿主机 /var/lib/docker/volumes 目录下。Bind Mount将宿主机目录直接挂载到容器内。Docker 的 Volume 和 Bind Mount 是容器级存储而 K8s 的 Volume 是 Pod 级抽象。K8s 在 Pod 层面管理卷再通过容器运行时如 Docker 或 containerd执行实际的挂载操作。8.3 Helm包管理器的存储机制Helm 是 K8s 的包管理器用于打包、部署、升级应用。Helm 的存储机制主要体现在 Release 记录上Helm 默认将 Release 信息存储在 K8s 集群内的 Secret 中。每个 Release 对应一个或多个 Secret记录 Chart 的版本、配置、状态等信息。Helm 3 不再使用 Tiller 服务端组件所有操作都在客户端完成Release 记录直接写入 K8s API。Helm 本身不存储业务数据它存储的是“应用部署状态”这类元数据。8.4 Prometheus监控系统的存储机制Prometheus 是 K8s 生态最常用的监控系统。它的存储机制有几个特点本地 TSDBPrometheus 默认将时序数据写入本地磁盘按 2 小时为一个 block 存储。数据保留策略通过 --storage.tsdb.retention.time 控制数据保留时长。远程存储支持通过 Thanos、VictoriaMetrics 等方案将数据持久化到对象存储或远程数据库。K8s 集成Prometheus Operator 通常配合 PVC 使用将 TSDB 数据挂载到持久化卷上避免 Pod 重启丢数据。Prometheus 的存储机制说明了一个常见模式即使应用本身支持本地存储在 K8s 中部署时也要通过 PVC 将数据持久化否则 Pod 重建后监控历史数据全部丢失。8.5 Harbor镜像仓库的存储机制Harbor 是企业级容器镜像仓库它的存储机制分为两部分镜像数据Harbor 后端使用 RegistryDocker Distribution存储镜像镜像层数据可以存储在本地文件系统、S3、OSS、Ceph 等对象存储中。元数据Harbor 使用数据库PostgreSQL存储项目、用户、权限、镜像标签等元数据使用 Redis 做缓存。在 K8s 中部署 Harbor 时镜像存储和数据库都需要通过 PVC 持久化否则重启后镜像和配置全部丢失。8.6 MinIO对象存储的存储机制MinIO 是兼容 S3 协议的对象存储常与 K8s 配合使用为应用提供对象存储能力。MinIO 的存储机制数据分片MinIO 将对象数据拆分为多个数据块和校验块分布在不同磁盘上。纠删码通过 Reed-Solomon 纠删码实现数据冗余即使部分磁盘损坏也能恢复数据。后端存储MinIO 直接使用本地磁盘或挂载的持久化卷在 K8s 中通常通过 PVC 提供存储。MinIO 适合作为 K8s 集群内的对象存储服务为应用提供统一的文件上传下载能力。9. 存储机制横向对比为了更直观地理解 K8s 存储体系与兄弟组件存储机制的区别下面做一个横向对比。组件存储内容存储类型持久化方式与 K8s 的关系K8s PV/PVC业务数据块存储、文件存储、对象存储PV 独立于 Pod 存在K8s 核心存储抽象etcd集群元数据键值存储WAL 快照落盘K8s 控制面依赖Docker Volume容器数据宿主机目录宿主机磁盘容器运行时层Helm Release部署记录Secretetcd 持久化应用管理工具Prometheus监控时序数据TSDB本地磁盘或远程存储监控生态Harbor镜像和元数据对象存储 数据库PVC 或外部存储镜像仓库MinIO对象数据对象存储本地磁盘或 PVC对象存储服务从对比可以看出K8s 的 PV/PVC 是面向业务数据的通用抽象etcd 是面向集群状态的专用存储Docker 是容器运行时的底层存储而 Helm、Prometheus、Harbor、MinIO 则是各自领域的存储方案它们要么依赖 K8s 的 PVC 体系要么独立管理自己的数据。10. K8s 存储机制是否随版本迭代而改变答案是肯定的。K8s 的存储机制经历了多次重要演进下面按版本脉络梳理关键变化。10.1 早期版本内置插件时代在 K8s 1.0 到 1.8 左右存储插件以内置方式存在于 K8s 核心代码中。每种存储AWS EBS、GCE PD、NFS、iSCSI 等都是 kubelet 和 controller-manager 中的一段内置代码。这种方式的缺点是新增存储类型必须修改 K8s 源码插件与核心代码耦合严重升级 K8s 可能破坏存储插件。10.2 CSI 引入1.9 到 1.13CSI 规范在 K8s 1.9 版本以 alpha 特性引入1.10 进入 beta1.13 正式 GA。CSI 的引入是 K8s 存储机制最重要的转折点存储插件从内置走向外置云厂商和存储厂商可以独立开发驱动K8s 核心代码不再需要为每种存储单独适配。CSI 的 GA 意味着存储插件与 K8s 版本解耦这是存储机制演进中最关键的一步。10.3 树内插件冻结1.14 到 1.26从 K8s 1.14 开始社区宣布冻结树内存储插件In-Tree Storage Plugins不再新增内置存储插件已有插件逐步迁移到 CSI。例如 AWS EBS、GCE PD、Cinder 等插件陆续从树内移除改为调用对应的 CSI 驱动。这一阶段的变化是用户需要安装 CSI 驱动才能使用云盘存储树内插件虽然仍然可用但功能不再演进。10.4 树内插件移除1.26 及以后K8s 1.26 移除了部分树内存储插件的代码例如 AWS EBS、GCE PD 等。这意味着使用这些存储的用户必须迁移到 CSI 驱动。到 1.29 左右绝大多数树内存储插件已经完成迁移或移除。这一变化对用户的影响是升级 K8s 版本前需要确认所使用的存储是否已经切换到 CSI 驱动否则存储功能可能不可用。10.5 其他重要演进Volume SnapshotK8s 1.20 引入 VolumeSnapshot 和 VolumeSnapshotContent 的 GA支持对持久化卷做快照备份。Volume ExpansionK8s 1.24 将卷扩容能力提升为 GA用户可以在 PVC 上直接扩容容量。Ephemeral VolumeK8s 1.22 引入通用临时卷Generic Ephemeral Volume允许使用 PVC 模板创建临时卷。CSI MigrationCSI 迁移机制让树内插件自动调用 CSI 驱动平滑过渡到 CSI 体系。Object StorageK8s 社区正在推进容器对象存储接口COSI用于统一管理对象存储的供给和消费。10.6 版本演进总结版本阶段存储机制状态关键变化1.0 - 1.8内置插件存储插件耦合在核心代码中1.9 - 1.13CSI 引入并 GA存储插件外置化标准接口确立1.14 - 1.25树内插件冻结不再新增内置插件逐步迁移 CSI1.26 及以后树内插件移除必须使用 CSI 驱动总体趋势是存储机制从“核心内置”走向“标准接口 外置驱动”从“静态供给”走向“动态供给 快照 扩容”从“单一存储类型”走向“块、文件、对象统一管理”。11. 实践建议基于前面的原理和演进分析给出几条实践建议优先使用 CSI 驱动新项目直接使用 CSI 驱动避免依赖已冻结或已移除的树内插件。合理设置 StorageClass为不同性能需求创建多个 StorageClass例如 SSD 和 HDD 分开。使用 WaitForFirstConsumer跨可用区部署时使用 WaitForFirstConsumer 避免 PV 创建在错误区域。定期备份 etcdetcd 是集群的命脉必须定期备份并验证恢复流程。为有状态应用配置 PVC数据库、消息队列、监控系统等有状态应用必须通过 PVC 持久化数据。关注版本升级兼容性升级 K8s 前检查存储插件是否已迁移到 CSI避免升级后存储不可用。12. 总结K8s 的存储机制是一个分层、解耦、可扩展的体系Volume 解决挂载问题PV/PVC 解决持久化和供给消费分离问题StorageClass 解决动态供给问题CSI 解决插件标准化问题。围绕 K8s 生态etcd、Docker、Helm、Prometheus、Harbor、MinIO 等组件各自承担不同的存储职责理解它们的存储机制有助于构建完整的知识体系。K8s 存储机制确实随版本迭代发生了显著变化核心趋势是插件外置化、供给动态化、能力丰富化。从内置插件到 CSI 标准从静态 PV 到动态供给和快照扩容K8s 的存储体系一直在演进。掌握这些演进脉络不仅有助于理解当前版本的存储机制也能为未来的技术选型和版本升级提供参考。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价