NodeStageVolume和NodePublishVolume必须分两步:前者负责映射远端存储、确保设备节点就绪并返回staging path,后者仅执行bind mount;合并会导致设备未就绪而挂载失败。

必须用 NodeStageVolume 和 NodePublishVolume 分开处理设备准备与挂载,合并或跳过任一环节会导致 rpc error: code = Internal desc = device not staged 或 MountVolume.NodeAffinityMismatching。
为什么不能在 NodePublishVolume 里直接 mount 远端块设备
因为 NodePublishVolume 的语义仅限 bind mount:它只负责把一个已就绪的 staging path(比如 /var/lib/kubelet/plugins/kubernetes.io/csi/pv/<volume-id>/globalmount</volume-id>)挂到 Pod 的 target path。此时设备节点(如 /dev/disk/by-path/pci-0000:00:1f.2-ata-1.0)必须已存在——而这正是 NodeStageVolume 的职责。
常见错误现象:
-
NodePublishVolume报device or resource busy:实际是NodeStageVolume没成功执行,设备未登录(iSCSI)、未 attach(EBS)、或 udev 未 settle,导致后续 bind mount 失败 -
mkfs被重复调用:NodeStageVolume必须判断是否首次格式化(通过检查 staging path 是否为空),否则每次调度都会重格 - fstype 不匹配:传入
volume_context["fstype"] = "xfs",但节点上没装xfsprogs,NodeStageVolume会静默失败
Probe 和 GetPluginInfo 怎么通过 kubelet 健康检查
Probe 和 GetPluginInfo 是 kubelet 启动插件后立刻发起的校验请求,失败即拒绝注册。最常被忽略的是网络绑定和字段赋值细节。
立即学习“go语言免费学习笔记(深入)”;
实操要点:
- gRPC server 必须监听
0.0.0.0:9999,而非localhost:9999或127.0.0.1:9999;插件若跑在容器中且未设hostNetwork: true,kubelet 根本连不上 -
ProbeResponse.Ready.Status必须显式赋值为true;Go 中 proto struct 字段默认零值(false),不赋值就会被序列化成false -
GetPluginInfoResponse.Name必须与集群中CSIDriver对象的spec.name完全一致(大小写敏感),例如nfs.csi.k8s.io写成NFS.csi.k8s.io就会注册失败 - 建议额外暴露 HTTP
/healthz端点,用curl http://localhost:9998/healthz快速验证进程存活,绕过 gRPC 层级问题
ControllerPublishVolume 权限与幂等性怎么落地
这个接口不是“挂载”,而是控制面授权:比如为某节点开通 iSCSI target ACL、给云盘添加挂载点权限、或分配 FC WWN zone。它必须可重入,且需适配不同存储后端的权限模型。
关键约束:
- 必须返回
ControllerPublishVolumeResponse.PublishContext(即使为空 map),否则 kubelet 会认为响应不完整而重试 - 对同一
volume_id + node_id的多次调用,应幂等:已授权则直接返回,避免重复创建 ACL 或触发云厂商配额限制 - 如果后端不支持多节点读写(如单节点块设备),需在
ControllerPublishVolume中校验VolumeCapability.AccessMode,对MULTI_NODE_*模式直接返回FAILED_PRECONDITION - 不要在该方法里执行耗时操作(如等待云盘 attach 完成),kubelet 默认 gRPC 超时是 15 秒;异步任务应拆到单独 controller 协程中跟踪状态
真正容易被忽略的点在于 staging path 的路径稳定性与清理时机:NodeStageVolume 返回的 staging path 必须全局唯一且可复用,而 NodeUnstageVolume 不能简单 umount -l 就完事——若设备是 iSCSI LUN,还需显式 logout,否则下次 NodeStageVolume 登录会失败。这些逻辑不在 spec 里明说,但线上故障八成出在这儿。



















