4、CSI存储插件架构:CSI规范概述、CSI Driver组件分解(Identity/Controller/Node)、CSI与Kubelet交互流程

4.1 CSI规范概述

Container Storage Interface(CSI)是CNCF定义的行业标准接口,旨在使存储供应商(如Ceph、NFS、云厂商块存储)能够以统一的插件形式接入Kubernetes。CSI规范将存储生命周期管理从Kubernetes核心代码中解耦,使得存储驱动的开发、部署和升级不再依赖Kubernetes版本发布周期。

核心设计目标:
  • 声明式接口:Kubernetes通过gRPC调用CSI Driver,完成卷的创建、挂载、卸载、删除等操作。
  • 三组件分离:Identity、Controller、Node三个独立gRPC服务,分别负责身份认证、控制面操作、节点本地操作。
  • 无状态与可插拔:CSI Driver以DaemonSet或Deployment形式运行,不修改Kubernetes核心二进制。

CSI规范定义了三个主要的gRPC服务接口,每个接口包含一组RPC方法。下表列出了各服务的关键方法及其用途:

gRPC服务 关键RPC方法 用途说明
Identity GetPluginInfo 返回Driver名称、版本、供应商信息
GetPluginCapabilities 声明Driver支持的能力(如卷扩展、快照、拓扑感知)
Probe 健康检查,确认Driver是否正常运行
Controller CreateVolume 在存储后端创建卷(如云盘、Ceph RBD image)
DeleteVolume 删除存储后端的卷
ControllerPublishVolume 将卷挂载到指定节点(如附加云盘到虚拟机)
ControllerUnpublishVolume 从节点卸载卷
ListVolumes 列出存储后端所有卷
CreateSnapshot 创建卷的快照
DeleteSnapshot 删除快照
Node NodeStageVolume 在节点上准备卷设备(如挂载到全局目录)
NodePublishVolume 将卷挂载到Pod的指定路径
NodeUnpublishVolume 从Pod路径卸载卷
NodeUnstageVolume 清理节点上的卷设备
NodeGetCapabilities 返回节点服务支持的能力

4.2 CSI Driver组件分解:Identity / Controller / Node

一个完整的CSI Driver由三个独立的gRPC服务组件构成,它们通常运行在同一个Pod中,但通过不同的Unix Socket或端口暴露。这种分离设计使得控制面操作(如创建卷)与数据面操作(如挂载卷)可以独立扩展和升级。

部署模式:Controller服务通常以Deployment形式运行(单副本或HA),Node服务以DaemonSet形式在每个节点上运行。Identity服务则同时存在于Controller和Node组件中。

4.2.1 Identity服务

Identity服务是所有CSI Driver必须实现的基础服务。它负责向Kubernetes(或外部编排器)报告Driver的身份信息、能力集和健康状态。Kubernetes的kubelet和external-provisioner等sidecar容器会在启动时调用GetPluginInfo和GetPluginCapabilities来验证Driver的兼容性。

4.2.2 Controller服务

Controller服务运行在控制面,负责与存储后端API交互,执行卷的生命周期管理操作。它通常不直接接触节点上的设备文件。Kubernetes通过external-provisioner、external-attacher等sidecar容器将PVC/PV的变化转换为对Controller服务的gRPC调用。

4.2.3 Node服务

Node服务运行在每个Kubernetes节点上,负责执行卷在节点本地的挂载操作。它直接操作设备文件、文件系统挂载点、符号链接等。kubelet通过Unix Socket与Node服务通信,完成Pod的卷挂载和卸载。

CSI Driver 三组件架构图 Kubernetes 控制面 external-provisioner external-attacher external-resizer external-snapshotter Controller 服务 CreateVolume DeleteVolume ControllerPublish CreateSnapshot 存储后端 云盘 / Ceph / NFS SAN / 本地存储 Kubernetes 节点 kubelet Pod 1 Pod 2 Node 服务 NodeStageVolume NodePublishVolume NodeUnpublishVolume 节点本地存储 /var/lib/kubelet/pods 设备文件 / 挂载点 Identity 服务(嵌入Controller/Node) Controller 和 Node 各自包含 Identity

