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

# Mounting disks to pods in a Managed Service for Kubernetes® cluster

Nebius AI Cloud offers persistent storage for pods in Managed Service for Kubernetes clusters. In this tutorial, you will mount a Compute disk as a persistent volume to a pod in your cluster.

## Background

By default, files created or modified by a container in a Kubernetes pod are lost when the container crashes, or is stopped or restarted. [Persistent volumes](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) help you avoid this: they keep the files for the lifetime of the pod, regardless of the states of its individual containers to the pod. These volumes are mounted to a node that is running the pod.

In Nebius AI Cloud, Managed Service for Kubernetes offers a native solution for persistent volumes in your clusters. You can mount disks from another Nebius AI Cloud service, Compute, to your pods as persistent volumes. Compute provides multiple disk types that vary in performance, reliability and price, and you can choose between them depending on your use case. For more details, see the [Compute documentation](../../compute/storage/types#disks).

Mounting disks to pods relies on support for Container Storage Interface (CSI), which is enabled on newer Managed Kubernetes clusters and can be enabled for older clusters (see prerequisites below).

A disk can be used on one node at a time. If you need to share data between pods and nodes, use Compute shared filesystems instead of disks. See [Mounting shared filesystems to pods in a Managed Service for Kubernetes® cluster](./filesystem-over-csi) for details.

## Costs

Nebius AI Cloud only charges for a Compute disk. For more details, see the [Compute pricing](../../compute/resources/pricing#disks).

## Prerequisites

1. [Create a Managed Kubernetes cluster](../clusters/manage) or choose an existing one.
2. If you are working with an existing cluster, [verify that it supports CSI](#verify-that-your-cluster-supports-csi).
3. [Install kubectl](https://kubernetes.io/docs/tasks/tools/#kubectl) and [connect to the cluster](../connect).

[Nebius AI Cloud disks](../../compute/storage/types#disks) are created automatically; you do not need to create them beforehand.

### Verify that your cluster supports CSI

If your Managed Kubernetes cluster was created on or after January 7, 2025, it already supports CSI and no additional configuration is required. Proceed to the tutorial's [steps](#steps).

If your cluster was created before January 7, 2025, enable CSI support in it:

<Accordion title="How to enable CSI support">
  1. Get IDs of the node groups in the cluster:

       <Tabs group="interfaces">
         <Tab title="Web console">
           1. In [Managed Kubernetes](https://console.nebius.com/mk8s), click on your cluster.
           2. Switch to the **Node groups** tab.
           3. For each node group, find its ID under its name and click <Icon icon="https://mintcdn.com/nebius-ai-cloud/1Ha0sWR6e1mnIaHS/_assets/button-copy.svg?fit=max&auto=format&n=1Ha0sWR6e1mnIaHS&q=85&s=78fcf2cb844ad8eda4598bfbb10b3680" width="24" height="24" data-path="_assets/button-copy.svg" /> to copy it.
         </Tab>

         <Tab title="CLI">
           1. Run <code>nebius mk8s cluster list</code> or <code>nebius mk8s cluster get-by-name --name \<cluster\_name></code> to get the cluster ID. It is returned in the `.metadata.id` field.
           2. Get the list of the cluster's node groups, by using the cluster ID as parent ID:

              ```bash theme={null}
              nebius mk8s node-group list --parent-id <cluster_ID>
              ```

              The IDs of the node groups are returned in the `.metadata.id` fields.
         </Tab>
       </Tabs>

  2. Upgrade each node group:

     ```bash theme={null}
     nebius mk8s node-group upgrade --id <node_group_ID> --latest-infra-version
     ```

  3. [Contact support](https://console.nebius.com/support) or your solution architect to enable CSI support.
</Accordion>

## Steps

### Create a storage class for custom provisioning (optional)

Before using Compute disks as persistent volumes, you can choose how disks are provisioned: the [disk type](../../compute/storage/types#disk-types), the filesystem type (ext4 or xfs) and when a disk should be created (together with a persistent volume claim or when the claim is used by a pod). To do this, define a custom Kubernetes storage class.

<Note>
  The default storage class offered by Managed Kubernetes, `compute-csi-default-sc`, creates a [Network SSD disk](../../compute/storage/types#disk-types) with an ext4 filesystem, and does so when a pod that uses a persistent volume claim with this storage class is created. If this configuration suits you, you can skip this step and proceed to [creating a persistent volume claim](#create-a-persistent-volume-claim).
</Note>

To create a custom storage class:

1. Create a manifest, e.g., `storage-class.yaml`, that defines the storage class. For example:

   ```yaml theme={null}
   apiVersion: storage.k8s.io/v1
   kind: StorageClass
   metadata:
     name: storage-test-class
   provisioner: compute.csi.nebius.com
   volumeBindingMode: WaitForFirstConsumer
   parameters:
     csi.storage.k8s.io/fstype: xfs
     type: "NETWORK_SSD"
   ```

   * `.metadata.name` — The name of the storage class. Use it when referring to the class in [persistent volume claims](#create-a-persistent-volume-claim) (`.spec.storageClassName`).

   * `.provisioner` — The volume [provisioner](https://kubernetes.io/docs/concepts/storage/storage-classes/#provisioner). For Nebius AI Cloud disks, the provisioner is `compute.csi.nebius.com`.

   * `.volumeBindingMode` — The [volume binding mode](https://kubernetes.io/docs/concepts/storage/storage-classes/#volume-binding-mode) that determines when a Nebius AI Cloud disk is created for a persistent volume claim of this storage class. Supported values are `WaitForFirstCustomer` (the disk is created together with a pod that uses the claim) or `Immediate` (the disk is created together with the claim, even if no pods use it yet).

     <Tip>
       Disks created in the `Immediate` binding mode may start to be [charged](../../compute/resources/pricing#disks) and to count towards [quotas](../../compute/resources/quotas-limits#storage) before being actually used in pods. To avoid this, use the `WaitForFirstCustomer` binding mode.
     </Tip>

   * `.parameters."csi.storage.k8s.io/fstype"` — The filesystem for disks: `ext4` or `xfs`.

   * `.parameters.type` — The Nebius AI Cloud disk type. See the [list of disk types and their IDs](../../compute/storage/types#disk-types). Write IDs in uppercase, for example, `NETWORK_SSD`, `NETWORK_SSD_IO_M3`.

2. Apply the manifest to your cluster:

   ```bash theme={null}
   kubectl apply -f storage-class.yaml
   ```

### Create a persistent volume claim

Persistent volume claims are requests that pods make for persistent volumes. These requests include what kind of storage should be provided (in our case, a Compute disk with the default or a custom storage class) and how large it should be.

To create a persistent volume claim:

1. Create a manifest, e.g., `pvc.yaml`, that defines the claim. For example:

   ```yaml theme={null}
   apiVersion: v1
   kind: PersistentVolumeClaim
   metadata:
     name: storage-test-claim
   spec:
     accessModes:
       - ReadWriteOnce
     storageClassName: compute-csi-default-sc
     resources:
       requests:
         storage: 4Gi
   ```

   * `.metadata.name` — The name of your claim. Use it when referring to the claim in pod configurations.
   * `.spec.accessModes` — An array of [access modes](https://kubernetes.io/docs/concepts/storage/persistent-volumes/#access-modes) that determine how the persistent volume can be mounted to nodes. The only mode supported for Nebius AI Cloud block storage is `ReadWriteOnce`; the volume can be mounted as read-write by a single node. For storage that can be mounted to multiple nodes (`ReadWriteMany`), see [Mounting shared filesystems to pods in a Managed Service for Kubernetes® cluster](./filesystem-over-csi).
   * `.spec.storageClassName` — The [storage class](https://kubernetes.io/docs/concepts/storage/storage-classes/) of the volume. The default storage class for Nebius AI Cloud block storage, `compute-csi-default-sc`, creates a [Network SSD disk](../../compute/storage/types#disk-types) with an ext4 filesystem. To use another disk type or filesystem, [create a custom storage class](#create-a-storage-class-for-custom-provisioning-optional) by using the Nebius AI Cloud provisioner and specify its name here.
   * `.spec.resources.requests.storage` — The volume size.

2. Apply the manifest to your cluster:

   ```bash theme={null}
   kubectl apply -f pvc.yaml
   ```

### Mount a volume to a pod and test it

When a persistent volume claim is used in a pod's specification, the Compute disk created for the claim is mounted to the pod as a persistent volume.

<Warning>
  A disk created for a claim is mounted to each pod that uses the claim, and is deleted together with the claim. Do not use a claim on multiple pods at one time, as a disk can only be mounted to a single node. For a solution that shares storage between nodes, see [Mounting shared filesystems to pods in a Managed Service for Kubernetes® cluster](./filesystem-over-csi).
</Warning>

To create a pod with a volume and test it:

1. Create a manifest, e.g. `pod.yaml`, that defines the pod. For example, in the manifest below, a volume named `persistent-storage`, created from the `test-claim` persistent volume claim, is mounted to the pod's container at `/data`:

   ```yaml theme={null}
   apiVersion: v1
   kind: Pod
   metadata:
     name: storage-test-app
   spec:
     volumes:
       - name: persistent-storage
         persistentVolumeClaim:
           claimName: storage-test-claim
     containers:
       - name: app
         image: centos
         command: ["/bin/sh"]
         args: ["-c", "while true; do echo $(date -u) >> /data/out.txt; sleep 5; done"]
         volumeMounts:
           - name: persistent-storage
             mountPath: /data
   ```

   * `.spec.volumes[0].name`: The name of the volume that is created for the pod.
   * `.spec.volumes[0].persistentVolumeClaim.claimName`: The name of the persistent volume claim that is used to create a volume.
   * `.spec.containers[0].volumeMounts[0].name`: The same volume name as in `.spec.volumes[0].name`.
   * `.spec.containers[0].volumeMounts[0].mountPath`: The mount point for the volume.

   <Note>
     You can configure volumes in Kubernetes resources that manage pods, like [deployments](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/) or [stateful sets](https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/), in the same way, by using sub-fields of `.spec.template.spec.volumes` and `.spec.template.spec.containers`.
   </Note>

2. Apply the manifest to your cluster:

   ```bash theme={null}
   kubectl apply -f pod.yaml
   ```

3. Wait until the pod is ready:

   ```bash theme={null}
   kubectl wait --for condition=Ready=true pod/storage-test-app
   ```

4. Test that the container has written into `/data/out.txt`:

   ```bash theme={null}
   kubectl exec storage-test-app -- cat /data/out.txt
   ```

## How to delete the created resources

The created Compute disk is chargeable. If you do not need it, delete the pod and the persistent volume claim, so that the disk is deleted and Nebius AI Cloud does not charge for it:

```bash theme={null}
kubectl delete pod/storage-test-app pvc/storage-test-claim
```

## See also

* [Mounting shared filesystems to pods in a Managed Service for Kubernetes® cluster](./filesystem-over-csi)
* [Types of storage volumes in Compute](../../compute/storage/types)
