How To Create & Mount Persistent Volumes & Claims In OpenShift – EX280 Series 2 (Lesson 7)

Last updated: November 2026

In this lesson, you will learn how to Create Persistent Volume & Claim in OpenShift, and mount it to a container In OpenShift

You will also have practical ex280 exam practice questions and answers to prepare you for the ex280 exam.

Understanding The Subject Matter

One of the important things to understand when deploying applications in Kubernetes or OpenShift is how to manage application data. Containers and Pods are designed to be replaceable. A Pod can be deleted, recreated, or scheduled on another node. If an application stores important data only inside its container’s writable filesystem, that data can disappear when the container is replaced.

This is particularly important for applications that need to retain information, such as databases, content management systems, file-processing applications, and other stateful workloads.

In this lesson, we will explore how persistent storage works in Kubernetes and OpenShift. We will also configure an NFS server and use it to provide shared storage to an OpenShift application through a PersistentVolume (PV) and a PersistentVolumeClaim (PVC).

By the end of the practical exercise, you will understand how to:

  • Differentiate between temporary, local, and remote persistent storage.
  • Understand PersistentVolumes and PersistentVolumeClaims.
  • Configure an NFS server on Red Hat Enterprise Linux.
  • Create a static PersistentVolume backed by NFS.
  • Create a PersistentVolumeClaim to request storage.
  • Mount the claimed storage inside an OpenShift workload.
  • Verify that application data remains available after a Pod is deleted and recreated.

1. Understanding storage in OpenShift

Before creating storage resources, let’s understand why persistent storage is necessary.

In a traditional virtualized environment, enterprise applications commonly use external storage systems such as SAN, NAS, and NFS. These storage systems provide a separate location for application data rather than keeping all data on the local disk of the virtual machine.

A similar concept applies to Kubernetes and OpenShift.

Consider an application running in a Pod. If the application writes important data into the container’s writable filesystem, that data is associated with the lifecycle of that container. If the container is replaced, the data may not be available in the replacement container.

Kubernetes provides volumes to address different storage requirements. Some volumes are temporary, while others provide persistent access to storage outside the lifecycle of an individual Pod.

1.1 Local storage versus shared storage

Imagine an application deployed with three replicas across three different worker nodes.

  • Pod A runs on Worker Node A.
  • Pod B runs on Worker Node B.
  • Pod C runs on Worker Node C.

If each Pod writes its data to a separate local directory on its respective node, the data is not automatically shared between the three locations.

For example, if Pod A writes a file to the local disk of Worker Node A, Pod B does not automatically see that file on Worker Node B.

This can become a problem when an application requires multiple instances to access the same files or when a workload is rescheduled onto another node.

A shared storage system provides a common storage location that can be accessed by multiple Pods or nodes, subject to the capabilities and access permissions of the storage system.

For example:

Pod A → NFS Server/Shared/remote Storage

Pod B → NFS Server/Shared/remote Storage

Pod C → NFS Server/Shared/remote Storage

Instead of each Pod maintaining a separate copy of the data on its own node, all three Pods can access the same exported NFS directory.

If Pod A is deleted and recreated on another worker node, the replacement Pod can mount the same persistent storage, provided the new node can reach the NFS server and the volume is configured to support that access.

1.2 Is remote storage always better than local storage?

Not necessarily. The storage option should depend on the application and its requirements.

Local storage can be suitable for workloads that need fast node-local access, temporary data, caching, or storage that is intentionally tied to a particular node.

Shared or remote storage is useful when data must remain independent of an individual Pod or node, or when multiple workloads need access to a common filesystem.

However, shared storage does not automatically make an application highly available. The storage system itself must be designed for availability, performance, backup, and recovery.

There is also an important consideration for databases. Although NFS can allow multiple clients to read and write to a shared filesystem, this does not mean that multiple database instances can safely write to the same database files. Database applications must use storage and replication architectures that are supported by the database vendor.

The key point is that persistent storage separates the lifecycle of application data from the lifecycle of a Pod.

