> ## Documentation Index
> Fetch the complete documentation index at: https://www.latitude.sh/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Persistent volumes

> StorageClasses, examples, limits and troubleshooting for LKS persistent volumes

This page covers the StorageClasses LKS provides, how to create, grow and delete volumes, and how to read the events the Cluster records. For the model behind it, see [Persistent storage](https://www.latitude.sh/docs/lks/persistent-storage.md). For volumes shared by Pods on several Nodes, see [File volumes](https://www.latitude.sh/docs/lks/file-volumes.md).

## StorageClasses

Every Cluster with persistent storage has two StorageClasses for block volumes. Both use the `block.csi.latitude.sh` provisioner.

| StorageClass | Default | Reclaim policy | When the claim is deleted |
| - | - | - | - |
| `latitude-block` | Yes | `Delete` | The volume and its data are deleted. |
| `latitude-block-retain` | No | `Retain` | The volume is detached and kept in your project. |

Both classes create volumes on first use (`volumeBindingMode: WaitForFirstConsumer`), allow expansion, and format volumes as ext4.

Don't edit or delete the built-in classes. For other settings, create your own StorageClass. See [Use xfs](#use-xfs).

## Create a volume

A claim that names no StorageClass uses `latitude-block`:

```yaml theme={null}
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: data
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
```

The claim stays `Pending` until a Pod uses it. Then the volume is created, attached to the Pod's Node and mounted:

```yaml theme={null}
apiVersion: v1
kind: Pod
metadata:
  name: app
spec:
  containers:
    - name: app
      image: busybox:1.37.0
      command: ['sh', '-c', 'df -h /data; sleep 3600']
      volumeMounts:
        - name: data
          mountPath: /data
  volumes:
    - name: data
      persistentVolumeClaim:
        claimName: data
```

```bash theme={null}
kubectl get pvc data
```

For a StatefulSet, use `volumeClaimTemplates` so each replica gets its own volume:

```yaml theme={null}
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: db
spec:
  serviceName: db
  replicas: 1
  selector:
    matchLabels:
      app: db
  template:
    metadata:
      labels:
        app: db
    spec:
      containers:
        - name: db
          image: busybox:1.37.0
          command: ['sh', '-c', 'sleep 3600']
          volumeMounts:
            - name: data
              mountPath: /data
  volumeClaimTemplates:
    - metadata:
        name: data
      spec:
        accessModes:
          - ReadWriteOnce
        resources:
          requests:
            storage: 10Gi
```

To keep a volume after its claim is deleted, set `storageClassName: latitude-block-retain` in the claim.

## Size and expansion

Volumes are sized in whole GiB, rounded up, with a minimum of 1 GiB. To grow a volume, increase the claim's request:

```bash theme={null}
kubectl patch pvc data -p '{"spec":{"resources":{"requests":{"storage":"20Gi"}}}}'
```

The volume and its filesystem grow while the Pod keeps running. Volumes can't shrink.

## Access modes

| Access mode | Supported | Behavior |
| - | - | - |
| `ReadWriteOnce` | Yes | Attached to one Node at a time. Pods on that Node can share it. |
| `ReadWriteOncePod` | Yes | Used by a single Pod in the Cluster. |
| `ReadWriteMany` | No | The claim stays `Pending` and its events give the reason. |
| `ReadOnlyMany` | No | The claim stays `Pending` and its events give the reason. |

To share a volume across Nodes, use a [file volume](https://www.latitude.sh/docs/lks/file-volumes.md).

## Use xfs

To format volumes as xfs, create a StorageClass that sets the filesystem type:

```yaml theme={null}
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: latitude-block-xfs
provisioner: block.csi.latitude.sh
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true
parameters:
  csi.storage.k8s.io/fstype: xfs
```

Then set `storageClassName: latitude-block-xfs` in your claims.

## Lifecycle

| Event | `latitude-block` (Delete) | `latitude-block-retain` (Retain) |
| - | - | - |
| Pod moves or restarts | The volume follows the Pod. | The volume follows the Pod. |
| Claim deleted | The volume is deleted. | The volume is detached and kept in your project. |
| Cluster deleted | The volume is deleted. | The volume is detached and kept in your project. |

Volumes appear in the dashboard under **Storage** > **Block storage**, named `lks-<cluster-id>-pvc-<uuid>`. A kept volume stays in your project until you delete it there.

> [!WARNING]
>
> Deleting a claim that uses `latitude-block`, or deleting the Cluster, permanently deletes the data on those volumes. There are no snapshots yet, so back up anything you need first.

## Limits

* Volumes count toward your team's Latitude Block Storage volume limit. To raise it, contact [support](https://www.latitude.sh/docs/support/contact-support.md).
* A Node can have up to 64 volumes attached.
* Volumes are created in the Cluster's location only.

## Pricing

> [!NOTE]
>
> Volumes are billed as [Latitude Block Storage](https://www.latitude.sh/docs/storage/block-storage.md#pricing), on provisioned capacity while the volume exists. That includes volumes kept by `latitude-block-retain` after their claim or Cluster is deleted. Delete them when you no longer need them.

## Troubleshooting

The Cluster records what's happening as events. Read them with `kubectl describe pvc <name>`, `kubectl describe pod <name>`, or `kubectl get events`.

| What you see | What it means |
| - | - |
| Claim `Pending`, `WaitForFirstConsumer` | Expected. The volume is created when a Pod uses the claim. |
| `Joining node … to the Latitude storage network` on a VolumeAttachment | The first attach in a project. It can take up to two minutes. |
| `ProvisioningFailed: Latitude team volume limit reached` | Your team is at its volume limit. Delete unused volumes or ask [support](https://www.latitude.sh/docs/support/contact-support.md) to raise the limit. |
| `ProvisioningFailed: access mode … not supported` | The claim asks for `ReadWriteMany` or `ReadOnlyMany`. Use `ReadWriteOnce` or `ReadWriteOncePod`, or [`latitude-file`](https://www.latitude.sh/docs/lks/file-volumes) for a shared volume. |
| `FailedAttachVolume: Multi-Attach error` | Another Node still has the volume. Expected for a moment while a Pod moves to a new Node. |
| `VolumeFailedDelete: … is still attached to node` | The volume is still detaching after its claim was deleted. It's deleted once the detach finishes. |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.