Migrating Ceph CSI to shturval-ceph-csi
- Before you start
- Step 1. Build the tool and generate manifests
- Images
- Step 2. Turn off both SSCs
- Step 3. Confirm the old StorageClasses are gone
- Step 4. Restore Secrets to the original namespaces
- Step 5. Create the operator namespace
- Step 6. Install the operator chart
- Step 7. Apply step1 and wait for the pods
- Step 8. Apply the StorageClasses
- Where manifest fields come from
На этой странице
- Before you start
- Step 1. Build the tool and generate manifests
- Images
- Step 2. Turn off both SSCs
- Step 3. Confirm the old StorageClasses are gone
- Step 4. Restore Secrets to the original namespaces
- Step 5. Create the operator namespace
- Step 6. Install the operator chart
- Step 7. Apply step1 and wait for the pods
- Step 8. Apply the StorageClasses
- Where manifest fields come from
On an update to 2.15.0 the platform moves shturval-ceph-cephfs and shturval-ceph-rbd to shturval-ceph-csi by itself. To migrate manually, follow this page before you start the update.
This page describes how to move the services shturval-ceph-cephfs and shturval-ceph-rbd, already running in the cluster, to shturval-ceph-csi. Data in Ceph is not lost. The drivers keep their names (cephfs.csi.ceph.com and rbd.csi.ceph.com), so existing volumes remain attached to the same disks.
Save the command output before step 2 and compare it after step 7.
| Check | How to run it |
|---|---|
| The volume list is unchanged | kubectl get pv and kubectl get pvc -A. The names are the same, the status is Bound. |
| The driver is the same | kubectl get pv <name> -o jsonpath='{.spec.csi.driver}{"\n"}'. A file volume shows cephfs.csi.ceph.com, a block volume shows rbd.csi.ceph.com. The line matches the output from before the migration. |
| The same disk in Ceph | kubectl get pv <name> -o jsonpath='{.spec.csi.volumeHandle}{"\n"}'. The value before and after the migration matches. |
| The volume mounts again | After step 7, delete the pod that uses this PVC and wait until it is Running. kubectl describe pod <name> -n <namespace> shows a SuccessfulMountVolume event. |
The migration tool only reads the cluster and writes YAML to disk. It does not change cluster objects. A person changes the cluster: disabling the services, kubectl apply, and the Helm install are separate steps below. Do not reorder them.
Before you start
| What you need | How to check |
|---|---|
Both modules are installed and running. For each SSC, status.appliedMode is auto and status.ready is true. Until that is true, the tool does not emit manifests for that driver. | kubectl get shturvalserviceconfig shturval-ceph-cephfs shturval-ceph-rbd -o custom-columns=NAME:.metadata.name,MODE:.status.appliedMode,READY:.status.ready. The output shows MODE auto and READY true. |
A kubeconfig that can read the SSCs and Secrets in the CSI namespaces. For the platform modules those namespaces are ceph-fs and ceph-rbd. | kubectl --kubeconfig <file> get shturvalserviceconfig shturval-ceph-cephfs and kubectl --kubeconfig <file> get secret -n ceph-fs. The same for shturval-ceph-rbd and namespace ceph-rbd. The commands finish without an access error. |
| Go 1.26, Helm, and kubectl. | go version, helm version, kubectl version --client. The Go line contains go1.26. |
The ceph-operator-migration directory. Run the commands below from there; manifests are written to ./manifests. | The directory contains main.go, constants.go, and README.md. Run the later commands from here. |
CephFS and RBD have different spec.customvalues.csiConfig[0].clusterID values. The same identifier gives both ClientProfile objects one metadata.name, which conflicts in a single namespace. Check this before generating manifests. | kubectl get shturvalserviceconfig shturval-ceph-cephfs shturval-ceph-rbd -o custom-columns=NAME:.metadata.name,CLUSTERID:.spec.customvalues.csiConfig[0].clusterID. The CLUSTERID values differ. |
Save the command output to a text file in the tool directory, for example pre-migration.txt. Do this before you turn the services off. The file is only for you: it is not applied to the cluster and does not belong in manifests/. After the services are set to Off, the chart StorageClass is removed. Keep the Secret in the old driver namespaces (ceph-fs, ceph-rbd). Use the file to check the Secret name and namespace, to confirm the old StorageClass is gone, and to see which pods must not be restarted until the operator CSI pods are Running.
Secret name (
spec.customvalues.secret.name) and namespace (spec.namespace) of each SSC.kubectl get shturvalserviceconfig shturval-ceph-cephfs shturval-ceph-rbd -o custom-columns=NAME:.metadata.name,NAMESPACE:.spec.namespace,SECRET:.spec.customvalues.secret.nameStorageClass name (
spec.customvalues.storageClass.name), if it is set.kubectl get shturvalserviceconfig shturval-ceph-cephfs shturval-ceph-rbd -o custom-columns=NAME:.metadata.name,STORAGECLASS:.spec.customvalues.storageClass.namePVCs that are already mounted. Do not restart their pods until the new operator CSI pods are
Running.kubectl get pvc -A --field-selector=status.phase=Bound
Do not turn the services off until the tool has finished and the files are in the manifests directory. It reads the SSCs and their Secrets while the services are still on. If you set the services to Off earlier, the Secrets are deleted and a second run cannot collect the credentials.
If only one of the two modules is installed, the tool exits with code 1 and reports an error for the missing SSC. Manifests for the ready module are still saved. For a full run, both services must be ready before you start.
Step 1. Build the tool and generate manifests
On this step the tool only writes YAML into the manifests/ directory. It applies nothing to the cluster: no Secret, no ConfigMap, no StorageClass. The image file does not exist until the tool has run, so there is nothing to edit beforehand.
go build -o ceph-operator-migration .
./ceph-operator-migration --kubeconfig /path/to/kubeconfig.conf
The kubeconfig path is not hardcoded; the flag is required. The same run without a binary: go run . --kubeconfig /path/to/kubeconfig.conf.
saved ... lines go to stderr. Exit code 0 means both SSCs were read. If stderr contains error:, do not disable the services: fix the cause and run the tool again.
| Flag | Required | Default | When to change it |
|---|---|---|---|
--kubeconfig | Yes | none | Path to the kubeconfig. The tool does not start without this flag. |
--operator-namespace | No | ceph-csi-operator | You need another operator namespace. Use the same name later in helm install -n. |
--monitors-cephfs | No | auto | Comma-separated CephFS monitor list, when it cannot be taken from SSC shturval-ceph-cephfs (spec.customvalues.csiConfig[0].monitors). |
--monitors-rbd | No | auto | The same for RBD and SSC shturval-ceph-rbd. |
--sub-volume-group | No | csi | CephFS subvolume group name on the ClientProfile. For the platform modules the group is csi. |
After a successful run the working directory must contain:
manifests/
├── step0/
│ └── namespace.yaml
├── backup/
│ ├── ceph-fs-csi-secret.yaml
│ └── ceph-rbd-csi-secret.yaml
├── step1/
│ ├── operator-images-configmap.yaml
│ ├── cephfs-driver.yaml
│ ├── rbd-driver.yaml
│ ├── ceph-fs-connection.yaml
│ ├── ceph-rbd-connection.yaml
│ ├── ceph-fs-client-profile.yaml
│ ├── ceph-rbd-client-profile.yaml
│ ├── ceph-fs-operator-secret.yaml
│ └── ceph-rbd-operator-secret.yaml
└── step2/
├── ceph-fs-storageclass.yaml
└── ceph-rbd-storageclass.yaml
Images
The CSI image file appears only after the tool has run: manifests/step1/operator-images-configmap.yaml. These images are not in the chart. The tool writes the default addresses there. If the pods must come from your registry, replace them in this file and apply it at step 7. You do not rebuild the tool.
The Driver manifests cephfs-driver.yaml and rbd-driver.yaml already point at this file:
spec:
imageSet:
name: operator-images
| Key in the file | Address the tool wrote |
|---|---|
plugin | quay.io/cephcsi/cephcsi:v3.16.2 |
provisioner | registry.k8s.io/sig-storage/csi-provisioner:v6.0.0 |
attacher | registry.k8s.io/sig-storage/csi-attacher:v4.10.0 |
resizer | registry.k8s.io/sig-storage/csi-resizer:v2.0.0 |
snapshotter | registry.k8s.io/sig-storage/csi-snapshotter:v8.4.0 |
registrar | registry.k8s.io/sig-storage/csi-node-driver-registrar:v2.15.0 |
Check this before you disable the SSCs:
- In
backup/, each Secret has the samemetadata.nameas the SSC, andmetadata.namespaceis the original CSI namespace (ceph-fsorceph-rbd). - In
step1/, the same Secrets are placed in the operator namespace. - In
step1/*-connection.yaml,spec.monitorsmatches the monitors of the corresponding SSC. - In
step2/, the classes are namedshturval-cephfsandshturval-rbd. The tool sets these names itself, even if the chart customvalues used another class name. -
parameters.clusterID,fsName(CephFS), andpool(RBD) match that SSC’s customvalues.
The tool writes Secret files with mode 0600. The manifests/ directory is gitignored: it is a snapshot of cluster credentials.
Step 2. Turn off both SSCs
Two drivers with the same name cannot run at once. Remove the chart-based CSI first, then start the operator.
For Ceph CSI Module - Ceph File System and Ceph CSI Module - Ceph Block Device:
- Services and repositories → Installed services.
- Open the service card → Manage.
- Set the management mode to Off.
- Click Save.
The same action with kubectl. The services are not critical, so you do not clear iscritical:
kubectl patch shturvalserviceconfig shturval-ceph-cephfs --type merge -p '{"spec":{"mode":"absent"}}'
kubectl patch shturvalserviceconfig shturval-ceph-rbd --type merge -p '{"spec":{"mode":"absent"}}'
Wait until the chart pods are gone:
kubectl get pods -n ceph-fs
kubectl get pods -n ceph-rbd
Turning a service off removes the controller and node plugin pods and the StorageClass created by the chart. Do not delete the Secret in the old driver namespaces (ceph-fs, ceph-rbd): existing volumes refer to it. PersistentVolume and PersistentVolumeClaim objects are not deleted. Data in Ceph stays. A volume that is already mounted on a node keeps working: the kernel mount or ceph-fuse mount is already in place.
From Off until every pod in the operator namespace is Running, do not restart pods that use these PVCs, do not drain nodes, and do not reboot nodes. A remount in this window hangs: the old plugin is gone and the new one is not up yet. Data is not lost; only the remount stops.
The SSC object and its customvalues stay in the cluster. Do not switch these two services back to Auto after the migration: the chart would create drivers with the same names and collide with the operator.
Step 3. Confirm the old StorageClasses are gone
kubectl get storageclass shturval-cephfs shturval-rbd
If customvalues used another class name, check that name too. Empty output is the expected result.
If the StorageClass is still there, delete it:
kubectl delete storageclass shturval-cephfs shturval-rbd
Do not delete the Secret in the old driver namespaces. It must stay in ceph-fs and ceph-rbd (or in the SSC spec.namespace). Do not delete PersistentVolumes or PersistentVolumeClaims either.
Step 4. Restore Secrets to the original namespaces
Secrets for existing volumes must stay in the old driver namespaces. If they are gone after the services are turned off, put the copies from manifests/backup/ back:
kubectl apply -f manifests/backup/
Secrets return to the namespaces the tool read them from (ceph-fs, ceph-rbd, or the actual spec.namespace). Existing PVCs reference the Secret in that namespace. You cannot change the Secret namespace on an existing PVC, so this step is required: without it the volume will not mount again after a pod restart.
Check:
kubectl get secret -n ceph-fs
kubectl get secret -n ceph-rbd
The names must match metadata.name in the backup/ files.
Step 5. Create the operator namespace
kubectl apply -f manifests/step0/
This creates the ceph-csi-operator namespace (or the --operator-namespace value). You do not need a separate kubectl create namespace: step0/namespace.yaml does the same thing.
Step 6. Install the operator chart
Chart ceph-csi-operator/ceph-csi-operator from https://ceph.github.io/ceph-csi-operator/. In values.yaml, change only the operator image:
controllerManager:
manager:
image:
repository: quay.io/cephcsi/ceph-csi-operator
tag: v1.0.5
helm install ceph-csi-operator ceph-csi-operator/ceph-csi-operator \
-n ceph-csi-operator --create-namespace=false \
--values values.yaml
The operator namespace then has one pod: ceph-csi-operator-controller-manager. The CSI pods are not running yet. The operator creates them after you apply the manifests from step1.
Step 7. Apply step1 and wait for the pods
kubectl apply -f manifests/step1/
kubectl get pods -n ceph-csi-operator -w
The operator receives Driver, CephConnection, ClientProfile, the operator-images ConfigMap, and Secrets in its namespace, and starts the controller plugin and node plugin for cephfs.csi.ceph.com and rbd.csi.ceph.com.
Until this step, ConfigMap operator-images existed only as the file manifests/step1/operator-images-configmap.yaml. It now appears in the operator namespace (ceph-csi-operator, or the --operator-namespace value). The operator reads it when it creates the driver pods: in the Driver manifest, spec.imageSet.name is operator-images. To see it: kubectl get configmap operator-images -n ceph-csi-operator -o yaml.
Go to step 8 only when every pod in the namespace is Running, including pods on each node where volumes must be mounted. ContainerCreating and CrashLoopBackOff mean the new plugin is not ready to remount. Check pod events: the usual causes are an image from the operator-images ConfigMap that cannot be pulled, or a bad ClientProfile (monitors, clusterID).
At this point you can restart a pod that uses an existing PVC and confirm the volume mounts again. That mount uses the Secret from backup, not the Secret in the operator namespace.
Step 8. Apply the StorageClasses
kubectl apply -f manifests/step2/
kubectl get storageclass shturval-cephfs shturval-rbd
The classes shturval-cephfs and shturval-rbd reference the Secret in the operator namespace. They are for new PVCs. Existing PVCs keep using the Secret from step 4 and the same driver name on the PV. You do not change their storageClassName.
To check a new volume, create a PVC with storageClassName: shturval-cephfs or shturval-rbd, and wait until it is Bound and the pod starts. If the PVC stays Pending, read kubectl describe pvc and the provisioner logs in the ceph-csi-operator namespace.
Where manifest fields come from
| Manifest | Source of the fields |
|---|---|
step0/namespace.yaml | --operator-namespace |
step1/operator-images-configmap.yaml | Image* constants in constants.go |
step1/cephfs-driver.yaml, step1/rbd-driver.yaml | fixed driver names and a reference to ConfigMap operator-images |
backup/*.yaml | Secret from the SSC spec.namespace, name from spec.customvalues.secret.name. Annotations meta.helm.sh/* and helm.sh/* are removed |
step1/*-operator-secret.yaml | the same Secret data, operator namespace |
step1/ceph-fs-connection.yaml | CephFS monitors (--monitors-cephfs or the SSC) |
step1/ceph-rbd-connection.yaml | RBD monitors |
step1/ceph-fs-client-profile.yaml | metadata.name = CephFS clusterID, subvolume group --sub-volume-group, reference to cephfs-connection |
step1/ceph-rbd-client-profile.yaml | metadata.name = RBD clusterID, reference to rbd-connection |
step2/ceph-fs-storageclass.yaml | name shturval-cephfs, fsName and clusterID from the CephFS SSC, Secret in the operator namespace |
step2/ceph-rbd-storageclass.yaml | name shturval-rbd, pool, imageFeatures, and clusterID from the RBD SSC. An empty imageFeatures is replaced with layering |