# Cloud Disk on Kubernetes

The Cloud Disk CSI driver provisions PersistentVolumes backed by Tigris. Each PVC becomes a Tigris-backed NBD block device, formatted with the filesystem of your choice and mounted into your pod.

Beta

Cloud Disk is in beta and under active development.

## Prerequisites[​](#prerequisites "Direct link to Prerequisites")

* Kubernetes 1.26+
* Linux worker nodes with the `nbd` kernel module available
* A Tigris bucket and access keys from the [Tigris console](https://console.storage.dev)

note

Nodes need the `nbd` kernel module, which isn't present on some minimal images (e.g. GKE Container-Optimized OS). Volumes are single-node — `ReadWriteOnce` or `ReadOnlyMany`.

## 1. Create the credentials secret[​](#1-create-the-credentials-secret "Direct link to 1. Create the credentials secret")

```
kubectl create secret generic tigris-csi-aws -n kube-system \

  --from-literal=AWS_ACCESS_KEY_ID=tid_... \

  --from-literal=AWS_SECRET_ACCESS_KEY=tsec_...
```

The endpoint defaults to Tigris. To use AWS, MinIO, or another endpoint, add `--from-literal=AWS_ENDPOINT_URL=<url>` and set `endpoint` on the StorageClass.

## 2. Deploy the driver[​](#2-deploy-the-driver "Direct link to 2. Deploy the driver")

```
kubectl apply -f https://cloud-disk.t3.tigrisfiles.io/csi-driver.yaml
```

## 3. Create a StorageClass[​](#3-create-a-storageclass "Direct link to 3. Create a StorageClass")

No parameters are required — a disk's bucket is derived from the PVC name and the endpoint defaults to Tigris:

```
apiVersion: storage.k8s.io/v1

kind: StorageClass

metadata:

  name: cloud-disk

provisioner: csi.tigris.dev

reclaimPolicy: Delete

volumeBindingMode: Immediate
```

## 4. Claim it from a pod[​](#4-claim-it-from-a-pod "Direct link to 4. Claim it from a pod")

```
apiVersion: v1

kind: PersistentVolumeClaim

metadata:

  name: my-data

spec:

  accessModes: ["ReadWriteOnce"]

  storageClassName: cloud-disk

  resources:

    requests:

      storage: 10Gi

---

apiVersion: v1

kind: Pod

metadata:

  name: my-app

spec:

  containers:

    - name: app

      image: busybox

      command: ["sh", "-c", "sleep 3600"]

      volumeMounts:

        - { name: data, mountPath: /data }

  volumes:

    - name: data

      persistentVolumeClaim:

        claimName: my-data
```

## StorageClass parameters[​](#storageclass-parameters "Direct link to StorageClass parameters")

All parameters are optional — the defaults target Tigris.

| Parameter        | Default                  | Description                         |
| ---------------- | ------------------------ | ----------------------------------- |
| `endpoint`       | `https://t3.storage.dev` | Endpoint                            |
| `fstype`         | `ext4`                   | Filesystem (`ext4`, `xfs`, `btrfs`) |
| `chunk-size`     | `1M`                     | Object size                         |
| `max-cache-size` | `1G`                     | Local cache size                    |
| `flush-workers`  | `8`                      | Concurrent upload workers to Tigris |

A disk's bucket is **not** a parameter — it's derived from the PVC name, so each PVC is its own disk. Any other disk setting can be a StorageClass parameter; see [Configuration & Tuning](/docs/cloud-disk/tuning/.md) for the full list.

## How it works[​](#how-it-works "Direct link to How it works")

A PVC creates its own bucket (`csi-vol-<pvc-name>`) with a metadata marker. When a pod is scheduled, the node's DaemonSet starts a `cloud-disk` process for the volume, attaches it to a free `/dev/nbdN`, formats it on first use (`fsck` thereafter), and mounts it into the pod. Deleting the pod flushes the cache to Tigris and detaches; deleting the PVC removes the bucket and its objects.

## Raw block volumes[​](#raw-block-volumes "Direct link to Raw block volumes")

For applications that manage their own storage (some databases), request a raw device with `volumeMode: Block` — no filesystem is created, and the device is exposed via `volumeDevices` instead of `volumeMounts`:

```
apiVersion: v1

kind: PersistentVolumeClaim

metadata:

  name: my-block

spec:

  volumeMode: Block

  accessModes: ["ReadWriteOnce"]

  storageClassName: cloud-disk

  resources:

    requests:

      storage: 10Gi

---

apiVersion: v1

kind: Pod

metadata:

  name: my-block-app

spec:

  containers:

    - name: app

      image: busybox

      command: ["sh", "-c", "sleep 3600"]

      volumeDevices:

        - { name: data, devicePath: /dev/xvda }

  volumes:

    - name: data

      persistentVolumeClaim:

        claimName: my-block
```
