New to KubeDB? Please start here.
Etcd Storage Migration
This guide gives an overview of how the KubeDB Ops-manager operator moves the data volumes of an
Etcd cluster from one StorageClass to another.
Before You Begin
- You should be familiar with the following
KubeDBconcepts:
Why It Is Not Just an Edit
spec.storageClassName on a PVC is immutable, and so is spec.volumeClaimTemplates on a PetSet.
Moving an etcd member onto a different StorageClass therefore means provisioning a new volume,
copying the data across, and giving the new volume the old claim’s name so the member picks it up
again. StorageMigration is the EtcdOpsRequest type that does all of that for you.
How the Storage Migration Process Works
The mechanics are the shared KubeDB migration machinery, identical to every other KubeDB database. The only etcd-specific part is the ordering: members are migrated one at a time, followers first and the Raft leader last, so the cluster keeps a quorum throughout.
The user creates an
EtcdOpsRequestof typeStorageMigrationwithspec.migration.storageClassName(the targetStorageClass) and aspec.timeout.The Ops-manager operator pauses the
Etcdobject, so the Provisioner operator does not fight the migration.It deletes the
PetSetwith an orphan propagation policy. ThePetSethas to go first — otherwise it would immediately recreate every pod the migration deletes — but the pods are orphaned, not deleted, so every member keeps serving until its own turn comes.It resolves the current Raft leader and splits the members into followers and the leader, so the leader’s volume is migrated last.
For each member, in that order:
- create a new PVC on the target
StorageClass, sized from the old one; - if the target
StorageClassusesWaitForFirstConsumer, run a short-lived mounter pod pinned to the member’s node, so the new volume is provisioned in the right topology; - stash the member pod’s manifest as an annotation on the ops request and delete the pod;
- run a migrator
Jobthatrsyncs the data directory from the old volume to the new one; - swap the names: delete the original PVC (with its PV temporarily set to
Retain, so no data is lost) and re-create the claim under the original name bound to the new volume; - recreate the member pod from the stashed manifest and wait for it to become
Ready; - wait for a healthy quorum before moving to the next member.
- create a new PVC on the target
Once every member has been migrated, the operator patches
spec.storage.storageClassNameon theEtcdobject, resumes it, and marks the requestSuccessful.
Preconditions
spec.migration.storageClassNameis required, and the targetStorageClassmust exist.spec.timeoutis required. The webhook rejects aStorageMigrationwithout it. Every step of the migration is bounded by that timeout, and the data-copyJobhas no other deadline at all — so size it against how much data you have, not against how long a pod takes to restart.spec.storageTypemust beDurable; there is nothing to migrate on anEphemeraletcd.- If the source
StorageClassusesvolumeBindingMode: WaitForFirstConsumer, the target must use it too. The webhook rejects the mismatch.
Keeping the source volumes. While the claims are being swapped, each PV’s reclaim policy is temporarily forced to
Retainso nothing is lost mid-flight, and the original policy is restored once the member is back — which means a source PV provisioned by aDelete-reclaimingStorageClassis eventually reclaimed. Setspec.migration.oldPVReclaimPolicy: Retainif you want the previous volumes to survive the migration.
In the next doc, we are going to show a
step-by-step guide on migrating the storage of an Etcd cluster using the EtcdOpsRequest CRD.
































