---
title: "The Comprehensive Guide to Kubernetes Volumes"
description: "Learn how to leverage Kubernetes volumes to effectively control containers and pods within Kubernetes in this ATA Learning tutorial!"
canonical: "https://adamtheautomator.com/kubernetes-volumes/"
---

# The Comprehensive Guide to Kubernetes Volumes

> Learn how to leverage Kubernetes volumes to effectively control containers and pods within Kubernetes in this ATA Learning tutorial!

Source: https://adamtheautomator.com/kubernetes-volumes/

---

ATA Learning

Tap to hide

[

ATA Learning

](/)

*   [Home](/)
*   [Tutorials](/tutorials/)
*   [Instructors](/author/)
*   [Advertising](/advertising/)
*   [Recommended Resources](/resources/)
*   [About Adam](/about-adam/)

Search for:  

*   [](https://twitter.com/adbertram)
*   [](https://github.com/Adam-the-Automator)
*   [](https://www.linkedin.com/company/adam-the-automator-llc)
*   [](/feed/)

![The Comprehensive Guide to Kubernetes Volumes](https://adamtheautomator.com/wp-content/uploads/2023/06/kubernetes-volumes.jpg)

# The Comprehensive Guide to Kubernetes Volumes

[![](https://secure.gravatar.com/avatar/b1faae2f957a0d43de36dfd25e8c08537718fb87c49cfd0a15b0e860a7f7b9a0?s=192&d=mm&r=g)Mercy Bassey](https://adamtheautomator.com/author/mercy-bassey/)26 June 202313 min. read

Categories: [DevOps](/category/devops/)

Tags:[Kubernetes](/tag/kubernetes/)

Table of Contents

*   [Prerequisites](#prerequisites)
*   [Configuring Short-lived Storage Within a Pod (emptyDir)](#configuring-short-lived-storage-within-a-pod-emptydir)
*   [Configuring a Direct File and Directory Access (hostPath)](#configuring-a-direct-file-and-directory-access-hostpath)
*   [Persisting Data via the PersistentVolumeClaim (PVC)](#persisting-data-via-the-persistentvolumeclaim-pvc)
*   [Injecting Configuration Settings Into Pods (ConfigMap)](#injecting-configuration-settings-into-pods-configmap)
*   [Encoding and Passing Secure Data to Pods (secret)](#encoding-and-passing-secure-data-to-pods-secret)
*   [Conclusion](#conclusion)

One fundamental aspect of working with data in Kubernetes is the concept of volumes. Kubernetes volumes enable containers to store and access data beyond a container’s lifetime.

In this tutorial, you will explore and learn about the different types of Kubernetes volumes and their use cases, diving deep into their configuration and best practices.

Indulge yourself in leveraging your Kubernetes volumes effectively!

## Prerequisites

Before jumping to Kubernetes volumes, ensure you have a Kubernetes cluster running to follow along in this tutorial’s hands-on demonstrations. This tutorial uses [kind](https://kind.sigs.k8s.io/) to run a cluster.

Related:[How to Get Started Building Kubernetes Clusters with kubeadm](https://adamtheautomator.com/kubeadm/)

## Configuring Short-lived Storage Within a Pod (`emptyDir`)

Effectively engaging Kubernetes volumes is crucial for building resilient and scalable applications in Kubernetes clusters. One factor that makes Kubernetes stand out is that it supports a plethora of volume types, like `emptyDir`, a simple yet powerful tool in Kubernetes.

This volume type provides temporary and short-lived storage within a pod, like having a temporary scratchpad, which containers within the same pod can read from and write to.

To configure an `emptyDir` volume, you need to define it in the pod’s YAML specification:

1\. Create a YAML file in your preferred editor, and populate the following configuration setting. This tutorial calls this file _empty-dir.yaml_, but you can name it differently.

The configuration below defines a pod named `ngnix-webserver` that runs an `nginx` container image and includes an `emptyDir` volume.

```yaml
apiVersion: v1
kind: Pod 
metadata:
  # The name of the pod.
  name: nginx-webserver 
spec:
  containers:
    - name: nginx
      # This pod will use an NGINX container image.
      image: nginx 
      volumeMounts:
        # Specify the name of the volume to use as a volume mount.
        - name: cache 
          # Specify the mount path.
          mountPath: /cache 
  volumes:
    # The volume name
    - name: cache 
      # The volume type
      emptyDir: {}
          # Uncomment the below and configure the size of the emptyDir volume
          # sizeLimit: 500Mi
```

2\. Next, run the following commands to apply the `empty-dir.yaml` configuration, and `get` the list of `pods` available.

```bash
kubectl apply -f empty-dir.yaml
kubectl get pods
```

![Creating and viewing the nginx-webserver pod](https://adamtheautomator.com/wp-content/uploads/2023/06/image-182.png)

Creating and viewing the **nginx-webserver** pod

3\. With a pod created, run the below `kubectl exec` command, which does not provide output, but writes some data to the `emptyDir` volume inside the container.

This command writes the text `"Hello, Kubernetes!"` to a file named `myfile.txt` (arbitrary) located in the `/cache` directory within the container.

```bash
kubectl exec -it nginx-webserver -- /bin/sh -c 'echo "Hello, Kubernetes!" > /cache/myfile.txt'
```

4\. Now, execute the command below inside the container to read and display the data of the `myfile.txt` file from the `emptyDir` volume.

```bash
kubectl exec -it nginx-webserver -- /bin/cat /cache/myfile.txt
```

If all goes well, you will see the following message.

![Creating data in the nginx-webserver pod](https://adamtheautomator.com/wp-content/uploads/2023/06/image-181.png)

Creating data in the _**nginx-webserver**_ pod

5\. Lastly, run each command below to perform the following:

*   `delete` – Delete the `nginx-webserver` pod.
*   `exec` – Attempt to read the `myfile.txt` file to verify if the `emptyDir` volume still exists.

```bash
kubectl delete pod nginx-webserver
kubectl exec -it nginx-webserver -- /bin/cat /cache/myfile.txt
```

The output below verifies that the `emptyDir` volume and other resources associated with the `nginx-webserver` pod no longer exist since the pod has been deleted.

Data stored in an `emptyDir` volume is tied to the pod’s lifecycle. Once the pod is terminated or restarted, the data within the `emptyDir` volume is lost forever.

This volume type is mainly used as a local cache or as a buffer for temporary data storage before moving to a more permanent storage solution.

![Deleting the nginx-webserver pod and confirming data persistence](https://adamtheautomator.com/wp-content/uploads/2023/06/image-180.png)

Deleting the **nginx-webserver** pod and confirming data persistence

## Configuring a Direct File and Directory Access (`hostPath`)

Instead of relying on the `emptyDir` volume, which becomes inaccessible when the associated pod is deleted, you can opt for a more persistent solution. How? Configure a [`hostPath`](https://kubernetes.io/docs/concepts/storage/volumes/#hostpath) volume type that allows direct access to files and directories on the host node’s filesystem from within the pod.

By mounting a specific directory into the pod, the data stored within the host remains accessible even if the pod is deleted and recreated.

To configure a direct file and directory access:

1\. Create a new YAML file called _hostpath-pod.yaml_, and add the configuration below.

This configuration defines the following:

*   Create a pod named `hostpath-pod` with a single container using the `busybox` image.
*   Mount the `/var/tmp/busybox` directory from the host node’s filesystem into the container at the `/data` path using the `hostpath` volume.

Conclusively, this configuration allows the container to directly access and manipulate the files within the `/var/tmp/` directory on the host node.

```yaml
apiVersion: v1
kind: Pod
metadata:
  # The pod's name.
  name: busybox-pod
spec:
  containers:
    - name: busybox
      # This pod will use a busybox container image.
      image: busybox 
      # Tells the busybox image to run the container using "/bin/sh" as the shell,
      # create a file "hello.txt" in a directory "/data", write the text 'hello k8s'
      # and then sleep for 3600 seconds, "One hour" before exiting.
      command: ["/bin/sh", "-c", "echo 'hello k8s' > /data/hello.txt && sleep 3600"] 
      volumeMounts:
        # The name of the volume to be used
        - name: hostpath-volume
          # The mount path
          mountPath: /data 
  volumes:
    # The volume name
    - name: hostpath-volume 
      # The volume type
      hostPath: 
        # The existing path to be used by the pod
        path: /var/tmp
```

> 💡 _When using a `hostPath` volume, ensure the path already exists in the Node. Otherwise, you will encounter an error. Worry not; you can [create a path from the pod configuration file](https://kubernetes.io/docs/concepts/storage/volumes/#hostpath-fileorcreate-example) when necessary._

2\. Next, run the following commands to apply the _`hostpath-pod.yaml`_ file’s configuration, and `get` all `pods` available.

```bash
kubectl apply -f hostpath-pod.yaml
kubectl get pods
```

![Creating and viewing busy-box pod with hostpath volume type](https://adamtheautomator.com/wp-content/uploads/2023/06/image-185.png)

Creating and viewing _**busy-box**_ pod with _hostpath_ volume type

3\. Execute the commands below sequentially if you are using a local Kubernetes cluster to view the contents of the `hostPath` volume on your Kubernetes node.

Ensure you replace `<your-node>` with the name of your Kubernetes node.

```bash
# Execute an interactive Bash session inside the Node
docker exec -it <your-node> Bash 
# Change directory
cd var/tmp/ 
# List the contents of the current directory.
ls 
# Display the contents of the hello.txt file.
cat hello.txt
```

![Accessing the host (node) to verify the hello.txt file’s content ](https://adamtheautomator.com/wp-content/uploads/2023/06/image-184.png)

Accessing the host (node) to verify the _**hello.txt**_ file’s content

> 💡 _Alternatively, run the `ssh <node-name>` command instead of the docker exec if you are using a cloud-based cluster._

4\. Now, run each command below to `delete` your `pod` (`busybox-pod`) and view (`cat`) the contents of the `hello.txt` file.

```bash
# Terminate an interactive Bash session inside the Node
exit 
# Delete the busy-box pod
kubectl delete pod busybox-pod 
# Execute an interactive Bash session inside the Node
docker exec -it <the-name-of-your-node> bash 
# Change the current directory to /var/tmp/.
cd var/tmp/ 
# Display the contents of the hello.txt file.
cat hello.txt
```

The output below shows the contents (_hello.txt_) of the `hostPath` volume, even if the pod using that volume has been deleted.

But remember to consider backup measures and handle critical data when using the `hostPath` volume type. Why?

The `hostPath` volume type is tightly coupled with the pod’s lifecycle — when the pod is deleted, the `hostPath` unmounts. As a result, in the event of a node failure, the data stored on the host may be lost.

![Deleting and verifying if the hello.txt file still exists after pod deletion](https://adamtheautomator.com/wp-content/uploads/2023/06/image-183.png)

Deleting and verifying if the **hello.txt** file still exists after pod deletion

## Persisting Data via the PersistentVolumeClaim (PVC)

Instead of using a potentially risky HostPath volume, consider the more robust PersistentVolumeClaim (PVC) volume type. In Kubernetes volumes, PVCs enable dynamic provisioning of storage resources, automatically creating PersistentVolumes (PVs) based on specified criteria.

This feature simplifies storage management and ensures data preservation even if pods or nodes are deleted. Additionally, PVCs allow multiple pods to share a file system for data sharing and synchronization.

To configure a persistent volume, follow the steps below:

1\. Create a YAML file (i.e., `pvc.yaml`) and input the following configuration.

This configuration creates a `PVC` named `my-pvc` (arbitrary) that requires `ReadWriteOnce` access mode. As a result, the `PVC` can be mounted by a single pod for reading and writing and requests for `1Gi` of storage capacity.

> 💡 _PVCs are commonly used for stateful applications that require persistent storage. They are ideal for databases like MySQL, PostgreSQL, or MongoDB, providing durable storage across pod restarts or rescheduling._

```yaml
apiVersion: v1
# Kubernetes resource type
kind: PersistentVolumeClaim 
metadata:
  # The PVC name
  name: my-pvc 
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      # The amount of storage needed by the PVC from a PV
      storage: 1Gi 
```

2\. Next, execute the following command to `apply` the configuration in the _pvc.yaml_ file, which creates a `PVC`.

```bash
# Apply the configuration from the pvc.yaml file
kubectl apply -f pvc.yaml
# List all PVCs
kubectl get pvc
# List all PVs
kubectl get pv
```

Once you create a `PVC`, Kubernetes automatically searches for an available `PV` that matches the `PVC’s` criteria.

If a suitable `PV` is found, it will be bound to the `PVC`; else, it will be pending, as shown in the output below.

![Creating and viewing a PVC](https://adamtheautomator.com/wp-content/uploads/2023/06/image-192.png)

Creating and viewing a PVC

3\. Create another YAML file (i.e., `pv.yaml`) and populate the below configuration, which creates a `PersistentVolume` named `my-pv` with a `hostPath` storage type.

```yaml
apiVersion: v1
# The Kubernetes resource type
kind: PersistentVolume
metadata:
  # The PV name
  name: my-pv 
spec:
  # The storage type
  storageClassName: hostpath 
  capacity:
    # The amount of storage available for the PV
    storage: 5Gi 
  accessModes:
    - ReadWriteOnce
  hostPath:
    # The already existing path to store data in the host file system
    path: /mnt/data 
```

> 💡 _Remember, the `hostPath` with `PersistentVolume` lets you access a directory or file from the host machine’s filesystem. But this configuration does not preserve data in case of pod or node deletion. Instead, consider other types of PVs like network-based storage solutions or cloud provider-specific storage options._

4\. Now, run each command below to `apply` the `pv.yaml` file’s configuration and view the `pv` and the current `pvc` status.

```bash
# Apply the pv.yaml configuration
kubectl apply -f pv.yaml
# View all PVs
kubectl get pv
# View all PVCs
kubectl get pvc
```

The output below shows that the PV was created, and the PVC is now bound to the PV.

![Creating PV and viewing PVC](https://adamtheautomator.com/wp-content/uploads/2023/06/image-191.png)

Creating PV and viewing PVC

5\. Create another YAML file (i.e., `postgres-statefulset.yaml`) and add the following configuration.

This configuration creates a `StatefulSet` with one replica running a PostgreSQL container image and a corresponding service to expose the database externally.

Related:[The Getting Started Guide to Kubernetes Services](https://adamtheautomator.com/kubernetes-services/)

```yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  # The name of the statefulset
  name: postgres 
spec:
  serviceName: postgres
  selector:
    matchLabels:
      app: postgres
  # The number of replicas
  replicas: 1 
  template:
    metadata:
      labels:
        app: postgres
    spec:
      containers:
        - name: postgres
          # Specifies this statefulset should use a Postgres container image
          image: postgres 
          env:
          # Sets the Postgres user environment variable
          - name: POSTGRES_USER 
            value: "admin"
          # Sets the Postgres password environment variable
          - name: POSTGRES_PASSWORD 
            value: "12345"
          imagePullPolicy: "IfNotPresent"
          ports:
          # Specifies the container port
          - containerPort: 5432 
          volumeMounts:
          - name: data
            mountPath: /var/lib/postgresql/data
      volumes:
      # Specifies the volume name
      - name: data 
        # Specifies a pvc volume type
        persistentVolumeClaim: 
          claimName: my-pvc
---
apiVersion: v1
# Kubernetes resource type
kind: Service 
metadata:
   # The service name
   name: postgres 
   labels:
     app: postgres
spec:
   selector:
     app: postgres
   ports:
     # Specifies the protocol used for the port
     - protocol: TCP 
       name: http
       # The port to export
       port: 5432 
       targetPort: 5432
```

6\. Next, run the below commands to create and view the `postgres` `statefulsets` and service (`svc`)

```bash
# Apply the postgres-statefulset.yaml configuration
kubectl apply -f postgres-statefulset.yaml
# View all statefulsets
kubectl get statefulsets
# View all pods
kubectl get pods
# View all SVCs
kubectl get svc
```

The output below shows that the PostgreSQL statefulset, pod, and service are created.

![Creating and viewing Postgres statefulset, pods, and service](https://adamtheautomator.com/wp-content/uploads/2023/06/image-190.png)

Creating and viewing Postgres statefulset, pods, and service

7\. With a statefulset made, run the following command to get the `bash` shell into the `postgres-0` pod. Doing so initializes creating data in the `postgres-0` pod to verify data persistence.

```bash
# Get the Bash shell into the postgres-0 pod
kubectl -it exec postgres-0 -- bash
# Switch to the admin user
psql --username=admin
```

![Getting into the postgres-0 container as an admin](https://adamtheautomator.com/wp-content/uploads/2023/06/image-189.png)

Getting into the postgres-0 container as an admin

8\. Now, run the following commands to create a database called `records` (arbitrary) and exit out of the `postgres-0` pod.

```bash
# Create a database called records
create database records;
# Logout from the admin user
\q
# Exit the postgress shell
exit
```

![Creating a database in the postgres-0 container](https://adamtheautomator.com/wp-content/uploads/2023/06/image-188.png)

Creating a database in the postgres-0 container

9\. After creating a database, run the below commands to `delete` and re-create the `postgres-0` pod to test if the database created within the PostgreSQL pod remains intact.

```bash
# Delete the postgres-0 pod
kubectl delete pod postgres-0
# Re-create the postgres-0 pod
kubectl get pods
# List all pods
kubectl get pods
```

Below, you can see the pod’s status changed from **ContainerCreating** to **Running**, which confirms the pod has been recreated successfully.

![Deleting and recreating postgres-0 pod](https://adamtheautomator.com/wp-content/uploads/2023/06/image-187.png)

Deleting and recreating **postgres-0** pod

10\. Ultimately, execute the commands below to get the `bash` shell into the `postgres-0` again, and confirm if the database you created in step eight still exists.

```bash
# Get the bash into the postgres-0 pod
kubectl -it exec postgres-0 -- bash
# Switch to the admin user
psql --username=admin
# List all databases
\l
```

As you can see below, the **records** database persists, which is what persistent volumes and claims provide out of the box.

![Verifying data persistence](https://adamtheautomator.com/wp-content/uploads/2023/06/image-186.png)

Verifying data persistence

## Injecting Configuration Settings Into Pods (ConfigMap)

Besides using fixed configurations, you can also inject configuration settings as files in your application using the ConfigMap volume type. This volume type is a key-value store that holds configuration settings, environment variables, or other configuration data that your application needs.

To see how to inject configuration settings:

1\. Create a configuration file called _nginx.conf_, and populate the following code, which configures an NGINX server to listen on port `8080` instead of the default port `80`

```
events {
    # Specify event-related settings here
    # For example:
    # worker_connections  1024;
}

http {
    server {
        # Configures the server to listen on port 8000
        listen 8080; 

        location / {
            root /usr/share/nginx/html;
            index index.html;
        }
    }
}
```

2\. Next, run the following commands to `create` a `configmap` from the `nginx.conf` file.

This command stores the contents of the `nginx.conf` file in an `nginx-config` ConfigMap, which can be referenced by pods or other resources in the Kubernetes cluster.

```bash
# Create a ConfigMap based on a configuration file
kubectl create configmap nginx-config --from-file=nginx.conf
# List all ConfigMaps
kubectl get configmap
```

![Creating and viewing a ConfigMap](https://adamtheautomator.com/wp-content/uploads/2023/06/image-196.png)

Creating and viewing a ConfigMap

3\. Create another file called _nginx.yaml_ (arbitrary) and add the following configuration, creating an `nginx` pod with an `nginx` container.

Additionally, this configuration mounts a `configMap` (`nginx-config`) as a volume inside the container at the `/etc/nginx/nginx.conf` path. The mounted ConfigMap allows the `nginx` container to access the configuration file (`nginx.conf`).

```nginx
apiVersion: v1
kind: Pod
metadata:
  # The pod's name
  name: nginx 
spec:
  containers:
    - name: nginx
      # Specifies that this port should use an NGINX container image
      image: nginx 
      ports:
        # Specifies the container port
        - containerPort: 8080 
      volumeMounts:
        # The volume name to use as a volume mount
        - name: my-nginx-config 
          mountPath: /etc/nginx/nginx.conf
          subPath: nginx.conf
  volumes:
    # The volume name
    - name: my-nginx-config 
      # The volume type
      configMap: 
        name: nginx-config
        items:
          # The key the pod should use from the config map
          - key: nginx.conf 
            path: nginx.conf
```

4\. Now, execute the commands below to create and view the `nginx` pod.

```bash
kubectl apply -f nginx.yaml
kubectl get pods 
```

![Creating and viewing the nginx pod](https://adamtheautomator.com/wp-content/uploads/2023/06/image-195.png)

Creating and viewing the nginx pod

5\. With the nginx pod running, execute the below to view the NGINX webserver welcome page on port `8080.` This command forwards port `8080` of the nginx pod to a local port on your machine.

```bash
kubectl port-forward pod/nginx 8080:8080
```

![Forwarding port 8080 of the nginx pod to the machine’s local port](https://adamtheautomator.com/wp-content/uploads/2023/06/image-193.png)

Forwarding port 8080 of the nginx pod to the machine’s local port

6\. Lastly, open your favorite web browser, and navigate to your localhost to access the NGINX web server on port 8080 (_[](http://localhost:8080/)http://localhost:8080_).

![Accessing the NGINX welcome page on port 8080](https://adamtheautomator.com/wp-content/uploads/2023/06/image-194.png)

Accessing the NGINX welcome page on port 8080

## Encoding and Passing Secure Data to Pods (`secret`)

Since passing raw data poses security risks, why not securely encode and inject data? The secret volume type allows you to securely store and manage sensitive information, such as passwords, API keys, and TLS certificates.

[Secrets](https://adamtheautomator.com/kubernetes-secrets/) are base64-encoded data that are stored in the Kubernetes cluster and can be mounted as volumes inside pods, deployments, and statefulsets.

Related:[How to Keep Kubernetes Secrets Safe](https://adamtheautomator.com/kubernetes-secrets/)

To secure data with the `secrets` volume type:

1\. Execute the below command to edit the `nginx.conf` to listen on port `8000` and convert the contents of the file to base64 format.

```bash
base64 -w0 nginx.conf
```

Take note of the converted content, as you will need it for your secret volume type configuration.

![Converting the contents of the nginx.conf file to base64 encoded value](https://adamtheautomator.com/wp-content/uploads/2023/06/image-201.png)

Converting the contents of the _nginx.conf_ file to base64 encoded value

2\. Next, create a new file called _secret.yaml_ (or name it differently), and input the following configuration settings. Make sure you replace `<base64-encoded-content>` with the converted content you noted in step one.

This configuration creates a secret object called `nginx-secret-config`, where you will store the content of the _`nginx.conf`_ file as a base64-encoded value.

```yaml
apiVersion: v1
kind: Secret
metadata:
  # The secret's name
  name: nginx-secret-config 
# Secret file
type: Opaque 
data:
  # Secret key and base64 encoded value
  nginx.conf: <base64-encoded-content> 
```

3\. Now, run the following commands to create and view the secret object specified in the `secret.yaml` file.

```bash
kubectl apply -f secret.yaml
kubectl get secrets
```

![Creating and viewing the secret object](https://adamtheautomator.com/wp-content/uploads/2023/06/image-200.png)

Creating and viewing the secret object

4\. Create another YAML file named _nginx02.yaml_ (arbitrary), and add the following configuration. This configuration performs the following:

*   Creates a `pod` with an `nginx` container that listens on port `8000`.
*   Mounts a specific file (`nginx.conf`) from a secret named `nginx-secret-config` into the container at the `/etc/nginx/nginx.conf` path.

In conclusion, this configuration allows the NGINX container to access the sensitive configuration stored in the secret object.

```yaml
apiVersion: v1
kind: Pod
metadata:
  # The pod's name
  name: nginx-02 
spec:
  containers:
    - name: nginx
      # Specifies the container image to use
      image: nginx 
      ports:
        # Specifies the container port as configured in the nginx.conf file
        - containerPort: 8000 
      volumeMounts:
        # The volume to use as a volume mount
        - name: my-nginx02-config 
          # The mount path
          mountPath: /etc/nginx/nginx.conf 
          subPath: nginx.conf
  volumes:
    # The volume name
    - name: my-nginx02-config 
      # The volume type
      secret: 
        # The secret's name
        secretName: nginx-secret-config 
        items:
          # The key contained in the secret to be used by the pod
          - key: nginx.conf 
            path: nginx.conf
```

5\. Execute the following commands to create and view the pod specified in the `nginx02.yaml` file.

```bash
kubectl apply -f nginx02.yaml
kubectl get pods
```

![Creating and viewing the nginx02 pod](https://adamtheautomator.com/wp-content/uploads/2023/06/image-199.png)

Creating and viewing the nginx02 pod

6\. With the new pod created, run the command below to forward port `8000` of the NGINX pod to a local port on your machine.

```bash
kubectl port-forward pod/nginx 8000:8000
```

![Forwarding port 8000 of the NGINX pod to a local port](https://adamtheautomator.com/wp-content/uploads/2023/06/image-198.png)

Forwarding port 8000 of the NGINX pod to a local port

7\. Finally, navigate to your localhost in your web browser to access the NGINX web server on port 8000 (_[](http://localhost:8080/)http://localhost:8080_).

If all goes well, you will see the NGINX welcome page, as shown below.

![Accessing the NGINX welcome page on port 8000](https://adamtheautomator.com/wp-content/uploads/2023/06/image-194.png)

Accessing the NGINX welcome page on port 8000

## Conclusion

Throughout this tutorial, you have learned what Kubernetes volumes are and how they help persist data for your applications. With many type of Kubernetes volumes at your disposal, you can now confidently persist your data for PostgreSQL database using a PVC.

Now, why not explore using a network-based storage solution, like a [Network File System (NFS)](https://shishirkh.medium.com/how-to-set-up-an-nfs-for-vms-kubernetes-6e6651d3d85b) Server?

Related:[How to Install and Configure a Linux Ubuntu NFS Server](https://adamtheautomator.com/ubuntu-nfs-server/)

Share this article

[Share on X](https://twitter.com/intent/tweet?url=https%3A%2F%2Fadamtheautomator.com%2Fkubernetes-volumes%2F&text=The%20Comprehensive%20Guide%20to%20Kubernetes%20Volumes)[Share on Facebook](https://www.facebook.com/sharer/sharer.php?u=https%3A%2F%2Fadamtheautomator.com%2Fkubernetes-volumes%2F)[Share on LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fadamtheautomator.com%2Fkubernetes-volumes%2F)

## Related Posts

![](https://adamtheautomator.com/wp-content/uploads/2026/07/featured_image-3.png)

### [Build Your First Internal Developer Platform](/build-first-internal-developer-platform/)

Build your first Internal Developer Platform with Backstage, a software catalog, software templates, CI/CD handoffs, and Kubernetes deployment manifests.

![](https://adamtheautomator.com/wp-content/uploads/2026/06/featured_image-9.png)

### [DevOps to Platform Engineer: 2026 Transition Roadmap](/devops-platform-engineer-2026-transition-roadmap/)

Learn how to move from DevOps to platform engineering in 2026 with a practical roadmap covering transferable skills, internal developer platforms, Backstage, Crossplane, and portfolio projects.

![](https://adamtheautomator.com/wp-content/uploads/2024/02/kubernetes-blue-green.jpg)

### [Learning the Kubernetes Blue Green Deployment Strategy](/kubernetes-blue-green/)

Dive into Kubernetes blue-green deployments for smooth updates. Enhance your release process with this smart Kubernetes strategy!

## Categories

*   [IT Ops](/category/it-ops/)
*   [Cloud](/category/cloud/)
*   [DevOps](/category/devops/)
*   [Home Ops](/category/home-ops/)
*   [Information Security](/category/infosec/)
*   [Software Development](/category/software-development/)

## Site

*   [Home](/)
*   [Tutorials](/tutorials/)
*   [Instructors](/author/)
*   [Advertising](/advertising/)
*   [Recommended Resources](/resources/)
*   [About Adam](/about-adam/)

Copyright 2026© ATA Learning | [Privacy Policy](/privacy/)
