3. CSI 基础概念:Container Storage Interface 规范、驱动架构与 PV/PVC 关系

在 Kubernetes 生态中,存储接入一直是一个复杂且碎片化的领域。每个云厂商或存储供应商都需要为 Kubernetes 编写特定的 in-tree(树内) 卷插件,这些插件与 kubelet 和 kube-controller-manager 的代码深度耦合,导致升级困难、维护成本高。Container Storage Interface(CSI)的出现,正是为了解决这一痛点,将存储驱动从 Kubernetes 核心代码中解耦,形成一个标准化的插件体系。

3.1 CSI 规范:存储插件的标准化契约

CSI 是由 CNCF(Cloud Native Computing Foundation) 主导的行业标准,定义了存储提供商(SP)实现存储插件的统一接口。它本质上是一个 gRPC 协议 的规范集合,Kubernetes 作为容器编排系统(CO),通过调用这些 gRPC 接口来管理存储的生命周期。

核心设计理念: CSI 将存储的“控制面”与“数据面”分离。控制面负责创建、删除、挂载、卸载等管理操作;数据面负责实际的 I/O 读写。这种分离使得存储驱动可以独立于 Kubernetes 主版本进行发布和升级。

CSI 规范定义了三大类 gRPC 服务,每类服务包含若干 RPC 方法:

服务类别 主要 RPC 方法 功能描述
Identity Service GetPluginInfo, GetPluginCapabilities, Probe 用于 CO 发现插件的身份、能力(如是否支持卷扩展、快照)以及健康检查。
Controller Service CreateVolume, DeleteVolume, ControllerPublishVolume, ControllerUnpublishVolume, CreateSnapshot, DeleteSnapshot 在存储后端(如云磁盘、SAN/NAS 阵列)上执行卷的创建、删除、挂载到节点、快照等操作。这些操作通常由集群级别的控制器执行。
Node Service NodeStageVolume, NodeUnstageVolume, NodePublishVolume, NodeUnpublishVolume, NodeGetVolumeStats 在单个节点上执行卷的格式化、挂载到 Pod 目录、卸载等操作。这些操作由运行在节点上的 kubelet 触发。
版本兼容性: CSI 规范目前已经演进到 v1.x 版本,Kubernetes v1.13 开始 GA(General Availability)。在部署 CSI 驱动时,务必确认驱动版本与 Kubernetes 集群版本的兼容性矩阵。

3.2 CSI 驱动架构:Controller 与 Node 组件

一个标准的 CSI 驱动通常由两个核心组件构成:Controller Plugin 和 Node Plugin。它们以 DaemonSet 或 Deployment 的形式运行在 Kubernetes 集群中,并通过 Unix Domain Socket 与 kubelet 或外部控制器通信。

CSI 驱动架构:Controller 与 Node 组件 CSI 驱动架构:Controller 与 Node 组件 存储后端 (云磁盘 / SAN / NAS) Kubernetes 控制面 (kube-controller-manager) CSI Controller Plugin (Deployment / StatefulSet) 处理 CreateVolume / DeleteVolume gRPC 调用 云 API / 存储协议 工作节点 (Node) (kubelet) CSI Node Plugin (DaemonSet) 处理 NodePublishVolume / NodeUnpublishVolume Unix Socket 通信 iSCSI / NFS / 本地挂载 说明: Controller Plugin 运行在控制面,负责卷的创建/删除;Node Plugin 运行在每个工作节点,负责卷的挂载/卸载。
关键区别: Controller Plugin 是集群范围的,通常以 Deployment 部署(1 个或少量副本);Node Plugin 是节点范围的,必须以 DaemonSet 部署,确保每个节点上都有一个实例来响应 kubelet 的挂载请求。

3.3 CSI 与 PV/PVC 的关系:从声明到绑定的完整链路

在 Kubernetes 中,用户通过 PersistentVolumeClaim(PVC) 声明存储需求,系统通过 PersistentVolume(PV) 提供实际的存储资源。CSI 驱动是连接 PVC 与 PV 的“执行者”,它负责将 PVC 的声明转化为对存储后端的真实操作。

下图展示了从用户创建 PVC 到 Pod 使用存储的完整流程:

CSI 与 PV/PVC 关系:从声明到绑定 CSI 与 PV/PVC 关系:从声明到绑定 ① 用户创建 PVC 声明存储需求(大小、访问模式) ② 控制面检测 PVC 寻找匹配的 StorageClass ③ CSI Controller 调用 CreateVolume ④ 存储后端 分配实际存储资源 ⑤ PV 自动创建 绑定到 PVC ⑥ Pod 使用 PVC CSI Node Plugin 挂载卷 关键流程说明: 1. PVC 中指定 StorageClass,StorageClass 的 provisioner 字段指向 CSI 驱动的名称。 2. Kubernetes 控制面发现 PVC 需要动态制备,调用 CSI Controller 的 CreateVolume 方法。 3. CSI Controller 在存储后端创建卷后,Kubernetes 自动创建对应的 PV 对象,并与 PVC 绑定。 4. Pod 调度到节点后,kubelet 调用 CSI Node Plugin 的 NodePublishVolume 将卷挂载到 Pod 内。

3.4 核心概念对比:In-tree 插件 vs CSI 驱动

为了更直观地理解 CSI 带来的变革,我们将传统的 in-tree 卷插件与 CSI 驱动进行对比:

对比维度 In-tree 卷插件 CSI 驱动
代码位置 Kubernetes 核心仓库(k8s.io/kubernetes) 独立仓库,由存储供应商维护
升级方式 必须跟随 Kubernetes 版本升级 独立升级,不依赖 Kubernetes 版本
部署方式 编译在 kubelet 二进制中 以 DaemonSet/Deployment 形式部署在集群内
接口标准 内部接口,无标准化 gRPC 标准接口,跨平台兼容
功能扩展 困难,需要修改 Kubernetes 核心代码 容易,通过实现 CSI 规范中的可选 RPC 方法
典型场景 早期 Kubernetes 版本(v1.13 之前) Kubernetes v1.13+ 推荐方式
实践建议: 在 Helm 部署 CSI 驱动时,通常需要同时部署 Controller Plugin 和 Node Plugin 两个组件。Controller Plugin 的 Deployment 需要配置 leader election 以防止多个副本同时操作存储后端;Node Plugin 的 DaemonSet 需要设置 tolerations 以确保在关键节点上也能运行。