For the complete documentation index, see llms.txt. This page is also available as Markdown.

Managing Volume Mounts in Spring Boot Pods

About

Spring Boot applications running inside containers often require access to:

  • Persistent storage (e.g., for file uploads, logs, or databases)

  • Externalized configurations (e.g., application.properties, YAML files)

  • Secrets (e.g., database passwords, tokens)

Kubernetes and OpenShift provide a declarative way to mount these as volumes into pods so that applications can access them like regular files.

Types of Volume Mounts for Spring Boot Apps

Volume Type
Purpose

PersistentVolumeClaim (PVC)

Store and retain application data persistently

ConfigMap

Inject application configuration files

Secret

Inject sensitive data like passwords

1. Mounting a PersistentVolumeClaim (PVC)

A Spring Boot application may need to:

  • Store or access files beyond its container lifecycle.

  • Persist logs, uploads, reports, caches, or temporary working data.

  • Retain state across pod restarts or re-deployments.

Since containers are ephemeral, persistent storage must be mounted into the pod using a PVC.

Internal Flow of PVC Mounting

Step-by-step Kubernetes (OpenShift) mechanics:

  1. User defines a PVC in a YAML manifest.

  2. The OpenShift controller checks for an available PV that satisfies the request (capacity, access mode, storage class).

  3. If found, the PVC is bound to that PV.

  4. During pod scheduling, the container runtime (like CRI-O) mounts the volume from the node (or network) into the pod at the specified path.

  5. Inside the container, the mount path behaves like a native directory.

If using dynamic provisioning:

  • A StorageClass is used.

  • A new PV is created on-the-fly using the storage plugin (e.g., AWS EBS, Ceph, NFS).

  • The PVC binds to that PV automatically.

Access Mode Considerations

The PVC must have an access mode compatible with how the Spring Boot app is deployed:

  • ReadWriteOnce (RWO): One pod on one node can mount as read-write.

  • ReadWriteMany (RWX): Multiple pods (across nodes) can mount concurrently.

Use RWX for clustered Spring Boot apps needing shared state (e.g., shared cache or uploads).

  • Spring Boot doesn’t manage storage; it simply uses the file system.

  • You must ensure that the mount path exists and has correct permissions.

  • Spring Boot must have read/write permissions for that path.

  • Avoid hardcoding paths in code. Use externalized configuration (e.g., environment variables or properties).

Use Case: File Upload Handling in Spring Boot Using PVC

We are building a Spring Boot app deployed on OpenShift that:

  • Lets users upload files via a REST API.

  • Saves these files to /data/uploads directory.

  • Ensures uploaded files persist across pod restarts.

YAML Definitions

StorageClass (if using dynamic provisioning)

PersistentVolumeClaim

Deployment (Spring Boot App Pod + PVC Mount)

Spring Boot Application Code

application.properties

This ensures:

  • If FILE_UPLOAD_PATH is passed (via env), it’s used.

  • Else, defaults to /tmp/uploads.

File Upload Controller

Expected Behavior

  1. User uploads a file via REST.

  2. File is stored under /data/uploads inside the container.

  3. This directory is mapped to the PVC → meaning file is stored on the persistent volume.

  4. If the pod crashes, the file remains available when the pod restarts.

Testing the Workflow

Upload a file using curl

Check if the file persists after a pod restart

Common Use Cases in Spring Boot

Use Case
Mount Path
Notes

File uploads

/data/uploads

Must persist even after app restarts

Exported reports

/data/reports

Can be backed up externally

Runtime temp storage

/tmp/data

Can use emptyDir or PVC if needed later

Log file persistence

/var/log/app

Useful for sidecar log shippers

Caches or binary blobs

/cache/store

Use with ReadWriteMany if clustered

2. Mounting ConfigMaps as Volumes

A ConfigMap in OpenShift is a key-value store used to manage non-sensitive configuration data independently from container images.

