This tutorial shows how to deploy nbgrader with ngshare on Jetstream Kubernetes where ngshare’s SQLite database lives on a Manila CephFS share instead of a Cinder volume.
It is the storage-backend update of the original ngshare tutorial: Deploy nbgrader on Jetstream with ngshare (Kubernetes).
Prerequisites
- A running Magnum cluster on Jetstream (see Deploy Kubernetes on Jetstream2 with Magnum and Cluster API).
- OpenStack credentials loaded, plus
openstack,jq,kubectl, andhelm. - The deployment repository cloned locally:
git clone https://github.com/zonca/jupyterhub-deploy-kubernetes-jetstream.git(all commands below run from its root).
Step 2: Configure access to the cluster
From the deployment repository root, with OpenStack credentials loaded:
export K8S_CLUSTER_NAME=k8s
bash kubernetes_magnum/configure_kubectl_locally.sh
export KUBECONFIG=$(pwd)/config
kubectl get nodesStep 3: Install the CephFS CSI driver
Copy the values template to a local, gitignored file (never edit the tracked template, it holds the share access key):
cp manila/cephfs-csi-values.yaml manila/cephfs-csi-values.local.yamlFill manila/cephfs-csi-values.local.yaml with:
<CEPH_FSID>: any stable ID string, e.g.manila-cephfs(it only needs to match the PV, see the next step)<ACCESS_RULE_NAME>: the access rule name (ngshare-rw, noclient.prefix)<ACCESS_KEY>: the access key from Step 1- the
monitorslist from the export location
Then install in kube-system (the nodeStageSecretRef of the PV below points there):
helm repo add ceph-csi https://ceph.github.io/csi-charts/
helm repo update
helm upgrade --install ceph-csi-cephfs ceph-csi/ceph-csi-cephfs \
--namespace kube-system \
-f manila/cephfs-csi-values.local.yamlVerify the driver is registered and pods run:
kubectl get csidriver cephfs.csi.ceph.com -o jsonpath='{.spec.fsGroupPolicy}'
kubectl get csidriver cephfs.csi.ceph.com
kubectl -n kube-system get pods | grep ceph-csi-cephfsExpected fsGroupPolicy: File.
Step 4: Create the StorageClass, PV and PVC
This repo ships templates for the ngshare Manila PV:
nbgrader/ngshare-standalone-repro-manila/00-storageclass.yaml:manila-cephfsStorageClass withprovisioner: kubernetes.io/no-provisionernbgrader/ngshare-manila-pv.yaml: static PV (fill<SHARE_ID>and<SHARE_PATH>)
Fill ngshare-manila-pv.yaml:
<SHARE_ID>: the Manila share UUID (any unique string is fine asvolumeHandle)<SHARE_PATH>:/volumes/_nogroup/...from Step 1clusterIDmust equal the<CEPH_FSID>used in Step 3
Apply the StorageClass and PV (do not create a PVC here: the ngshare Helm chart creates its own PVC in Step 5, and a static PV can be bound only once):
kubectl create namespace jhub --dry-run=client -o yaml | kubectl apply -f -
kubectl apply -f nbgrader/ngshare-standalone-repro-manila/00-storageclass.yaml
kubectl apply -f nbgrader/ngshare-manila-pv.yaml
kubectl get pv ngshare-manila-pvExpected: PV Available, access modes RWX.
Why a no-provisioner StorageClass: the ngshare Helm chart creates its own PVC and we bind it statically with a selector. A StorageClass with a real provisioner would make the controller attempt dynamic provisioning, and the CephFS provisioner rejects PVC selectors with claim Selector is not supported.
Notes
- No initContainer is required: the Manila CephFS volume honors
fsGroupon RWX claims. - The ngshare PVC is standalone metadata storage; 10 GiB is plenty for typical classes.
- The
nbgrader/ngshare-standalone-repro-manila/folder contains a standalone repro (same ngshare runtime conditions) if you want to verify a fresh setup before deploying. It uses its own PV (ngshare-repro-pv) and its own Manila share or subdirectory: never point it at the same share/path as the deployed ngshare volume, because its with-init variant recursivelychowns the mount.
Troubleshooting
PVC stuck Pending, event claim Selector is not supported: the StorageClass has a real provisioner. Recreate it with provisioner: kubernetes.io/no-provisioner as in 00-storageclass.yaml.
PVC Pending after the PV was previously bound and released: clear the claimRef on the PV:
kubectl patch pv ngshare-manila-pv --type=merge -p '{"spec":{"claimRef":null}}'Pod stuck ContainerCreating with Ceph mount errors: check the secret referenced by nodeStageSecretRef exists in kube-system, and that rootPath is only the /volumes/... part of the export location.
Old sqlite error still appears: make sure the ngshare pod uses the Manila PVC and that the volume directory is not a leftover Cinder mount. Delete the ngshare pod so it re-creates the DB on the new volume:
kubectl -n jhub delete pod -l app.kubernetes.io/instance=ngshare