Skip to content

Volumes

A volume is disk that outlives the pod using it. You ask for one with a PersistentVolumeClaim, and the storage operator provisions the disk and binds it to your claim.

For the same steps in the console, see the console walkthrough.

Choose a storage class

The storage class decides what kind of disk you get, and how many workloads can use it at once:

oc get storageclass
Kind Access mode Use it for
Block ReadWriteOnce One workload at a time - databases, anything with its own storage engine
File ReadWriteMany Several workloads at once - shared uploads, content directories

ReadWriteOnce means one node at a time, which in practice means one pod. A Deployment with two replicas on a block volume will leave the second pod Pending forever, and the event on the pod says the volume is already attached elsewhere. That is the single most common storage mistake - reach for a file class when more than one pod needs the same data.

Omitting storageClassName uses the cluster default.

Create

volume.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: <volume>
  namespace: <project>
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi
  storageClassName: <storage-class>
oc apply -f volume.yaml

Storage classes here provision on demand, so the disk is created when the claim is, not matched against something that already exists.

List

oc get pvc -n <project>

A claim reaches Bound once a disk is attached to it. A claim that stays Pending is normally one of:

  • a storage class name that does not exist - check the spelling
  • an access mode the class cannot provide
  • no capacity left on the backend

The event on the claim says which:

oc describe pvc <volume> -n <project> | tail -20

Attach it to a workload

spec:
  volumes:
    - name: data
      persistentVolumeClaim:
        claimName: <volume>
  containers:
    - name: <container>
      volumeMounts:
        - name: data
          mountPath: /var/lib/data

Change

A volume can be grown, never shrunk:

oc patch pvc <volume> -n <project> --type=merge \
  -p '{"spec":{"resources":{"requests":{"storage":"10Gi"}}}}'

The filesystem is expanded when the pod next starts, and some classes expand it while the pod is running. Watch the claim's conditions to see which happened:

oc get pvc <volume> -n <project> -o jsonpath='{.status.conditions}{"\n"}'

Nothing else about a claim can be changed. The storage class and the access mode are fixed - to move data to a different class, create a second claim and copy across.

Delete

oc delete pvc <volume> -n <project>

This usually destroys the data

Whether the disk survives depends on the storage class's reclaimPolicy. On this platform the classes are set to Delete, so the disk and its contents go with the claim.

oc get storageclass <storage-class> -o jsonpath='{.reclaimPolicy}{"\n"}'

A claim in use by a running pod will not delete: it stays Terminating until the pod that mounts it is gone. That is protection working, not a stuck resource - scale the workload down rather than forcing the delete.

  • Storage - what the storage offering covers
  • S3 buckets - object storage, for data that does not need a filesystem
  • Redis - an example of a workload that claims its own volume