Kubernetes resources like ConfigMap, Secret, or PersistentVolumeClaim objects can be created and exist within the cluster. However, to associate them with an application, they must be attached as volumes to Pods. This attachment process requires a two-part declaration within the Pod manifest: first defining the volume at the Pod level, and then mounting it into the desired location within a specific container.
This mechanism is consistent across different volume types, providing a standard way to connect external data and configuration to your application workloads. A volume defined for a Pod can be shared among all its containers, or mounted uniquely into each one.
volumes and volumeMountsConnecting a volume to a container inside a Pod always involves two distinct specifications in the manifest:
spec.volumes: An array at the Pod specification level. This is where you declare a list of volumes available to the Pod. Each entry in this list is given a unique name within the Pod and specifies its source, such as a ConfigMap, a Secret, or a PersistentVolumeClaim. Think of this as creating a named pointer to an external resource.spec.containers.volumeMounts: An array inside a container's specification. This list tells the container which volumes from the Pod's volumes list to mount and where to place them within its own filesystem. It uses the name from the volumes list to identify the source and specifies a mountPath for the destination.The name field acts as the bridge connecting a Pod-level volume definition to a container-level mount point.
The
namefield in thespec.volumesarray is referenced by thenamefield in a container'svolumeMountsarray to establish the connection.
Let's examine how to apply this pattern for each of the resource types we have discussed.
ConfigMaps are frequently used to supply configuration files to an application. By mounting a ConfigMap as a volume, each data key in the ConfigMap becomes a file within the specified mount directory, with the key as the filename and the value as the file's content.
Imagine you have the following ConfigMap to configure a web server:
# my-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
# The 'settings.json' will become the filename
settings.json: |
{
"theme": "dark",
"logLevel": "info"
}
# The 'user.properties' will also become a file
user.properties: |
username=default_user
allow_guests=false
To mount this ConfigMap into a Pod, you would write a manifest like this:
# my-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: configmap-pod
spec:
containers:
- name: my-app
image: busybox
command: ["sleep", "3600"]
# Step 2: Mount the volume into the container's filesystem
volumeMounts:
- name: config-volume # This name must match a volume below
mountPath: /etc/config # Directory where files will appear
# Step 1: Define the volume at the Pod level
volumes:
- name: config-volume # A unique name for this volume within the Pod
configMap:
# Specify the name of the ConfigMap to use
name: app-config
After applying this manifest, you can inspect the Pod's filesystem:
# Exec into the running pod
kubectl exec -it configmap-pod -- /bin/sh
# List the contents of the mount path
/ # ls /etc/config
settings.json
user.properties
# View the content of one of the files
/ # cat /etc/config/settings.json
{
"theme": "dark",
"logLevel": "info"
}
The files settings.json and user.properties are now present in the /etc/config directory inside the container. This approach successfully decouples the configuration from the application's container image.
The procedure for mounting a Secret is almost identical to that of a ConfigMap. This consistency makes it simple to manage both sensitive and non-sensitive data. The primary difference is specifying secret instead of configMap as the volume source.
Suppose you have a Secret containing credentials:
# my-secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: db-credentials
type: Opaque
stringData: # Using stringData for readability
username: "admin"
password: "SuperSecretPassword123"
You can mount this Secret into a Pod as follows:
# secret-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: secret-pod
spec:
containers:
- name: my-app
image: busybox
command: ["sleep", "3600"]
volumeMounts:
- name: secret-volume
mountPath: /etc/secrets
readOnly: true # It is good practice to mount secrets as read-only
volumes:
- name: secret-volume
secret:
# Specify the name of the Secret to use
secretName: db-credentials
When this Pod is running, the keys from the Secret (username and password) will be available as files in the /etc/secrets directory. The contents of these files will be the decoded values from the Secret.
# Exec into the running pod
kubectl exec -it secret-pod -- /bin/sh
# List the files in the secret mount directory
/ # ls /etc/secrets
password
username
# Display the password
/ # cat /etc/secrets/password
SuperSecretPassword123
For stateful applications that require durable storage, you attach a PersistentVolumeClaim (PVC). This gives your Pod access to a persistent disk that exists independently of the Pod's lifecycle. The Pod manifest references the PVC, not the underlying PersistentVolume (PV), maintaining the abstraction between the user's storage request and the administrator's provisioned storage.
Assuming a PersistentVolumeClaim named my-data-pvc has already been created and is in the Bound state, you can attach it to a Pod like this:
# stateful-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: stateful-app
spec:
containers:
- name: web-server
image: nginx
ports:
- containerPort: 80
volumeMounts:
- name: data-storage # Refers to the volume defined below
mountPath: /usr/share/nginx/html # Mount path for web content
volumes:
- name: data-storage # A name for the volume
persistentVolumeClaim:
# Reference the name of the PVC
claimName: my-data-pvc
In this example, the storage managed by my-data-pvc is mounted into the container at /usr/share/nginx/html. Any files the Nginx server writes to this directory will be stored on the persistent volume. If the Pod is deleted and recreated, a new Pod can mount the same PVC and regain access to the previously written data. This is the foundation for running databases, content management systems, and other stateful workloads on Kubernetes.
A Pod's
volumessection references different cluster resources, while thevolumeMountssection in each container maps them to specific paths.
By mastering this pattern of defining volumes and creating volume mounts, you gain the ability to manage a wide range of application requirements, from stateless services with externalized configuration to complex stateful applications that rely on durable storage.
Was this section helpful?
© 2026 ApX Machine LearningEngineered with