卷是分成三层的
一句话总结
Kubernetes 存储分为 **StorageClass(蓝图)→ PersistentVolume(实物)→ PersistentVolumeClaim(需求单)**三层。它们分别代表不同角色的关注点,因此被拆开;只要不匹配,PVC 就会悄无声息地保持 Pending。
为什么需要它
开发者想要“一块 1Gi、可供多个节点同时使用的磁盘”。管理员决定“在 NAS 的 /volume1/k8s 下使用 NFS v4.1、hard mount、nconnect 4”。若把两种关注点混进同一对象,开发者就必须了解存储厂商。
所以 PVC 只写需求,StorageClass 定义把需求变成实物的方法,PV 代表实物。binding 条件很简单:storageClassName 相同,PV 的 accessModes 包含 PVC 的要求,并且 PV 容量不小于 PVC 请求,即可绑定。任一条件不符都会无错误地 Pending。
CSI 的出现也源于相同的解耦需求。过去存储插件位于 Kubernetes 核心代码内部(in-tree),添加新存储必须修改 Kubernetes 本身。CSI 解除了这种耦合,driver 分为 controller(Deployment,负责 volume 创建、删除、扩展、snapshot)和 node plugin(DaemonSet,负责 mount/unmount)。node plugin 使用 DaemonSet,是因为所有可能调度 Pod 的节点都必须具备它。
它如何运作
StorageClass 中有三个一旦写错就很难挽回的字段。
| 字段 | 含义 | 写错后果 |
|---|---|---|
reclaimPolicy |
PVC 删除后 PV 的命运 | 设为 Delete 会连数据一起消失 |
volumeBindingMode |
何时创建 volume | Immediate 可能让 volume 与 Pod 出现在不同 zone |
allowVolumeExpansion |
日后是否可以扩容 | 使用 false 类别的 PVC 永远无法扩容 |
WaitForFirstConsumer 会在得知 Pod 将调度到哪个节点后再创建 volume,是多 zone 环境的必需设置。
访问模式有四种:RWO(单节点读写)、ROX(多节点只读)、RWX(多节点读写)、RWOP(单 Pod 专用)。block storage 通常只支持到 RWO,RWX 属于 NFS 等 file storage 的领域。
在设有默认 StorageClass 的集群中,如果不想使用该类,不能省略 storageClassName,而要明确写为空字符串。省略时会注入默认值。这一区别也会出现在考试中。
在实际工作中会遇到的情况
案例 1——先确认 mount。家庭实验室运行 kubectl get sc 时得到 No resources found。没有 StorageClass,PVC 会永远 Pending,任何有状态 workload 都无法部署。决定接入家中的 Synology NAS 后,没有先装 driver,而是先确认能否从 Pod mount NFS。第一次失败了。
mount.nfs: Operation not permitted for 10.0.0.109:/volume1/k8s on /mnt/t
即使设置 privileged: true 仍被拒绝,缺少的是 hostNetwork: true。NFS mount 会与 rpcbind 通信,并使用低于 1024 的 reserved port 作为 source port,在 Pod network namespace 内这种行为会受限。**privileged 提供 capability,却无法解决 network namespace 问题。**因为遵循了顺序,所以很快确认原因不在 driver。
**案例 2——按用途拆分类别。**安装 csi-driver-nfs 4.13.4 后创建了两套 StorageClass。
nfs-synology(默认)——reclaimPolicy: Delete、onDelete: archive、allowVolumeExpansion: true,mount option 为nfsvers=4.1, hard, nconnect=4, noatimenfs-synology-retain——reclaimPolicy: Retain、onDelete: retain
选择 hard 的原因尤其重要。soft 会在 timeout 时向应用返回 I/O error,数据库写入途中收到错误,可能造成无声的数据损坏。hard 会无限重试直至 server 恢复,数据更安全;代价是 NAS 故障时 Pod 看似无错误地停住,难以判断原因。所有存储设置都有这种取舍。
subDir pattern 也设为 네임스페이스-PVC이름-PV이름。只使用 PV 名称,NAS file explorer 中只会看到 pvc-da6bb53d-... 这样的 UUID,日后无法判断哪些可以删除。
案例 3——容量不会被强制执行。PVC 请求 2Gi,但 NFS 没有强制它的手段。Pod 使用 100GB 也不会被阻止。PVC 容量只是用于 scheduling 和 accounting 的 metadata,真正限制必须由 backend 实现。block storage 的 volume size 本身就是物理限制,自然可以强制;NFS 子目录则不是。
还亲眼看到了 archive 策略的代价。打开 NFS export root 后,发现旧集群留下了 32 个目录,Prometheus 和 OpenSearch 数据仍在,19.9T 中已使用 9.4T。它虽然安全,但如果无人清理就会不断堆积。
后续实验要做什么
创建两套 StorageClass 并确认三个字段的差异,静态绑定 PV 与 PVC,创建 RWX volume,并观察 StatefulSet 的 volumeClaimTemplates 自动创建 PVC。最后一步是明确拒绝默认 StorageClass。