Qingular

StorageClass 与动态存储

·CKAk8s练习

CKA 考试 Domain 4 — StorageClass 定义、动态 PV 供给、CSI 驱动、默认 StorageClass

← 返回 CKA 练习目录 StorageClass 为管理员提供了一种描述存储"类"的方法,实现动态 PV 供给,避免管理员手动预置 PV。


1. StorageClass 定义与 provisioner

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: fast
provisioner: kubernetes.io/aws-ebs
parameters:
  type: gp3
  fsType: ext4
  encrypted: "true"
reclaimPolicy: Delete
allowVolumeExpansion: true
volumeBindingMode: Immediate

核心字段:

字段说明
provisioner存储后端驱动名称
parameters传递给 provisioner 的参数
reclaimPolicy动态 PV 的回收策略(Delete 或 Retain)
allowVolumeExpansion是否允许 PVC 扩容
volumeBindingMode绑定模式(Immediate 或 WaitForFirstConsumer)
mountOptions挂载选项

2. 动态 PV 供给原理

  1. 用户创建 PVC(指定 storageClassName: fast
  2. Kubernetes 控制平面找到对应的 StorageClass
  3. 调用 StorageClass 的 provisioner 创建存储资源
  4. 自动创建 PV 并绑定到 PVC
  5. Pod 使用 PVC 挂载存储
User (PVC) ──► StorageClass ──► Provisioner ──► 实际存储 ──► PV

3. 默认 StorageClass

设置默认 StorageClass 后,创建 PVC 时不指定 storageClassName 会自动使用默认 StorageClass。

# 查看当前默认 StorageClass
kubectl get storageclass

# 将某个 StorageClass 设为默认
kubectl patch storageclass standard -p \
  '{"metadata": {"annotations": {"storageclass.kubernetes.io/is-default-class": "true"}}}'
metadata:
  annotations:
    storageclass.kubernetes.io/is-default-class: "true"

注意:PVC 中 storageClassName: "" 表示不使用默认 StorageClass,而是使用静态 PV。


4. 常用 Provisioner

AWS EBS

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: aws-ebs-gp3
provisioner: ebs.csi.aws.com
parameters:
  type: gp3
  fsType: ext4
  encrypted: "true"
  iopsPerGB: "10"
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer

GCE PD

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: gce-pd-ssd
provisioner: pd.csi.storage.gke.io
parameters:
  type: pd-ssd
  replication-type: none
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer

Azure Disk

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: azure-disk
provisioner: disk.csi.azure.com
parameters:
  skuname: Premium_LRS
  cachingMode: ReadOnly
reclaimPolicy: Delete
allowVolumeExpansion: true

NFS(通过 CSI)

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs-csi
provisioner: nfs.csi.k8s.io
parameters:
  server: nfs-server.example.com
  share: /exports
reclaimPolicy: Delete
volumeBindingMode: Immediate
mountOptions:
  - hard
  - nfsvers=4.1

5. volumeBindingMode

模式说明
Immediate创建 PVC 后立即创建 PV 并绑定
WaitForFirstConsumer等到第一个 Pod 使用 PVC 时才创建 PV(可感知 Pod 调度节点的 AZ)

WaitForFirstConsumer 常用于多云/多可用区环境,确保 PV 创建在与 Pod 相同的可用区。


6. volumeBindingMode 绑定模式对比

# 延迟绑定:PV 会创建在 Pod 调度到的节点所在 AZ
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: regional-ssd
provisioner: pd.csi.storage.gke.io
volumeBindingMode: WaitForFirstConsumer

7. CSI 驱动的概念与使用

CSI(Container Storage Interface)是 Kubernetes 推荐的存储插件机制。

优势:

  • 插件无需编译进 Kubernetes 二进制文件
  • 通过 DaemonSet 部署,热插拔
  • 支持快照、扩容、克隆等高级功能
# 查看已安装的 CSI 驱动
kubectl get csidriver

# 查看 CSI 节点状态
kubectl get csinodes

8. 实用命令

# 查看所有 StorageClass
kubectl get sc
kubectl get storageclass

# 查看 StorageClass 详情
kubectl describe sc <storage-class-name>

# 创建 StorageClass(X YAML)
kubectl create -f sc.yaml

# 删除 StorageClass
kubectl delete sc <storage-class-name>

# 检查默认 StorageClass
kubectl get sc -o jsonpath='{.items[*].metadata.annotations.storageclass\.kubernetes\.io/is-default-class}'

9. 考试要点

  • PVC 不指定 storageClassName = 使用默认 StorageClass
  • PVC 指定 storageClassName: "" = 使用静态 PV(手动创建)
  • WaitForFirstConsumer 在拓扑感知环境中非常重要
  • 动态 PV 的 reclaimPolicy 默认为 Delete
  • CSI 是目前官方推荐的存储扩展方式

🧪 完整操作实例:使用 StorageClass 动态创建 PV

场景描述

定义一个 StorageClass 并使用其自动创建 PV,观察动态供给的完整流程以及回收策略(Delete)的效果。

前置条件

  • 集群中需要有 CSI 驱动的 provisioner(如 ebs.csi.aws.compd.csi.storage.gke.io 等)
  • 如果使用 minikube,启用 standard StorageClass 即可;以下示例使用本地 standard 作为模拟

操作步骤

Step 1: 查看集群中已有的 StorageClass

kubectl get sc
# NAME                   PROVISIONER                     RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
# standard (default)     k8s.io/minikube-hostpath        Delete          Immediate             false                  15d

Step 2: 创建自定义 StorageClass

cat <<EOF | kubectl apply -f -
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: fast-storage
provisioner: k8s.io/minikube-hostpath
parameters:
  type: pd-ssd
reclaimPolicy: Delete
volumeBindingMode: Immediate
allowVolumeExpansion: true
EOF

kubectl get sc
# NAME                   PROVISIONER                     RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
# fast-storage           k8s.io/minikube-hostpath        Delete          Immediate             true                   5s
# standard (default)     k8s.io/minikube-hostpath        Delete          Immediate             false                  15d

Step 3: 创建 PVC 引用该 StorageClass

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: dynamic-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  storageClassName: fast-storage
EOF

Step 4: 观察 PV 被动态创建

kubectl get pvc
# NAME          STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
# dynamic-pvc   Bound    pvc-8f3b2c1d-...                          1Gi        RWO            fast-storage    10s

kubectl get pv
# NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                 STORAGECLASS   AGE
# pvc-8f3b2c1d-...                           1Gi        RWO            Delete           Bound    default/dynamic-pvc   fast-storage    10s

PV 的名称是动态生成的 UUID 格式,RECLAIM POLICY 自动继承 StorageClass 的 Delete

Step 5: 查看动态 PV 的详细信息

kubectl describe pv pvc-8f3b2c1d-...
# ...
# Source:
#     Type:          HostPath (bare host directory volume)
#     Path:          /data/hostpath-provisioner/default/dynamic-pvc
# ...
# Reclaim Policy:  Delete
# StorageClass:    fast-storage

Step 6: 删除 PVC 观察 PV 自动删除

kubectl delete pvc dynamic-pvc

kubectl get pvc
# No resources found in default namespace.

kubectl get pv
# (之前动态创建的 PV 已被自动删除,不显示)

由于 reclaimPolicy: Delete,PVC 删除后关联的 PV 会被自动删除,无需手动干预。

验证结果

# 验证 StorageClass 是否成功创建
kubectl get sc fast-storage -o jsonpath='{.provisioner}'
# k8s.io/minikube-hostpath

# 验证 PVC 引用的是正确的 StorageClass
kubectl get pvc dynamic-pvc -o jsonpath='{.spec.storageClassName}'
# fast-storage

# 验证动态 PV 的回收策略
kubectl get pv -o jsonpath='{.items[0].spec.persistentVolumeReclaimPolicy}'
# Delete

考试提示

  • PVC 不指定 storageClassName 会使用集群默认的 StorageClass
  • PVC 指定 storageClassName: "" 表示使用静态 PV,不启用动态供给
  • 动态 PV 的回收策略默认为 Delete,如果希望保留数据应改为 Retain
  • WaitForFirstConsumer 模式下 PVC 创建后 STATUS 仍为 Pending,直到第一个 Pod 使用它
  • 考试中如果出现动态供给场景,记得检查 StorageClass 的 provisioner 是否匹配

官方文档