2. Understanding PersistentVolumes and PersistentVolumeClaims

Kubernetes and OpenShift use two important resources to manage persistent storage:

  • PersistentVolume (PV)
  • PersistentVolumeClaim (PVC)

Although they work together, they serve different purposes.

2.1 What is a PersistentVolume?

A PersistentVolume is a storage resource made available to a Kubernetes or OpenShift cluster.

It represents storage that has been provisioned and configured for use by workloads. The underlying storage can be provided by different technologies, including NFS, SAN-backed storage, cloud storage services, and storage systems accessed through Container Storage Interface (CSI) drivers.

A PV is a cluster-scoped resource. This means it is not created inside a particular project or namespace.

A PV describes information such as:

  • Storage capacity.
  • Supported access modes.
  • Storage class.
  • Reclaim policy.
  • The underlying storage system.

For example, an administrator can create a PersistentVolume that represents a 13 GiB NFS export.

2.2 What is a PersistentVolumeClaim?

A PersistentVolumeClaim is a request for persistent storage made by a user or application.

Instead of directly configuring the underlying storage system inside an application deployment, the workload references a PVC.

A PVC specifies requirements such as:

  • Requested storage capacity.
  • Required access mode.
  • Storage class, where applicable.

The Kubernetes control plane attempts to match the PVC with a suitable PersistentVolume.

For example, an application can request 10 GiB of storage with ReadWriteMany access. If an available PV satisfies the claim’s requirements, Kubernetes binds the PVC to that PV.

A PVC is namespaced. This means it belongs to the project or namespace in which it is created.

2.3 How PV and PVC work together

The relationship can be understood as follows:

  1. The storage administrator provisions storage and makes it available as a PersistentVolume.
  2. An application or user creates a PersistentVolumeClaim requesting storage.
  3. Kubernetes identifies a suitable PV.
  4. The PVC is bound to the PV.
  5. A Pod references the PVC in its volume configuration.
  6. Kubernetes mounts the storage into the container.

The relationship looks like this:

NFS Server → PersistentVolume → PersistentVolumeClaim → Pod → Container

A Pod does not normally need to know whether the underlying storage is an NFS server, SAN, or another supported storage system. It references the PVC, which provides an abstraction between the application and the storage implementation.

3. Understanding storage access modes

When creating a PersistentVolume or PersistentVolumeClaim, you will need to specify an access mode.

The access mode describes how the storage can be mounted by workloads.

The common access modes are:

Access modeMeaning
ReadWriteOnce (RWO)The volume can be mounted as read-write by a single node. Multiple Pods on that same node may still access it.
ReadOnlyMany (ROX)The volume can be mounted as read-only by multiple nodes.
ReadWriteMany (RWX)The volume can be mounted as read-write by multiple nodes.
ReadWriteOncePod (RWOP)The volume can be mounted as read-write by one Pod only.

Not every storage technology supports every access mode. For example, NFS supports ReadWriteMany, while other storage systems may have different capabilities.

It is also important to understand that access modes are used for volume matching and mounting capabilities. They do not automatically enforce application-level write coordination or guarantee that multiple writers can safely modify the same data.

For this practical exercise, we will use ReadWriteMany because our NFS storage can be accessed by multiple nodes.

Create Persistent Volume & Claim In OpenShift - ex280 dumps 2028

4. Understanding static and dynamic volume provisioning

PersistentVolumes can be provisioned in two main ways.

4.1 Static provisioning

With static provisioning, an administrator creates the storage resource first and then creates a PersistentVolume to represent it in the cluster.

The user subsequently creates a PVC to request the available storage.

This is the approach we will use in this lesson.

For example:

  • An administrator configures an NFS server.
  • The administrator creates an NFS export.
  • A PersistentVolume is created to represent that export.
  • A user creates a PVC to request storage from the PV.
  • A Pod mounts the PVC.

4.2 Dynamic provisioning

