Deploy Milvus on CKS
Deploy Milvus Vector Database on CoreWeave Kubernetes Service (CKS)
These instructions explain how to deploy Milvus, an open-source vector database built for GenAI applications, on CoreWeave Kubernetes Service (CKS).
Prerequisites
Before you start, you need:
- A working CKS cluster with at least one CPU Node. GPU Nodes are also supported, but CPU Nodes are preferred unless you plan to use GPU-based indexing.
- Access Key and Secret Key with permissions to use a CoreWeave AI Object Storage bucket.
You'll need the following tools on your local machine:
It's also helpful to have an Object Storage command-line tool such as the AWS CLI to access your bucket when testing.
Step 1. Verify your system configuration
-
Verify that you can access your cluster with
kubectl
. For example:$kubectl cluster-infoYou should see something similar to:
Kubernetes control plane is running at...CoreDNS is running at...node-local-dns is running at... -
Verify your cluster has at least one CPU Node. GPU Nodes are also supported, but CPU Nodes are preferred unless you plan to use GPU-based indexing. For example:
$kubectl get nodes -o=custom-columns="NAME:metadata.name,CLASS:metadata.labels['node\.coreweave\.cloud\/class']"You should see something similar to the following:
NAME CLASSg137a10 gpug5424e0 cpug77575e cpugd926d4 gpu
Step 2. Deploy Milvus
-
Install the Milvus Operator. See the Operator installation guide for more details.
$helm install milvus-operator \-n milvus-operator --create-namespace \--wait --wait-for-jobs \https://github.com/zilliztech/milvus-operator/releases/download/v1.3.0/milvus-operator-1.3.0.tgzThis installs the Milvus Custom Resource Definition (CRD), which is used to define Milvus clusters, along with the Operator that manages them. It creates a new namespace called
milvus-operator
for the Operator itself.It's possible to add
milvus-operator
as a dependency to the CoreWeave chart (which you'll download in the next step), but it's preferred to install it in a separate namespace from the database. The Operator can manage multiple Milvus clusters in different namespaces. -
Clone the CoreWeave Milvus chart repository at:
https://github.com/coreweave/reference-architecture/tree/main/tooling/vector_dbs/cw-milvus
-
Edit the chart's
values.yaml
with your details:caiosBucketName: YOUR_BUCKET_NAMEcaiosAccessKey: YOUR_ACCESS_KEYcaiosSecretKey: YOUR_SECRET_KEYCheck the deleteDependencies policyThis chart automatically deletes dependencies like
etcd
andkafka
by default. This makes it easier to clean up after an experiment is complete.You should set
deleteDependencies
tofalse
if you want to retain these dependencies after deleting the Milvus custom resource. -
If you plan to use GPU-based indexing, set the
gpuIndexing
value totrue
invalues.yaml
. This will schedule the relevant components on GPU Nodes as shown.dataNode:affinity:nodeAffinity:# override global component affinity when using GPU indexingrequiredDuringSchedulingIgnoredDuringExecution:nodeSelectorTerms:- matchExpressions:- key: node.coreweave.cloud/classoperator: Invalues:- gpuqueryNode:affinity:nodeAffinity:# override global component affinity when using GPU indexingrequiredDuringSchedulingIgnoredDuringExecution:nodeSelectorTerms:- matchExpressions:- key: node.coreweave.cloud/classoperator: Invalues:- gpu
Chart defaults explained
The CoreWeave chart handles the following items:
-
It provisions a secret with the Object Storage credentials you specified in
values.yaml
. -
It configures the Object Storage bucket you specified, with
aliyun
as the provider. This ensures that Milvus uses virtual-host style addressing.config:minio:# Use "aliyun" as cloud provider, as that enables virtual host style bucket requestscloudProvider: aliyunuseVirtualHost: truebucketName: {{ .Values.caiosBucketName }}# Optional, config the prefix of the bucket milvus will userootPath: {{ include "cw-milvus.name" . }}useSSL: true -
It sets the storage type to
S3
and uses the CoreWeave AI Object Storage endpoint (cwobject.com:443
).dependencies:storage:# enable external object storageexternal: truetype: S3 # MinIO | S3# the endpoint of AWS S3endpoint: cwobject.com:443# the secret storing the access key and secret keysecretRef: '{{ include "cw-milvus.name" . }}-caios-secret' -
It configures Kafka as the message storage service and overrides the default image (which is not yet available).
kafka:inCluster:deletionPolicy: DeletepvcDeletion: truevalues:image:repository: bitnami/kafkatag: 3.7.0-debian-12-r6 -
It sets Node affinities for the Milvus components to CPU Nodes. However, scheduling onto GPU Nodes is also possible when using GPU-based indexing as described in Step 2.
affinity:nodeAffinity:# prefer running on CPU nodes, if available# see also queryNode and dataNode affinities for GPU-based indexingpreferredDuringSchedulingIgnoredDuringExecution:- weight: 100preference:matchExpressions:- key: node.coreweave.cloud/classoperator: Invalues:- cpu -
It configures a
CronJob
for backup using milvus-backup. You can control the cron expression for scheduling the job, as well as settings for the backup bucket via values invalues.yaml
. If you do not specify a bucket name and credentials for backups, the ones specified for the database are used.backupCaiosBucketName: YOUR_BACKUP_BUCKET_NAMEbackupCaiosAccessKey: YOUR_BACKUP_BUCKET_ACCESS_KEYbackupCaiosSecretKey: YOUR_BACKUP_BUCKET_SECRET_KEY# defaults to "backup"backupCaiosBucketRootPath:backupCronExpression: "30 7 * * *"Backups will accumulateBackup names are based on timestamps, so are unique. This means backups will accumulate in your bucket unless you clean out unneeded ones periodically.
Step 3. Install the chart
-
Change to the chart directory:
$cd reference-architecture/tooling/vector_dbs/cw-milvus -
Install the chart in a new namespace, e.g.
milvus
:$helm install -n milvus cw-milvus . -
Check the status of the custom resource. This may take several minutes to complete, as the Operator sets up the database and its dependencies.
kubectl -n milvus describe milvus cw-milvusThe
Conditions
block will show the status of individual components. Once everything is set up, that block should look like this:Conditions:Last Transition Time: 2025-09-22T21:47:24ZMessage: All Milvus components are healthyReason: ReasonMilvusHealthyStatus: TrueType: MilvusReadyLast Transition Time: 2025-09-18T23:14:29ZMessage: Milvus components are all updatedReason: MilvusComponentsUpdatedStatus: TrueType: MilvusUpdatedLast Transition Time: 2025-09-18T23:12:32ZMessage: Etcd endpoints is healthyReason: EtcdReadyStatus: TrueType: EtcdReadyLast Transition Time: 2025-09-18T23:12:32ZReason: StorageReadyStatus: TrueType: StorageReadyLast Transition Time: 2025-09-18T23:13:29ZReason: MsgStreamReadyStatus: TrueType: MsgStreamReady
Step 4. Access the database
After the database is ready, the web UI service is available on port 9091, and the database service is available on port 19530. To access these, forward local ports from your machine to the service.
-
Forward a local port to the database service.
$kubectl port-forward --address 0.0.0.0 service/cw-milvus-milvus 27017:19530Forwarding from 0.0.0.0:27017 -> 19530 -
Forward a local port to the web UI service.
kubectl port-forward --address 0.0.0.0 service/cw-milvus-milvus 27018:9091Forwarding from 0.0.0.0:27018 -> 9091
You can now access the web UI at http://localhost:27018
and connect to the database at localhost:27017
.
Additional resources
See the Milvus documentation to learn more.