You are looking at the documentation of a prior release. To read the documentation of the latest release, please
visit here.
New to KubeDB? Please start here.
Milvus Storage Migration
This guide will show you how to use the KubeDB Ops-manager operator to migrate the persistent volumes of a Milvus database from one StorageClass to another.
Before You Begin
You should be familiar with the following
KubeDBconcepts:Complete the dependency setup from Prepare Dependencies. It installs MinIO, creates the
my-release-miniosecret, and installs the etcd operator required by Milvus.You need at least two
StorageClasses — the current one and the target one. This guide migrates fromlocal-pathtolonghorn-custom:$ kubectl get sc NAME PROVISIONER ALLOWVOLUMEEXPANSION AGE local-path (default) rancher.io/local-path false 11h longhorn-custom driver.longhorn.io true 11h
Note: The yaml files used in this tutorial are stored in docs/guides/milvus/storage-migration/yamls folder in GitHub repository kubedb/docs.
Storage Migration — Standalone Milvus
Deploy a standalone Milvus on local-path and wait until it is Ready:
$ kubectl get pvc -n demo -l app.kubernetes.io/instance=milvus-standalone
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
data-milvus-standalone-0 Bound pvc-... 1Gi RWO local-path 14m
Apply the StorageMigration OpsRequest
storage-migration-standalone.yaml
apiVersion: ops.kubedb.com/v1alpha1
kind: MilvusOpsRequest
metadata:
name: storage-migration
namespace: demo
spec:
type: StorageMigration
databaseRef:
name: milvus-standalone
migration:
storageClassName: longhorn-custom
oldPVReclaimPolicy: Delete
timeout: 10m
Here,
spec.migration.storageClassNameis the targetStorageClass.spec.migration.oldPVReclaimPolicycontrols what happens to the old PersistentVolume (DeleteorRetain).
$ kubectl apply -f https://github.com/kubedb/docs/raw/v2026.7.10/docs/guides/milvus/storage-migration/yamls/storage-migration-standalone.yaml
milvusopsrequest.ops.kubedb.com/storage-migration created
Watch Progress
$ kubectl get milvusopsrequest storage-migration -n demo
NAME TYPE STATUS AGE
storage-migration StorageMigration Successful 87s
$ kubectl describe milvusopsrequest storage-migration -n demo
...
Status:
Conditions:
Message: StorageClass migration is in progress
Reason: Running
Type: Running
Message: pet set deleted; ConditionStatus:True; PodName:milvus-standalone
Type: PetSetDeleted--milvus-standalone
Message: get storage class; ConditionStatus:True
Type: GetStorageClass
...
Phase: Successful
During migration, the operator runs a migrator job to copy the data, recreates the PVC on the new StorageClass, and recreates the pod.
Verify the Migration
The PVC is now backed by longhorn-custom, and the database spec reflects the new class:
$ kubectl get pvc -n demo -l app.kubernetes.io/instance=milvus-standalone
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
data-milvus-standalone-0 Bound pvc-... 1Gi RWO longhorn-custom 33s
$ kubectl get milvuses.kubedb.com milvus-standalone -n demo -o jsonpath='{.spec.storage.storageClassName}'
longhorn-custom
Storage Migration — Distributed Milvus
For a distributed Milvus, migration targets the workloads that carry persistent storage — i.e. streamingnode. Point spec.databaseRef.name at milvus-cluster:
storage-migration-distributed.yaml
apiVersion: ops.kubedb.com/v1alpha1
kind: MilvusOpsRequest
metadata:
name: storage-migration
namespace: demo
spec:
type: StorageMigration
databaseRef:
name: milvus-cluster
migration:
storageClassName: longhorn-custom
oldPVReclaimPolicy: Delete
timeout: 10m
The operator migrates the PVC of every streamingnode replica. Starting from local-path:
$ kubectl get pvc -n demo -l app.kubernetes.io/instance=milvus-cluster -o custom-columns=NAME:.metadata.name,SIZE:.status.capacity.storage,SC:.spec.storageClassName
NAME SIZE SC
data-milvus-cluster-streamingnode-0 1Gi local-path
data-milvus-cluster-streamingnode-1 1Gi local-path
After the migration completes:
$ kubectl get milvusopsrequest storage-migration -n demo
NAME TYPE STATUS AGE
storage-migration StorageMigration Successful 3m40s
$ kubectl get pvc -n demo -l app.kubernetes.io/instance=milvus-cluster -o custom-columns=NAME:.metadata.name,SIZE:.status.capacity.storage,SC:.spec.storageClassName
NAME SIZE SC
data-milvus-cluster-streamingnode-0 1Gi longhorn-custom
data-milvus-cluster-streamingnode-1 1Gi longhorn-custom
$ kubectl get milvuses.kubedb.com milvus-cluster -n demo -o jsonpath='{.spec.topology.distributed.streamingnode.storage.storageClassName}'
longhorn-custom
(This example was run with streamingnode scaled to two replicas; both PVCs are migrated.)
Cleaning up
$ kubectl delete milvusopsrequest -n demo storage-migration
$ kubectl delete milvus.kubedb.com -n demo milvus-standalone
$ kubectl delete ns demo
Next Steps
- Learn about volume expansion of a Milvus database.
- Detail concepts of Milvus object.
- Want to hack on KubeDB? Check our contribution guidelines.































