把存储的三层编在一起
目标
亲手创建 StorageClass、PV、PVC 三层对象,掌握绑定条件,并确认 StatefulSet 如何处理卷。
为什么这很重要
PVC 处于 Pending 的原因始终是三者之一:class 名称不匹配、访问模式不匹配,或者容量不足。此外,还有因 provisioner 不存在而无法动态创建的情况。本实验环境没有真正的 CSI 驱动,因此会通过静态绑定逐一确认这些条件。虽然无法写入真实数据,但考试大多数题目检查的也正是对象 spec 和绑定状态。
提前了解 allowVolumeExpansion 这类事后修改也无效的字段,同样很重要。由值为 false 的 class 创建的 PVC,即使后来修改 class,也无法扩容。
步骤
- 创建 namespace
cka-storage和 StorageClasscka-fast。provisioner 为nfs.csi.k8s.io,reclaimPolicy 为Delete,volumeBindingMode 为WaitForFirstConsumer,allowVolumeExpansion 为true。 - 创建 StorageClass
cka-archive。provisioner 为nfs.csi.k8s.io,reclaimPolicy 为Retain,volumeBindingMode 为Immediate。然后为cka-fast添加注解storageclass.kubernetes.io/is-default-class: "true",将其设为默认 class。默认 class 必须恰好只有一个。 - 创建 PersistentVolume
cka-pv-1。capacity 为 2Gi,accessModes 为[ReadWriteOnce],persistentVolumeReclaimPolicy 为Retain,storageClassName 为cka-manual,卷源为 hostPath/mnt/cka-data。 - 在
cka-storage中创建 PVCcka-pvc-1。请求 1Gi,accessModes 为[ReadWriteOnce],storageClassName 为cka-manual。它应与cka-pv-1绑定为 Bound。 - 创建 PersistentVolume
cka-pv-rwx。capacity 为 5Gi,accessModes 为[ReadWriteMany],storageClassName 为cka-shared,卷源为 NFS(server10.0.0.109,path/volume1/k8s)。然后创建 PVCcka-pvc-rwx(5Gi、RWX、cka-shared)并使其绑定为 Bound。 - 创建 headless Service
db-headless(clusterIP None、port 5432、selectorapp=db)和 StatefulSetdb。serviceName 为db-headless,副本数为 2,镜像为nginx:1.27,podManagementPolicy 为Parallel;volumeClaimTemplates 名称为data(accessModes[ReadWriteOnce]、storageClassNamecka-fast、1Gi);persistentVolumeClaimRetentionPolicy 设置 whenDeletedDelete/ whenScaledRetain。应自动创建 PVCdata-db-0和data-db-1。 - 在
cka-storage中创建 Podvol-demo(镜像nginx:1.27)。卷cache使用 emptyDir,medium 为Memory,sizeLimit 为128Mi,挂载到/cache。卷hostlogs使用 hostPath path/var/log,type 为Directory,以 readOnly 方式挂载到/hostlogs。 - 创建 PersistentVolume
cka-pv-static(capacity 1Gi、accessModes[ReadWriteOnce]、完全不设置 storageClassName、hostPath/mnt/cka-static),再创建 PVCcka-pvc-static(1Gi、RWO),明确将 storageClassName 设为空字符串,并使其绑定为 Bound。
参考
- 第 6 步的 PVC 会因没有 provisioner 而保持 Pending。这是正常情况,评分会检查 PVC 对象是否已创建。
- 使用
kubectl get pvc -n cka-storage同时查看 STATUS 与 VOLUME 列,就能一眼了解绑定状态。 - 常见错误 1:将 PV 的回收策略字段写成
reclaimPolicy。PV 中应为persistentVolumeReclaimPolicy。 - 常见错误 2:第 8 步省略
storageClassName。省略后会注入默认 classcka-fast,导致无法绑定。
创建 StorageClass
创建 namespace cka-storage 和 StorageClass cka-fast。provisioner 为 nfs.csi.k8s.io,reclaimPolicy 为 Delete,volumeBindingMode 为 WaitForFirstConsumer,allowVolumeExpansion 为 true。
provisioner 是字符串,即使驱动实际上不存在,也可以创建对象。reclaimPolicy、volumeBindingMode、allowVolumeExpansion 是 StorageClass 的顶层字段,不在 parameters 中。
创建第二个 class 并指定默认 class
创建 StorageClass cka-archive。provisioner 为 nfs.csi.k8s.io,reclaimPolicy 为 Retain,volumeBindingMode 为 Immediate。然后为 cka-fast 添加注解 storageclass.kubernetes.io/is-default-class: "true",将其设为默认 class。默认 class 必须恰好只有一个。
默认 class 通过注解指定。如果默认 class 超过一个,就无法预测会使用哪一个,因此必须恰好只有一个。
手动创建 PersistentVolume
创建 PersistentVolume cka-pv-1。capacity 为 2Gi,accessModes 为 [ReadWriteOnce],persistentVolumeReclaimPolicy 为 Retain,storageClassName 为 cka-manual,卷源为 hostPath /mnt/cka-data。
PV 是集群作用域资源。请注意,它的回收策略字段名称与 StorageClass 不同。
确认静态绑定
在 cka-storage 中创建 PVC cka-pvc-1。请求 1Gi,accessModes 为 [ReadWriteOnce],storageClassName 为 cka-manual。它应与 cka-pv-1 绑定为 Bound。
绑定条件有三项:class 名称一致、包含所需访问模式、容量满足需求。任何一项不匹配,PVC 都会悄无声息地保持 Pending。
创建 RWX 卷
创建 PersistentVolume cka-pv-rwx。capacity 为 5Gi,accessModes 为 [ReadWriteMany],storageClassName 为 cka-shared,卷源为 NFS(server 10.0.0.109,path /volume1/k8s)。然后创建 PVC cka-pvc-rwx(5Gi、RWX、cka-shared)并使其绑定为 Bound。
PV 与 PVC 的 accessModes 必须匹配才能绑定。NFS 卷源要求 server 和 path 两个字段。
通过 volumeClaimTemplates 自动创建 PVC
创建 headless Service db-headless(clusterIP None、port 5432、selector app=db)和 StatefulSet db。serviceName 为 db-headless,副本数为 2,镜像为 nginx:1.27,podManagementPolicy 为 Parallel;volumeClaimTemplates 名称为 data(accessModes [ReadWriteOnce]、storageClassName cka-fast、1Gi);persistentVolumeClaimRetentionPolicy 设置 whenDeleted Delete / whenScaled Retain。应自动创建 PVC data-db-0 和 data-db-1。
PVC 名称由模板名称与 Pod 名称组合而成。需要改变默认行为,避免第一个 Pod 未 Ready 时阻止创建后续 Pod。
挂载 emptyDir 与 hostPath
在 cka-storage 中创建 Pod vol-demo(镜像 nginx:1.27)。卷 cache 使用 emptyDir,medium 为 Memory,sizeLimit 为 128Mi,挂载到 /cache。卷 hostlogs 使用 hostPath path /var/log,type 为 Directory,以 readOnly 方式挂载到 /hostlogs。
卷定义位于 spec.volumes,挂载位于容器的 volumeMounts。内存型 emptyDir 通过 medium 字段指定。
综合:拒绝使用默认 StorageClass
创建 PersistentVolume cka-pv-static(capacity 1Gi、accessModes [ReadWriteOnce]、完全不设置 storageClassName、hostPath /mnt/cka-static),再创建 PVC cka-pvc-static(1Gi、RWO),明确将 storageClassName 设为空字符串,并使其绑定为 Bound。
省略字段与明确设置为空字符串并不相同。前者会注入默认值,后者表示拒绝使用默认值。