4. PowerStore CSI集成实战
本节把前面学到的 CSI 原理落到 Dell PowerStore 上,完成一条从阵列侧到 Pod 侧的完整链路:先在 PowerStore 上准备可供 CSI 使用的 NAS 服务器与文件系统,再在 Kubernetes 集群中安装 PowerStore CSI 驱动,接着定义 StorageClass,最后通过 PVC 触发动态卷供给,并把卷挂载进 Pod 验证读写。整条链路的判断依据是:PVC 能 Bound、PV 在 PowerStore 上真实存在、Pod 内可读写且数据落盘。
一、PowerStore 阵列侧准备
PowerStore CSI 驱动同时支持块(iSCSI/FC)与文件(NFS)两种访问方式。本节以 NFS 文件卷为例,因为它对实验环境最友好,不需要在每台节点上配置多路径。阵列侧需要准备三样东西:一个 NAS 服务器、一个文件系统、一个供 CSI 使用的存储网络地址。
登录 PowerStore Manager,进入 Storage → NAS Servers,创建一个 NAS 服务器,例如命名为 nas-k8s,选择文件系统所在的数据网络。随后进入 Storage → File Systems 创建文件系统,示例参数如下:名称 fs-k8s-csi,容量 200 GB,所属 NAS 服务器 nas-k8s,访问策略允许 Kubernetes 节点网段 192.168.30.0/24 读写。创建完成后记录 NAS 服务器 IP,例如 192.168.30.50,这个地址会作为 CSI 的 NFS 服务端。
还需要在 PowerStore 上创建一个供 CSI 调用的本地用户,例如 csi-user,赋予其管理文件系统的权限。CSI 驱动通过 REST API 与该用户通信,因此要记录用户名和密码,后续写入 Secret。若使用块存储,则改为准备主机组、iSCSI 或 FC 启动器,并确保节点已登录到阵列;文件方式无需这一步。
二、安装 PowerStore CSI 驱动
PowerStore CSI 驱动以 Helm Chart 形式发布,官方仓库为 https://dell.github.io/csm-helm-charts。安装前先确认集群版本与驱动版本匹配,并确认所有工作节点都能访问 NAS 服务器 IP 的 2049 端口。
helm repo add dell https://dell.github.io/csm-helm-charts
helm repo update
helm search repo dell/powerstore --versions | head -5
创建命名空间并写入连接凭据。PowerStore 的凭据以 Secret 形式提供,包含阵列管理 IP、用户名和密码:
kubectl create namespace powerstore
kubectl -n powerstore create secret generic powerstore-config \
--from-literal=username='csi-user' \
--from-literal=password='YourPassword' \
--from-literal=endpoint='https://192.168.30.50'
随后安装驱动。文件卷场景需要显式开启 NFS 能力,并指定 NAS 服务器地址:
helm -n powerstore install powerstore dell/powerstore \
--set nfs.enabled=true \
--set nfs.nasServerIP=192.168.30.50 \
--set controller.replicas=1 \
--set node.replicas=3
安装完成后检查 Pod 状态,应看到 controller 与 node 两类组件全部 Running:
kubectl -n powerstore get pods
# powerstore-controller-0 5/5 Running
# powerstore-node-xxxxx 3/3 Running (每个节点一个)
controller 负责与 PowerStore REST API 交互,完成卷的创建、删除、扩容和快照;node 以 DaemonSet 形式运行在每个节点上,负责把远端文件系统挂载到本地路径。两者都 Running,才说明驱动已就绪。
三、配置 StorageClass
StorageClass 是 PVC 与驱动之间的“契约”,它告诉 Kubernetes:这类 PVC 应该由哪个 provisioner 供给、用什么参数、回收策略是什么。PowerStore 驱动的 provisioner 名称为 csi-powerstore.dellemc.com。文件卷场景的示例如下:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: powerstore-nfs
provisioner: csi-powerstore.dellemc.com
reclaimPolicy: Delete
volumeBindingMode: Immediate
parameters:
csi.storage.k8s.io/fstype: nfs
arrayID: "APM00123456789"
其中 arrayID 是 PowerStore 阵列的唯一标识,可在阵列管理界面或 REST API 中查询;fstype: nfs 表示走文件卷路径。若使用块卷,则去掉 fstype 并改为指定协议类型。创建后执行 kubectl get sc,应看到 powerstore-nfs 且 provisioner 正确。
四、动态卷供给与 Pod 挂载验证
动态供给的关键在于:用户只声明 PVC,不手动创建 PV。先写一个 PVC,指定 storageClassName 与容量:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-data
spec:
accessModes: ["ReadWriteMany"]
storageClassName: powerstore-nfs
resources:
requests:
storage: 10Gi
应用后观察状态变化:kubectl get pvc pvc-data -w。正常情况下会从 Pending 变为 Bound,同时 kubectl get pv 会出现一个自动创建的 PV,其名称通常带有阵列生成的卷 ID。此时回到 PowerStore Manager,在文件系统下应能看到 CSI 自动创建的子目录或卷对象,容量为 10Gi。这就是“动态供给”的直接证据:PV 不是人写的,而是驱动调用阵列 API 创建的。
接着创建 Pod 挂载该 PVC:
apiVersion: v1
kind: Pod
metadata:
name: app-pod
spec:
containers:
- name: app
image: busybox:1.36
command: ["sh","-c","sleep 3600"]
volumeMounts:
- name: data
mountPath: /data
volumes:
- name: data
persistentVolumeClaim:
claimName: pvc-data
Pod Running 后进入容器验证:
kubectl exec -it app-pod -- sh
/ # echo "powerstore-csi-test" > /data/test.txt
/ # cat /data/test.txt
powerstore-csi-test
为了确认数据真正落在 PowerStore 而非节点本地,可以删除 Pod 再重建,重新挂载同一 PVC 后再次读取 /data/test.txt。如果内容仍在,说明卷是持久化的、由阵列承载的。进一步可在 PowerStore 侧查看该文件系统已用容量增加,或通过 NFS 客户端从节点直接挂载 NAS 服务器 IP 查看同一目录,形成交叉验证。
五、结果判读与常见问题
整条链路的成功标志可以归纳为四个可观察点:PVC 状态为 Bound;PV 自动出现且容量与请求一致;Pod 内 /data 可读写;删除重建 Pod 后数据仍在。任何一点不满足,都说明链路某处断开。
常见问题中,PVC Pending 多因 StorageClass 名称不匹配或 provisioner 未就绪;挂载失败多因节点到 NAS 服务器 2049 端口不通或防火墙拦截;认证失败则检查 Secret 中的用户名密码与阵列是否一致。排查时按“阵列 → 驱动 → StorageClass → PVC → Pod”的顺序逐段确认,比盲目重启组件更有效。
完成本节后,你已经打通了 PowerStore CSI 从阵列准备到 Pod 挂载的完整路径。这条路径也是后续快照、扩容、克隆等高级能力的基础:只要动态供给链路是通的,其余操作都只是在同一套 CSI 接口上增加参数与调用。