avatar🌌
TangentTangent Blog

技术博客 | Go & Kubernetes & Linux

技术博客 | Go & Kubernetes & Linux

Kubernetes StorageClass 详解与实验教程

一、StorageClass 简介 ​

1.1 什么是 StorageClass ​

StorageClass(存储类)是 Kubernetes 中用于描述存储类型和策略的资源对象。它为管理员提供了一种方式来描述他们提供的存储的"类别",不同的类别可能会映射到不同的服务质量等级、备份策略或由集群管理员决定的任意策略。

1.2 StorageClass 的核心作用 ​

  1. 动态卷供应(Dynamic Volume Provisioning):自动创建 PV,无需管理员手动预配置
  2. 存储抽象:为用户提供统一的存储访问接口,隐藏底层存储实现细节
  3. 策略管理:定义存储的回收策略、挂载选项等
  4. 多存储后端支持:支持不同类型的存储系统(NFS、云存储、本地存储等)

1.3 StorageClass 与 PV/PVC 的关系 ​

用户创建 PVC → 指定 StorageClass → Provisioner 动态创建 PV → PVC 绑定 PV → Pod 使用存储

二、StorageClass 核心组件 ​

2.1 Provisioner(存储提供者) ​

Provisioner 是负责动态创建 PV 的组件,常见类型包括:

  • 内置 Provisioner:

    • kubernetes.io/aws-ebs(AWS EBS)
    • kubernetes.io/gce-pd(Google Cloud Persistent Disk)
    • kubernetes.io/azure-disk(Azure Disk)
  • 外部 Provisioner:

    • k8s-sigs.io/nfs-subdir-external-provisioner(NFS)
    • csi.driver.name(CSI 驱动)

2.2 Parameters(参数) ​

定义存储的具体配置参数,不同 Provisioner 支持的参数不同。

2.3 ReclaimPolicy(回收策略) ​

  • Delete:默认策略,PVC 删除时自动删除 PV 和底层存储
  • Retain:保留 PV 和数据,需要手动清理

2.4 VolumeBindingMode(卷绑定模式) ​

  • Immediate:立即绑定(默认)
  • WaitForFirstConsumer:等待第一个消费者(Pod)调度后再绑定

三、NFS StorageClass 实验环境搭建 ​

3.1 环境准备 ​

本实验需要以下环境:

  • Kubernetes 集群(v1.18+)
  • NFS 服务器(IP: 10.128.0.5)
  • NFS 共享目录:/nfs/share

3.2 NFS 服务器配置 ​

在 NFS 服务器上执行以下命令:

bash
dnf install nfs-utils rpcbind

mkdir -p /nfs/share
chown nobody:nobody /nfs/share
chmod 755 /nfs/share

echo "/nfs/share *(rw,sync,no_subtree_check,no_root_squash)" >> /etc/exports

systemctl enable --now rpcbind
systemctl enable --now nfs-server

exportfs -ra

showmount -e localhost

3.3 Kubernetes 节点配置 ​

在所有 Kubernetes 节点上安装 NFS 客户端:

bash
dnf install nfs-utils

apt-get update && apt-get install -y nfs-common

showmount -e 10.128.0.5

四、部署 NFS External Provisioner ​

4.1 创建命名空间 ​

bash
kubectl create namespace nfs-storageclass

4.2 部署 RBAC 权限 ​

创建 serviceAccount.yaml 文件:

yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: nfs-client-provisioner
  namespace: nfs-storageclass
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: nfs-client-provisioner-runner
rules:
  - apiGroups: [""]
    resources: ["nodes"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["persistentvolumes"]
    verbs: ["get", "list", "watch", "create", "delete"]
  - apiGroups: [""]
    resources: ["persistentvolumeclaims"]
    verbs: ["get", "list", "watch", "update"]
  - apiGroups: ["storage.k8s.io"]
    resources: ["storageclasses"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["events"]
    verbs: ["create", "update", "patch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: run-nfs-client-provisioner
subjects:
  - kind: ServiceAccount
    name: nfs-client-provisioner
    namespace: nfs-storageclass
roleRef:
  kind: ClusterRole
  name: nfs-client-provisioner-runner
  apiGroup: rbac.authorization.k8s.io
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: leader-locking-nfs-client-provisioner
  namespace: nfs-storageclass
rules:
  - apiGroups: [""]
    resources: ["endpoints"]
    verbs: ["get", "list", "watch", "create", "update", "patch"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: leader-locking-nfs-client-provisioner
  namespace: nfs-storageclass
subjects:
  - kind: ServiceAccount
    name: nfs-client-provisioner
    namespace: nfs-storageclass
roleRef:
  kind: Role
  name: leader-locking-nfs-client-provisioner
  apiGroup: rbac.authorization.k8s.io

4.3 部署 NFS Provisioner ​

创建 nfs-client.yaml 文件:

yaml
kind: Deployment
apiVersion: apps/v1
metadata:
  name: nfs-client-provisioner
  namespace: nfs-storageclass
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nfs-client-provisioner
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: nfs-client-provisioner
    spec:
      serviceAccountName: nfs-client-provisioner
      containers:
        - name: nfs-client-provisioner
          image: k8s.dockerproxy.com/sig-storage/nfs-subdir-external-provisioner:v4.0.2
          volumeMounts:
            - name: nfs-client-root
              mountPath: /persistentvolumes
          env:
            - name: PROVISIONER_NAME
              value: k8s-sigs.io/nfs-subdir-external-provisioner
            - name: NFS_SERVER
              value: 10.140.0.8  # NFS 服务器 IP
            - name: NFS_PATH
              value: /nfs/share  # NFS 共享路径
      volumes:
        - name: nfs-client-root
          nfs:
            server: 10.140.0.8
            path: /nfs/share

4.4 创建 StorageClass ​

创建 storageClass.yaml 文件:

yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs-client
  namespace: nfs-storageclass
provisioner: k8s-sigs.io/nfs-subdir-external-provisioner
parameters:
  pathPattern: ${.PVC.namespace}/${.PVC.name}
  onDelete: delete

参数说明:

  • pathPattern:定义在 NFS 服务器上创建的目录路径模式
    • ${.PVC.namespace}:PVC 所在的命名空间
    • ${.PVC.name}:PVC 的名称
  • onDelete:PVC 删除时的行为
    • delete:删除对应的 NFS 目录
    • retain:保留 NFS 目录

五、StorageClass 实验操作 ​

5.1 部署所有组件 ​

bash
kubectl apply -f serviceAccount.yaml

kubectl apply -f nfs-client.yaml

kubectl apply -f storageClass.yaml

kubectl get pods -n nfs-storageclass
kubectl get storageclass

5.2 创建测试 PVC 和 Pod ​

创建 pod.yaml 测试文件:

yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: test-claim
spec:
  accessModes:
    - ReadWriteMany  # 支持多节点读写
  resources:
    requests:
      storage: 1Mi   # 请求 1MB 存储空间
  storageClassName: nfs-client  # 指定使用的 StorageClass
---
kind: Pod
apiVersion: v1
metadata:
  name: test-pod
spec:
  containers:
    - name: test-pod
      image: wangyanglinux/myapp:v1.0  # Nginx 镜像
      volumeMounts:
        - name: nfs-pvc
          mountPath: "/usr/share/nginx/html"  # 挂载到 Nginx 网站根目录
  restartPolicy: "Never"
  volumes:
    - name: nfs-pvc
      persistentVolumeClaim:
        claimName: test-claim

5.3 执行测试 ​

bash
kubectl apply -f pod.yaml

kubectl get pvc test-claim

kubectl get pv

kubectl get pods test-pod -o wide

ls -la /nfs/share/default/test-claim/

5.4 验证存储功能 ​

bash
POD_IP=$(kubectl get pod test-pod -o jsonpath='{.status.podIP}')

curl $POD_IP

kubectl exec -it test-pod -- /bin/bash
echo "Hello from NFS StorageClass!" > /usr/share/nginx/html/index.html
exit

curl $POD_IP

cat /nfs/share/default/test-claim/index.html

六、StorageClass 高级特性 ​

6.1 设置默认 StorageClass ​

bash
kubectl patch storageclass nfs-client -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'

kubectl get storageclass

6.2 卷绑定模式配置 ​

yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs-client-wait
provisioner: k8s-sigs.io/nfs-subdir-external-provisioner
volumeBindingMode: WaitForFirstConsumer  # 等待第一个消费者
parameters:
  pathPattern: ${.PVC.namespace}/${.PVC.name}
  onDelete: delete

6.3 挂载选项配置 ​

yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs-client-custom
provisioner: k8s-sigs.io/nfs-subdir-external-provisioner
mountOptions:
  - hard          # 硬挂载
  - nfsvers=4     # 使用 NFSv4
  - timeo=600     # 超时时间
parameters:
  pathPattern: ${.PVC.namespace}/${.PVC.name}
  onDelete: retain  # 保留数据

七、故障排查与维护 ​

7.1 常见问题诊断 ​

bash
kubectl logs -n nfs-storageclass deployment/nfs-client-provisioner

kubectl describe pvc test-claim

kubectl describe storageclass nfs-client

kubectl exec -it test-pod -- df -h

journalctl -u nfs-server -f

7.2 性能优化建议 ​

  1. NFS 挂载参数优化:

    yaml
    mountOptions:
      - vers=4.1
      - rsize=1048576
      - wsize=1048576
      - hard
      - timeo=600
      - retrans=2
  2. 网络优化:

    • 使用千兆或万兆网络
    • 配置 NFS 专用网络
    • 调整 MTU 大小
  3. 存储优化:

    • 使用 SSD 存储
    • 配置 RAID
    • 定期备份重要数据

7.3 清理资源 ​

bash
kubectl delete -f pod.yaml

kubectl delete -f storageClass.yaml

kubectl delete -f nfs-client.yaml
kubectl delete -f serviceAccount.yaml

kubectl delete namespace nfs-storageclass

八、实验总结 ​

通过本实验,我们学习了:

  1. StorageClass 的基本概念:了解了存储类的作用和核心组件
  2. 动态卷供应:掌握了如何通过 StorageClass 自动创建 PV
  3. NFS 集成:学会了如何将 NFS 存储集成到 Kubernetes 中
  4. 实际应用:通过完整的实验验证了 StorageClass 的工作流程

关键要点 ​

  • StorageClass 简化了存储管理,实现了存储的动态供应
  • Provisioner 是 StorageClass 的核心,负责实际的存储创建
  • 不同的存储后端需要不同的 Provisioner 和参数配置
  • 合理的存储策略配置对于生产环境至关重要

生产环境建议 ​

  1. 安全性:配置适当的 RBAC 权限和网络策略
  2. 高可用:部署多副本 Provisioner,配置存储高可用
  3. 监控:建立完善的存储监控和告警机制
  4. 备份:制定数据备份和恢复策略
  5. 测试:定期进行故障恢复测试
KEDA Scale to Zero in Practice
PV(PersistentVolume)与 PVC(PersistentVolumeClaim)详解
由 Valaxy v1.2.2 驱动|主题-Yunv1.2.2