Milvus 向量数据库架构手册——以多种方式部署 Milvus

0 阅读19分钟

本章将聚焦于部署 Milvus,也就是让数据库在生产或测试环境中可用,并准备好处理查询。首先,我们需要了解常见部署方式,包括 Docker、Docker Compose、Kubernetes Operator 和 Helm charts 等开源工具。在介绍这些技术的同时,我们会突出它们各自的优势和适用场景,并提供对比分析,帮助进行技术选型。讨论完理论部分后,我们将进入实际操作,分别使用这些方法部署 Milvus。本章覆盖以下内容:

  • 理解常见服务部署方式
  • 通过 Docker Compose 部署 Milvus
  • 通过 Helm charts / operators 部署 Milvus

技术要求

本章重点学习如何使用开源工具部署服务。为了学习本章中的 Milvus 部署方式,你需要安装以下工具:

  • Docker:安装 Docker Compose,可以是独立工具,也可以是插件。在本指南中,我们将使用 Docker Compose v2,它通常直接集成在 Docker Desktop 中,并通过 docker compose 命令访问。如果你使用的是较旧版本 Docker,或者以独立工具形式安装了 Docker Compose,那么命令可能是 docker-compose

如需更详细信息,可以参考 Docker 官方文档:

  • Docker:https://docs.docker.com/get-started/docker-overview/
  • Docker Compose:https://docs.docker.com/compose/

使用以下命令验证安装:

对于独立安装,使用这个命令:

docker --version
docker-compose version

对于插件安装,使用这个命令:

docker --version
docker compose version

还需要安装:

  • Minikube
  • Kubectl
  • Helm

本章使用的代码可以在我们的 GitHub 仓库中找到:

https://github.com/PacktPublishing/The-Architecture-Handbook-for-Milvus-Vector-Database

理解常见服务部署方式

本节中,我们不仅会介绍部署 Milvus 时常用的技术,还会突出它们各自的优势,并提供对比分析,帮助你选择合适工具。

介绍 Docker 和 Docker Compose

Docker 是一个开源平台,用于自动化应用的部署、扩展和管理。它通过容器化方式打包应用及其依赖,使应用能够在不同计算环境中保持一致运行。这让应用交付更高效、更可靠。Docker 中有两个核心概念:containers 和 images。Containers 是轻量、可移植的运行时环境,包含应用及其所有依赖。与传统虚拟机相比,容器共享宿主机操作系统内核,因此启动速度更快。Images 则是用于创建容器的只读模板。它们允许打包应用及其环境,便于分发和版本控制。这类似于编程中的类和对象概念:类作为模板,对象是类的实例化结果。

如果想进一步了解 Docker containers,可以参考这个资源:

https://www.docker.com/blog/containers-are-not-vms/

此外,在使用 Docker 时,你经常会遇到 Dockerfiles 和 Docker Hub。Dockerfile 是一个文本文件,包含构建 images 的指令,使用户能够定义应用环境和依赖。Docker Hub 是一个公共容器镜像仓库,用户可以上传和下载 images,使共享和管理更方便。许多公司也会搭建自己的私有 Docker 镜像仓库,以提供更快的上传和下载速度,并进行内部镜像测试。

Docker 有许多优势,包括:

  • 一致性:由于容器封装所有依赖,应用在开发、测试和生产环境中的行为保持一致,减少 “it works on my machine” 问题。
  • 轻量级:容器共享宿主机内核,启动时间只有几秒,相比传统虚拟机显著降低资源使用。
  • 可移植性:容器可以在任何支持 Docker 的环境中运行,包括本地开发环境、私有数据中心和公有云。
  • 可扩展性:Docker 支持应用快速扩容或缩容,使其更容易响应流量波动和负载需求。
  • 微服务架构:Docker 非常适合微服务架构,可以将应用拆分成多个可独立部署的服务。

Docker 有多种使用场景,例如应用开发和测试、微服务部署、持续集成和持续交付(CI/CD),以及跨多云环境的统一管理。通过简化开发、交付和部署流程,Docker 提升了开发效率和系统稳定性,已成为现代软件开发中的重要工具。

介绍 Docker Compose

