> ## 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.

# Storage

> Explains OpenShift persistent storage using PersistentVolumes, PersistentVolumeClaims and StorageClasses, showing provisioning, access modes, dynamic provisioning, and how to mount volumes into pods.

Welcome to this OpenShift for Absolute Beginners lesson on storage. This article explains how OpenShift (Kubernetes) provides persistent storage for containerized applications using Persistent Volumes (PVs), Persistent Volume Claims (PVCs), and StorageClasses. You'll learn how storage is provisioned, claimed, and mounted into pods, plus an example manifest and verification commands.

Containers are ephemeral by design: when a container is removed, any data stored inside it is lost. To retain data beyond a container's lifecycle, attach persistent storage. OpenShift uses the Kubernetes persistent volume framework to expose cluster storage to applications. Storage can come from many backends and plugins, such as local disks, iSCSI, Fibre Channel, NFS, GlusterFS, Ceph RBD, OpenStack Cinder, cloud provider disks (AWS, GCE, Azure), or VMware vSphere.

<Frame>
  <img src="https://mintcdn.com/kodekloud-c4ac6d9a/EeHAFJo7ohYv6ASi/images/OpenShift-3-for-the-Absolute-Beginners/Storage-Templates-and-Catalog/Storage/storage-plugins-slide-red-stack-diagram.jpg?fit=max&auto=format&n=EeHAFJo7ohYv6ASi&q=85&s=51acbc71cbffb915eed317bb0d21ab99" alt="A presentation slide titled &#x22;Plugins&#x22; showing a bullet list of storage plugins (Local, iSCSI, Fibre Channel, NFS, GlusterFS, Ceph RBD, OpenStack Cinder, AWS/GCE/Azure disks, VMWare vSphere, etc.). On the right is a red 3D diagram with stacked blocks and cylinder database icons." width="1920" height="1080" data-path="images/OpenShift-3-for-the-Absolute-Beginners/Storage-Templates-and-Catalog/Storage/storage-plugins-slide-red-stack-diagram.jpg" />
</Frame>

When a storage provider is added to an OpenShift cluster, it contributes PersistentVolumes to the cluster’s pool of PV resources. Projects (namespaces) request storage from this pool by creating PersistentVolumeClaims. The control plane binds a PVC to an appropriate PV. Once bound, the PV can be mounted into pods and used as durable application storage.

<Frame>
  <img src="https://mintcdn.com/kodekloud-c4ac6d9a/EeHAFJo7ohYv6ASi/images/OpenShift-3-for-the-Absolute-Beginners/Storage-Templates-and-Catalog/Storage/kubernetes-pvc-pv-10gb-100gb-20gb.jpg?fit=max&auto=format&n=EeHAFJo7ohYv6ASi&q=85&s=07dd0c366efe524190d92ed63d2c17b8" alt="A stylized Kubernetes storage diagram showing three red PVC cubes labeled &#x22;PVC – 10GB&#x22;, &#x22;PVC – 100GB&#x22;, and &#x22;PVC – 20GB&#x22; placed over larger red PV resource blocks. Disk stack icons and the label &#x22;PV Resources – 1TB&#x22; indicate those PVCs are backed by persistent storage." width="1920" height="1080" data-path="images/OpenShift-3-for-the-Absolute-Beginners/Storage-Templates-and-Catalog/Storage/kubernetes-pvc-pv-10gb-100gb-20gb.jpg" />
</Frame>

From the OpenShift web console you can create storage by clicking Create Storage. Give the claim a name, choose an access mode, and set the requested size. Access modes control how the volume may be mounted by nodes:

| Access Mode | Behavior | Typical use case |
| - | - | - |
| `ReadWriteOnce` (RWO) | Mounted read-write by a single node (multiple pods on that node may share it). | Standard for block storage where a single node writes to the volume. |
| `ReadWriteMany` (RWX) | Mounted read-write by many nodes simultaneously (requires filesystem that supports multi-node RW). | Shared filesystems like NFS, GlusterFS, or cloud file services. |
| `ReadOnlyMany` (ROX) | Mounted read-only by many nodes. | Distributing read-only content (e.g., static files or reference data). |

