Skip to main content

Command Palette

Search for a command to run...

Cloud native storage with Rook

Block, file and object storage on k8s with Ceph using Rook

Updated
4 min read
Cloud native storage with Rook
M
I have been hardening enterprise systems since the era of vSphere 5, Linux 3, and Python 3. My career tracked the transition from legacy hardware to All-Flash and Software-Defined Storage. Today, I architect high-scale Python automation for Block, File, and Object storage tailored for the AI age.

Introduction

This is part of the Distributed Storage series. We assume you have a Kubernetes cluster running as described in Kubernetes With Microk8s. Using the same virtual machines, we have deployed a Ceph cluster and enabled different types of storage: file, object, and block (default). This ensures that we have covered the prerequisites.

Rook is an open source cloud-native storage orchestrator, providing the platform, framework, and support for Ceph storage to natively integrate with cloud-native environments. The storage architecture is well documented. We focus on getting it up and running.

Enable Rook

First, we enable rook on the k8s cluster

manas@manas-s01:~$ sudo microk8s enable rook-ceph
Infer repository core for addon rook-ceph
Add Rook Helm repository <https://charts.rook.io/release>
"rook-release" has been added to your repositories
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "rook-release" chart repository
Update Complete. ⎈Happy Helming!⎈
Install Rook version v1.11.9
NAME: rook-ceph
LAST DEPLOYED: Fri Jun 13 16:01:21 2025
NAMESPACE: rook-ceph
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
The Rook Operator has been installed. Check its status by running:
  kubectl --namespace rook-ceph get pods -l "app=rook-ceph-operator"
...

Check Rook Status

manas@manas-s01:~$ microk8s kubectl --namespace rook-ceph get pods -l "app=rook-ceph-operator"
NAME                                  READY   STATUS    RESTARTS   AGE
rook-ceph-operator-684bbd569f-82dv9   1/1     Running   0          30m

Connect Ceph and k8s cluster

manas@manas-s01:~$ sudo microk8s connect-external-ceph
[sudo] password for manas: 
Looking for MicroCeph on the host
Detected existing MicroCeph installation
Attempting to connect to Ceph cluster
Successfully connected to e43d58a8-deb0-43d9-b7ef-d6159f114c02 (192.168.148.134:0/1580887393)
Creating pool microk8s-rbd0 in Ceph cluster
Configuring pool microk8s-rbd0 for RBD
Successfully configured pool microk8s-rbd0 for RBD
Creating namespace rook-ceph-external
namespace/rook-ceph-external created
Configuring Ceph CSI secrets
Successfully configured Ceph CSI secrets
Importing Ceph CSI secrets into MicroK8s
secret/rook-ceph-mon created
configmap/rook-ceph-mon-endpoints created
secret/rook-csi-rbd-node created
secret/rook-csi-rbd-provisioner created
storageclass.storage.k8s.io/ceph-rbd created
Importing external Ceph cluster
W0613 16:32:46.334927  129114 warnings.go:70] unknown field "spec.upgradeOSDRequiresHealthyPGs"
NAME: rook-ceph-external
LAST DEPLOYED: Fri Jun 13 16:32:45 2025
NAMESPACE: rook-ceph-external
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
The Ceph Cluster has been installed. Check its status by running:
  kubectl --namespace rook-ceph-external get cephcluster

Visit <https://rook.io/docs/rook/latest/CRDs/Cluster/ceph-cluster-crd/> for more information about the Ceph CRD.

Important Notes:
- You can only deploy a single cluster per namespace
- If you wish to delete this cluster and start fresh, you will also have to wipe the OSD disks using `sfdisk`

=================================================

Successfully imported external Ceph cluster. You can now use the following storageclass
to provision PersistentVolumes using Ceph CSI:

NAME       PROVISIONER                  RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
ceph-rbd   rook-ceph.rbd.csi.ceph.com   Delete          Immediate           true                   2s

Check Ceph cluster status

# Initial 
manas@manas-s01:~$ microk8s kubectl --namespace rook-ceph-external get cephcluster
NAME                 DATADIRHOSTPATH   MONCOUNT   AGE   PHASE   MESSAGE   HEALTH   EXTERNAL   FSID
rook-ceph-external   /var/lib/rook     3          67s                              true       
# Final
manas@manas-s01:~$ microk8s kubectl --namespace rook-ceph-external get cephcluster
NAME                 DATADIRHOSTPATH   MONCOUNT   AGE    PHASE       MESSAGE                          HEALTH      EXTERNAL   FSID
rook-ceph-external   /var/lib/rook     3          6m1s   Connected   Cluster connected successfully   HEALTH_OK   true       e43d58a8-deb0-43d9-b7ef-d6159f114c02
ma

Wait until all k8s resources are in Running status:

manas@manas-s01:~$ microk8s kubectl get all --namespace rook-ceph
NAME                                                READY   STATUS    RESTARTS   AGE
pod/csi-cephfsplugin-chz2w                          2/2     Running   0          5m7s
pod/csi-cephfsplugin-n2wxd                          2/2     Running   0          5m7s
pod/csi-cephfsplugin-provisioner-7bd8fb7c64-fbmw6   5/5     Running   0          5m7s
pod/csi-cephfsplugin-provisioner-7bd8fb7c64-tbqlp   5/5     Running   0          5m7s
pod/csi-cephfsplugin-zpltk                          2/2     Running   0          5m7s
pod/csi-rbdplugin-7dgxz                             2/2     Running   0          5m7s
pod/csi-rbdplugin-8x5x7                             2/2     Running   0          5m7s
pod/csi-rbdplugin-provisioner-5f7d95b6fb-s4znf      5/5     Running   0          5m7s
pod/csi-rbdplugin-provisioner-5f7d95b6fb-wjk7q      5/5     Running   0          5m7s
pod/csi-rbdplugin-zccc7                             2/2     Running   0          5m7s
pod/rook-ceph-operator-684bbd569f-82dv9             1/1     Running   0          39m

NAME                              DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
daemonset.apps/csi-cephfsplugin   3         3         3       3            3           <none>          5m7s
daemonset.apps/csi-rbdplugin      3         3         3       3            3           <none>          5m8s

NAME                                           READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/csi-cephfsplugin-provisioner   2/2     2            2           5m7s
deployment.apps/csi-rbdplugin-provisioner      2/2     2            2           5m7s
deployment.apps/rook-ceph-operator             1/1     1            1           39m

NAME                                                      DESIRED   CURRENT   READY   AGE
replicaset.apps/csi-cephfsplugin-provisioner-7bd8fb7c64   2         2         2       5m7s
replicaset.apps/csi-rbdplugin-provisioner-5f7d95b6fb      2         2         2       5m7s
replicaset.apps/rook-ceph-operator-684bbd569f             1         1         1       39m
manas@manas-s01:~$

Meanwhile, If you want to explore the possible API Resources, you the following command:

manas@manas-s01:~$ microk8s kubectl api-resources --namespace rook-ceph-external | grep ceph
cephblockpoolradosnamespaces                          ceph.rook.io/v1                   true         CephBlockPoolRadosNamespace
cephblockpools                                        ceph.rook.io/v1                   true         CephBlockPool
cephbucketnotifications                               ceph.rook.io/v1                   true         CephBucketNotification
cephbuckettopics                                      ceph.rook.io/v1                   true         CephBucketTopic
cephclients                                           ceph.rook.io/v1                   true         CephClient
cephclusters                                          ceph.rook.io/v1                   true         CephCluster
cephfilesystemmirrors                                 ceph.rook.io/v1                   true         CephFilesystemMirror
cephfilesystems                                       ceph.rook.io/v1                   true         CephFilesystem
cephfilesystemsubvolumegroups                         ceph.rook.io/v1                   true         CephFilesystemSubVolumeGroup
cephnfses                           nfs               ceph.rook.io/v1                   true         CephNFS
cephobjectrealms                                      ceph.rook.io/v1                   true         CephObjectRealm
cephobjectstores                                      ceph.rook.io/v1                   true         CephObjectStore
cephobjectstoreusers                rcou,objectuser   ceph.rook.io/v1                   true         CephObjectStoreUser
cephobjectzonegroups                                  ceph.rook.io/v1                   true         CephObjectZoneGroup
cephobjectzones                                       ceph.rook.io/v1                   true         CephObjectZone
cephrbdmirrors                                        ceph.rook.io/v1                   true         CephRBDMirror

To see Block storage status, you can use cephblockpools. Similarly, cephobjectstores is for Object and cephnfses is for NFS.

Refer to examples from https://github.com/rook/rook/tree/master/deploy/examples

Create Block Storage

$ microk8s kubectl create -f storageClass.yaml 
cephblockpool.ceph.rook.io/replicapool created
storageclass.storage.k8s.io/rook-ceph-block created

$ microk8s kubectl -n rook-ceph get cephblockpools
NAME          PHASE
replicapool   Progressing

$ microk8s kubectl create -f mysql.yaml 
service/wordpress-mysql created
persistentvolumeclaim/mysql-pv-claim created
deployment.apps/wordpress-mysql created

Create Object Stores

This requires rgw that we have already enabled

$ kubectl create -f object.yaml

$ microk8s kubectl -n rook-ceph get cephobjectstores
NAME       PHASE
my-store   Progressing

Create Share File Systems

$ kubectl create -f file.yaml
$ microk8s kubectl get cephfilesystems -n rook-ceph
NAME   ACTIVEMDS   AGE     PHASE
myfs   1           5m38s   Progressing

That’s it! We have completed deploying a cloud native storage solution, that too, locally.

Distributed Storage

Part 1 of 4

In this series, we will deploy a distributed storage cluster locally. Start by creating VMs to deploy multi node clusters. Create multi node Kubernetes and Ceph clusters. Integrate the k8s and Ceph using Rook

Up next

MicroCeph is the easy way to Ceph

Deploy a local multi node Ceph cluster with VMs