在复杂应用系统中,通常会依赖各种第三方服务,例如消息服务、键值存储和缓存服务。这意味着只有这些第三方服务正常运行时,我们的应用服务才能成功启动。Docker Compose 是一个允许用户定义并运行多容器 Docker 应用的工具。借助 Compose,用户可以使用 YAML 文件配置应用服务、网络和 volumes,从而简化多容器环境的管理和部署。通过几个简单命令,就可以快速启动或停止应用中的所有服务。例如,可以使用 docker-compose up 启动服务,使用 docker-compose down 停止服务。

Docker Compose 有很多好处:

  • 快速开发:开发者可以快速搭建和测试应用的多个组件,而无需手动管理每个容器。
  • 可复现性:通过配置文件,应用的部署和运行环境可以在不同机器上保持一致,减少环境相关问题。
  • 易于扩展:添加或移除服务非常直接,使应用扩展变得容易。
  • 集成测试:它非常适合集成测试,可以在同一环境中测试多个服务之间的交互。

目前,单独使用 Docker 已经不那么常见;它通常与 Compose 搭配,用来定义和运行多个 Docker 容器。你可能会注意到两种命令格式:有时是 docker-compose,有时是 docker compose。这种区别来自两种安装方式:

  • 一种是独立安装,命令是 docker-compose,它独立于 Docker 运行。值得注意的是,这种方式已经被弃用,请使用另一种方式。
  • 另一种是作为插件安装,命令是 docker compose,它作为 Docker 的子命令运行。

接下来,我们将了解 Kubernetes operator。

介绍 Kubernetes operator

Kubernetes,有时称为 K8s,是一个开源容器编排平台,用于自动化容器化应用的部署、扩展和管理。它会将组成应用的容器分组为逻辑单元,便于管理和发现。

在 Kubernetes 中,Operator 是一个使用 Kubernetes Custom Resources 安装和管理应用的 controller。为了更好理解这个定义,我们拆解两个关键词:controller 和 custom resource。

Kubernetes 中的 controller 是一个例程,会监控 Kubernetes 配置的期望状态,以及集群资源的实际状态。当它检测到期望状态和实际状态不一致时,无论这种差异来自管理变更还是内部故障,controller 都会尝试调和它们。例如,如果部署了一个描述应用期望状态的配置,controller 会识别该配置并应用它,前提是它符合 Kubernetes cluster 的整体状态。Kubernetes cluster 是一组由 Kubernetes 管理的节点,也就是运行容器化应用和工作负载的 worker machines。

Kubernetes 中的 custom resources 是 Kubernetes API 的扩展,允许你添加默认情况下不可用的功能。这是通过创建 custom resource definition(CRD)实现的。如果你想使用 Kubernetes Operator 安装或管理一个应用,可以创建一个体现该应用所需功能的 CRD。当 CRD 与 Operator 的 controller 结合后,Kubernetes controller 例程会检测并相应部署它。

Operators 可以帮助自动化复杂应用管理任务,使在 Kubernetes 环境中部署和维护应用更加容易。

Kubernetes 的一些关键特性包括:

  • 容器编排:Kubernetes 可以自动部署和管理数千个容器,确保它们在集群中无缝运行。
  • 负载均衡:它会自动分发流量,以保持应用可用性和性能。
  • 自愈能力:如果容器失败,Kubernetes 会自动重启或替换它,以确保应用持续运行。
  • 滚动更新:该功能允许无缝更新应用,确保用户在更新过程中不受影响。
  • 服务发现和负载均衡:Kubernetes 会自动为容器分配 IP 地址,并提供 DNS 名称用于容器之间通信。
  • 存储编排:它可以自动挂载各种存储系统,包括本地存储和云存储。

介绍 Helm charts

Helm chart 是一种包格式,包含在 Kubernetes 上部署应用所需的资源,这些资源被封装在所谓的 chart 中。Helm 是 Kubernetes 的包管理和配置管理工具,使用户能够轻松安装 Helm charts。

Helm charts 和 Helm 包管理器,类似于 Ubuntu 上的 Debian packages 和 apt-get,或者 Red Hat 上的 RPM packages 和 DNF。但有一个关键区别:不同于操作系统应用包,Helm charts 通常不包含应用二进制文件。相反,它们包含指向部署应用所需 container images 或 images 的文件。