4.3 CSI与Kubelet交互流程

当Pod被调度到某个节点后,kubelet负责将Pod中声明的CSI卷挂载到容器内。整个交互流程分为三个阶段:Stage(阶段挂载)、Publish(发布挂载)、Unpublish/Unstage(卸载清理)。

4.3.1 挂载流程(Stage & Publish)

  1. kubelet调用NodeStageVolume:kubelet通过Unix Socket向CSI Node服务发送NodeStageVolume请求,包含卷ID、挂载参数、访问模式等。Node服务将卷设备挂载到节点的全局 staging 路径(如/var/lib/kubelet/plugins/kubernetes.io/csi/pv/{pvname}/globalmount)。
  2. kubelet调用NodePublishVolume:Stage完成后,kubelet调用NodePublishVolume,将卷从 staging 路径绑定挂载到Pod的特定路径(如/var/lib/kubelet/pods/{podUID}/volumes/kubernetes.io~csi/{volname}/mount)。
  3. 容器启动:kubelet将Pod的卷挂载路径映射到容器内,启动容器。

4.3.2 卸载流程(Unpublish & Unstage)

  1. kubelet调用NodeUnpublishVolume:Pod删除或迁移时,kubelet先调用NodeUnpublishVolume,解除Pod路径上的绑定挂载。
  2. kubelet调用NodeUnstageVolume:Unpublish完成后,kubelet调用NodeUnstageVolume,从全局 staging 路径卸载卷设备。
  3. 清理:如果卷不再被任何Pod使用,kubelet可能触发Controller服务的ControllerUnpublishVolume和DeleteVolume。
关键注意事项:
  • kubelet与CSI Node服务之间的通信通过Unix Socket进行,Socket文件通常位于/var/lib/kubelet/plugins/{drivername}/csi.sock。
  • Stage和Publish的分离设计允许同一个卷被多个Pod共享(如ReadWriteMany),只需一次Stage,多次Publish。
  • 如果CSI Driver不支持NodeStageVolume(通过NodeGetCapabilities声明),kubelet会跳过Stage阶段,直接调用Publish。
CSI 与 Kubelet 交互流程(挂载阶段) kubelet Pod 调度到节点 1. NodeStageVolume 挂载到 staging 路径 /var/lib/kubelet/plugins/.../globalmount 2. NodePublishVolume 绑定挂载到 Pod 路径 /var/lib/kubelet/pods/{uid}/.../mount 3. 容器启动 卷映射到容器内路径 Pod 删除/迁移 kubelet 触发卸载 4. NodeUnpublishVolume 解除 Pod 路径绑定挂载 5. NodeUnstageVolume 卸载 staging 路径设备 说明:Stage 和 Publish 分离设计允许同一卷被多个 Pod 共享(ReadWriteMany)

4.4 总结与最佳实践

架构要点回顾:
  • CSI规范通过Identity、Controller、Node三个gRPC服务实现存储插件的标准化,使得存储供应商可以独立开发驱动。
  • Controller服务运行在控制面,负责卷的创建/删除/附加/快照等操作;Node服务运行在每个节点,负责卷的本地挂载/卸载。
  • kubelet通过Unix Socket与CSI Node服务交互,执行Stage→Publish的挂载流程,以及Unpublish→Unstage的卸载流程。
  • Stage和Publish的分离设计是CSI实现卷共享和高性能挂载的关键。
生产环境建议:
  • 始终使用官方或经过CNCF认证的CSI Driver,避免使用已废弃的in-tree卷插件。
  • 为CSI Driver的Controller组件配置合适的资源限制和健康检查,避免控制面操作超时。
  • 监控CSI Node服务的Socket文件状态,确保kubelet与Driver之间的通信畅通。
  • 在部署CSI Driver时,仔细阅读供应商文档,确认其支持的CSI能力(如卷扩展、拓扑约束、快照等)。