Dynamic provisioning automates the process of creating storage.

Instead of manually creating a PV for every storage request, an administrator configures a StorageClass with an appropriate storage provisioner.

When a user creates a PVC requesting that StorageClass, the provisioner can automatically create the underlying storage and make it available to the cluster.

StorageClasses are particularly useful in enterprise environments where different storage options may be offered to applications, such as:

  • High-performance storage.
  • General-purpose storage.
  • Shared file storage.
  • Encrypted storage.
  • Different performance or availability tiers.

We will cover StorageClasses and dynamic provisioning in a separate lesson.

5. Practical: Configure an NFS server for OpenShift persistent storage

Now that we understand the storage concepts, let’s implement a practical example.

In an enterprise environment, you may have a dedicated storage array from vendors such as Dell, HPE, or IBM. You can integrate supported storage platforms with Kubernetes or OpenShift using the appropriate storage drivers and interfaces.

For this demonstration, however, we will use a separate Red Hat Enterprise Linux server as our remote storage server.

We will configure Network File System (NFS) on that server and make an exported directory available to the OpenShift cluster.

5.1 Lab environment

The environment consists of the following:

ComponentConfiguration
Storage serverRed Hat Enterprise Linux 9
NFS server IP192.168.37.128
Shared directory/nfsshare
Storage protocolNFS
PersistentVolume capacity13Gi
PVC request10Gi
Access modeReadWriteMany
StorageClass namestatic
ApplicationTest workload running in OpenShift

The NFS server must be reachable from the OpenShift worker nodes, because the nodes perform the storage mounts on behalf of the Pods.

The IP address and directory above are from this demonstration. Replace them with the values in your own environment.

ACTION TIME

5.2 Install the NFS utilities

Log in to the RHEL server that will act as the NFS server.

Install the NFS utilities package:

[tekneed@osl ~]$ sudo dnf install nfs-utils -y

The package provides the utilities required to configure and manage NFS services.

5.3 Start and enable the NFS server

Start the NFS server service:

[tekneed@osl ~]$ sudo systemctl enable --now nfs-server

Check its status:

[tekneed@osl ~]$ sudo systemctl status nfs-server

You should see that the service is active and running.

For NFSv4, the NFS server service is the main service required for serving the export. The rpcbind service is primarily relevant to NFSv3 and related RPC-based services, so it is not necessary to start it simply because you are configuring an NFSv4 export.

5.4 Create the NFS shared directory

Next, create the directory that will be exported to the OpenShift cluster.

[tekneed@osl ~]$ sudo mkdir -p /nfsshare

For this isolated learning lab, we will temporarily allow write access to the directory so that the test workload can demonstrate persistent file creation.

[tekneed@osl ~]$ sudo chmod 0777 /nfsshare

Security note: The permissions above are deliberately broad for a simple lab exercise. Do not use them as a production storage-permission model. In production, configure appropriate ownership, group permissions, client restrictions, and access controls based on the identities used by your workloads.

5.5 Configure the NFS export

The NFS export configuration is maintained in:

/etc/exports

Open the file:

[tekneed@osl ~]$ sudo vi /etc/exports

Add the following entry:

/nfsshare *(rw,sync,root_squash,no_subtree_check)

This example makes the export accessible to any client that can reach the server. It is suitable only for an isolated lab network.

For a real environment, replace * with the IP address or subnet of the OpenShift worker nodes. For example, use a suitable worker-node subnet in CIDR notation.

Let’s understand the options:

OptionDescription
rwAllows clients to read and write to the export.
syncEnsures changes are committed to stable storage before the server replies to the client.
root_squashMaps remote root access to an unprivileged identity on the NFS server.
no_subtree_checkDisables subtree checking, which can simplify access to exported directories.

Notice that we use root_squash, not no_root_squash. Disabling root squashing can give remote root users excessive privileges over the exported filesystem and should not be used casually.

Save the file and exit the editor.

5.6 Apply the export configuration

Run:

[tekneed@osl ~]$ sudo exportfs -rav

This reloads the export configuration and displays the exports being made available.

To list the active exports, run:

[tekneed@osl ~]$ sudo exportfs -v

You can also inspect the exports using:

[tekneed@osl ~]$ showmount -e localhost

5.7 Configure the firewall

Do not disable the firewall simply to make NFS work.

For an NFSv4 lab, allow NFS traffic through the firewall:

s[tekneed@osl ~]$ udo firewall-cmd --permanent --add-service=nfs
[tekneed@osl ~]$ sudo firewall-cmd --reload

NFSv4 normally uses TCP port 2049.

If you are using NFSv3, additional RPC services and ports may be required, including rpcbind and mountd. Configure those according to the NFS version and the firewall requirements of your environment.

5.8 Verify the NFS server

Check that the NFS server is running:

[tekneed@osl ~]$ sudo systemctl status nfs-server

Check the exported directory:

[tekneed@osl ~]$ sudo exportfs -v

At this point, the NFS server has been configured and is ready to provide the shared directory to authorized clients.

6. Test NFS connectivity from an OpenShift worker node

Before creating the PersistentVolume, confirm that the OpenShift worker nodes can reach the NFS server.

This is important because a successful connection from your laptop or administration workstation does not prove that the cluster nodes can mount the NFS export.

From a suitable client or worker node, you can inspect the exported directory:

[tekneed@osl ~]$ showmount -e 192.168.37.128

Expected output:

Export list for 192.168.37.128:
/nfsshare *

The output confirms that the NFS server is advertising the export. It does not, by itself, prove that a Pod can mount it successfully.

Where you have the necessary administrative access, you can also test an actual NFS mount from a suitable Linux client:

[tekneed@osl ~]$ sudo mkdir -p /mnt/nfs-test
[tekneed@osl ~]$ sudo mount -t nfs -o vers=4.1 192.168.37.128:/nfsshare /mnt/nfs-test

Check the mounted filesystem:

[tekneed@osl ~]$ df -h

You should see an entry similar to:

192.168.37.128:/nfsshare    13G    40M    13G    1% /mnt/nfs-test

The exact capacity and usage will depend on the filesystem backing the NFS export.

After the test, unmount it:

[tekneed@osl ~]$ sudo umount /mnt/nfs-test

If the mount fails, investigate network connectivity, firewall rules, NFS version compatibility, export permissions, and the NFS server configuration before proceeding.

7. Create a PersistentVolume in OpenShift

Now that the NFS server is configured, we can create a PersistentVolume in OpenShift.

A PersistentVolume tells the cluster that a particular storage resource is available for workloads to consume.

In this example, the PV will represent the /nfsshare directory on the NFS server.

Create a file named pv.yml:

[tekneed@osl ~]$ vi pv.yml

Add the following configuration:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-lun1
spec:
  storageClassName: static
  capacity:
    storage: 13Gi
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain
  volumeMode: Filesystem
  mountOptions:
    - vers=4.1
  nfs:
    server: 192.168.37.128
    path: /nfsshare

Let’s understand the important fields.

  • kind: PersistentVolume identifies the resource as a PV.
  • metadata.name specifies the name of the PersistentVolume.
  • storageClassName identifies the storage class associated with the PV. We are using the name static for this manually provisioned example.
  • capacity.storage specifies the capacity advertised by the PV.
  • accessModes specifies that the volume supports read-write access from multiple nodes.
  • persistentVolumeReclaimPolicy determines what happens to the storage resource after its claim is released.
  • volumeMode specifies that the volume will be mounted as a filesystem.
  • mountOptions specifies the NFS version to use.
  • nfs.server identifies the NFS server.
  • nfs.path identifies the exported directory.

We use the Retain reclaim policy because we want the underlying data to remain available when the PVC is released. This means that an administrator must handle the storage reclamation process manually before the PV can be reused.

