系列导航
本系列从 K8s 存储模型入手,逐步展开到 CSI 标准与云原生存储全景。
① 概念 → ② Volume 生命周期 → ③ CSI 架构 → ④ FlexVolume 演进 → ⑤ 对比 → ⑥ 排障 ‖ ⑦ 开发 → ⑧ 高级特性 → ⑨ 演进展望
| 顺序 | 文章 | 定位 |
|---|---|---|
| ① | 本篇 - 概念与入门 | 基础——K8s 存储模型、PV/PVC/StorageClass、Volume 分类树、CSI 标准概述 |
| ② | Volume 生命周期全解析 | 全貌——两阶段处理(Attach+Mount)、动态/静态供应、Volume 流转路径 |
| ③ | CSI 架构详解 | 标准——gRPC 三服务、Sidecar 模式、External Components |
| ④ | FlexVolume 与 CSI 演进 | 演进——FlexVolume 原理、CSI 设计思想、为什么 CSI 替代 FlexVolume |
| ⑤ | 存储方案对比与选型 | 选型——主流 CSI 插件横向对比 + 决策树 |
| ⑥ | 排障思路与常用命令 | 运维——工具链 + 场景排查 + 性能 |
| — | 核心路径 ↑ | 扩展展望 ↓ |
| ⑦ | CSI 插件开发指南 | 扩展——从零开发一个 CSI 插件 |
| ⑧ | 高级特性详解 | 进阶——快照、克隆、扩容、拓扑感知 |
| ⑨ | 云原生存储演进与展望 | 展望——容器原生存储、DPU 卸载、未来方向 |
重要
本文是系列地基,回答一个问题:K8s 怎么管理持久化存储,CSI 又是什么。
脉络按两条线索展开,在 Pod 怎么用上存储 处汇合:
- 自底向上——找出问题:物理存储 → 文件系统 → K8s Volume → Pod 挂载 → 为什么需要 PV/PVC 抽象
- 自顶向下——给出方案:K8s 存储模型 → PV/PVC/StorageClass → Volume 生命周期 → CSI 标准
先补齐 K8s 存储基础概念,再看 PV/PVC 体系解决什么问题,最后给出 CSI 标准的全貌。后续文章按 CSI 架构的枝叶逐一深入。
1. K8s 存储模型
1.1 容器为什么需要持久化存储
容器的设计原则是"无状态"——容器销毁后,容器文件系统内的数据随之消失。但现实中有大量应用需要持久化数据:
| 应用类型 | 存储需求 | 典型场景 |
|---|---|---|
| 数据库 | 高 IOPS 块存储 | MySQL、PostgreSQL |
| 消息队列 | 持久化日志 | Kafka、RabbitMQ |
| 分布式存储 | 多 Pod 共享文件 | Ceph、GlusterFS |
| CI/CD | 构建缓存、制品仓库 | Jenkins、Nexus |
| AI 训练 | 大容量数据集 | GPU 训练数据、模型权重 |
K8s 通过 Volume 机制解决容器持久化存储问题。Volume 是 Pod 的一部分,生命周期独立于容器——容器重启不丢失,Pod 删除才释放。
1.2 Volume:Pod 级别的存储声明
Volume 定义在 Pod 的 spec.volumes 字段中,容器通过 volumeMounts 挂载:
| |
K8s 内置约 20 种 Volume 类型:
| 类型 | 说明 | 典型场景 |
|---|---|---|
emptyDir | Pod 级临时目录,Pod 删除即消失 | 同 Pod 多容器共享临时数据 |
hostPath | 挂载宿主机目录 | 测试、节点级数据(不推荐生产) |
nfs | NFS 网络文件系统 | 共享文件存储 |
iscsi | iSCSI 块设备 | SAN 存储 |
cephfs | Ceph 文件系统 | 分布式文件存储 |
rbd | Ceph RBD 块设备 | 分布式块存储 |
configMap / secret | 配置数据注入 | 配置文件、密钥 |
persistentVolumeClaim | 引用 PVC | 生产推荐方式 |
1.3 Volume 的局限:为什么需要 PV/PVC
直接在 Pod YAML 里声明 Volume 类型存在三个问题:
| 问题 | 说明 |
|---|---|
| 开发与运维耦合 | 开发人员需要在 Pod YAML 里指定存储类型(NFS? Ceph? iSCSI?),但存储基础设施应该由运维管理 |
| 无法动态分配 | 所有 Volume 都需要运维提前准备好底层存储资源(NFS 目录、iSCSI LUN 等),不能按需自动创建 |
| 无法资源管理 | 没有 IPAM 那样的统一分配机制,容易出现存储资源冲突和浪费 |
PV/PVC 体系就是为解决这些问题而设计的。
2. PV/PVC/StorageClass 体系
2.1 三个核心对象
| 对象 | 职责 | 谁创建 |
|---|---|---|
| PersistentVolume (PV) | 描述一块具体的持久化存储资源(类型、容量、访问模式) | 运维人员或动态供应自动创建 |
| PersistentVolumeClaim (PVC) | 描述 Pod 想要的存储属性(大小、权限、类型) | 开发人员 |
| StorageClass (SC) | 描述存储"类"——哪个 CSI 插件、什么参数、动态供应策略 | 运维人员 |
三者的关系类似"面向对象":
PVC = 接口(我要什么存储) PV = 实现(具体的存储资源) SC = 工厂(怎么自动生产 PV)
2.2 PV 示例
| |
2.3 PVC 示例
| |
2.4 绑定机制
PVC 和 PV 的绑定由 PersistentVolumeController 控制循环完成。绑定条件:
| 条件 | 说明 |
|---|---|
| storageClassName 匹配 | PVC 和 PV 的 storageClassName 必须一致 |
| accessModes 兼容 | PV 的访问模式必须满足 PVC 的要求 |
| 容量足够 | PV 的 capacity.storage >= PVC 的 requests.storage |
绑定后,Pod 通过 volumes.persistentVolumeClaim.claimName 引用 PVC:
| |
2.5 AccessModes(访问模式)
| 模式 | 缩写 | 说明 | 典型存储 |
|---|---|---|---|
| ReadWriteOnce | RWO | 单节点读写 | 块存储(iSCSI、RBD) |
| ReadOnlyMany | ROX | 多节点只读 | NFS(只读挂载) |
| ReadWriteMany | RWX | 多节点读写 | NFS、CephFS |
| ReadWriteOncePod | RWOP | 单 Pod 读写(K8s 1.22+) | 块存储(更严格隔离) |
3. StorageClass 与动态供应
3.1 静态供应 vs 动态供应
| 方式 | 流程 | 适用场景 |
|---|---|---|
| 静态供应 | 运维手动创建 PV → 开发创建 PVC → 自动绑定 | 已有存储资源(NFS 目录、LUN) |
| 动态供应 | 开发创建 PVC → StorageClass 自动创建 PV → 绑定 | 云存储、分布式存储(按需分配) |
3.2 StorageClass 示例
| |
关键字段:
| 字段 | 说明 |
|---|---|
provisioner | CSI 插件名称(决定调用哪个 CSI 插件) |
parameters | 传递给 CSI 插件的自定义参数 |
reclaimPolicy | PV 删除后底层存储的处理方式(Delete / Retain) |
volumeBindingMode | Immediate(立即绑定)/ WaitForFirstConsumer(等 Pod 调度后再绑定,用于拓扑感知) |
allowVolumeExpansion | 是否允许在线扩容 |
3.3 动态供应流程
1. 开发创建 PVC(指定 StorageClass) 2. PersistentVolumeController 发现未绑定的 PVC 3. External Provisioner(Sidecar)监听 PVC,匹配 StorageClass 的 provisioner 4. External Provisioner 调用 CSI 插件的 ControllerCreateVolume 5. CSI 插件在后端存储系统创建卷,返回卷信息 6. External Provisioner 创建 PV 对象 7. PersistentVolumeController 将 PV 与 PVC 绑定 8. Pod 调度后,Kubelet 调用 CSI 插件执行 Attach + Mount
4. 存储分类树
K8s 的持久化存储方案可以从两个维度分类:
4.1 按存储接口分类
| |
4.2 按存储类型分类
| 类型 | 特点 | AccessModes | 典型方案 |
|---|---|---|---|
| 块存储 | 高性能、单节点独占、低延迟 | RWO | Ceph RBD、AWS EBS、vSphere VMDK |
| 文件存储 | 多节点共享、POSIX 兼容 | RWX | NFS、CephFS、GlusterFS |
| 对象存储 | HTTP API 访问、无限容量 | 不适用(通过 SDK 访问) | S3、MinIO、Ceph RGW |
4.3 CSI 解决的三件事
CSI 标准本质上解决三件事:
| 职责 | 说明 | gRPC 服务 |
|---|---|---|
| 创建/删除卷 | 在后端存储系统上分配/回收存储空间 | Controller Service |
| 挂载/卸载卷 | 将卷 Attach 到节点、Mount 到 Pod 目录 | Node Service |
| 身份信息 | 报告插件名称、版本、支持的能力 | Identity Service |
所有 CSI 插件的能力都可以归到这三个维度。后续文章按 CSI 架构的枝叶逐一深入。
5. CSI 与 CNI 的类比
如果读者已了解 CNI(Container Network Interface),可以通过类比快速理解 CSI:
| 维度 | CNI | CSI |
|---|---|---|
| 解决什么 | Pod 网络连通性 | Pod 持久化存储 |
| 接口形式 | 可执行文件(stdin/stdout) | gRPC 服务 |
| 调用者 | Kubelet(通过 CRI) | Kubelet + External Sidecar 组件 |
| 生命周期 | Pod 创建/销毁时调用 | 卷创建/删除、Pod 调度/销毁时调用 |
| 核心操作 | 分配 IP + 创建 veth + 配路由 | 创建卷 + Attach 磁盘 + Mount 目录 |
| 标准制定者 | CNCF | CNCF(CSI)/ Kubernetes SIG Storage |
6. 系列文章脉络
本文建立了 K8s 存储的基础概念。后续文章按以下脉络展开:
| 文章 | 接续本文的哪个部分 |
|---|---|
| ② Volume 生命周期 | 展开 §3.3 动态供应流程,详解 Attach/Mount 两阶段 |
| ③ CSI 架构 | 展开 §4.3 CSI 三服务,详解 gRPC 接口和 Sidecar |
| ④ FlexVolume 演进 | 展开 §4.1 分类树中 FlexVolume → CSI 的历史 |
| ⑤ 对比选型 | 基于分类树做横向比较和决策 |
| ⑥ 排障 | 基于 Volume 生命周期做问题定位 |
| ⑦ 开发指南 | 基于 CSI 架构写一个完整插件 |
| ⑧ 高级特性 | 超出基本 CRUD 的能力(快照/克隆/扩容) |
| ⑨ 演进展望 | CSI 之上的云原生存储趋势 |