🗺️ Why Cloud-Native Storage?
Cloud-managed disks (EBS, GCP PD) work well in a single cloud but limit portability and cost control. Cloud-native storage systems run inside the cluster — using your nodes' disks — and expose Kubernetes-native interfaces (StorageClass, PVC, CSI).
Two dominant open-source options: Rook/Ceph (enterprise-grade distributed storage, highly scalable) and Longhorn (simpler, lightweight distributed block storage designed for ease of use).
🟠 Rook / Ceph
- CNCF graduated project
- Block, File (RWX), and Object storage
- Enterprise-grade scalability (petabyte-scale)
- Complex to operate; large footprint
- Best for: large clusters, multi-tenant, need RWX
🟢 Longhorn
- CNCF incubating project (Rancher origins)
- Block storage only (RWO)
- Simple install, built-in UI, easy backup
- Lower operational overhead
- Best for: small-medium clusters, edge, simplicity
🟠 Rook / Ceph Deep Dive
Key Components
| Component | Role |
|---|---|
| Rook Operator | Kubernetes controller that manages the entire Ceph lifecycle via CRDs |
| MON (Monitor) | Maintains the Ceph cluster map; requires a quorum (3 or 5 pods) |
| MGR (Manager) | Provides metrics, dashboard, and orchestration modules |
| OSD (Object Storage Daemon) | One per disk; stores actual data with replication |
| MDS (Metadata Server) | Required for CephFS (shared filesystem / RWX volumes) |
| RGW (RADOS Gateway) | S3/Swift-compatible object storage endpoint |
Install via Helm
# Add Rook Helm chart repo
helm repo add rook-release https://charts.rook.io/release
helm repo update
# Install Rook operator
helm install rook-ceph rook-release/rook-ceph \
--namespace rook-ceph \
--create-namespace \
--version v1.13.0
# Deploy a CephCluster (uses raw disks on each node)
kubectl apply -f - <<EOF
apiVersion: ceph.rook.io/v1
kind: CephCluster
metadata:
name: rook-ceph
namespace: rook-ceph
spec:
cephVersion:
image: quay.io/ceph/ceph:v18
dataDirHostPath: /var/lib/rook
mon:
count: 3
allowMultiplePerNode: false
storage:
useAllNodes: true
useAllDevices: false
deviceFilter: "^sd[b-z]" # use all non-boot disks
dashboard:
enabled: true
EOF
Block Storage StorageClass (RBD)
apiVersion: ceph.rook.io/v1
kind: CephBlockPool
metadata:
name: replicapool
namespace: rook-ceph
spec:
replicated:
size: 3 # 3-way replication
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: rook-ceph-block
provisioner: rook-ceph.rbd.csi.ceph.com
parameters:
clusterID: rook-ceph
pool: replicapool
imageFormat: "2"
imageFeatures: layering
csi.storage.k8s.io/provisioner-secret-name: rook-csi-rbd-provisioner
csi.storage.k8s.io/provisioner-secret-namespace: rook-ceph
csi.storage.k8s.io/node-stage-secret-name: rook-csi-rbd-node
csi.storage.k8s.io/node-stage-secret-namespace: rook-ceph
reclaimPolicy: Delete
allowVolumeExpansion: true
Shared Filesystem (CephFS / RWX)
apiVersion: ceph.rook.io/v1
kind: CephFilesystem
metadata:
name: myfs
namespace: rook-ceph
spec:
metadataPool:
replicated: { size: 3 }
dataPools:
- name: replicated
replicated: { size: 3 }
metadataServer:
activeCount: 1
activeStandby: true
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: rook-cephfs
provisioner: rook-ceph.cephfs.csi.ceph.com
parameters:
clusterID: rook-ceph
fsName: myfs
pool: myfs-replicated
reclaimPolicy: Delete
allowVolumeExpansion: true
ReadWriteMany — multiple pods across nodes can mount the same volume simultaneously. Essential for shared config files, media uploads, or ML training datasets.
ReadWriteMany — multiple pods across nodes can mount the same volume simultaneously. Essential for shared config files, media uploads, or ML training datasets.
🟢 Longhorn Deep Dive
Longhorn is a lightweight, CNCF-incubating distributed block storage system. Each volume is replicated across a configurable number of nodes. It ships with a rich web UI, built-in snapshots, and backup to S3-compatible storage — all without requiring dedicated storage nodes.
How Longhorn Works
Volume Engine
Each volume gets its own engine process (longhorn-engine), isolating failures per-volume.
Replica Scheduling
Replicas are spread across nodes. Default replication factor is 3. Configurable per StorageClass.
Built-in Snapshots
On-demand and scheduled snapshots stored on-disk. Can be promoted to a new volume.
S3 Backup
Incremental backups to any S3-compatible store (AWS S3, MinIO). Restore to a new volume cross-cluster.
Install via Helm
# Prerequisites: open-iscsi must be installed on every node
# On Ubuntu: apt-get install open-iscsi
# Check requirements
curl -sSfL https://raw.githubusercontent.com/longhorn/longhorn/v1.6.0/scripts/environment_check.sh | bash
helm repo add longhorn https://charts.longhorn.io
helm repo update
helm install longhorn longhorn/longhorn \
--namespace longhorn-system \
--create-namespace \
--version 1.6.0 \
--set defaultSettings.defaultReplicaCount=3
Access the UI
# Port-forward the Longhorn UI
kubectl port-forward -n longhorn-system svc/longhorn-frontend 8080:80
# Open http://localhost:8080
StorageClass
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: longhorn-fast
provisioner: driver.longhorn.io
parameters:
numberOfReplicas: "3"
staleReplicaTimeout: "30"
diskSelector: "ssd" # schedule only to SSD-tagged nodes
nodeSelector: "storage" # schedule only to nodes with label storage=true
reclaimPolicy: Delete
allowVolumeExpansion: true
volumeBindingMode: Immediate
Configuring S3 Backup Target
# Create secret with S3 credentials
kubectl create secret generic longhorn-backup-secret \
--namespace longhorn-system \
--from-literal=AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE \
--from-literal=AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG... \
--from-literal=AWS_ENDPOINTS=https://s3.amazonaws.com
# Set backup target via Longhorn Setting CRD
kubectl apply -f - <<EOF
apiVersion: longhorn.io/v1beta2
kind: Setting
metadata:
name: backup-target
namespace: longhorn-system
value: "s3://my-longhorn-backups@us-east-1/"
---
apiVersion: longhorn.io/v1beta2
kind: Setting
metadata:
name: backup-target-credential-secret
namespace: longhorn-system
value: longhorn-backup-secret
EOF
Recurring Backup Jobs
apiVersion: longhorn.io/v1beta2
kind: RecurringJob
metadata:
name: daily-backup
namespace: longhorn-system
spec:
cron: "0 3 * * *"
task: backup
groups:
- default # applies to all volumes in the "default" group
retain: 7 # keep 7 backups
concurrency: 2
⚖️ Rook/Ceph vs Longhorn
| Dimension | Rook / Ceph | Longhorn |
|---|---|---|
| Storage types | Block (RBD), File (CephFS RWX), Object (RGW) | Block only (RWO) |
| Maturity | CNCF Graduated — battle-tested at petabyte scale | CNCF Incubating — production-ready for most use cases |
| Complexity | High — large resource footprint, many components | Low — simple install, minimal footprint |
| Min. nodes | 3+ dedicated storage nodes recommended | 3+ nodes (storage co-located with workloads is fine) |
| Built-in UI | Ceph Dashboard (via MGR) | Full Longhorn UI with volume and backup management |
| Backup | Rook toolbox + Velero integration | Native incremental backup to S3 |
| Snapshot | CSI VolumeSnapshot (RBD) | Native snapshots + CSI VolumeSnapshot |
| Encryption | RBD encryption at rest (dm-crypt) | Volume-level encryption via LUKS |
| Best for | Large enterprises, RWX workloads, object storage | Small–medium clusters, edge, simplicity, easy DR |
Production Recommendations
Dedicated Storage Nodes
Taint storage nodes so only Ceph/Longhorn pods schedule there. Prevents noisy-neighbor CPU/memory contention.
Separate OS and Data Disks
Never use the OS disk for OSD/Longhorn replicas. Use dedicated unformatted disks for storage data.
Monitor Storage Metrics
Track ceph_cluster_total_used_bytes and Longhorn volume_actual_size_bytes. Alert at 70% capacity.
Test Failure Recovery
Periodically kill an OSD or Longhorn replica pod and verify automatic re-replication completes within SLA.