Important: The 13Gi capacity is the capacity advertised to Kubernetes. A manually configured NFS PV does not automatically enforce a 13 GiB quota on the exported directory. If you need an actual capacity limit, configure a quota or an appropriately sized filesystem on the storage server.

Create the PV:

[tekneed@osl ~]$ oc create -f pv.yml

Check the PersistentVolumes:

[tekneed@osl ~]$ oc get pv

You should see an entry similar to:

NAME      CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS
pv-lun1   13Gi       RWX            Retain           Available           static

The Available status means that the PV has been created and is not yet bound to a PVC.

8. Create a PersistentVolumeClaim

We now have a PersistentVolume available in the cluster. The next step is to create a PersistentVolumeClaim that requests storage from it.

Create a file named pvc.yml:

[tekneed@osl ~]$ vi pvc.yml

Add the following configuration:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nginx-pvc
spec:
  storageClassName: static
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 10Gi

Let’s examine the configuration.

  • kind: PersistentVolumeClaim identifies the resource as a storage request.
  • metadata.name specifies the name of the PVC.
  • storageClassName: static ensures that the claim requests the same storage class as the PV created earlier.
  • accessModes requests read-write access from multiple nodes.
  • resources.requests.storage requests 10 GiB of storage.

Notice that our PV advertises 13 GiB, while the PVC requests 10 GiB. The PV therefore has sufficient advertised capacity to satisfy the claim.

Create the PVC:

[tekneed@osl ~]$ oc create -f pvc.yml

Check the claim:

[tekneed@osl ~]$ oc get pvc

Expected output:

NAME        STATUS   VOLUME    CAPACITY   ACCESS MODES   STORAGECLASS
nginx-pvc   Bound    pv-lun1   13Gi       RWX            static

The Bound status means that the PVC has successfully been matched with a PersistentVolume.

You can also inspect the PV:

[tekneed@osl ~]$ oc get pv

Its status should now be Bound, and the CLAIM column should identify the PVC.

For more detailed information, run:

[tekneed@osl ~]$ oc describe pvc nginx-pvc

At this point, the storage has been provisioned and claimed. We can now attach it to an application.

9. Mount the PersistentVolumeClaim inside a Pod

Creating a PV and PVC does not automatically make the storage available inside a container.

We must reference the PVC in the workload’s volume configuration and mount that volume into the container.

For this demonstration, we will create a simple test workload using a Red Hat UBI container. The workload will remain running while we create and inspect files on the mounted NFS share.

First, create a file named nginx.yml:

[tekneed@osl ~]$ vi nginx.yml

Add the following configuration:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: registry.access.redhat.com/ubi9/ubi:latest
          command:
            - /bin/sh
            - -c
            - sleep infinity
          volumeMounts:
            - name: nginx-vol
              mountPath: /usr/share/nginx/html
      volumes:
        - name: nginx-vol
          persistentVolumeClaim:
            claimName: nginx-pvc

Although the Deployment is named nginx, this particular container is being used as a storage test workload. It is not running an NGINX web server. We are using it to demonstrate how an application container can access persistent storage.

Let’s understand the important configuration.

The volumeMounts section

volumeMounts:
  - name: nginx-vol
    mountPath: /usr/share/nginx/html

This tells the container where the storage should be mounted.

The directory /usr/share/nginx/html inside the container will point to the mounted persistent volume.

The volumes section

volumes:
  - name: nginx-vol
    persistentVolumeClaim:
      claimName: nginx-pvc

This connects the volume to the PVC named nginx-pvc.

The volumeMounts.name and volumes.name values must match.

The container does not directly reference the NFS server IP address. Instead, it references the PVC, which is already bound to the PV representing the NFS export.

Create the Deployment:

[tekneed@osl ~]$ oc create -f nginx.yml

Check the Pod:

oc get pods

You can watch the Pod until it becomes ready:

[tekneed@osl ~]$ oc get pods -w

Expected output:

NAME                     READY   STATUS    RESTARTS   AGE
nginx-xxxxxxxxxx-xxxxx   1/1     Running   0          30s

