New to KubeDB? Please start here.
Milvus Compute Autoscaling
This guide will show you how to use the KubeDB Autoscaler operator to autoscale the compute resources (CPU/memory) of a Milvus database.
Before You Begin
You should be familiar with the following
KubeDBconcepts:Install the KubeDB Autoscaler operator and a metrics server in your cluster — the autoscaler’s built-in recommender needs metrics to produce recommendations.
$ kubectl get deploy metrics-server -n kube-system NAME READY UP-TO-DATE AVAILABLE AGE metrics-server 1/1 1 1 5mComplete the dependency setup from Prepare Dependencies. It installs MinIO and creates the object-storage secrets (
milvus-storage-configformilvus-standalone,milvus-cluster-storage-configformilvus-cluster).
Note: The yaml files used in this tutorial are stored in docs/guides/milvus/autoscaler/compute/yamls folder in GitHub repository kubedb/docs.
Compute Autoscaling — Standalone Milvus
Deploy the standalone quickstart manifest and wait until it is Ready:
If you deleted a Milvus of the same name in an earlier guide, delete its object-storage prefix first, as shown in Prepare Dependencies. Otherwise the new database can hang in
Provisioning.
$ kubectl apply -f https://github.com/kubedb/docs/raw/v2026.10.12/docs/guides/milvus/quickstart/yamls/standalone.yaml
milvus.kubedb.com/milvus-standalone created
$ kubectl get milvuses.kubedb.com -n demo milvus-standalone -w
Then create a MilvusAutoscaler targeting the standalone node:
compute-standalone.yaml
apiVersion: autoscaling.kubedb.com/v1alpha1
kind: MilvusAutoscaler
metadata:
name: milvus-standalone-compute-autoscaler
namespace: demo
spec:
databaseRef:
name: milvus-standalone
compute:
node:
trigger: "On"
podLifeTimeThreshold: 10m
minAllowed:
cpu: 100m
memory: 1Gi
maxAllowed:
cpu: 1000m
memory: 2Gi
resourceDiffPercentage: 20
controlledResources: ["cpu", "memory"]
opsRequestOptions:
apply: IfReady
timeout: 5m
Here,
minAllowed.memory: 1Gikeeps the autoscaler from shrinking Milvus below what it needs. The generated OpsRequest sets the memory limit equal to the request, so a lower floor (for example256Mi) leaves no headroom and Milvus is OOM-killed under real load.podLifeTimeThreshold: 10mandresourceDiffPercentage: 20damp the autoscaler. Every OpsRequest it creates restarts the pods, and a freshly started Milvus briefly uses much more CPU. With a shortpodLifeTimeThresholdand a smallresourceDiffPercentage, that startup spike immediately triggers another re-scale (and another restart). Waiting 10 minutes after a pod starts and ignoring differences below 20% prevents this.
$ kubectl apply -f https://github.com/kubedb/docs/raw/v2026.10.12/docs/guides/milvus/autoscaler/compute/yamls/compute-standalone.yaml
milvusautoscaler.autoscaling.kubedb.com/milvus-standalone-compute-autoscaler created
The autoscaler runs its own built-in recommender (it does not create a VerticalPodAutoscaler object). Once the recommender produces a recommendation that differs from the current resources by more than resourceDiffPercentage, the autoscaler creates a VerticalScaling MilvusOpsRequest.
Each autoscaler-created OpsRequest restarts the pods of the role it scales (it uses
Restartmode). For a standalone Milvus, that means a short outage every time the autoscaler re-scales.
$ kubectl get milvusautoscaler -n demo
NAME AGE
milvus-standalone-compute-autoscaler 59s
The recommender (fed by the metrics server) records its recommendation in the autoscaler status. Once enough samples are collected, the RecommendationProvided condition becomes True and a target resource set is published. The status has this shape (values and the large checkpoints array elided):
$ kubectl get milvusautoscaler milvus-standalone-compute-autoscaler -n demo -o jsonpath='{.status}' | jq .
{
"checkpoints": [ ... ],
"conditions": [ ... ],
"vpas": [
{
"conditions": [
{ "type": "RecommendationProvided", "status": "True", ... }
],
"recommendation": {
"containerRecommendations": [
{
"containerName": "milvus",
"lowerBound": { "cpu": ..., "memory": ... },
"target": { "cpu": ..., "memory": ... },
"uncappedTarget": { "cpu": ..., "memory": ... },
...
}
]
},
"vpaName": "milvus-standalone"
}
]
}
To see just the recommended target:
$ kubectl get milvusautoscaler milvus-standalone-compute-autoscaler -n demo -o jsonpath='{.status.vpas[0].recommendation.containerRecommendations[0].target}'
An idle standalone uses far less CPU than its 500m request, so the CPU target is lower, while the memory target is held at minAllowed (1Gi). When the recommendation differs from the current request by more than resourceDiffPercentage (20%) and stays within minAllowed/maxAllowed, the autoscaler creates a VerticalScaling MilvusOpsRequest. This is recorded in the autoscaler status as a CreateOpsRequest condition:
$ kubectl get milvusautoscaler milvus-standalone-compute-autoscaler -n demo \
-o jsonpath='{.status.conditions[?(@.type=="CreateOpsRequest")].message}'
Successfully created MilvusOpsRequest demo/mvops-milvus-standalone-xqwkhv
$ kubectl get milvusopsrequest -n demo
NAME TYPE STATUS AGE
mvops-milvus-standalone-xqwkhv VerticalScaling Progressing 2s
The Ops-manager then applies the vertical scaling exactly as in the vertical scaling guide, right-sizing the pod to the recommended resources.
Compute Autoscaling — Distributed Milvus
For a distributed Milvus, the autoscaler is keyed by role (proxy, mixcoord, datanode, querynode, streamingnode). The sample below enables compute autoscaling for all five roles.
Deploy the distributed quickstart manifest and wait until it is Ready:
$ kubectl apply -f https://github.com/kubedb/docs/raw/v2026.10.12/docs/guides/milvus/quickstart/yamls/distributed.yaml
milvus.kubedb.com/milvus-cluster created
$ kubectl get milvuses.kubedb.com -n demo milvus-cluster -w
compute-distributed.yaml
apiVersion: autoscaling.kubedb.com/v1alpha1
kind: MilvusAutoscaler
metadata:
name: milvus-compute-autoscaler
namespace: demo
spec:
databaseRef:
name: milvus-cluster
compute:
proxy:
trigger: "On"
podLifeTimeThreshold: 10m
minAllowed:
cpu: 100m
memory: 1Gi
maxAllowed:
cpu: 1000m
memory: 2Gi
resourceDiffPercentage: 20
controlledResources: ["cpu", "memory"]
mixcoord: { ... }
datanode: { ... }
querynode: { ... }
streamingnode: { ... }
opsRequestOptions:
apply: IfReady
timeout: 5m
(Each role block is identical to the proxy block above; see the full file in the yamls folder.)
$ kubectl apply -f https://github.com/kubedb/docs/raw/v2026.10.12/docs/guides/milvus/autoscaler/compute/yamls/compute-distributed.yaml
milvusautoscaler.autoscaling.kubedb.com/milvus-compute-autoscaler created
The behavior is identical to standalone, except a resource recommendation is produced per role (one status.vpas[] entry per role, for example vpaName: milvus-cluster-proxy). When any role’s recommendation differs from its current resources by more than resourceDiffPercentage, the autoscaler creates a VerticalScaling MilvusOpsRequest scoped to that role (see the vertical scaling guide for what that ops request looks like). The OpsRequests run one at a time, and each restarts the pods of its role.
Cleaning up
The OpsRequests created by a MilvusAutoscaler are owned by it, so deleting the autoscaler also deletes them, including one that is still running. An OpsRequest deleted mid-flight can leave the database paused or with pods that don’t match its spec. Before deleting the autoscaler, wait until none of its OpsRequests is Progressing:
$ kubectl get milvusopsrequest -n demo
Then clean up:
$ kubectl delete milvusautoscaler -n demo --all
$ kubectl patch -n demo milvus.kubedb.com milvus-standalone -p '{"spec":{"deletionPolicy":"WipeOut"}}' --type="merge"
$ kubectl patch -n demo milvus.kubedb.com milvus-cluster -p '{"spec":{"deletionPolicy":"WipeOut"}}' --type="merge"
$ kubectl delete milvus.kubedb.com -n demo milvus-standalone milvus-cluster
$ kubectl delete ns demo
Next Steps
- Learn about storage autoscaling.
- Want to hack on KubeDB? Check our contribution guidelines.
































