Persistent storage is the hardest part of self-hosted Kubernetes to get right. The stateless layer — deployments, services, ingress — is relatively forgiving. Storage is not. A bad storage decision leads to slow databases, inconsistent replicas, or failed restores when you need them most.
In 2026, the three serious self-hosted options are Longhorn, Rook/Ceph, and OpenEBS. Each has a distinct philosophy and a specific cluster profile where it shines.
Storage Options Overview
Longhorn
Longhorn (CNCF graduated) is a lightweight distributed block storage system built specifically for Kubernetes. It runs entirely as Kubernetes-native workloads, stores volumes as files on each node's disk, and replicates synchronously using a custom iSCSI/NVMe-oF engine.
The killer feature is simplicity: Longhorn installs in minutes, requires no pre-formatted disks, and ships with a built-in UI and S3 backup integration. It is the right default for most self-hosted clusters under 20 nodes.
Rook/Ceph
Rook is a Kubernetes operator that manages a Ceph cluster. Ceph is a mature, battle-tested distributed storage system with support for block (RBD), filesystem (CephFS), and object storage (RGW). It powers petabyte-scale deployments at major cloud providers.
The tradeoff is complexity and resource requirements. Ceph monitors, OSDs, and managers consume significantly more RAM than Longhorn. Running Ceph well requires dedicated storage nodes, Ceph-specific knowledge, and careful tuning. The reward is features and scale that Longhorn cannot match.
OpenEBS
OpenEBS takes a different approach: it is a collection of storage engines rather than a single system. The two most relevant engines in 2026 are:
- ›Mayastor (now NVMe-oF native, renamed to OpenEBS Dynamic NFS): High-performance NVMe-oF-based block storage, competitive with Ceph for throughput
- ›LocalPV: Host-local volumes with no replication — the fastest option, but no HA
OpenEBS is positioned between Longhorn (simple) and Ceph (powerful) on most dimensions.
Comparison Table
| Dimension | Longhorn | Rook/Ceph | OpenEBS Mayastor |
|---|---|---|---|
| Installation complexity | Low (helm, 5 min) | High (CRDs, disk config, 30+ min) | Medium (15 min) |
| Min nodes for HA | 3 | 3 (with dedicated disks) | 3 |
| RAM per storage node | ~300 MB | 1.5–3 GB | ~400 MB |
| Block storage (RWO) | Yes | Yes (RBD) | Yes |
| Shared filesystem (RWX) | No | Yes (CephFS) | No |
| Object storage (S3) | No (backup only) | Yes (Ceph RGW) | No |
| Replication | Synchronous, configurable | Synchronous (CRUSH) | Synchronous |
| Built-in backup | Yes (S3/NFS) | No (needs Velero) | No (needs Velero) |
| Built-in UI | Yes | Yes (Ceph Dashboard) | No |
| Performance (sequential) | Good | Excellent | Excellent |
| Performance (random IOPS) | Good | Good-Excellent | Excellent |
| Upgrade complexity | Low | High | Medium |
| Community size | Large (CNCF) | Very large | Medium |
| Best cluster size | 3–20 nodes | 5–100+ nodes | 3–30 nodes |
Longhorn: Install and Basic Configuration
Longhorn is the right starting point for most teams. Here is a production-ready install.
Prerequisites
On every node that will serve as a Longhorn storage node:
# Install required packages
apt-get install -y open-iscsi nfs-common cryptsetup dmsetup
# Enable and start iscsid
systemctl enable --now iscsid
# Verify
iscsiadm --version
Run the Longhorn environment check script before installing:
curl -sSfL https://raw.githubusercontent.com/longhorn/longhorn/master/scripts/environment_check.sh | bash
Install via Helm
helm repo add longhorn https://charts.longhorn.io
helm repo update
helm install longhorn longhorn/longhorn \
--namespace longhorn-system \
--create-namespace \
--set defaultSettings.defaultReplicaCount=3 \
--set defaultSettings.storageMinimalAvailablePercentage=15 \
--set defaultSettings.storageOverProvisioningPercentage=100 \
--set ingress.enabled=true \
--set ingress.host=longhorn.internal.example.com \
--set ingress.ingressClassName=nginx
Key settings explained:
- ›
defaultReplicaCount=3: Every volume is replicated to 3 nodes. Use2on smaller clusters to reduce write amplification. - ›
storageMinimalAvailablePercentage=15: Longhorn refuses to schedule volumes if a node has less than 15% free disk. - ›
storageOverProvisioningPercentage=100: Allows thin provisioning up to 2x the physical space. Set to0to disable.
Configure a StorageClass
Longhorn creates a default StorageClass. Create additional ones for different replication and performance profiles:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: longhorn-fast
provisioner: driver.longhorn.io
allowVolumeExpansion: true
parameters:
numberOfReplicas: "2"
dataLocality: "best-effort"
diskSelector: "nvme"
nodeSelector: "storage"
reclaimPolicy: Delete
volumeBindingMode: Immediate
Use the Kubernetes PVC Generator to create PVC manifests targeting this StorageClass.
Configure S3 Backup
Longhorn's built-in backup is one of its strongest features. Configure a backup target pointing to any S3-compatible endpoint:
# Longhorn Settings — set via UI or patch the ConfigMap
defaultSettings:
backupTarget: "s3://my-longhorn-backups@us-east-1/"
backupTargetCredentialSecret: "longhorn-backup-secret"
kubectl create secret generic longhorn-backup-secret \
--namespace longhorn-system \
--from-literal=AWS_ACCESS_KEY_ID="your-key-id" \
--from-literal=AWS_SECRET_ACCESS_KEY="your-secret" \
--from-literal=AWS_ENDPOINTS="https://s3.hetzner.com"
Then create a recurring backup job via CRD:
apiVersion: longhorn.io/v1beta2
kind: RecurringJob
metadata:
name: daily-backup
namespace: longhorn-system
spec:
cron: "0 2 * * *"
task: backup
groups:
- default
retain: 7
concurrency: 2
labels:
type: daily
Use the Longhorn Storage Calculator to plan capacity including replica overhead, snapshot retention, and S3 backup sizing.
When Each Solution Fits
Use Longhorn when:
- ›Running 3–20 nodes
- ›You need block storage (databases, stateful apps) — no requirement for shared filesystems
- ›You want S3 backup without additional tooling
- ›Your team does not have Ceph expertise
- ›Fast iteration matters — Longhorn's UI and simple CRDs make operations fast
Use Rook/Ceph when:
- ›You need shared filesystem access (RWX volumes via CephFS) — common for media storage, shared config mounts, or NFS-like use cases
- ›You need S3-compatible object storage from within the cluster (Ceph RGW is production-grade)
- ›You have 10+ nodes and dedicated storage nodes with raw disks
- ›You have team members with Ceph experience, or are willing to invest in learning it
- ›Scale and performance are primary concerns
See the Longhorn vs Rook/Ceph comparison for a side-by-side breakdown.
Use OpenEBS Mayastor when:
- ›You need NVMe-level performance with replication (Mayastor saturates NVMe disks)
- ›You are running latency-sensitive databases (PostgreSQL, etcd) on NVMe nodes
- ›You want something more performant than Longhorn but less complex than Ceph
- ›Your team is comfortable with a less mature ecosystem
See the Longhorn vs OpenEBS comparison for detailed benchmarks.
Use OpenEBS LocalPV when:
- ›HA is handled at the application layer (e.g., Kafka with replication factor 3, Redis Cluster)
- ›You need maximum performance and can tolerate node-local failure
- ›Your pods have anti-affinity rules ensuring replicas land on different nodes
# LocalPV StorageClass — no replication, maximum performance
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: openebs-hostpath
provisioner: openebs.io/local
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer
parameters:
storageType: hostpath
basePath: /var/openebs/local
Migration Path
The practical migration path as your cluster grows:
- ›Start with Longhorn — simple, reliable, good enough for most workloads
- ›Add Ceph alongside Longhorn when you need CephFS (RWX) or object storage — run both simultaneously, route different StorageClasses to each
- ›Migrate block volumes to Ceph only if you've hit Longhorn's performance ceiling or need features it lacks — use Velero for backup/restore migration
Migrating storage systems is a maintenance window operation. There is no live migration between storage providers. Plan it deliberately, not reactively.