The exact Pod name will differ in your environment.

If the Pod remains in ContainerCreating or enters CreateContainerConfigError, inspect its events:

[tekneed@osl ~]$ oc describe pod <pod-name>

Common causes include NFS connectivity problems, export permissions, incorrect NFS mount options, and storage access issues.

10. Verify that the Pod can write to persistent storage

Now that the Pod is running, let’s verify that the NFS volume has been mounted successfully.

First, identify the Pod:

[tekneed@osl ~]$ oc get pods

Open a shell inside it:

[tekneed@osl ~]$ oc exec -it <pod-name> -- /bin/sh

Navigate to the mounted directory:

cd /usr/share/nginx/html

List the files:

ls -la

You may see files that already existed in the NFS export.

Create two test files:

touch testfile1
touch testfile2

List the directory again:

ls -la

You should now see the two files.

Exit the container:

exit

The files have been created through the container, but they are stored on the NFS server rather than in the container’s temporary writable filesystem.

11. Verify persistence after deleting the Pod

This is one of the most important parts of the exercise.

We want to prove that the files remain available even when the Pod is deleted and recreated.

Delete the current Pod:

[tekneed@osl ~]$ oc delete pod <pod-name>

Because the Pod is managed by a Deployment, Kubernetes will automatically create a replacement Pod to maintain the desired replica count.

Watch the replacement Pod:

[tekneed@osl ~]$ oc get pods -w

When the new Pod is running, identify its name and open a shell:

[tekneed@osl ~]$ oc exec -it <new-pod-name> -- /bin/sh

Navigate to the same directory:

cd /usr/share/nginx/html

List the files:

ls -la

You should still see:

testfile1
testfile2

This demonstrates that the data survived the deletion and recreation of the Pod.

The reason is that the files were stored on the NFS server. The replacement Pod mounted the same PVC, which remained bound to the same PV.

The lifecycle of the Pod and the lifecycle of the persistent data are therefore independent.

13. Troubleshooting common OpenShift NFS storage issues

When working with NFS-backed persistent storage, you may encounter some common problems.

13.1 PVC remains in Pending state

Check the PVC:

[tekneed@osl ~]$ oc describe pvc nginx-pvc

Check available PVs:

[tekneed@osl ~]$ oc get pv

Possible causes include:

  • The requested storage capacity is greater than the available PV capacity.
  • The access modes do not match.
  • The StorageClass names do not match.
  • The PV has already been claimed by another PVC.

In our example, both resources use the static StorageClass name and ReadWriteMany access mode.

13.2 Pod remains in ContainerCreating

Inspect the Pod:

[tekneed@osl ~]$ oc describe pod <pod-name>

Review the Events section for errors relating to volume mounting.

Possible causes include:

  • The NFS server is unreachable from the worker node.
  • The NFS export is not configured correctly.
  • The NFS server firewall blocks the required traffic.
  • The NFS version or mount options are incompatible.
  • The worker node cannot mount the NFS filesystem.

Remember that the storage mount is performed by the node, not by your workstation.

13.3 Permission denied when creating files

If the Pod can read the mounted directory but cannot create files, inspect the directory permissions and ownership on the NFS server.

For example:

[tekneed@osl ~]$ sudo ls -ld /nfsshare

OpenShift commonly runs containers with an assigned, non-root user ID. Consequently, the user inside the container may not have the same UID or group ownership as the directory on the NFS server.

For a production deployment, configure directory ownership and group permissions to match the application’s security requirements. Also consider the project’s Security Context Constraints (SCC), supplemental groups, and SELinux configuration.

Avoid solving production permission problems by granting unrestricted write permissions or disabling security controls.

13.4 NFS mount succeeds but the application cannot write

A successful mount does not necessarily mean the application has permission to write.

Check:

  1. The NFS export’s read/write settings.
  2. The POSIX permissions and ownership of the exported directory.
  3. The effective UID and group memberships of the container.
  4. SELinux settings on the NFS server and client nodes.
  5. The application’s own filesystem requirements.

