> For the complete documentation index, see [llms.txt](https://docs.cloud.olakrutrim.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.cloud.olakrutrim.com/basics/core-infrastructure/krutrim-kubernetes-system/storage-configuration.md).

# Storage Configuration

This guide explains how to configure persistent storage in Krutrim Kubernetes Service (KKS) using Kubernetes-native storage resources and the KKS-managed Container Storage Interface (CSI) integration.

The underlying storage implementation is managed by KKS. Applications interact with standard Kubernetes objects and do not need infrastructure credentials, backend resource identifiers, or implementation-specific configuration.

### Kubernetes storage concepts

| Resource                    | Purpose                                                                                                                           |
| --------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| Volume                      | Makes storage available to containers in a Pod. The lifetime and behavior depend on the volume type.                              |
| PersistentVolume (PV)       | A cluster-scoped storage resource with capacity, access modes, and a reclaim policy.                                              |
| PersistentVolumeClaim (PVC) | A namespaced request for persistent storage made by an application.                                                               |
| StorageClass                | Defines how Kubernetes dynamically provisions storage and manages properties such as reclaim policy, binding mode, and expansion. |
| VolumeSnapshot              | Represents a point-in-time snapshot of a PVC when snapshot support is enabled.                                                    |

For most applications, you create a PVC and reference it from a Pod, Deployment, or StatefulSet. KKS and Kubernetes manage the corresponding PV and storage lifecycle.

```
flowchart LR
    A[Workload] --> B[PersistentVolumeClaim]
    B --> C[StorageClass]
    C --> D[Managed persistent volume]
```

### Managed CSI storage add-on

The KKS-managed CSI storage add-on enables dynamic volume provisioning. When the add-on is active, KKS provides one or more supported StorageClasses and can designate a default StorageClass.

Without a dynamic provisioner, Kubernetes can still use administrator-created PVs, but PVCs are not automatically backed by new managed storage. This guide focuses on dynamic provisioning through the KKS-managed add-on.

#### Before you begin

Confirm that:

* Your KKS cluster is running.
* `kubectl` is configured for the cluster.
* The managed CSI storage add-on is active.
* Your account has sufficient storage quota.
* Your workload requirements match a supported access mode and volume size.

### Verify storage availability

List the available StorageClasses:

```
kubectl get storageclass
```

The default class is marked with `(default)`. Inspect its behavior:

```
kubectl describe storageclass <STORAGE_CLASS_NAME>
```

Check these fields before creating production claims:

| Field                  | Meaning                                                                                                |
| ---------------------- | ------------------------------------------------------------------------------------------------------ |
| `ReclaimPolicy`        | Determines whether dynamically provisioned storage is deleted or retained after its claim is released. |
| `VolumeBindingMode`    | Determines whether provisioning occurs immediately or waits for a consuming Pod.                       |
| `AllowVolumeExpansion` | Indicates whether PVCs using the class can request a larger capacity.                                  |

You can also verify that CSI drivers are registered:

```
kubectl get csidriver
```

KKS manages the provisioner and its parameters. Do not create a custom StorageClass or copy provisioner-specific parameters unless they are explicitly documented and supported by KKS.

### Create a PersistentVolumeClaim

Create a file named `pvc.yaml`:

```
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-app-data
  namespace: default
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
```

Because `storageClassName` is omitted, Kubernetes uses the default StorageClass. To select another KKS-supported class, set `spec.storageClassName` to its exact name from `kubectl get storageclass`.

Apply the claim:

```
kubectl apply -f pvc.yaml
```

Watch its status:

```
kubectl get pvc my-app-data --watch
```

The PVC is ready when its status becomes `Bound`.

If the selected StorageClass uses `WaitForFirstConsumer`, the PVC can remain `Pending` until a Pod references it. This is expected because Kubernetes waits for scheduling information before provisioning the volume.

Inspect details and events:

```
kubectl describe pvc my-app-data
```

### Access modes

The selected storage system determines which access modes are available.

| Mode               | Abbreviation | Behavior                                                                                               |
| ------------------ | ------------ | ------------------------------------------------------------------------------------------------------ |
| `ReadWriteOnce`    | RWO          | The volume can be mounted read-write by one node. Multiple Pods on that same node may still access it. |
| `ReadOnlyMany`     | ROX          | The volume can be mounted read-only by multiple nodes.                                                 |
| `ReadWriteMany`    | RWX          | The volume can be mounted read-write by multiple nodes.                                                |
| `ReadWriteOncePod` | RWOP         | The volume can be mounted read-write by one Pod across the cluster when supported.                     |

Do not assume that every StorageClass supports every mode. If an application needs shared writable storage across nodes, confirm RWX support before deploying it.

For strict single-Pod attachment, use `ReadWriteOncePod` when it is supported. `ReadWriteOnce` alone does not guarantee that only one Pod can access the volume.

### Mount a PVC in a Pod

```
apiVersion: v1
kind: Pod
metadata:
  name: app-with-storage
  namespace: default
spec:
  containers:
    - name: app
      image: nginx:1.27.4
      volumeMounts:
        - name: data
          mountPath: /data
  volumes:
    - name: data
      persistentVolumeClaim:
        claimName: my-app-data
```

Apply the manifest and verify the mount:

```
kubectl apply -f pod.yaml
kubectl get pod app-with-storage
kubectl exec app-with-storage -- df -h /data
```

The Pod and PVC must be in the same namespace.

### Use persistent storage with StatefulSets

Use a StatefulSet with `volumeClaimTemplates` when each replica needs its own persistent volume.

```
apiVersion: v1
kind: Service
metadata:
  name: database
  namespace: default
spec:
  clusterIP: None
  selector:
    app.kubernetes.io/name: database
  ports:
    - name: database
      port: 5432
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: database
  namespace: default
spec:
  serviceName: database
  replicas: 3
  selector:
    matchLabels:
      app.kubernetes.io/name: database
  template:
    metadata:
      labels:
        app.kubernetes.io/name: database
    spec:
      containers:
        - name: database
          image: example/database:1.0
          ports:
            - name: database
              containerPort: 5432
          volumeMounts:
            - name: data
              mountPath: /var/lib/database
  volumeClaimTemplates:
    - metadata:
        name: data
      spec:
        accessModes:
          - ReadWriteOnce
        resources:
          requests:
            storage: 50Gi
```

This creates one PVC per replica, such as `data-database-0`, `data-database-1`, and `data-database-2`. Scaling down or deleting a StatefulSet does not automatically delete its PVCs. Review and delete unused claims deliberately.

### Choose the appropriate storage resource

| Requirement                                | Recommended resource                                 |
| ------------------------------------------ | ---------------------------------------------------- |
| Persistent application or database data    | PVC                                                  |
| Temporary Pod-local scratch data           | `emptyDir`                                           |
| Non-sensitive configuration                | ConfigMap                                            |
| Credentials or sensitive configuration     | Secret or an approved secrets-management integration |
| One persistent volume per stateful replica | StatefulSet `volumeClaimTemplates`                   |
| Shared writable data across multiple nodes | A KKS-supported StorageClass that provides RWX       |

Do not use a PVC for immutable application configuration when a ConfigMap or Secret is more appropriate. Avoid writing plaintext credentials into application data volumes.

### Expand a volume

You can request a larger volume when the StorageClass has `allowVolumeExpansion: true`.

Confirm the setting:

```
kubectl get storageclass <STORAGE_CLASS_NAME> -o yaml
```

Increase the PVC request:

```
kubectl patch pvc my-app-data --type merge \
  -p '{"spec":{"resources":{"requests":{"storage":"20Gi"}}}}'
```

Watch the resize:

```
kubectl get pvc my-app-data --watch
kubectl describe pvc my-app-data
```

Verify the filesystem size from the workload:

```
kubectl exec app-with-storage -- df -h /data
```

Important considerations:

* A PVC can be expanded but not reduced.
* The requested size must be supported by the StorageClass and available quota.
* Supported in-use filesystems can expand without recreating the Pod.
* Restart a workload only if PVC events or application behavior show that it is necessary, and follow the application's safe-restart procedure.
* Do not edit PV capacity directly; request expansion through the PVC.

### Snapshots and backups

Snapshot support is optional and depends on the features enabled for the cluster and StorageClass.

Check whether snapshot resources and classes are available:

```
kubectl api-resources | grep -i volumesnapshot
kubectl get volumesnapshotclass
```

If a default VolumeSnapshotClass is configured, you can request a snapshot without naming an implementation-specific class:

```
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
  name: my-app-data-snapshot
  namespace: default
spec:
  source:
    persistentVolumeClaimName: my-app-data
```

Check snapshot readiness:

```
kubectl get volumesnapshot my-app-data-snapshot
kubectl describe volumesnapshot my-app-data-snapshot
```

Restore a new PVC from a ready snapshot:

```
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-app-data-restored
  namespace: default
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
  dataSource:
    name: my-app-data-snapshot
    kind: VolumeSnapshot
    apiGroup: snapshot.storage.k8s.io
```

The restored PVC size must meet the requirements of the source snapshot and selected StorageClass.

Snapshots are not a complete backup strategy. They can share failure domains and lifecycle dependencies with the source storage. For critical workloads:

* Use application-consistent backup procedures.
* Store backup copies in a separate failure domain when possible.
* Define retention and access-control policies.
* Test restores regularly.

### Understand deletion and reclaim policy

Before deleting a PVC, find its PV and reclaim policy:

```
kubectl get pvc my-app-data -o wide
kubectl get pv <PV_NAME>
```

With a `Delete` reclaim policy, deleting the PVC normally causes the dynamically provisioned PV and its underlying storage to be deleted. This operation can permanently remove data.

With a `Retain` policy, the PV and underlying storage remain after the claim is deleted, but an administrator must recover, reuse, or delete them manually.

For important data:

1. Stop or quiesce writes as required by the application.
2. Create and verify a backup.
3. Confirm the PV name and reclaim policy.
4. Delete the PVC only after the recovery plan has been validated.

Cluster administrators can change the reclaim policy of a bound PV before deleting its claim:

```
kubectl patch pv <PV_NAME> \
  -p '{"spec":{"persistentVolumeReclaimPolicy":"Retain"}}'
```

Changing the reclaim policy is not a backup. It prevents automatic storage deletion but leaves manual lifecycle work for the administrator.

### View storage resources

```
# List StorageClasses
kubectl get storageclass

# List cluster-scoped PersistentVolumes
kubectl get pv

# List PersistentVolumeClaims in all namespaces
kubectl get pvc --all-namespaces

# Describe a claim and its events
kubectl describe pvc my-app-data

# Show recent namespace events in time order
kubectl get events --sort-by=.metadata.creationTimestamp
```

### Troubleshooting

#### PVC remains Pending

Check the claim, StorageClass, and events:

```
kubectl get pvc <PVC_NAME> -o wide
kubectl describe pvc <PVC_NAME>
kubectl get storageclass
kubectl get events --sort-by=.metadata.creationTimestamp
```

Common causes include:

* No default StorageClass exists and the claim does not name one.
* The named StorageClass does not exist.
* The managed storage add-on is not active or ready.
* Storage quota or capacity is exhausted.
* The requested size or access mode is unsupported.
* The StorageClass waits for a consuming Pod before provisioning.
* The consuming Pod cannot be scheduled in a compatible topology.

#### Pod remains in ContainerCreating

Inspect the Pod and claim:

```
kubectl describe pod <POD_NAME>
kubectl get pvc <PVC_NAME>
kubectl describe pvc <PVC_NAME>
```

Check for:

* An unbound PVC.
* A claim in a different namespace.
* An incorrect claim name.
* A volume already attached to an incompatible node.
* Access-mode conflicts.
* Node or storage add-on health problems.
* Filesystem or mount errors in Pod events.

To review managed CSI components without relying on implementation-specific labels:

```
kubectl get pods --namespace kube-system | grep -i csi
```

If the problem persists, collect the Pod description, PVC description, PV description, and recent events before contacting Krutrim support.

#### Volume is full

Check filesystem usage:

```
kubectl exec <POD_NAME> -- df -h <MOUNT_PATH>
```

Then either:

* Expand the PVC if the StorageClass supports expansion.
* Apply the application's documented retention or cleanup procedure.
* Move archival data to an appropriate storage service.

Do not run broad deletion commands against a mounted production volume without verifying the target path, retention requirements, and recovery plan.

#### Expansion does not complete

Check the requested and current capacities, PVC conditions, and events:

```
kubectl get pvc <PVC_NAME> -o yaml
kubectl describe pvc <PVC_NAME>
kubectl get storageclass <STORAGE_CLASS_NAME> -o yaml
```

Confirm that:

* `allowVolumeExpansion` is enabled.
* The new request is larger than the current request.
* The requested capacity is within quota and supported limits.
* The workload and filesystem support online expansion.

Do not repeatedly increase the request while an earlier resize is failing. Record the events and contact Krutrim support if the controller continues retrying.

#### Snapshot cannot be created

Verify that the snapshot APIs and a compatible class are installed:

```
kubectl api-resources | grep -i volumesnapshot
kubectl get volumesnapshotclass
kubectl describe volumesnapshot <SNAPSHOT_NAME>
kubectl describe pvc <PVC_NAME>
```

Snapshot support may not be enabled for every cluster version or StorageClass. Use the backup method supported for your workload if snapshots are unavailable.

### Best practices

* Use PVCs for data that must survive Pod replacement or rescheduling.
* Use StatefulSet claim templates when each replica needs independent storage.
* Confirm access-mode support before selecting an application architecture.
* Treat `ReadWriteOnce` as a single-node mode, not a strict single-Pod lock.
* Set capacity from measured demand, growth rate, retention, and recovery requirements rather than generic size estimates.
* Monitor filesystem utilization, PVC capacity, provisioning failures, and expansion events.
* Alert before a filesystem is full and leave room for growth and maintenance operations.
* Verify the reclaim policy before deleting any claim.
* Back up critical data and test restores on a schedule.
* Use application-consistent backup procedures for databases and queues.
* Avoid mutable image tags for production workloads.
* Keep credentials in Secrets or an approved secrets manager, not in persistent application data.
* Review unused StatefulSet PVCs after scale-down or workload deletion.
* Use only StorageClasses and options explicitly supported by KKS.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.cloud.olakrutrim.com/basics/core-infrastructure/krutrim-kubernetes-system/storage-configuration.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
