本文以 seaweedfs-csi-driver 1.4.5版本讲解下其工作流程和原理

1、Kubernetes CSI 概述

Kubernetes CSI(Container Storage Interface)是一套标准化的存储插件接口,用于将第三方存储系统集成到 Kubernetes 中

1)、CSI 驱动核心组件
  • Controller plugin:以 Deployment 方式部署,负责集群级存储资源管理,比如 Volume 的创建、删除、扩容、快照
  • Node plugin:以 DaemonSet 方式部署,处理节点级存储操作,负责在具体的节点上执行 Volume 的挂载和卸载等任务
2)、Kubernetes CSI 核心架构图

在这里插入图片描述

3)、核心 CSI Sidecar 容器

为简化 CSI 驱动开发,Kubernetes 提供了一系列标准化的 Sidecar 容器,封装了与 Kubernetes 核心组件的交互逻辑,开发者只需实现 CSI 标准接口即可。核心 Sidecar 容器包括:

  1. external-provisioner
    • 监听 PVC 对象变更,结合 PVC 关联的 StorageClass(需指定该 CSI 驱动为 provisioner)
    • 调用 CSI Controller 服务的 CreateVolume(创建卷)/DeleteVolume(删除卷)接口
    • 自动创建 PV 并与 PVC 绑定(创建卷后)或删除 PV(删除卷后)
  2. node-driver-registrar
    • 调用 CSI Node 服务的 NodeGetInfo 接口获取驱动信息
    • 将驱动注册到节点的 /var/lib/kubelet/plugins_registry/ 目录(Kubelet 监听该目录)
    • 完成 Node Plugin 向 Kubelet 的注册,以便 Kubelet 后续调用
  3. external-attacher
    • 监听 VolumeAttachment 对象,调用 CSI Controller 服务的 ControllerPublishVolume(Attach,将卷关联到节点)/ControllerUnpublishVolume(Detach,解除卷与节点的关联)接口
    • 区别于 Node 侧的 Mount:Attach 是集群级操作(卷→节点),Mount 是节点级操作(卷→容器目录)
    • 对于 SeaweedFS CSI 而言,由于 SeaweedFS 是分布式文件存储(无块设备/物理卷挂载到节点的概念),无需执行卷关联到节点的 Attach/Detach 操作,因此其 CSI 驱动中 ControllerPublishVolumeControllerUnpublishVolume 接口均为空实现,仅返回成功状态以满足 CSI 协议规范
  4. external-resizer:监听 PVC 扩容请求,调用 CSI Controller 服务的 ControllerExpandVolume 接口,完成卷的容量扩容
  5. external-snapshotter:监听 VolumeSnapshot 对象,调用 CSI Controller 服务的 CreateSnapshot/DeleteSnapshot 接口,处理卷快照的创建与删除
  6. livenessprobe:通过调用 CSI 驱动的 Probe 接口,监控 CSI 驱动进程的健康状态,异常时触发重启
4)、CSI 与 Kubernetes 组件的交互逻辑
  • Controller Plugin:通过 Sidecar 容器(如 external-provisionerexternal-attacher)与 Kubernetes APIServer 交互,监听 PVC/PV/VolumeAttachment 等资源的变更事件,执行对应的存储资源操作
  • Node Plugin:通过 node-driver-registrar Sidecar 容器向 Kubelet 完成注册,Kubelet 发现注册信息后,通过 Unix Domain Socket 向 Node Plugin 发起节点级存储操作调用

2、SeaweedFS CSI 工作原理

1)、部署架构

SeaweedFS CSI 驱动部署后包含 1 个 Deployment + 2 个 Daemonset:

1)seaweedfs-controller(Deployment,集群级)

包含 1 个核心业务容器 + 4 个 Sidecar 容器:

  • seaweedfs-csi-plugin(核心):实现 CSI Controller 接口,是 SeaweedFS 卷管理的核心逻辑载体:
    • CreateVolume:调用 SeaweedFS Filer 的接口创建 Volume(指定存储桶、副本策略、容量等参数)
    • DeleteVolume:调用 SeaweedFS Filer 的接口删除对应 Volume,清理存储资源
    • 额外实现 ControllerExpandVolume(扩容)、CreateSnapshot(快照)等接口
  • Sidecar 容器:csi-provisionercsi-resizercsi-attachercsi-liveness-probe

2)seaweedfs-node(DaemonSet,节点级)

