> ## Documentation Index
> Fetch the complete documentation index at: https://notes.kodekloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Demo Storage Classes in Action

> Shows Kubernetes StorageClasses in action listing, inspecting fields, creating PVCs, mounting to Pods and how reclaim policies affect PersistentVolume lifecycle

Every application that stores data needs storage. In Kubernetes, workloads request storage through StorageClasses, which define how PersistentVolumes (PVs) are provisioned and managed. Think of a StorageClass as the platform’s storage menu: fast SSD-backed volumes for databases, cost-effective spinning disks for archives, cloud block storage provisioned on demand, or replicated volumes for production workloads. Teams pick what they need and Kubernetes handles provisioning.

![A presentation slide showing "Demo" on the left and a large blue curved shape on the right with the title "Storage Classes in Action." A small "© Copyright KodeKloud" appears in the bottom-left corner.](https://mintcdn.com/kodekloud-c4ac6d9a/jFwNGqGMK4QeJs-g/images/Prep-Course-Certified-Cloud-Native-Platform-Engineering-CNPE/Platform-Architecture-and-Infrastructure/Demo-Storage-Classes-in-Action/storage-classes-demo-slide-blue-curve.jpg?fit=max\&auto=format\&n=jFwNGqGMK4QeJs-g\&q=85\&s=725dd6cdf17b6cab4432ee0d79e68a49)

This guide walks through:

* Listing StorageClasses
* Inspecting important StorageClass fields
* Creating PVCs that request specific StorageClasses
* Attaching Pods to those PVCs
* Observing how reclaim policies affect the PV lifecycle

References:

* [Kubernetes Storage Classes](https://kubernetes.io/docs/concepts/storage/storage-classes/)
* [Persistent Volumes](https://kubernetes.io/docs/concepts/storage/persistent-volumes/)

## 1 — List StorageClasses

To list StorageClasses available in the cluster:

```bash theme={null}
kubectl get sc
```

Sample output:

```text theme={null}
NAME                          PROVISIONER             RECLAIMPOLICY  VOLUMEBINDINGMODE       ALLOWVOLUMEEXPANSION  AGE
archive                       rancher.io/local-path   Retain         WaitForFirstConsumer    false                 16m
fast                          rancher.io/local-path   Delete         WaitForFirstConsumer    false                 16m
local-path (default)          rancher.io/local-path   Delete         WaitForFirstConsumer    false                 16m
```

Note the `(default)` annotation on `local-path`. If a PVC does not explicitly request a `storageClassName`, it will be provisioned using the default StorageClass.

## 2 — Inspect a StorageClass (example: fast)

Describe the `fast` StorageClass to view its key fields:

```bash theme={null}
kubectl describe storageclass fast
```

Example (trimmed) output:

```text theme={null}
Name:                fast
IsDefaultClass:      No
Provisioner:         rancher.io/local-path
ReclaimPolicy:       Delete
VolumeBindingMode:   WaitForFirstConsumer
AllowVolumeExpansion: <unset>
Parameters:          <none>
MountOptions:        <none>
Events:              <none>
```

Key fields explained:

| Field | Purpose |
| - | - |
| `Provisioner` | The plugin that provisions volumes (e.g., cloud provider, local-path). |
| `ReclaimPolicy` | What happens to the PV after its PVC is deleted (`Delete`, `Retain`). |
| `VolumeBindingMode` | When binding/provisioning occurs (`Immediate` vs `WaitForFirstConsumer`). |
| `AllowVolumeExpansion` | Whether the volume can be expanded after creation. |

Reclaim policy and volume binding behavior are crucial for correctness and cost control:

| ReclaimPolicy | Behavior | Use case |
| - | - | - |
| `Delete` | Underlying PV and storage resource are removed when PVC is deleted. | Ephemeral workloads, autoscaled test environments. |
| `Retain` | PV remains and moves to `Released` state; data remains on the volume. Administrator action required to reuse or delete. | Databases or critical workloads where preserving data is required. |

| VolumeBindingMode | Behavior | Benefit |
| - | - | - |
| `Immediate` | PV is provisioned/bound as soon as PVC is created. | Simple — but can provision in wrong zone for scheduled Pod. |
| `WaitForFirstConsumer` | Provisioning/binding waits until a Pod using the PVC is scheduled. | Avoids cross-zone or wrong-node provisioning; ensures local affinity. |

## 3 — Create a PVC using the `fast` StorageClass

This PVC requests 1Gi and specifies `storageClassName: fast`:

```yaml theme={null}
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: app-storage
  namespace: storage
spec:
  accessModes:
  - ReadWriteOnce
  storageClassName: fast
  resources:
    requests:
      storage: 1Gi
```

Apply it:

```bash theme={null}
kubectl apply -f pvc-fast.yaml
```

Because the `fast` StorageClass uses `WaitForFirstConsumer`, the PVC will remain in `Pending` until a Pod that mounts it is scheduled:

```bash theme={null}
kubectl get pvc -n storage
```

Example (Pending):

```text theme={null}
NAME          STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
app-storage   Pending   <none>   <unset>    <none>         fast           25s
```

## 4 — Attach a Pod to the PVC

Create a Pod manifest that mounts the PVC:

```yaml theme={null}
apiVersion: v1
kind: Pod
metadata:
  name: app
  namespace: storage
spec:
  containers:
  - name: app
    image: nginx
    volumeMounts:
    - mountPath: /data
      name: storage
  volumes:
  - name: storage
    persistentVolumeClaim:
      claimName: app-storage
```

Apply the Pod:

```bash theme={null}
kubectl apply -f pod-app.yaml
```

Watch the PVC transition from `Pending` to `Bound`:

```bash theme={null}
kubectl get pvc -n storage -w
```

Sample transition (trimmed):

```text theme={null}
app-storage   Pending                                   fast
app-storage   Pending   pvc-1dcc29bc-a8a1-4c97-a5f9-bb0e19dadcd7   0   fast
app-storage   Bound     pvc-1dcc29bc-a8a1-4c97-a5f9-bb0e19dadcd7   1Gi  RWO  fast
```

A PV is dynamically provisioned and bound to the PVC. Verify the PV:

```bash theme={null}
kubectl get pv
```

Example PV output:

```text theme={null}
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM
pvc-1dcc29bc-a8a1-4c97-a5f9-bb0e19dadcd7   1Gi        RWO            Delete           Bound    storage/app-storage
```

## 5 — Demonstrate a `Retain` reclaim policy (archive)

Inspect the `archive` StorageClass:

```bash theme={null}
kubectl describe storageclass archive
```

Example (trimmed):

```text theme={null}
Name:                archive
IsDefaultClass:      No
Provisioner:         rancher.io/local-path
ReclaimPolicy:       Retain
VolumeBindingMode:   WaitForFirstConsumer
```

Create a PVC that uses `archive` (500Mi):

```yaml theme={null}
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: archive-storage
  namespace: storage
spec:
  accessModes:
  - ReadWriteOnce
  storageClassName: archive
  resources:
    requests:
      storage: 500Mi
```

Apply the PVC and attach a Pod (Pod manifest similar to the previous one, using `claimName: archive-storage`). After creating the Pod, the PVC becomes `Bound` and a PV appears.

Check PVCs and PVs:

```bash theme={null}
kubectl get pvc -n storage
kubectl get pv
```

Example outputs showing both PVs:

```text theme={null}
# PVCs
NAME             STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS
app-storage      Bound    pvc-1dcc29bc-a8a1-4c97-a5f9-bb0e19dadcd7   1Gi        RWO            fast
archive-storage  Bound    pvc-ad21aa2d-5f95-4ec7-8f61-bfa1774d10d6   500Mi      RWO            archive

# PVs
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM
pvc-1dcc29bc-a8a1-4c97-a5f9-bb0e19dadcd7   1Gi        RWO            Delete           Bound    storage/app-storage
pvc-ad21aa2d-5f95-4ec7-8f61-bfa1774d10d6   500Mi      RWO            Retain           Bound    storage/archive-storage
```

Now delete the PVC that used the `Retain` StorageClass:

```bash theme={null}
kubectl delete pvc -n storage archive-storage
```

Because the reclaim policy is `Retain`, the PV is not deleted. Instead, it transitions to `Released` after the binding is removed. Watch the PV:

```bash theme={null}
kubectl get pv -w
```

Example PV state change:

```text theme={null}
pvc-ad21aa2d-5f95-4ec7-8f61-bfa1774d10d6   500Mi   RWO   Retain   Bound     storage/archive-storage
pvc-ad21aa2d-5f95-4ec7-8f61-bfa1774d10d6   500Mi   RWO   Retain   Released  <none>
```

When a PV is `Released`, the underlying data remains on the volume. An administrator must manually inspect, scrub, or reclaim that volume before it can be reused.

## 6 — Quick reference and recommendations

Quick commands:

| Task | Command |
| - | - |
| List StorageClasses | `kubectl get sc` |
| Describe StorageClass | `kubectl describe storageclass <name>` |
| Create PVC | `kubectl apply -f pvc.yaml` |
| Create Pod | `kubectl apply -f pod.yaml` |
| Watch PVCs | `kubectl get pvc -n <ns> -w` |
| Watch PVs | `kubectl get pv -w` |

Best practices when choosing a StorageClass:

* Use `Retain` for stateful workloads where you must preserve data (databases, critical workloads).
* Use `Delete` for ephemeral workloads that should be cleaned up automatically.
* Prefer `WaitForFirstConsumer` in multi-zone clusters to avoid provisioning volumes in the wrong zone.
* Choose the right access mode: `ReadWriteOnce` (RWO), `ReadWriteMany` (RWX) depending on application needs.
* Verify `AllowVolumeExpansion` when you expect to grow volumes after initial provisioning.

When preparing for an exam or designing a cluster, always list your StorageClasses and inspect their `reclaimPolicy` and `volumeBindingMode`. These fields determine if storage is provisioned immediately or later, where it will be provisioned, and what happens to the backing storage when a PVC is deleted.

> **[Watch Video](https://learn.kodekloud.com/user/courses/prep-course-certified-cloud-native-platform-engineer-cnpe/module/989346de-0207-4837-af11-bf456d188972/lesson/d09019f0-e51f-485c-aa53-736128144afd)**

> **[Practice Lab](https://learn.kodekloud.com/user/courses/prep-course-certified-cloud-native-platform-engineer-cnpe/module/989346de-0207-4837-af11-bf456d188972/lesson/b55e9c11-0076-440f-b2bb-735326813468)**


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.