avatar🌌
TangentTangent Blog

技术博客 | Go & Kubernetes & Linux

技术博客 | Go & Kubernetes & Linux

Kubernetes StorageClass Explained and Lab Tutorial

1. Introduction to StorageClass ​

1.1 What is StorageClass ​

StorageClass is a resource object in Kubernetes used to describe storage types and policies. It provides administrators with a way to describe "classes" of storage they offer. Different classes may map to different quality-of-service levels, backup policies, or arbitrary policies set by the cluster admin.

1.2 Core Functions of StorageClass ​

  1. Dynamic Volume Provisioning: Automatically creates PVs, no need for manual pre-provisioning
  2. Storage Abstraction: Provides users with a unified storage access interface, hiding backend details
  3. Policy Management: Defines reclaim policies, mount options, etc.
  4. Multi-backend Support: Supports different storage systems (NFS, cloud storage, local storage, etc.)

1.3 Relationship with PV/PVC ​

User creates PVC → specifies StorageClass → Provisioner dynamically creates PV → PVC binds PV → Pod uses storage

2. Core Components of StorageClass ​

2.1 Provisioner ​

The Provisioner is responsible for dynamically creating PVs. Common types include:

  • Built-in Provisioners:

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

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

2.2 Parameters ​

Defines specific configuration parameters for storage. Supported parameters vary by provisioner.

2.3 ReclaimPolicy ​

  • Delete: Default. PV and backend storage are deleted when PVC is deleted
  • Retain: PV and data are retained, manual cleanup required

2.4 VolumeBindingMode ​

  • Immediate: Bind immediately (default)
  • WaitForFirstConsumer: Wait until the first consumer (Pod) is scheduled before binding

3. NFS StorageClass Lab Environment Setup ​

3.1 Prerequisites ​

This lab requires:

  • Kubernetes cluster (v1.18+)
  • NFS server (IP: 10.128.0.5)
  • NFS shared directory: /nfs/share

3.2 NFS Server Configuration ​

On the NFS server, run:

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 Node Configuration ​

On all Kubernetes nodes, install the NFS client:

bash
dnf install nfs-utils

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

showmount -e 10.128.0.5

4. Deploy NFS External Provisioner ​

4.1 Create Namespace ​

bash
kubectl create namespace nfs-storageclass

4.2 Deploy RBAC Permissions ​

Create 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 Deploy NFS Provisioner ​

Create 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 server IP
            - name: NFS_PATH
              value: /nfs/share  # NFS share path
      volumes:
        - name: nfs-client-root
          nfs:
            server: 10.140.0.8
            path: /nfs/share

4.4 Create StorageClass ​

Create 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

Parameter Explanation:

  • pathPattern: Defines the directory path pattern created on the NFS server
    • ${.PVC.namespace}: PVC’s namespace
    • ${.PVC.name}: PVC’s name
  • onDelete: Behavior when PVC is deleted
    • delete: Delete the corresponding NFS directory
    • retain: Retain the NFS directory

5. Lab Operations ​

5.1 Deploy All Components ​

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 Create Test PVC and Pod ​

Create pod.yaml:

yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: test-claim
spec:
  accessModes:
    - ReadWriteMany  # Multi-node read/write
  resources:
    requests:
      storage: 1Mi   # Request 1MB storage
  storageClassName: nfs-client  # Specify StorageClass
---
kind: Pod
apiVersion: v1
metadata:
  name: test-pod
spec:
  containers:
    - name: test-pod
      image: wangyanglinux/myapp:v1.0  # Nginx image
      volumeMounts:
        - name: nfs-pvc
          mountPath: "/usr/share/nginx/html"  # Mount to Nginx web root
  restartPolicy: "Never"
  volumes:
    - name: nfs-pvc
      persistentVolumeClaim:
        claimName: test-claim

5.3 Run the Test ​

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 Verify Storage Functionality ​

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

6. Advanced Features ​

6.1 Set Default StorageClass ​

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

kubectl get storageclass

6.2 Volume Binding Mode ​

yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs-client-wait
provisioner: k8s-sigs.io/nfs-subdir-external-provisioner
volumeBindingMode: WaitForFirstConsumer  # Wait for first consumer
parameters:
  pathPattern: ${.PVC.namespace}/${.PVC.name}
  onDelete: delete

6.3 Mount Options ​

yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs-client-custom
provisioner: k8s-sigs.io/nfs-subdir-external-provisioner
mountOptions:
  - hard          # Hard mount
  - nfsvers=4     # Use NFSv4
  - timeo=600     # Timeout
parameters:
  pathPattern: ${.PVC.namespace}/${.PVC.name}
  onDelete: retain  # Retain data

7. Troubleshooting and Maintenance ​

7.1 Common Issue Diagnosis ​

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 Performance Optimization Suggestions ​

  1. NFS Mount Option Optimization:

    yaml
    mountOptions:
      - vers=4.1
      - rsize=1048576
      - wsize=1048576
      - hard
      - timeo=600
      - retrans=2
  2. Network Optimization:

    • Use gigabit or 10-gigabit networks
    • Configure dedicated NFS network
    • Adjust MTU size
  3. Storage Optimization:

    • Use SSD storage
    • Configure RAID
    • Regularly back up important data

7.3 Clean Up Resources ​

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

8. Lab Summary ​

Through this lab, we learned:

  1. Basic concepts of StorageClass: Understanding its role and core components
  2. Dynamic volume provisioning: How to automatically create PVs via StorageClass
  3. NFS integration: How to integrate NFS storage into Kubernetes
  4. Practical application: Validated the StorageClass workflow through a complete lab

Key Points ​

  • StorageClass simplifies storage management and enables dynamic provisioning
  • The Provisioner is the core of StorageClass, responsible for actual storage creation
  • Different storage backends require different provisioners and parameter configs
  • Proper storage policy configuration is critical for production

Production Advice ​

  1. Security: Configure proper RBAC and network policies
  2. High Availability: Deploy multiple Provisioner replicas, configure storage HA
  3. Monitoring: Set up comprehensive storage monitoring and alerting
  4. Backup: Develop data backup and recovery strategies
  5. Testing: Regularly perform disaster recovery tests
KEDA Scale to Zero in Practice
Detailed Explanation of PV (PersistentVolume) and PVC (PersistentVolumeClaim)
由 Valaxy v1.2.2 驱动|主题-Yunv1.2.2