1. CSI 架构总览:规范演进、核心组件与集成原理
Container Storage Interface(CSI)是 Kubernetes 生态中接入外部存储系统的标准协议。本章从规范演进、核心组件职责、与 Kubernetes 的集成原理三个维度,建立 CSI 架构的整体认知。
1.1 CSI 规范演进历史
CSI 规范由 Kubernetes SIG-Storage 与 CNCF 社区共同推动,旨在终结各存储厂商各自为战的 in-tree 插件模式。下表梳理了关键里程碑:
| 版本 | 发布时间 | 核心变化 |
|---|---|---|
| CSI 0.0 | 2017.03 | 社区提出 CSI 概念,定义 gRPC 接口雏形 |
| CSI 0.1 | 2017.06 | 发布首个 Alpha 草案,包含 Identity/Controller/Node 三大 RPC 组 |
| CSI 0.2 | 2017.09 | 引入 VolumeCapability、MountOptions 等关键字段 |
| CSI 1.0 | 2018.04 | 正式 GA,Kubernetes 1.10 开始 Alpha 集成 |
| CSI 1.1 | 2018.07 | 增加 Volume Expansion(扩容)支持 |
| CSI 1.2 | 2018.10 | 引入 Volume Snapshot(快照)基础接口 |
| CSI 1.3 | 2019.03 | 增加 Topology(拓扑感知调度)能力 |
| CSI 1.5 | 2020.01 | 完善 Volume Group Snapshot、Volume Clone |
| CSI 1.6+ | 2021+ | 持续优化:Secrets 管理、NodeStage 细化、多平台支持 |
关键趋势:CSI 从 1.0 到 1.6+ 的演进,核心围绕“功能完备性”与“生产稳定性”两条主线。Kubernetes 自 1.13 起将 CSI 作为存储插件默认集成方式,in-tree 插件逐步冻结。
1.2 核心组件职责
CSI 规范将存储插件拆分为三个独立的 gRPC 服务(Service),每个服务运行在独立的容器中,通过 Unix Domain Socket 或 TCP 通信。三者职责严格分离:
| 组件 | 部署位置 | 核心 RPC 接口 | 职责说明 |
|---|---|---|---|
| Identity Service | 与 Controller/Node 同 Pod | GetPluginInfo, GetPluginCapabilities, Probe | 插件身份声明、能力通告、健康检查 |
| Controller Service | 控制面(通常为 Deployment) | CreateVolume, DeleteVolume, ControllerPublishVolume, CreateSnapshot, ListVolumes 等 | 存储资源生命周期管理(创建/删除/挂载/快照/扩容) |
| Node Service | 每个工作节点(DaemonSet) | NodePublishVolume, NodeUnpublishVolume, NodeStageVolume, NodeGetVolumeStats | 节点级卷挂载、卸载、阶段挂载、指标采集 |
设计原则:Controller 与 Node 分离,使得存储控制面操作(如创建卷)与数据面操作(如挂载卷)可以独立扩缩容、独立升级,且 Controller 可以运行在任意节点上,不依赖具体工作节点。
1.3 与 Kubernetes 的集成原理
Kubernetes 通过 CSI Sidecar 容器 模式实现与 CSI 驱动的无缝集成。Sidecar 容器与 CSI 驱动容器运行在同一个 Pod 中,负责将 Kubernetes 原生 API 对象(PersistentVolumeClaim、StorageClass、VolumeAttachment)转换为 CSI gRPC 调用。
下图展示了 CSI 驱动在 Kubernetes 集群中的完整部署架构与数据流:
1.4 集成关键流程:从 PVC 到 Pod 挂载
一个典型的 CSI 卷从创建到挂载,经历以下核心步骤:
- 用户创建 PVC:指定 StorageClass,StorageClass 中引用 CSI 驱动名称(provisioner)。
- CSI-Provisioner Sidecar 监听:发现未绑定的 PVC,调用 CSI Driver 的
CreateVolumeRPC。 - CSI Driver 创建存储资源:在存储后端创建卷,返回卷 ID 和属性。
- Kubernetes 创建 PV:将返回的卷信息绑定为 PersistentVolume 对象。
- Pod 调度到工作节点:kubelet 根据 VolumeAttachment 对象,调用 CSI Driver 的
ControllerPublishVolume(将卷挂载到节点)。 - NodeStageVolume:kubelet 调用 CSI Driver 的
NodeStageVolume,执行全局阶段挂载(如格式化、挂载到全局路径)。 - NodePublishVolume:kubelet 调用
NodePublishVolume,将卷绑定到 Pod 的挂载点。 - Pod 启动:卷就绪,Pod 开始读写。
常见误区:很多初学者认为 CSI 驱动直接与 kubelet 通信。实际上,kubelet 通过 Unix Domain Socket 与 CSI Driver 的 Node Service 通信,而 Controller Service 由 Sidecar 容器通过 gRPC 调用。两者路径不同,职责分离。
1.5 核心组件交互时序
下图以“创建并挂载卷”为例,展示 Identity、Controller、Node 三大服务在完整生命周期中的交互顺序:
1.6 架构设计要点总结
| 维度 | 设计要点 | 生产建议 |
|---|---|---|
| 组件分离 | Identity / Controller / Node 三服务独立部署,职责单一 | Controller 使用 Deployment 保证高可用;Node 使用 DaemonSet 保证每节点覆盖 |
| Sidecar 模式 | Kubernetes 通过 Sidecar 容器将 API 对象转换为 CSI gRPC 调用 | Sidecar 版本需与 CSI Driver 版本兼容,避免接口不匹配 |
| 通信协议 | gRPC over Unix Domain Socket(本地通信,高性能) | 确保 Socket 路径不冲突,使用 hostPath 卷共享 |
| 生命周期 | 创建 → 挂载 → 使用 → 卸载 → 删除,每个阶段有明确 RPC 对应 | 实现幂等性:所有 RPC 必须支持重复调用不产生副作用 |
| 错误处理 | gRPC 返回标准错误码(OK/NotFound/AlreadyExists/FailedPrecondition 等) | Sidecar 根据错误码决定重试或报错,避免死循环 |
学习路径建议:理解 CSI 架构后,下一步应深入每个 RPC 的请求/响应结构(protobuf 定义),以及 Sidecar 容器(provisioner、attacher、resizer、snapshotter)的源码逻辑。这是后续章节“多后端适配”与“性能优化”的基础。