milvus/deploy
sunyaofei 1d6668156c
use envoy and headless service to get `low latency、high throughput` support (#4544)
* init deploy

Signed-off-by: sunyaofei <sunyaofei@ke.com>

* deploy with envoy

Signed-off-by: sunyaofei <sunyaofei@ke.com>

* fix markdown format issues

Signed-off-by: sunyaofei <sunyaofei@ke.com>

* configuration piece error fix

Signed-off-by: sunyaofei <sunyaofei@ke.com>

Co-authored-by: sunyaofei <sunyaofei@ke.com>
2021-01-06 03:52:37 +00:00
..
kubernetes use envoy and headless service to get `low latency、high throughput` support (#4544) 2021-01-06 03:52:37 +00:00
storage use envoy and headless service to get `low latency、high throughput` support (#4544) 2021-01-06 03:52:37 +00:00
README.md use envoy and headless service to get `low latency、high throughput` support (#4544) 2021-01-06 03:52:37 +00:00

README.md

A solution to achive low latency and high throughput

We can get from Mishards milvus can be deployed with Mishards as cluster to support massive-scale(10 billion, 100 billion or even larger datasets). However, when it comes to case that datasets is limited(say, millions or tens million) and low latency、high throughput is required, Mishards cannot handle it. Here, we give a proposal to solve the problem above in production environment based on envoy.

How to

Under kubernetes, we can use kubectl to handle resources

Step 1: Docker and Kubernetes environment

If no Docker and Kubernetes environment available, you can build one with docker and Highly Available Kubernetes clusters as reference.

Step 2: Distributed file system

Milvus cluster relys on Distributed file system to hold data. We can know from Storge Classes, kubernetes support plenty of plugins to communicate with specific storage engine(such as CephFs、AWS EBS、Azure Disk、GCE PD、Glusterfs ...)

If one Distributed file system is already available, this step can be skipped, otherwise, GlusterFs can be a option, and we can deploy it following gluster-kubernetes

After we deployed glusterfs, we can create StorageClass following glusterfs StorageClass. To be brief, we can create StorageClass from storageclass.yaml

kubectl apply -f storage/storageclass.yaml

Step 3: Namespace

We can create a Namespace for isolation, and all the resource created will be within this namespace(if we need more Milvus cluster, we can create more namespace).

kubectl apply -f kubernetes/milvus_namespace.yaml

What is important to keep in mind is that StorageClass created in step 2 can be used across namespaces.

Step 4: PVC

Based on StorageClass from step 2, we can create PVC from milvus_pvc.yaml. Pvcs will be mounted to mysql、envoy、milvus in the following steps.

kubectl apply -f kubernetes/milvus_pvc.yaml

Step 5. Configmap

Configmap can be used to store all the configurations to be used in the following steps.

kubectl apply -f kubernetes/configmap/*

Step 6: Mysql

Milvus use mysql to support cluster deployment. From Deploying MySQL Server with Docker we known, mysql server can deploy with docker and we can create mysql service from milvus_mysql.yaml.

kubectl apply -f kubernetes/milvus_mysql.yaml

Step 7: Milvus rw/ro

Following milvus_rw_servers.yaml and milvus_ro_servers.yaml, we can create milvus rw、ro services.

Step 8: envoy

The last but the most.

Envoy is an open source edge and service proxy, designed for cloud-native application, we can use envoy to distinguish milvus read/write and get scalability when high throughput is required. We can create envoy following envoy_proxy.yaml

kubectl apply -f kubernetes/envoy_proxy.yaml

Milvus read/write can be distinguished following configuration piece in envoy-configmap.yaml as below:

... ...
                  domains:
                  - "*"
                  routes:
                  - match:
                      prefix: "/milvus.grpc.MilvusService/Search"
                    route:
                      cluster: milvus_backend_ro
                      timeout: 1s
                      priority: HIGH
                  - match:
                      prefix: "/"
                    route:
                      cluster: milvus_backend_rw
                      timeout: 3600s
                      priority: HIGH
... ...  

Milvus can get get scalability following configuration piece in envoy-configmap.yaml and milvus_ro_servers.yaml as below(Headless Service and Strict DNS can help to get scalability when gRPC is used):

envoy-configmap.yaml

... ...
      clusters:
      - name: milvus_backend_ro
        type: STRICT_DNS
        connect_timeout: 1s
        lb_policy: ROUND_ROBIN
        dns_lookup_family: V4_ONLY
        http2_protocol_options: {}
        circuit_breakers:
          thresholds:
            priority: HIGH
            max_pending_requests: 20480
            max_connections: 20480
            max_requests: 20480
            max_retries: 1
        load_assignment:
          cluster_name: milvus_backend_ro
          endpoints:
          - lb_endpoints:
            - endpoint:
                address:
                  socket_address:
                    address: milvus-ro-servers
                    port_value: 19530
                    protocol: TCP
... ...  

milvus_ro_servers.yaml

... ...
kind: Service
apiVersion: v1
metadata:
  name: milvus-ro-servers
  namespace: milvus-demo
spec:
  type: ClusterIP
  clusterIP: None
  selector:
    app: milvus
    tier: ro-servers
  ports:
    - protocol: TCP
      port: 19530
      targetPort: 19530
      name: engine
    - protocol: TCP
      port: 19121
      targetPort: 19121
      name: web
... ...  

Finally, we can access milvus grpc api at port 32000 as configuration piece in envoy_proxy.yaml below:

apiVersion: v1
kind: Service
metadata:
  name: envoy
  namespace: milvus-demo
spec:
  type: NodePort
  ports:
  - port: 80
    targetPort: 80
    nodePort: 32000
  selector:
    app: milvus
    tier: proxy

Extra

Speed up image pulling

To speed up image pulling, a private registry can be deployed, and we can add extra configuration(specifying-imagepullsecrets-on-a-pod) to use it.

Resource assign

Managing Resources for Containers can tells us how memory and cpu usage can be controlled.

Pod schedule

As described in assign-pod-node, we can use NodeSelector and Affinity to control where Milvus pod can be located

Probes

Probes can be used to detect when Milvus pod is ready, when Milvus pod need to be restarted.

DaemonSet vs Deployment

DaemonSet and Deployment are two optional ways to deploy envoy and milvus ro pod.

helm

helm can be used to put all in one just as milvus-helm