For SELinux-related issues, consult the Red Hat OpenShift NFS storage documentation before changing security settings.

14. Cleaning up the lab resources

After completing the exercise, you can remove the resources created in OpenShift.

Delete the Deployment:

[tekneed@osl ~]$ oc delete deployment nginx

Delete the PVC:

[tekneed@osl ~]$ oc delete pvc nginx-pvc

Because the PV uses the Retain policy, deleting the PVC does not automatically delete the underlying NFS data.

Check the PV:

[tekneed@osl ~]$ oc get pv

It may show a Released status.

If you are finished with the lab and want to remove the PV object, you can delete it:

[tekneed@osl ~]$ oc delete pv pv-lun1

This deletes the Kubernetes PV resource, not the files stored in /nfsshare.

Only remove or clean up the NFS data when you are certain that it is no longer required.

Conclusion

In this lesson, we explored persistent storage in OpenShift and why it is important for applications that need to retain data beyond the lifecycle of individual Pods.

We also examined the differences between local and shared storage, learned how PersistentVolumes and PersistentVolumeClaims work together, and configured an NFS server to provide shared storage to an OpenShift workload.

Finally, we created a static PersistentVolume, claimed the storage using a PVC, mounted it inside a container, and verified that files remained available after the Pod was deleted and recreated.

The next step is to understand StorageClasses and dynamic volume provisioning. With dynamic provisioning, OpenShift can request and provision storage automatically through a configured storage provisioner, reducing the need for administrators to manually create PersistentVolumes for every application.

Recent EX280 Exam Questions & Answers On How To Create Persistent Volume & Claim In OpenShift – EX280 Series 2

For Complete Exam Practice Questions & Answer, use this link.

For EX280 Exam Tips, use this link


An application team requires persistent storage for an application running in an OpenShift cluster.

Create a new project named storage-project.

Create a PersistentVolumeClaim named app-storage with a storage request of 5Gi, ReadWriteOnce access mode, and the default StorageClass.

Deploy an Nginx application named nginx-app using the nginx:latest image and attach the app-storage PVC to the deployment.

Mount the persistent volume inside the container at /usr/share/nginx/html.


Answer

Method 1: Imperative Approach

Step 1: Create the project

Create a new OpenShift project named storage-project.

[api@sno ~]$ oc new-project storage-project


Now using project "storage-project".

Step 2: Check the available StorageClasses

Before creating the PVC, verify that a default StorageClass is available.

[api@sno ~]$ oc get storageclass

output:

NAME                 PROVISIONER             RECLAIMPOLICY   VOLUMEBINDINGMODE
standard (default)   example.csi.driver      Delete          Immediate

The output will depend on the storage provisioner configured in your cluster.

The (default) label indicates the default StorageClass. We will use this StorageClass without explicitly specifying its name in the PVC manifest.

Step 3: Create the PersistentVolumeClaim

Create a YAML file named app-storage.yaml.

[api@sno ~]$ vi app-storage.yaml

Add the following configuration:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: app-storage
  namespace: storage-project
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi

Save and close the file.

Notice that storageClassName is omitted. This allows OpenShift to use the cluster’s default StorageClass.

Create the PVC:

[api@sno ~]$ oc create -f app-storage.yaml

persistentvolumeclaim/app-storage created

Step 4: Verify the PVC

[api@sno ~]$ oc get pvc app-storage

Example output:

NAME          STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS
app-storage   Bound     pvc-xxx  5Gi        RWO            standard

Step 5: Deploy the Nginx application

Create a Deployment named nginx-app using the nginx:latest image.

[api@sno ~]$ oc create deployment nginx-app --image=nginx:latest

deployment.apps/nginx-app created

Step 6: Attach the PVC to the Deployment

Use oc set volume to attach the existing PVC to the Deployment and mount it inside the container.