每个节点部署一份,包含 1 个核心业务容器 + 2 个 Sidecar 容器:

  • csi-seaweedfs-plugin(核心):实现 CSI Node 接口,负责节点侧卷挂载/卸载:
    • NodePublishVolume(核心):接收 Kubelet 调用,通过 Unix Domain Socket 调用同节点 seaweedfs-mount 容器的 /mount 接口,触发 weed mount 命令挂载卷
    • NodeUnpublishVolume:调用 seaweedfs-mount 容器的 /unmount 接口,执行卸载并清理挂载目录
    • NodeGetInfo:向 driver-registrar 提供节点信息,完成驱动注册。
  • Sidecar 容器:driver-registrarcsi-liveness-probe

3)seaweedfs-mount(DaemonSet,节点级)

每个节点部署一份,仅包含 seaweedfs-mount 容器:

  • 核心职责:通过 Unix Domain Socket 暴露 /mount/unmount HTTP 接口,接收 seaweedfs-node 的挂载/卸载请求
  • 核心能力:管理 weed mount 进程的生命周期(启动/停止),是节点侧卷挂载的实际执行者
2)、使用过程

在这里插入图片描述

1)CSI 驱动准备阶段

驱动部署完成后:

  • seaweedfs-controller 中的 external-provisioner 向 Kubernetes APIServer 注册监听器,监听 PVC、StorageClass 等资源变更
  • seaweedfs-node 中的 node-driver-registrar 向节点 Kubelet 完成驱动注册,Kubelet 记录驱动信息并建立通信通道(Unix Domain Socket)

2)卷的动态配置(PVC → PV → SeaweedFS Volume)

  1. 集群管理员创建 StorageClass,指定 provisioner 为 seaweedfs-csi-driver
  2. 用户创建 PVC,指定上述 StorageClass 并声明存储容量
  3. external-provisioner 监听到 PVC 创建事件后,向 seaweedfs-csi-plugin 发起 gRPC 调用 CreateVolume
  4. seaweedfs-csi-plugin 调用 SeaweedFS Filer 的接口创建对应 Volume
  5. external-provisioner 自动创建 PV,将 PV 与 PVC 绑定,卷配置完成

3)创建 Pod 并使用卷

用户创建 Pod 并引用已绑定的 PVC,触发节点侧挂载流程:

  1. Kubernetes 调度器将 Pod 调度到目标节点,节点 Kubelet 发起 NodeStageVolume 调用(卷准备):
    • csi-seaweedfs-plugin 解析挂载参数(filer 地址、卷路径、挂载选项等)
    • 通过 Unix Socket(/var/lib/seaweedfs-mount/seaweedfs-mount.sock)向 seaweedfs-mount 发送 POST /mount 请求
    • seaweedfs-mount 启动 weed mount 进程(命令:weed mount -filer=<filer地址> <目标挂载路径>),并返回本地通信 Socket 信息
  2. Kubelet 发起 NodePublishVolume 调用(卷发布):
    • csi-seaweedfs-plugin 通过 bind mount 方式,将 weed mount 挂载的目录绑定到 Pod 的指定路径(如 /var/lib/kubelet/pods/<pod-id>/volumes/kubernetes.io~csi/<pvc-name>/mount
  3. Pod 启动后,应用程序可直接访问挂载路径,像使用本地文件系统一样操作 SeaweedFS 分布式存储卷

3、SeaweedFS Mount 实现原理

在 SeaweedFS CSI 驱动的节点侧挂载流程中,seaweedfs-mount 容器通过启动 weed mount 进程完成了分布式存储卷到节点本地的挂载,那为什么 weed mount 能让应用像操作本地文件系统一样访问 SeaweedFS 集群呢?

内核态(Kernel)

  • FUSE 内核:作为内核态桥接层,与 VFS 交互,表现形式与普通文件系统无异。接到文件操作请求后,不直接处理业务逻辑,而是将请求存入队列并转发给用户空间

用户态(Userspace)

  • GO-FUSEFUSE 内核的通信桥梁。负责与 /dev/fuse 设备交互,接收内核队列的请求并转发给 WFS,同时回传结果
  • WFS业务逻辑层。基于 GO-FUSE 实现文件系统接口,实现了GO-FUSE包中定义的文件系统接口,负责与 SeaweedFS 进行交互

完整数据流转流程:

  1. 应用程序发起 read 系统调用,陷入内核
  2. VFS 识别出 FUSE 挂载点,将请求交由 FUSE 内核处理
  3. FUSE 内核将请求存入队列,并通过 /dev/fuse 转发
  4. WFS 通过 GO-FUSE 从内核队列中取出请求,进行业务逻辑处理
  5. WFS 通过 RPC 调用与 SeaweedFS 集群通信完成数据读写,结果沿原路(WFS → GO-FUSE → FUSE 内核 → VFS → Java APP)返回
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