By mounting a ConfigMap as a volume into a Spring Boot pod, we can:

  • Externalize application configuration

  • Avoid rebuilding images for configuration changes

  • Support environment-specific setups (e.g., dev, test, prod)

  • Override default configurations such as application.properties, YAML files, logging configurations, or arbitrary static files

Internal Flow of Mounting a ConfigMap as a Volume

  1. A ConfigMap is defined containing configuration content (e.g., application.properties).

  2. The ConfigMap is mounted into a directory inside the container’s file system using a volume and volumeMount.

  3. Spring Boot is configured to load its config files from that directory.

  4. On container startup, Spring Boot reads the file(s) as if they were on the local file system.

This approach allows runtime reconfiguration without rebuilding the image, and even supports rolling updates on config changes.

Spring Boot Configuration Mechanism

Spring Boot supports external configuration through various sources in a specific order:

  1. Command-line arguments

  2. Environment variables

  3. application.properties or application.yml files on the classpath

  4. Files in directories specified using spring.config.location

Mounting a ConfigMap into a path like /config and then pointing Spring Boot to load from there lets we override default values inside the JAR.

Use Case: Inject externalized application.properties into a Spring Boot application

Create application.properties

Create a file named application.properties with the following content:

This file will be injected into the container through a ConfigMap.

Create the ConfigMap

Create a ConfigMap from the file:

This creates a ConfigMap named spring-config where the key is application.properties and the value is the content of the file.

We can verify:

Or use a YAML definition instead:

Apply it with:

Modify Spring Boot Application

Ensure the Spring Boot app:

  1. Reads configuration from an external directory

  2. Has a controller that uses the app.title value

Controller Example:

Important: This value must be picked up from the ConfigMap file mounted in the pod.

Step 4: Create Deployment with Volume Mount

Create a deployment that:

  • Mounts the ConfigMap into /config

  • Tells Spring Boot to load config from /config/application.properties

springboot-deployment.yaml

Apply it:

Expose the Application

Or in OpenShift:

Get the URL:

Test the Endpoint

Access:

Expected output:

This confirms that:

  • The application read config from the mounted /config/application.properties

  • The ConfigMap is functioning correctly

3. Mounting Secrets as Volumes

A Secret in OpenShift is a Kubernetes object used to store sensitive data such as:

  • Database credentials

  • API keys

  • OAuth tokens

  • TLS certificates

Mounting Secrets as volumes into a Spring Boot pod enables the application to securely access sensitive configuration at runtime without hardcoding or baking credentials into container images.

Secrets are base64-encoded and are mounted into the container’s file system as plain files. These files can then be read by the Spring Boot application as needed.

Internal Behavior of Secret Volumes

  1. A Secret object is created, containing key-value pairs.

  2. The pod declares a volume from the secret and a corresponding volumeMount to define the mount path.

  3. Kubernetes injects the contents of each secret key as a separate file in the specified directory.

  4. Spring Boot (or other application logic) reads the secrets from disk, either during startup or on demand.

Each key becomes a file with the key as filename and the value as its contents.

When to Use Secrets as Volumes

  • When we do not want to expose sensitive data through environment variables.

  • When external libraries or tools (e.g., database clients, messaging clients, TLS consumers) expect config as files.

  • When we want to rotate secrets dynamically (e.g., mount a new TLS cert).

Use Case: Injecting Database Credentials into a Spring Boot App

Create the Kubernetes Secret

Imperative Method (using CLI)

This creates a Secret named db-credentials with two keys: username and password.

Declarative YAML Alternative

Mount the Secret into the Spring Boot Pod

Deployment YAML Snippet

Spring Boot Code to Read Credentials

We can use either:

Option 1: @Value with file: syntax

application.properties

Spring Boot will read the contents of the file /secrets/username and /secrets/password.

Make sure to pass SPRING_CONFIG_ADDITIONAL_LOCATION=file:/secrets/ as an environment variable or as a --spring.config.additional-location argument in our container.

Option 2: Read files programmatically

We can then use this service in our DB configuration or elsewhere.

Configure our DataSource (Optional)

If we are manually configuring our DataSource, we can use the credential service above:

Last updated