Kubernetes subPath Examples | MountPath vs subPath Explained


Kubernetes Tutorial

Introduction to Kubernetes SubPath

We recently explained how it is possible to update secrets and configmaps in Kubernetes without restarting any pods. One of the pitfalls of this approach was that when we specify a mount path in our deployment, and it already exists inside the container, all the existing files and directories inside that path become inaccessible. That doesn't mean that existing data is deleted, it simply ceases to exist for the time being.

This is the general behavior in Linux. When a filesystem is mounted into a non-empty directory, the directory then only contains the files from the newly mounted filesystem. The original files in that directory are inaccessible for as long as the filesystem remains mounted. In cases, when the directory contains crucial data, mounting a configmap or a secret in non-empty directory could break the functionality of the container.

To overcome this limitation, Kubernetes offers an alternative in the form of subPath. The official Kubernetes documentation defines this as follows:

Sometimes, it is useful to share one volume for multiple uses in a single pod. The volumeMounts.subPath property specifies a sub-path inside the referenced volume instead of its root.

The Kubernetes subPath property prevents overwriting of existing data by mounting a single file from the volume instead of mounting the whole volume. We'll explain this by mounting a configMap in an nginx deployment.

 

Known Limitation

At the time of writing this article, there is a known limitation when using Kubernetes subPath. ConfigMaps and secrets mounted using subPath cannot be updated dynamically. To update the configmap and secrets, new pods will need to be created.

 

Prerequisites

  • Working K8s cluster
  • Working knowledge of K8s and yaml language

 

Create a sample deployment (Optional)

We're first going to create a sample nginx deployment using a single replicaset as follows.

apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: nginx
  name: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx
        name: nginx

Once the deployment has been created, access the container and list the contents under the /etc/nginx directory. As can be seen, the /etc/nginx directory contains multiple files and a directory. Make a note of this and proceed to delete this deployment.

kubectl get pods

kubectl exec -it nginx-8f458dc5b-zkbdt bash

cd /etc/nginx/; ls -l

exit

Kubernetes subPath Examples | MountPath vs subPath Explained

 

Mount ConfigMap using Kubernetes mountPath

Let's create a simple nginx.conf file with the following content and mount it inside the container using a configmap using mountPath. There are multiple ways to access a configmap inside the container.

events {
	worker_connections 1024;
}

http {
	server {
		listen 80 default_server;
		server_name example.com;
		root /var/www;
	}
}

Create the configmap from the file.

kubectl create configmap nginx-cm --from-file=nginx.conf

Kubernetes subPath Examples | MountPath vs subPath Explained

 

Once the configmap has been created, create a new nginx deployment as follows. We're going to mount the sample nginx.conf file in /etc/nginx directory inside the container using a configmap.

apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: nginx
  name: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx
        name: nginx
        volumeMounts:
        - name: nginx-vol
          mountPath: /etc/nginx
      volumes:
      - name: nginx-vol
        configMap:
          name: nginx-cm

Once the deployment has been created, access the container and list the contents of /etc/nginx directory.

kubectl get pods

kubectl exec -it nginx-bd6ccf697-d99vq bash

cd /etc/nginx/; ls

cat nginx.conf

subpath

 

As you can see, only a single file i.e. nginx.conf, which contains the content of our configmap, is present in the /etc/nginx directory. All the files which we had previously seen when creating a sample deployment in the first example are not being shown.

This shows that whenever we mount in a non-empty directory, the existing data becomes inaccessible. We're now going to fix this by mounting our configMap using the subPath property. Delete the deployment and associated resources.

kubectl delete all -l app=nginx

 

Mount configMap using Kubernetes subPath

There is no need to change the configMap created in the last example. We'll just need to update our deployment file and make the following two changes:

  • Change the mountPath from /etc/nginx to /etc/nginx/nginx.conf
  • Add the Kubernetes subPath property under mountPath and set it's value to nginx.conf.

The value for Kubernetes subPath must match the path specified in mountPath. The updated deployment should be as follows:

apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: nginx
  name: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx
        name: nginx
        volumeMounts:
        - name: nginx-vol
          mountPath: /etc/nginx/nginx.conf
          subPath: nginx.conf
      volumes:
      - name: nginx-vol
        configMap:
          name: nginx-cm

Once the deployment has been created, access the container and list the contents under /etc/nginx.

kubectl get pods

kubectl exec -it nginx-65996f4c4d-lmcmj bash

cd /etc/nginx/; ls -l

kubernetes

As evident from the above output, all the files inside /etc/nginx including our configMap file, are being shown. This shows that KubernetessubPath property should be used when mounting a configMap in a non-empty directory inside the container. Otherwise, existing data will be overwritten.

 

mountPath vs subPath

Following are some of the differences between Kubernetes mountPath and subPath when using for ConfigMap and Secrets:

  • The mountPath will overwrite existing directory with the configmap/secret. This is similar to mounting multiple directories on the same path. For example in Linux, if you have /mnt directory with some content and then you mount /dev/sda1 to /mnt then the exiting content of /mnt will not be visible. Similarly if you again mount /dev/sda2 to /mnt then the content of both /mnt and /dev/sda1 will be overwritten by content of /dev/sda2. But the content is not actually deleted, if you unmount /dev/sda2 then the content of /dev/sda1 will be visible again. The same way mountPath works in Kubernetes.
  • The subPath on the other hand will just add your content on top of the existing directory so the existing content are not lost and both new mount and existing content can be accessed.
  • The downside of using mountPath is that dynamic update of configmap or secret is not possible while the same is supported with subPath. So if you mount a configmap using subPath, then you can do some change to your secret on controller and the same will get refreshed on the container as well.

 

Summary

Kubernetes Subpaths prove useful when mounting in a non-empty directory inside the container. However, there's a limitation associated with this approach. A container using a configMap or a secret as a subpath volume mount cannot be updated dynamically. The same approach can be used for Kubernetes secrets as well. Although if you have an isolated directory then you can prefer to use mountPath in which case you will have the flexibility to dynamically update the configmap and secret content.

 

Deepak Prasad

Deepak Prasad

He is the founder of GoLinuxCloud and brings over a decade of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive experience, he excels in various domains, from development to DevOps, Networking, and Security, ensuring robust and efficient solutions for diverse projects. You can connect with him on his LinkedIn profile.

Can't find what you're searching for? Let us assist you.

Enter your query below, and we'll provide instant results tailored to your needs.

If my articles on GoLinuxCloud has helped you, kindly consider buying me a coffee as a token of appreciation.

Buy GoLinuxCloud a Coffee

For any other feedbacks or questions you can send mail to admin@golinuxcloud.com

Thank You for your support!!

Leave a Comment