KubeBlocks
BlogsKubeBlocks Cloud
⌘K
​
Overview
Quickstart

Topologies

Milvus Standalone Cluster
Milvus Cluster

Operations

Lifecycle Management
Vertical Scaling
Horizontal Scaling
Manage Milvus Services
Decommission Milvus Replica

Monitoring

Observability for Milvus Clusters

tpl

  1. Prerequisites
  2. Deploying the Milvus Cluster
    1. Step 1. Deploy an ETCD Cluster
    2. Step 2. Deploy a minio Cluster
    3. Step 3. Deploy a Pulsar Cluster
    4. Deploy a Milvus Cluster
  3. Verifying the Deployment
    1. Check the Cluster Status
    2. Verify Component and Pod Status
  4. Cleanup

Deploying a Milvus Cluster with KubeBlocks

Milvus Cluster is a distributed deployment for production workloads with multiple specialized components:

Access Layer

  • Stateless proxies that handle client connections and request routing

Compute Layer

  • Query Nodes: Execute search operations
  • Data Nodes: Handle data ingestion and compaction
  • Index Nodes: Build and maintain vector indexes

Coordination Layer

  • Root Coordinator: Manages global metadata
  • Query Coordinator: Orchestrates query execution
  • Data Coordinator: Manages data distribution
  • Index Coordinator: Oversees index building

Storage Layer

  • Metadata Storage (ETCD): Cluster metadata and configuration
  • Object Storage (MinIO/S3): Persistent vector data storage
  • Log Storage (Pulsar): Message queue for change data capture

