3. Dell CSI驱动架构解析
Dell CSI Driver 并不是一个单一二进制,而是针对不同存储产品线分别实现的 CSI 插件集合。理解其架构的关键,是先分清“CSI 规范定义的通用角色”与“Dell 针对各产品线补充的私有组件”,再理解它们在 Kubernetes 中的部署形态与通信路径。本节围绕 PowerStore、PowerScale、PowerFlex、Unity XT 四条产品线展开。
一、CSI 通用角色与 Dell 的映射
CSI 规范把存储接入拆成两个必须实现的 gRPC 服务:Identity(标识与能力上报)和 Controller(卷生命周期管理),以及一个可选但实际必需的 Node 服务(节点侧挂载/卸载)。在 Kubernetes 中,它们分别由两类工作负载承载:
- Controller 插件:通常以 Deployment 形式运行在控制平面或工作节点上,负责 CreateVolume、DeleteVolume、ControllerPublishVolume、CreateSnapshot 等操作,通过存储阵列的管理 API 下发指令。
- Node 插件:以 DaemonSet 形式运行在每个工作节点上,负责 NodeStageVolume、NodePublishVolume,把远端卷映射为节点上的设备或文件系统路径,再 bind mount 到 Pod 的挂载点。
Dell 在此基础上为每条产品线增加了私有组件。PowerStore 与 Unity XT 属于块存储,走 iSCSI/FC,需要 csi-powerstore 与 csi-unity 驱动,并依赖节点上的多路径(multipathd)与 iSCSI 发起端;PowerScale 属于 NAS,走 NFS/SMB,驱动为 csi-powerscale,节点侧依赖 NFS 客户端;PowerFlex 是 SDS 软件定义存储,驱动为 csi-powerflex,节点侧需要 SDC(PowerFlex 客户端)与 scini 内核模块。四者的 Controller 与 Node 组件名称、依赖项和通信目标各不相同。
二、部署模式:Controller 与 Node 的落点
Dell CSI 驱动支持两种典型部署模式。第一种是标准分离模式:Controller 插件以 Deployment 运行,Node 插件以 DaemonSet 运行,二者通过 Unix Domain Socket 与 kubelet 的 CSI 注册机制协作。第二种是单节点/融合模式(常见于 PowerFlex 或边缘场景):Controller 与 Node 合并为一个 DaemonSet,减少组件数量,但会牺牲部分高可用能力。
以 PowerStore 为例,Controller 插件需要访问 PowerStore 管理 IP(默认 443)下发 REST 请求;Node 插件需要访问存储数据 IP(iSCSI 3260 或 FC 端口)。因此部署前必须确认:Controller Pod 所在节点能通管理网,所有工作节点能通数据网,且 iSCSI 服务与 multipathd 已启用。PowerScale 则要求 Controller 与 Node 都能访问 PowerScale 的 NFS 导出与 API 端点,节点侧还需挂载 NFS 客户端。
三、通信流程:从 PVC 到 Pod 挂载
下面这张图展示了 Dell CSI 驱动在 Kubernetes 中的组件拓扑与一次卷挂载的通信链路,覆盖 Controller、Node、外部组件与存储阵列之间的交互方向。
一次完整的卷挂载大致经历以下阶段。首先,用户创建 PVC 后,external-provisioner 监听到未绑定的 PVC,调用 CSI Controller 的 CreateVolume。Controller 插件读取 StorageClass 中的参数(如 arrayIP、protocol、size),通过 REST API 在阵列上创建卷或文件系统,并返回卷 ID 与容量信息。随后 external-attacher 调用 ControllerPublishVolume,把卷与目标节点关联,块存储会返回 iSCSI target IQN 或 FC WWN。
节点侧,kubelet 通过 CSI 注册 socket 发现 Node 插件,调用 NodeStageVolume。Node 插件根据协议执行登录 iSCSI target、扫描 LUN、由 multipathd 聚合路径,再把设备格式化为指定文件系统并挂载到全局暂存目录。最后 NodePublishVolume 把暂存目录 bind mount 到 Pod 的 /var/lib/kubelet/pods/<podUID>/volumes/… 路径,容器即可读写。
四、四条产品线的关键差异
| 产品线 | 驱动名称 | 协议 | 节点侧依赖 | Controller 通信目标 |
|---|---|---|---|---|
| PowerStore | csi-powerstore | iSCSI / FC / NFS | multipathd、iscsid | 管理 IP:443 |
| PowerScale | csi-powerscale | NFS / SMB | NFS 客户端 | API 8080、NFS 2049 |
| PowerFlex | csi-powerflex | SDC 数据路径 | SDC、scini 模块 | MDM API |
| Unity XT | csi-unity | iSCSI / FC / NFS | multipathd、iscsid | 管理 IP:443 |
差异最明显的是 PowerFlex:它不依赖传统 LUN 映射,而是通过 SDC 直接访问分布式存储池,因此 Node 插件不需要 iSCSI 登录,但必须确保 scini 内核模块已加载、SDC 已与 MDM 建立连接。PowerScale 则完全走文件路径,Node 插件执行的是 NFS mount 而非设备挂载,因此快照与克隆的语义也不同于块存储。
kubectl get csidrivers 确认驱动已注册,用 kubectl logs -n <namespace> <controller-pod> 观察 CreateVolume 是否成功,再检查节点侧 iscsiadm -m session 或 mount | grep nfs 判断挂载是否真正完成。理解这套组件与通信链路后,后续排查挂载失败时就能快速定位:是 Controller 无法访问管理 API,还是 Node 插件无法登录数据路径,抑或 kubelet 与 CSI socket 注册异常。不同产品线的排障入口不同,但都遵循“控制面下发 → 节点侧落地 → 存储侧确认”这条主线。