<Frame>
  <img src="https://mintcdn.com/kodekloud-c4ac6d9a/EeHAFJo7ohYv6ASi/images/OpenShift-3-for-the-Absolute-Beginners/Storage-Templates-and-Catalog/Storage/create-storage-form-shared-users-icon.jpg?fit=max&auto=format&n=EeHAFJo7ohYv6ASi&q=85&s=39ae358bb7b92fdf0f37380df26b8f23" alt="A screenshot of a &#x22;Create Storage&#x22; form showing fields for name, access mode (Single User / Shared Access / Read Only) and size. To the right is a red icon illustrating three users connecting to a shared storage volume." width="1920" height="1080" data-path="images/OpenShift-3-for-the-Absolute-Beginners/Storage-Templates-and-Catalog/Storage/create-storage-form-shared-users-icon.jpg" />
</Frame>

Add the claim in your project and then reference that claim from pod or deployment specs. If your cluster has a `StorageClass` that supports dynamic provisioning, creating a PVC will automatically create a matching PV. Otherwise, a cluster administrator must create a PV that satisfies the PVC.

<Callout icon="lightbulb" color="#1CB2FE">
  If a StorageClass exists that supports dynamic provisioning, a PVC will trigger automatic PV creation. If no suitable StorageClass is available, the PVC will remain unbound until an admin provides a matching PV.
</Callout>

Below is a concise example demonstrating how to create a PVC and mount it into a Deployment. Save the manifests into files and apply them with `oc apply -f <file>` or `kubectl apply -f <file>`.

PersistentVolumeClaim example (10Gi, `ReadWriteOnce`):

```yaml theme={null}
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-app-storage
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
  # Optional: specify a StorageClass
  # storageClassName: standard
```

Deployment example that mounts the PVC at `/data`:

```yaml theme={null}
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
        - name: my-app
          image: nginx:stable
          volumeMounts:
            - name: app-storage
              mountPath: /data
      volumes:
        - name: app-storage
          persistentVolumeClaim:
            claimName: my-app-storage
```

Create the PVC and deployment:

```bash theme={null}
oc apply -f pvc.yaml
oc apply -f deployment.yaml
# or
kubectl apply -f pvc.yaml
kubectl apply -f deployment.yaml
```

Verify the PVC is bound and see which PV satisfies it:

```bash theme={null}
oc get pvc my-app-storage
# Example output:
# NAME            STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
oc describe pvc my-app-storage
# Shows bound PV name, events, and provisioning details
```

Key points to remember:

* The manifest pattern is the same across controllers: reference the claim under `volumes` and mount it in `volumeMounts` inside the container spec.
* Dynamic provisioning via `StorageClass` simplifies lifecycle management by automatically creating PVs.
* Choose access modes based on whether multiple nodes must access the same storage and whether they need read-write access.

References and further reading:

* [OpenShift Persistent Storage Concepts](https://docs.openshift.com/)
* [Kubernetes Persistent Volumes](https://kubernetes.io/docs/concepts/storage/persistent-volumes/)
* [StorageClass and Dynamic Provisioning](https://kubernetes.io/docs/concepts/storage/storage-classes/)

This concludes the overview of how storage is provisioned and consumed in OpenShift. Once a PVC is bound and mounted into a pod, data written to the mounted path persists independently of the pod lifecycle.

<CardGroup>
  <Card title="Watch Video" icon="video" cta="Learn more" href="https://learn.kodekloud.com/user/courses/openshift-3-for-the-absolute-beginners/module/b01015b4-ff27-4531-8507-ffb64893375d/lesson/51275c04-0125-436f-84eb-340737117aea" />
</CardGroup>


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