使用 Helm charts 可以简化在 Kubernetes 中部署和管理应用的流程,使定义、安装和升级复杂应用可以通过单个命令完成。

Helm charts 和 operators 是两种依赖 Kubernetes 的部署方法。

当你希望本地测试尽可能简单时,可以使用 docker compose。对于运维,你可能会更多处理 Helm,因为它提供了更强可扩展性,例如资源扩缩容,而这对线上业务更关键。

接下来,我们看看 Helm charts 和 Kubernetes 部署方式有何不同。

对比 Helm charts 和 Kubernetes operators

Docker Compose 是最简单的部署方式。它通常用于开发和测试。它缺少资源控制能力,也就是说,它只能安装应用。相比之下,Helm charts 和 Kubernetes operators 都可以安装和管理应用。

我们将重点在下面的表格中比较后两者:

FeaturesHelm chartKubernetes operator
Scope and functionality范围更窄:其主要目的是安装能够基于现有 container images 运行的标准应用。配置选项有限:你可以在安装时传递参数来自定义应用,但前提是该 chart 被设计为支持这些参数。通过编写代码提供更强的自定义能力,几乎允许在应用部署中实现无限制的自定义逻辑。
Complexity and flexibility更容易创建:你可以使用相对直接的 YAML 代码构建 Helm chart。安装也不复杂,因为可以用单个命令安装 chart。虽然提供更高灵活性,但 Operators 本身更复杂。创建 Operator 需要编写 CRD,安装过程通常涉及更长的 kubectl 命令。
Automation自动化原本需要手工完成的应用安装和管理任务。但 Helm 的自动化能力仅限于管理标准应用。虽然可以基于 container images 自动安装或更新应用,但无法超出 Helm 内置功能自动化自定义配置变更。自动化应用安装和管理任务,并可以自动化 Kubernetes API 和 controllers 支持的任何操作,因此更适合复杂部署。
Lifecycle management支持应用生命周期管理,包括安装、更新和删除。你可以使用 installupgradeuninstall 等内置命令管理应用生命周期。可以用新版本替换旧版本,或完全移除应用。与 Helm charts 一样,也很好支持生命周期管理。不同之处在于,修改应用的 Operator 可以进行更细粒度调整,从而对应用生命周期提供更详细控制。

表 2.1:Helm chart 与 Kubernetes operator 特性对比

总之,在 Helm charts 和 Kubernetes Operators 之间选择,取决于你在 Kubernetes 环境中部署和管理应用时,对灵活性、复杂度和自动化程度的具体需求。

现在你已经对常见部署方式有了一些了解。接下来开始实践。

部署 Milvus

部署 Milvus 时,我们将先关注 Docker Compose 部署,因为它相对简单。你不需要马上走完 Milvus 的两种部署选项;可以选择你觉得更容易学习的方法。之后如果你需要使用某种具体方式,也可以随时回到本节作为复习或参考。

使用 Docker Compose 部署 Milvus

使用 Docker Compose 可以简化 Milvus 等服务的部署,更方便实验和理解其功能。单独使用 Docker 部署可能很笨重且不实用,因此 Docker Compose 是测试和学习时更推荐的方法。

按照以下步骤使用 Docker Compose 部署 Milvus:

  1. 打开浏览器,访问以下链接下载 Milvus Docker Compose 文件:
https://github.com/milvus-io/milvus/releases/download/v2.4.17/milvus-standalone-docker-compose.yml

2. 将这个 YAML 文件保存到本地机器上的一个空目录中,并将 milvus-standalone-docker-compose.yaml 文件重命名为 docker-compose.yaml。 3. 打开终端,并进入保存 docker-compose.yaml 文件的目录。 4. 根据你的安装方式,使用以下命令之一启动服务。

对于独立安装方式(该安装方式已被弃用,请使用另一种方式):

# Start the Docker service
docker-compose up -d

对于插件安装方式:

# Start the Docker service
docker compose up -d

接下来,我们需要通过向 Milvus 发送请求,验证服务是否正常。这里我们使用 curl 命令向 Milvus 发送 POST 请求。当然,你也可以使用其他 UI 工具,例如 Postman。需要注意的是,POST 的 body 必须是 JSON 字符串:

# Get the collection list to see if the milvus service is normal

curl -X POST http://localhost:19530/v2/vectordb/collections/list -d '{}' -H "Content-Type: application/json"

如果请求结果返回正常 JSON 且没有异常,就表示 Milvus 已经部署完成。

{
    "code":0,"data":[] 
}

要停止 Milvus 及其相关服务,请根据你的安装方式使用以下命令:

对于独立安装方式(该方式已被弃用,请使用另一种方式):

# Stop the Docker service
docker-compose down

对于插件安装方式:

# Stop the Docker service
docker compose down

现在,让我们继续进入 Milvus 的 Kubernetes 部署。

通过 Kubernetes 部署 Milvus

本地 Kubernetes 部署有很多方法。常见本地 Kubernetes 部署方式如下:

  • Minikube:一个可以在本地机器上快速运行单节点 Kubernetes 集群的工具,支持各种虚拟化驱动,例如 VirtualBox、VMware。
  • kind:Kubernetes in Docker(kind)允许在 Docker 容器中运行 Kubernetes 集群,非常适合开发和测试环境。
  • K3s:一个轻量 Kubernetes 发行版,适合资源受限设备或本地开发环境。
  • Docker Desktop:对于使用 Docker Desktop 的用户,可以通过设置启用 Kubernetes 支持。
  • 手动安装:你也可以使用 kubeadm 等工具,在物理机或虚拟机上手动安装 Kubernetes。

接下来的部署中,我们将使用 Minikube 在本地设置 Kubernetes。首先,你需要安装 Minikube。详细安装步骤请参考 Minikube 文档中的 Minikube start 页面:

https://minikube.sigs.k8s.io/docs/start

安装完成后,可以运行以下命令验证:

minikube version

使用 operators 部署 Milvus

Milvus Operator 在 Kubernetes custom resources 之上定义 Milvus cluster custom resources,以确保其可扩展性和高可用性。下面开始使用它部署 Milvus。

开始之前,我们需要启动 Minikube。可以使用以下命令:

minikube start --driver=docker

然后需要安装 cert-manager,因为 Milvus Operator 使用它为 webhook server 提供证书。运行以下命令:

kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.5.3/cert-manager.yaml

该命令完成后,检查 pods 状态以验证安装:

kubectl get pods -n cert-manager

如果所有 pods 都处于 Running 状态,说明安装成功。

接下来安装 Milvus Operator:

kubectl apply -f https://raw.githubusercontent.com/zilliztech/milvus-operator/main/deploy/manifests/deployment.yaml

执行该命令后,再次检查 pod 状态:

kubectl get pods -n milvus-operator

如果所有 pods 都处于 Running 状态,说明安装成功。

现在,我们可以使用 Milvus Operator pod 部署 Milvus。创建一个名为 demo_operator.yaml 的文件。

你可以在本书官方仓库中找到该文件:

https://github.com/PacktPublishing/The-Architecture-Handbook-for-Milvus-Vector-Database/blob/main/ch2/demo_operator.yaml
# This is a sample to deploy a milvus cluster in milvus-operator's default configurations.
apiVersion: milvus.io/v1beta1
kind: Milvus
metadata:
  name: my-release
  labels:
    app: milvus
spec:
  config: {}
  components:
    image: milvusdb/milvus:v2.4.17
    standalone:
      replicas: 1
      serviceType: LoadBalancer
  dependencies:
    msgStreamType: "rocksmq" # or "pulsar"
    etcd:
      inCluster:
        values:
          replicaCount: 1
        deletionPolicy: Delete
        pvcDeletion: true
    storage:
      inCluster:
        values:
          resources:
            requests:
              memory: 100Mi
          persistence:
              size: 20Gi
        deletionPolicy: Delete
        pvcDeletion: true

执行以下命令:

kubectl apply -f demo_operator.yaml

运行该命令后,检查 Milvus cluster 状态:

>>kubectl get milvus my-release -o yaml
{
  ...
  "updatedReplicas": 1
  },
  "conditions": [
    {
      "lastTransitionTime": "2024-12-18T03:33:17Z",
      "message": "All Milvus components are healthy",
      "reason": "ReasonMilvusHealthy",
      "status": "True",
      "type": "MilvusReady"
    },
    {
      "lastTransitionTime": "2024-12-18T03:33:17Z",
      "message": "Milvus components are all updated",
      "reason": "MilvusComponentsUpdated",
      "status": "True",
      "type": "MilvusUpdated"
    },
    {
      "lastTransitionTime": "2024-12-18T03:32:53Z",
      "message": "Etcd endpoints is healthy",
      "reason": "EtcdReady",
      "status": "True",
      "type": "EtcdReady"
    },
    {
      "lastTransitionTime": "2024-12-18T03:32:53Z",
      "reason": "StorageReady",
      "status": "True",
      "type": "StorageReady"
    },
    {
      "lastTransitionTime": "2024-12-18T03:32:53Z",
      "reason": "MsgStreamReady",
      "status": "True",
      "type": "MsgStreamReady"
    }
  ],
  "ingress": {
    "loadBalancer": {}
  },
  "observedGeneration": 3,
  "rollingModeVersion": 2,
  "status": "Healthy"
}

当你的 Milvus cluster 就绪后,status 字段应该是 Healthy。如果它仍然是 UnhealthyPending,则说明你的 Milvus cluster 仍在创建中。

你也可以使用以下命令检查所有 Milvus 服务和相关服务的状态。名称中包含 init 的 pods 状态应为 Completed,其他所有 pods 应处于 Running 状态:

kubectl get pods
NAME                             READY   STATUS    RESTARTS   AGE
my-release-etcd-0                 1/1     Running   0         8m39s
my-release-milvus-standalone-5b554989df-4rlb5 1/1 Running  0  8m28s
my-release-minio-697b74df-98lqj   1/1     Running   0       8m39s

要找到 Milvus cluster 提供服务的端口,请运行以下命令:

你应该将 pod 名称替换为上一步输出中的实际名称。

# Replace the pod name in this command with the actual name of your own pod
kubectl get pod my-release-milvus-standalone-5b554989df-4rlb5 --template='{{(index (index .spec.containers 0).ports 0).containerPort}}{{"\n"}}'

输出会表明 Milvus 实例在默认端口 19530 上提供服务。

然后运行以下命令,将本地端口转发到 Milvus 服务:

# Replace the pod name in this command with the actual name of your own pod
kubectl port-forward my-release-milvus-standalone-5b554989df-4rlb5  :19530

最后,我们通过向 Milvus 发送请求,验证服务是否正常。为此,请按照 “使用 Docker Compose 部署 Milvus” 部分中的第 5 步执行:

curl -X POST http://localhost:19530/v2/vectordb/collections/list -d '{}' -H "Content-Type: application/json"

如果请求结果返回正常 JSON 且无异常,就表示 Milvus 已成功部署:

{"code":0,"data":[]}

如果你想卸载 Milvus,请使用以下命令:

kubectl delete –f demo_operator.yaml

接下来看看如何使用 Helm charts 部署。

使用 Helm charts 部署 Milvus

开始之前,我们需要准备运行环境。

安装 Helm CLI 工具:如果你使用 Mac,可以用以下命令安装:

brew install helm

如果使用其他操作系统,安装也很直接。详细步骤请参考官网:

https://helm.sh/docs/intro/install/

创建 Kubernetes cluster:前一节已经介绍过。安装 Helm 后,可以使用以下命令启动 cluster:

minikube start

另外,还需要安装 kubectl 命令行工具。如果你使用 Mac,使用以下命令:

brew install kubectl

对于其他操作系统,安装也很容易。更多信息可以在这里找到:

https://kubernetes.io/docs/tasks/tools/

启动 cluster 后,使用以下命令验证其状态:

kubectl cluster-info

安装 Milvus Helm charts 之前,需要添加 Milvus Helm repository:

helm repo add milvus https://zilliztech.github.io/milvus-helm/

然后,从 repository 获取或更新 Milvus charts:

helm repo update

接下来开始部署 Milvus。步骤如下:

先使用以下命令启动部署,但暂时不要执行:

helm install my-release milvus/milvus --set cluster.enabled=false --set etcd.replicaCount=1  --version 4.2.25