[api@sno ~]$ oc set volume deployment/nginx-app \
  --add \
  --name=app-storage \
  --type=pvc \
  --claim-name=app-storage \
  --mount-path=/usr/share/nginx/html

output:

deployment.apps/nginx-app volume updated

This command performs two important configurations:

  • Creates a volume reference to the existing PVC named app-storage.
  • Mounts the volume inside the Nginx container at /usr/share/nginx/html.

Step 7: Verify the Deployment and PVC attachment

Check the Deployment:

[api@sno ~]$ oc get deployment nginx-app

Check the pod:

[api@sno ~]$ oc get pods

Check the volume configuration:

[api@sno ~]$ oc describe deployment nginx-app

Confirm that the volume references the app-storage PVC and that the mount path is /usr/share/nginx/html.

Wait for the application to become ready:

[api@sno ~]$ oc rollout status deployment/nginx-app

output:

deployment "nginx-app" successfully rolled out

Method 2: Declarative Approach

In the declarative approach, we define the desired PVC and Deployment configurations in YAML manifests and create the resources using oc apply.

Step 1: Create the project

[api@sno ~]$ oc new-project storage-project

Now using project "storage-project".

Step 2: Create the PVC manifest

Create a file named app-storage.yaml:

[api@sno ~]$ vi app-storage.yaml

Add the following configuration:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: app-storage
  namespace: storage-project
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi

Save and close the file.

Apply the manifest:

[api@sno ~]$ oc apply -f app-storage.yaml


persistentvolumeclaim/app-storage created

Step 3: Create the Deployment manifest

Create a file named nginx-app.yaml:

[api@sno ~]$ vi nginx-app.yaml

Add the following configuration:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-app
  namespace: storage-project
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx-app
  template:
    metadata:
      labels:
        app: nginx-app
    spec:
      containers:
        - name: nginx
          image: nginx:latest
          ports:
            - containerPort: 80
          volumeMounts:
            - name: app-storage
              mountPath: /usr/share/nginx/html
      volumes:
        - name: app-storage
          persistentVolumeClaim:
            claimName: app-storage

Save and close the file.

    Step 4: Apply the Deployment manifest

    [api@sno ~]$ oc apply -f nginx-app.yaml
    
    deployment.apps/nginx-app created

    Step 5: Verify the Deployment

    [api@sno ~]$ oc get deployment nginx-app

    Check the pod:

    [api@sno ~]$ oc get pods

    Wait for the Deployment to become ready:

    [api@sno ~]$ oc rollout status deployment/nginx-app

    EX280 Exam Tips (2026-2027)

    1. Understand PV and PVC: A PersistentVolume (PV) represents storage provisioned for the cluster, while a PersistentVolumeClaim (PVC) is an application’s request for storage.
    2. Know the access modes: ReadWriteOnce (RWO) allows read-write mounting by a single node. It does not necessarily mean only one pod can use the volume.
    3. Understand StorageClasses: Omitting storageClassName allows the default StorageClass to be used, provided one is configured.
    4. Remember dynamic provisioning: A PVC can trigger automatic PV provisioning when a suitable dynamic provisioner is available.
    5. Know how to attach storage: In imperative operations, oc set volume can attach an existing PVC to a Deployment.
    6. Understand volumeMounts and volumes: volumes references the PVC, while volumeMounts specifies where the storage appears inside the container.
    7. Verify the PVC status: A Bound PVC indicates that storage has been successfully matched or provisioned. A Pending PVC requires investigation or may be waiting for pod scheduling.
    8. Remember persistent data: Data stored on a properly configured persistent volume survives container restarts and pod replacement, subject to the storage backend and volume lifecycle.
    9. Know your verification commands: Be comfortable with oc get pvc, oc describe pvc, oc get pv, oc describe deployment, and oc exec.

    Both methods can satisfy the task. The imperative approach uses individual commands to create and configure the resources, while the declarative approach defines the desired configuration in YAML manifests.

    Be the first to comment

    Leave a Reply

    Your email address will not be published.


    *