Prerequisites

    Before proceeding, ensure the following:

    • Environment Setup:
      • A Kubernetes cluster is up and running.
      • The kubectl CLI tool is configured to communicate with your cluster.
      • KubeBlocks CLI and KubeBlocks Operator are installed. Follow the installation instructions here.
    • Namespace Preparation: To keep resources isolated, create a dedicated namespace for this tutorial:
    kubectl create ns demo namespace/demo created

    Deploying the Milvus Cluster

    Step 1. Deploy an ETCD Cluster

    ETCD cluster is for metadata storage

    apiVersion: apps.kubeblocks.io/v1 kind: Cluster metadata: name: etcdm-cluster namespace: demo spec: terminationPolicy: WipeOut componentSpecs: - name: etcd componentDef: etcd-3-1.0.0 serviceVersion: 3.5.6 replicas: 1 resources: limits: cpu: '0.5' memory: 0.5Gi requests: cpu: '0.5' memory: 0.5Gi volumeClaimTemplates: - name: data spec: storageClassName: "" accessModes: - ReadWriteOnce resources: requests: storage: 20Gi

    Step 2. Deploy a minio Cluster

    Minio is for object storage

    apiVersion: apps.kubeblocks.io/v1 kind: Cluster metadata: name: miniom-cluster namespace: demo spec: terminationPolicy: WipeOut componentSpecs: - name: minio componentDef: milvus-minio-1.0.0 replicas: 1 resources: limits: cpu: '0.5' memory: 0.5Gi requests: cpu: '0.5' memory: 0.5Gi volumeClaimTemplates: - name: data spec: accessModes: - ReadWriteOnce resources: requests: storage: 20Gi

    Step 3. Deploy a Pulsar Cluster

    Pulsar is for log storage

    apiVersion: apps.kubeblocks.io/v1 kind: Cluster metadata: name: pulsarm-cluster namespace: demo spec: terminationPolicy: Delete # The value must be `pulsar` to create a Pulsar Cluster clusterDef: pulsar topology: pulsar-basic-cluster services: - name: broker-bootstrap serviceName: broker-bootstrap componentSelector: broker spec: type: ClusterIP ports: - name: pulsar port: 6650 targetPort: 6650 - name: http port: 80 targetPort: 8080 - name: kafka-client port: 9092 targetPort: 9092 - name: zookeeper serviceName: zookeeper componentSelector: zookeeper spec: type: ClusterIP ports: - name: client port: 2181 targetPort: 2181 componentSpecs: - name: broker serviceVersion: 3.0.2 replicas: 1 env: - name: KB_PULSAR_BROKER_NODEPORT value: "false" resources: limits: cpu: "1" memory: "512Mi" requests: cpu: "200m" memory: "512Mi" - name: bookies serviceVersion: 3.0.2 replicas: 4 resources: limits: cpu: "1" memory: "512Mi" requests: cpu: "200m" memory: "512Mi" volumeClaimTemplates: - name: ledgers spec: accessModes: - ReadWriteOnce resources: requests: storage: 8Gi - name: journal spec: accessModes: - ReadWriteOnce resources: requests: storage: 8Gi - name: zookeeper serviceVersion: 3.0.2 replicas: 1 resources: limits: cpu: "1" memory: "512Mi" requests: cpu: "100m" memory: "512Mi" volumeClaimTemplates: - name: data spec: accessModes: - ReadWriteOnce resources: requests: storage: 8Gi

    Deploy a Milvus Cluster

    The cluster will be created with the following components:

    • Proxy
    • Data Node
    • Index Node
    • Query Node
    • Mixed Coordinator

    And each component will be created with serviceRef to the corresponding service: etcd, minio, and pulsar created previously.

    apiVersion: apps.kubeblocks.io/v1 kind: Cluster metadata: namespace: demo name: milvus-cluster spec: terminationPolicy: Delete # The value must be `milvus` to create a Milvus Cluster clusterDef: milvus # Valid options are: [standalone,cluster] topology: cluster componentSpecs: - name: proxy replicas: 1 resources: limits: cpu: "0.5" memory: "0.5Gi" requests: cpu: "0.5" memory: "0.5Gi" # Defines a list of ServiceRef for a Component serviceRefs: - name: milvus-meta-storage # Specifies the identifier of the service reference declaration, defined in `componentDefinition.spec.serviceRefDeclarations[*].name` namespace: demo # namepspace of referee cluster, update on demand # References a service provided by another KubeBlocks Cluster clusterServiceSelector: cluster: etcdm-cluster # ETCD Cluster Name, update the cluster name on demand service: component: etcd # component name, should be etcd service: headless # Refer to default headless Service port: client # Refer to port name 'client' - name: milvus-log-storage namespace: demo clusterServiceSelector: cluster: pulsarm-cluster # Pulsar Cluster Name service: component: broker service: headless port: pulsar - name: milvus-object-storage namespace: demo clusterServiceSelector: cluster: miniom-cluster # Minio Cluster Name service: component: minio service: headless port: http credential: # Specifies the SystemAccount to authenticate and establish a connection with the referenced Cluster. component: minio # for component 'minio' name: admin # the name of the credential (SystemAccount) to reference, using account 'admin' in this case - name: mixcoord replicas: 1 resources: limits: cpu: "0.5" memory: "0.5Gi" requests: cpu: "0.5" memory: "0.5Gi" serviceRefs: - name: milvus-meta-storage namespace: demo clusterServiceSelector: cluster: etcdm-cluster service: component: etcd service: headless port: client - name: milvus-log-storage namespace: demo clusterServiceSelector: cluster: pulsarm-cluster service: component: broker service: headless port: pulsar - name: milvus-object-storage namespace: demo clusterServiceSelector: cluster: miniom-cluster service: component: minio service: headless port: http credential: component: minio name: admin - name: datanode replicas: 1 resources: limits: cpu: "0.5" memory: "0.5Gi" requests: cpu: "0.5" memory: "0.5Gi" serviceRefs: - name: milvus-meta-storage namespace: demo clusterServiceSelector: cluster: etcdm-cluster service: component: etcd service: headless port: client - name: milvus-log-storage namespace: demo clusterServiceSelector: cluster: pulsarm-cluster service: component: broker service: headless port: pulsar - name: milvus-object-storage namespace: demo clusterServiceSelector: cluster: miniom-cluster service: component: minio service: headless port: http credential: component: minio name: admin - name: indexnode replicas: 1 resources: limits: cpu: "0.5" memory: "0.5Gi" requests: cpu: "0.5" memory: "0.5Gi" serviceRefs: - name: milvus-meta-storage namespace: demo clusterServiceSelector: cluster: etcdm-cluster service: component: etcd service: headless port: client - name: milvus-log-storage namespace: demo clusterServiceSelector: cluster: pulsarm-cluster service: component: broker service: headless port: pulsar - name: milvus-object-storage namespace: demo clusterServiceSelector: cluster: miniom-cluster service: component: minio service: headless port: http credential: component: minio name: admin - name: querynode replicas: 2 resources: limits: cpu: "0.5" memory: "0.5Gi" requests: cpu: "0.5" memory: "0.5Gi" serviceRefs: - name: milvus-meta-storage namespace: demo clusterServiceSelector: cluster: etcdm-cluster service: component: etcd service: headless port: client - name: milvus-log-storage namespace: demo clusterServiceSelector: cluster: pulsarm-cluster service: component: broker service: headless port: pulsar - name: milvus-object-storage namespace: demo clusterServiceSelector: cluster: miniom-cluster service: component: minio service: headless port: http credential: component: minio name: admin
    NOTE

    Clusters, such as Pulsar, Minio and ETCD, have multiple ports for different services. When creating Cluster with serviceRef, you should know which port providing corresponding services. For instance, in MinIO, there are mainly four ports: 9000, 9001, 3501, and 3502, and they are used for different services or functions.

    Service References are specified using serviceRefs as follows, please update cluster names and ports accordingly w.r.t your running environment.

    # Defines a list of ServiceRef for a Component serviceRefs: - name: milvus-meta-storage # Specifies the identifier of the service reference declaration, defined in `componentDefinition.spec.serviceRefDeclarations[*].name` namespace: demo # namepspace of referee cluster, update on demand # References a service provided by another KubeBlocks Cluster clusterServiceSelector: cluster: etcdm-cluster # ETCD Cluster Name, update the cluster name on demand service: component: etcd # component name, should be etcd service: headless # Refer to default headless Service port: client # NOTE: Refer to port name 'client', for port number '3501' - name: milvus-log-storage namespace: demo clusterServiceSelector: cluster: pulsarm-cluster # Pulsar Cluster Name service: component: broker service: headless port: pulsar # NOTE: Refer to port name 'pulsar', for port number '6650' - name: milvus-object-storage namespace: demo clusterServiceSelector: cluster: miniom-cluster # Minio Cluster Name service: component: minio service: headless port: http # NOTE: Refer to port name 'http', for port number '9000' credential: # Specifies the SystemAccount to authenticate and establish a connection with the referenced Cluster. component: minio # for component 'minio' name: admin # NOTE: the name of the credential (SystemAccount) to reference, using account 'admin' in this case

    Verifying the Deployment

    Check the Cluster Status

    Once the cluster is deployed, check its status:

    kubectl get cluster milvus-cluster -n demo -w

    Expected Output:

    NAME CLUSTER-DEFINITION TERMINATION-POLICY STATUS AGE milvus-cluster milvus Delete Running 4m38s

    Verify Component and Pod Status

    kubectl get component -l app.kubernetes.io/instance=milvus-cluster -n demo

    Expected Output:

    NAME DEFINITION SERVICE-VERSION STATUS AGE milvus-cluster-datanode milvus-datanode-1.0.0 v2.3.2 Running 5m8s milvus-cluster-indexnode milvus-indexnode-1.0.0 v2.3.2 Running 5m8s milvus-cluster-mixcoord milvus-mixcoord-1.0.0 v2.3.2 Running 5m8s milvus-cluster-proxy milvus-proxy-1.0.0 v2.3.2 Running 5m8s milvus-cluster-querynode milvus-querynode-1.0.0 v2.3.2 Running 5m8s

    Check pods:

    kubectl get pods -l app.kubernetes.io/instance=milvus-cluster -n demo

    Expected Output:

    NAME READY STATUS RESTARTS AGE milvus-cluster-datanode-0 1/1 Running 0 5m30s milvus-cluster-indexnode-0 1/1 Running 0 5m31s milvus-cluster-mixcoord-0 1/1 Running 0 5m32s milvus-cluster-proxy-0 1/1 Running 0 5m32s milvus-cluster-querynode-0 1/1 Running 0 5m31s milvus-cluster-querynode-1 1/1 Running 0 3m51s

    Cleanup

    To remove all resources created during this tutorial:

    kubectl delete cluster milvus-cluster -n demo kubectl delete cluster etcdm-cluster -n demo kubectl delete cluster miniom-cluster -n demo kubectl delete cluster pulsarm--cluster -n demo kubectl delete ns demo

    © 2025 ApeCloud PTE. Ltd.