我们先理解这些参数含义。在该命令中,my-release 是 release name,你可以将 my-release 替换为自己选择的名称。为了避免潜在冲突,尤其是当你在实验或运行多个部署时,建议自定义该名称以确保唯一性,例如 my-release-yourname

milvus/milvus 表示 chart repository。cluster.enable 表示部署的 Milvus 处于 standalone mode,etcd.replicaCount 表示 etcd 也是 standalone,而不是多个副本;version 表示使用的 Milvus Helm chart 版本,其中 4.2.25 对应 Milvus 2.4.17。

要检查 Milvus cluster 中所有 pods 的状态,请运行:

kubectl get pods

如果所有 pods 都处于 Running 状态,除了 pulsar-zookeeper-metadata pod,则表示一切运行正常。

kubectl get pods -o wide
NAME                                          READY   STATUS    RESTARTS        AGE     IP          NODE       NOMINATED NODE   READINESS GATES
my-release-etcd-0                             1/1     Running   0               3m46s   172.17.0.8  minikube   <none>           <none>
my-release-milvus-standalone-59565d99d-jq4v8   1/1     Running   2 (3m22s ago)  3m46s   172.17.0.4  minikube   <none>           <none>
my-release-minio-0                            1/1     Running   0               3m46s   172.17.0.3  minikube   <none>           <none>
my-release-minio-1                            1/1     Running   0               3m46s   172.17.0.5  minikube   <none>           <none>
my-release-minio-2                            1/1     Running   0               3m46s   172.17.0.7  minikube   <none>           <none>
my-release-minio-3                            1/1     Running   0               3m46s   172.17.0.6  minikube   <none>           <none>

屏幕上的输出效果如下:

image.png

图 2.1:Milvus 健康 pod 状态

要找到 Milvus cluster 提供服务的端口,请使用以下命令。注意,你应该将该命令中的 pod 名称替换为上一步获得的名称:

# Replace the pod name in this command with the actual name of your own pod
kubectl get pod my-release-milvus-proxy-6bd7f5587-ds2xv --template='{{(index (index .spec.containers 0).ports 0).containerPort}}{{"\n"}}'

输出会表明 Milvus 实例在默认端口 19530 上提供服务。然后,运行以下命令将本地端口转发到 Milvus:

# Replace the pod name in this command with the actual name of your own pod
kubectl port-forward my-release-milvus-standalone-59565d99d-jq4v8 :19530

你需要使用自己的 pod 名称。

此外,执行该命令时,它会一直占用终端,不会返回命令提示符。因此,我们需要新建一个终端窗口来验证 Milvus 状态:

# Replace the pod name in this command with the actual name of your own pod
>>kubectl port-forward my-release-milvus-standalone-59565d99d-jq4v8 :19530

Forwarding from 127.0.0.1:63897 -> 19530
Forwarding from [::1]:63897 -> 19530

最后,我们通过向 Milvus 发送请求验证服务是否正常。为此,请按照 “使用 Docker Compose 部署 Milvus” 部分中的第 5 步执行:

curl -X POST http://localhost:19530/v2/vectordb/collections/list -d '{}' -H "Content-Type: application/json"

如果请求结果返回正常 JSON 且没有异常,就表示 Milvus 已经部署完成:

{"code":0,"data":[]}

如果你想卸载 Milvus,请使用以下命令:

helm uninstall my-release
kubectl delete milvus my-release

至此,部署完成。

小结

本章中,我们探索了 Milvus 的多种常见部署方式,包括 Docker Compose、Helm chart 和 Kubernetes operators。我们学习了它们的基本功能和特性,进行了简单功能对比,然后逐一使用它们部署了 Milvus。现在你已经理解这些方法,可以针对不同应用场景选择最合适的部署方式。例如,如果只是需要在本地测试某些功能,Docker Compose 是一个不错选择。如果不需要资源自定义,Helm chart 是简单快速的选择。然而,如果需要对资源进行更细粒度控制,那么 Kubernetes operator 是最佳选择。现在你已经部署了 Milvus,下一章将介绍如何与 Milvus 通信,具体来说,我们会看看如何使用 SDK 发送各种请求。