OpenShift Persistent Volume Claims (PVC) for Java Applications
Learn how Java and Spring Boot applications use Persistent Volume Claims (PVC) in OpenShift for file uploads, reports, logs, and persistent storage. Understand PVC architecture, implementation, and enterprise best practices.
Introduction
Enterprise Java applications frequently need to store data that must survive application restarts.
Examples include:
- User uploaded documents
- PDF reports
- Images
- Invoice files
- Log archives
- Batch processing files
- CSV imports
- Exported Excel reports
If these files are stored inside a container, they disappear whenever the Pod restarts.
This is why Java applications running on OpenShift should use Persistent Volume Claims (PVCs).
A PVC allows your Spring Boot application to read and write files to persistent storage that remains available even after deployments, scaling events, or Pod failures.
Learning Objectives
By the end of this article, you will understand:
- Why Java applications need PVCs
- PVC architecture
- File upload implementation
- Spring Boot integration
- Mounting storage
- Enterprise storage patterns
- Shared storage
- Backup strategies
- Best practices
Problem Without PVC
Suppose a customer uploads an important document.
flowchart LR
User[Customer]
--> Pod[Spring Boot Pod]
Pod --> LocalStorage[Container Storage]
LocalStorage --> Upload[Uploaded File]
Pod -. Restart .-> Lost[❌ File Lost]
After the Pod restarts, the uploaded file is permanently lost.
Solution Using PVC
flowchart LR
User[Customer]
--> SpringBoot[Spring Boot Pod]
--> PVC[Persistent Volume Claim]
--> PV[Persistent Volume]
--> Storage[(Cloud Storage)]
Files remain available regardless of Pod lifecycle.
Real-World Java Use Cases
Spring Boot applications commonly use PVCs for:
| Application | Persistent Data |
|---|---|
| Banking | Customer Documents |
| Insurance | Claim Attachments |
| Healthcare | Medical Images |
| E-Commerce | Product Images |
| HRMS | Employee Documents |
| CRM | PDF Reports |
| Batch Processing | CSV Files |
| Analytics | Generated Reports |
PVC Architecture
flowchart TD
SpringBoot[Spring Boot Application]
PVC[Persistent Volume Claim]
PV[Persistent Volume]
Storage[(AWS EBS / Azure Disk)]
SpringBoot --> PVC
PVC --> PV
PV --> Storage
File Upload Workflow
sequenceDiagram
participant Customer
participant SpringBoot
participant PVC
participant Storage
Customer->>SpringBoot: Upload File
SpringBoot->>PVC: Save File
PVC->>Storage: Persist File
Storage-->>Customer: Upload Successful
Create PVC
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: upload-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
Deploy:
oc apply -f pvc.yaml
Verify PVC
oc get pvc
Example:
NAME STATUS
upload-pvc Bound
Mount PVC
Deployment YAML
spec:
containers:
- name: payment-api
volumeMounts:
- name: upload-storage
mountPath: /app/uploads
volumes:
- name: upload-storage
persistentVolumeClaim:
claimName: upload-pvc
Storage Architecture
flowchart LR
PVC
--> Volume
Volume
--> SpringBoot
SpringBoot
--> UploadFolder["/app/uploads"]
Spring Boot File Upload
@RestController
@RequestMapping("/files")
public class FileUploadController {
@PostMapping("/upload")
public String upload(
@RequestParam MultipartFile file)
throws Exception {
Path path = Paths.get(
"/app/uploads/" +
file.getOriginalFilename());
Files.copy(
file.getInputStream(),
path,
StandardCopyOption.REPLACE_EXISTING);
return "Upload Successful";
}
}
Files are now stored on persistent storage.
Download File
@GetMapping("/{name}")
public ResponseEntity<Resource> download(
@PathVariable String name)
throws Exception {
Path path = Paths.get(
"/app/uploads/" + name);
Resource resource =
new UrlResource(path.toUri());
return ResponseEntity.ok(resource);
}
Upload Flow
flowchart LR
Customer
--> RESTAPI
RESTAPI
--> SpringBoot
SpringBoot
--> PVC
PVC
--> PersistentStorage
Report Generation
Many enterprise applications generate reports.
flowchart LR
BatchJob
--> PDFReport
PDFReport
--> PVC
PVC
--> Download
Reports remain available even after application restart.
Spring Batch Example
flowchart LR
INPUT["CSV Input"]
JOB["Spring Batch Job"]
WRITER["Item Writer"]
FILE["Generated Output File"]
STORAGE["PersistentVolumeClaim (PVC)"]
INPUT --> JOB
JOB --> WRITER
WRITER --> FILE
FILE --> STORAGE
Banking Example
Customer uploads KYC documents.
flowchart TD
CUSTOMER["Customer"]
API["Upload API"]
APP["Spring Boot"]
PVC["PersistentVolumeClaim"]
EBS["AWS EBS"]
CUSTOMER --> API
API --> APP
APP --> PVC
PVC --> EBS
Documents remain safe after deployment.
Insurance Example
Claim documents.
flowchart LR
CUSTOMER["Customer"]
CLAIM["Claim Service"]
PVC["PersistentVolumeClaim"]
DISK["Azure Disk"]
CUSTOMER --> CLAIM
CLAIM --> PVC
PVC --> DISK
Healthcare Example
Medical images.
flowchart TD
PORTAL["Doctor Portal"]
APP["Spring Boot Application"]
PVC["PersistentVolumeClaim"]
STORAGE["Cloud Storage"]
PORTAL --> APP
APP --> PVC
PVC --> STORAGE
Shared Storage
Some applications require multiple Pods to access the same storage.
flowchart LR
Pod1
--> SharedPVC
Pod2
--> SharedPVC
Pod3
--> SharedPVC
SharedPVC
--> Storage
Requires ReadWriteMany (RWX) support.
Access Modes
| Mode | Description |
|---|---|
| ReadWriteOnce | One Node |
| ReadOnlyMany | Read Only |
| ReadWriteMany | Shared Read/Write |
Most Java applications use:
- ReadWriteOnce
Shared document systems may require:
- ReadWriteMany
Verify Mount
Enter Pod.
oc rsh payment-api-xxxxx
Check directory.
ls /app/uploads
Pod Restart Test
flowchart LR
POD1["Pod 1"]
PVC["PersistentVolumeClaim"]
RESTART["Pod Restart"]
POD2["New Pod"]
POD1 --> PVC
RESTART --> POD2
POD2 --> PVC
Files remain available.
Scale Application
flowchart LR
SpringBoot
--> Pod1
SpringBoot
--> Pod2
SpringBoot
--> Pod3
Pod1 --> PVC
Pod2 --> PVC
Pod3 --> PVC
All Pods share persistent storage when supported.
Enterprise Architecture
flowchart TD
USERS["Users"]
ROUTE["Route"]
SERVICE["Service"]
PODS["Spring Boot Pods"]
PVC["PVC"]
STORAGE_CLASS["Storage Class"]
CLOUD_STORAGE["Cloud Storage"]
POSTGRES["PostgreSQL"]
DB_PVC["Database PVC"]
USERS --> ROUTE
ROUTE --> SERVICE
SERVICE --> PODS
PODS --> PVC
PVC --> STORAGE_CLASS
STORAGE_CLASS --> CLOUD_STORAGE
PODS --> POSTGRES
POSTGRES --> DB_PVC
Logging Example
Store application logs.
logging.file.name=/app/uploads/logs/payment.log
Logs remain available after restart.
Backup Strategy
flowchart LR
PVC["PersistentVolumeClaim"]
BACKUP["Backup Job"]
STORAGE["Object Storage"]
DR["Disaster Recovery"]
PVC --> BACKUP
BACKUP --> STORAGE
STORAGE --> DR
Always back up persistent storage.
Monitoring Storage
Useful commands.
oc get pvc
oc describe pvc upload-pvc
df -h
Common Problems
PVC Pending
Possible causes:
- StorageClass missing
- No storage available
Verify:
oc get storageclass
Permission Denied
Check:
- Security Context
- File ownership
- Mount path
Disk Full
Verify:
df -h
Increase PVC size if supported.
Missing Files
Verify:
ls /app/uploads
Ensure the PVC is mounted correctly.
Best Practices
- Never store uploaded files inside containers.
- Use PVC for reports and documents.
- Separate database storage from file storage.
- Enable automated backups.
- Monitor disk usage.
- Use RWX only when required.
- Use StorageClasses for dynamic provisioning.
- Test recovery after Pod restart.
Common Mistakes
❌ Saving files inside /tmp.
❌ Running databases without PVC.
❌ Deleting PVC accidentally.
❌ Ignoring storage monitoring.
❌ Sharing one PVC across unrelated applications.
Advantages
- Persistent storage
- Survives Pod restart
- Cloud-native architecture
- Enterprise ready
- Better scalability
- Reliable file management
- Easy backups
- Simplified storage operations
Summary
Persistent Volume Claims are essential for Java applications that need durable storage.
Key takeaways:
- Containers are temporary, but PVC-backed storage is persistent.
- Spring Boot applications can store uploads, reports, and generated files on PVCs.
- PVCs abstract the underlying storage implementation, making applications portable across cloud providers.
- StorageClasses simplify dynamic provisioning.
- Enterprise applications should always use PVCs for critical business data.
Interview Questions
- What is a Persistent Volume Claim (PVC)?
- Why do Java applications need persistent storage?
- What happens to container data after a Pod restart?
- How do you mount a PVC into a Spring Boot application?
- What are the different PVC access modes?
- When should you use ReadWriteMany?
- How do you verify that a PVC is mounted?
- Why should uploaded files never be stored inside a container?
- What is the role of a StorageClass?
- What are the best practices for persistent storage in enterprise Java applications?