升级

有三种不同的操作,彼此并不相同:

  • OLM 安装中的 operator 升级。OLM 会替换 operator;你的实例会继续运行。
  • 从 chart 插件 chart-milvus-operator(最后一个版本为 1.3.5)迁移到此 OLM operator。这是一个手动、单向的操作步骤。
  • 升级实例的 Milvus 引擎。你需要更改实例的引擎镜像; 上述两种操作都不会替你完成这项工作。

升级 operator

该 operator 在 OLM channel stable 中提供。如果 Subscription 使用 Automatic 升级策略,OLM 会在该 channel 中有更新版本可用时立即升级 operator。使用 Manual 时,会创建一个 InstallPlan 并等待你批准:在 Marketplace > OperatorHub 中批准, 或使用 kubectl:

kubectl get installplan -A | grep milvus-operator
kubectl -n <operator-namespace> patch installplan <installplan-name> \
  --type merge -p '{"spec":{"approved":true}}'

升级后,请检查新的 ClusterServiceVersion 是否已达到 Succeeded,并且每个 实例是否都恢复为 Healthy:

kubectl get csv -A | grep milvus-operator
kubectl get milvus -A

从 chart 插件迁移 (chart-milvus-operator 1.3.5)

请勿先卸载 chart 插件

chart-milvus-operator 插件会将三个 Milvus CRD 作为其自身 release 的一部分安装。 卸载插件会删除这些 CRD,随后 Kubernetes 会删除所有命名空间中属于这些类型的每个 Milvus 实例。 请按以下给定顺序执行步骤。只有在第 2 节完成并验证后,才能卸载插件。

此操作步骤已在 ACP 4.2.5 上使用 v1.3.10-rc.116 端到端测试:从插件 chart-milvus-operator 1.3.5 迁移到 OLM operator,并使用一个配有集群内 etcd 和 MinIO 的独立 Milvus 实例。未测试的步骤会标注 (未测试)。

1. 范围

  • OLM operator milvus-operator(Alauda Data Services Vector Database E1)支持新 安装。对于已通过 chart-milvus-operator 插件运行 Milvus 的集群(最后一个版本为 1.3.5), 本节介绍的是手动、单向迁移。
    • 从 chart 插件到 OLM operator 没有自动升级路径。
    • 产品不会替你执行或检查这些步骤。
    • 没有任何 chart release 会替你保护 CRD。第 2 节是手动操作步骤。
  • 迁移仅转移 operator。以下内容保持原样,并由新的 operator 接管:
    • 你的 Milvus 实例(Milvus / MilvusCluster 自定义资源);
    • 它们的 PVC 和数据;
    • operator 安装的 etcd / MinIO 依赖项。

顺序(请勿调整):

  1. 将 CRD 从插件的 Helm release 中移除,并进行验证。
  2. 备份。
  3. 卸载 chart 插件。
  4. 安装 OLM operator。
  5. 验证现有 Milvus 实例已被接管。

2. 将 CRD 从插件的 Helm release 中移除

为什么需要此步骤

chart-milvus-operator chart(包括 1.3.5 在内的所有版本)会将三个 CRD (milvuses.milvus.io、milvusclusters.milvus.io、milvusupgrades.milvus.io)作为普通的 Helm 模板安装(由值 installCRDs: true 控制)。

卸载插件会删除 CRD。随后 Kubernetes 会删除所有命名空间中属于这些类型的每个自定义资源:

  • 三个 CRD 都会被删除,每个 Milvus 自定义资源都会被标记为待删除;
  • 平台在插件 HelmRequest 上设置的 captain-keep-resources: "true" 注解 无法阻止这种情况;
  • 该资源随后会等待 operator 的 finalizer。之后处理该资源的任何 operator 都会删除实例,并且根据实例的依赖项 deletionPolicy,还会删除其集群内依赖项及其 PVC。

在 ACP 上不起作用的方法

  • 在插件 release 上使用 helm get manifest / helm upgrade。 平台的 Helm controller 会将插件 release 存储在自己的 releases.app.alauda.io 对象中,而不是 Helm Secret 中。helm CLI 看不到该 release。
  • 编辑已存储的 release 以添加 helm.sh/resource-policy: keep。平台在处理卸载时以及每次重新同步时都会重新渲染 chart,因此编辑会丢失。
  • 只为在线 CRD 添加注解。 卸载操作针对的是 release,而不是在线对象。

可行方法:保留在线 CRD,然后将它们从 release 中移除

Helm 在升级时会删除从 release 中消失的对象,除非在线对象具有 helm.sh/resource-policy: keep。因此:为在线 CRD 添加注解,然后使用 installCRDs: false 升级插件。CRD 会从 release 中移除,但仍保留在集群中,之后卸载时便不会再处理它们。

  1. 查找插件。它的 HelmRequest 和 Application 名称相同:

    kubectl get helmrequests.app.alauda.io -A | grep chart-milvus-operator

    记下名称 <app> 和命名空间 <ns>。以下所有命令都会使用它们。

  2. 为三个在线 CRD 添加注解:

    kubectl annotate crd milvuses.milvus.io milvusclusters.milvus.io milvusupgrades.milvus.io \
      helm.sh/resource-policy=keep --overwrite
  3. 使用 installCRDs: false 升级插件,保留你设置的所有其他值。在控制台中,更新插件的值并添加 installCRDs: false。使用 kubectl:

    v=$(kubectl -n <ns> get application <app> -o jsonpath='{.metadata.annotations.app\.cpaas\.io/chart\.values}')
    new=$(printf '%s' "${v:-{\}}" | jq -c '. + {"installCRDs": false}')
    kubectl -n <ns> annotate application <app> app.cpaas.io/chart.values="$new" --overwrite

    测试中,新值在约 10 秒内到达 HelmRequest,并写入了新的 release 修订版。operator Deployment 继续运行,Milvus pod 均未重启。

  4. 验证。以下三项检查都必须通过:

    # a) the HelmRequest has the new value: prints {"installCRDs":false,...}
    kubectl -n <ns> get helmrequest <app> -o jsonpath='{.spec.values}'; echo
    
    # b) the deployed release no longer contains any CRD: prints 0
    kubectl -n <ns> get releases.app.alauda.io -l name=<app>,status=deployed \
      -o jsonpath='{.items[0].spec.manifestData}' | base64 -d | gunzip \
      | grep -o 'kind: CustomResourceDefinition' | wc -l
    
    # c) the three CRDs still exist and carry the keep annotation: prints keep 3 times
    kubectl get crd milvuses.milvus.io milvusclusters.milvus.io milvusupgrades.milvus.io \
      -o jsonpath='{range .items[*]}{.metadata.annotations.helm\.sh/resource-policy}{"\n"}{end}'

    如果任何一项检查失败,请停止。不要卸载插件。

之后不要将插件的值改回去。之后使用 installCRDs: true 升级会将 CRD 重新放回 release 中。

3. 备份

按上述顺序操作时,迁移不会删除数据,但开始之前仍应进行备份:

  • 对象存储:存放 Milvus 数据的 MinIO / S3 bucket。

  • 元数据:每个 Milvus 实例使用的 etcd 数据。

  • 自定义资源:导出每个 Milvus 自定义资源,以供参考,并在需要时手动重新创建:

    kubectl get milvuses.milvus.io,milvusclusters.milvus.io,milvusupgrades.milvus.io -A -o yaml > milvus-crs-backup.yaml

operator 不提供通用的 Milvus 备份功能。MilvusUpgrade 在版本升级期间创建的元数据备份不能替代完整备份。请使用组织针对对象存储和 etcd 的备份操作步骤。

记录每个实例的镜像和 pod UID,以便在第 6 节检查哪些资源被重新创建:

kubectl get milvus -A -o custom-columns=NS:.metadata.namespace,NAME:.metadata.name,IMAGE:.spec.components.image,RUNASNONROOT:.spec.components.runAsNonRoot,STATUS:.status.status
kubectl get pods -A -l app.kubernetes.io/instance -o custom-columns=NS:.metadata.namespace,POD:.metadata.name,UID:.metadata.uid,RESTARTS:.status.containerStatuses[0].restartCount | grep -E 'etcd|minio|milvus'

4. 卸载 chart 插件

先重复第 2 节中的检查 4b 和 4c。然后在控制台中卸载 chart-milvus-operator 插件。使用 kubectl 时,对应操作为 kubectl -n <ns> delete application <app>。

预期结果:

  • operator Deployment、其 RBAC、HelmRequest 和 release 对象均已删除。
  • 三个 CRD 仍然存在,且没有删除时间戳。
  • 每个 Milvus 自定义资源仍然存在,UID 未变,且没有删除时间戳。
  • 实例的 pod、PVC 和依赖项 release(etcd / MinIO)继续运行。
  • 在第 5 节之前,实例处于非托管状态:operator 不会进行协调、扩缩容或自我修复。请缩短此时间窗口,并且不要在此期间更改自定义资源。

不要同时运行 chart 插件和 OLM operator。 两者会协调相同的资源,而且由于它们运行在不同的命名空间中,leader election 无法协调它们。

5. 安装 OLM operator

5.1 先从 milvuses.milvus.io 中移除 chart 的转换 webhook

chart 的 milvuses.milvus.io CRD 会将其版本转换指向 chart operator 的 webhook service。该 service 已在第 4 节中移除。

当 OLM 接管现有 CRD 时,它会先列出所有版本中的现有自定义资源以进行验证(参见 5.2)。列出 v1alpha1 需要转换 webhook,因此在修复此问题之前,安装计划会卡在 Installing:

error validating existing CRs against new CRD's schema for "milvuses.milvus.io": ...
conversion webhook for milvus.io/v1beta1, Kind=Milvus failed: Post "https://<app>-milvus-operator-webhook-service.<ns>.svc:443/convert?timeout=30s": service ... not found

安装前,请将策略设为 None。OLM bundle 正好提供了此设置:

kubectl get crd milvuses.milvus.io -o jsonpath='{.spec.conversion.strategy}'; echo   # Webhook
kubectl patch crd milvuses.milvus.io --type=json \
  -p '[{"op":"replace","path":"/spec/conversion","value":{"strategy":"None"}}]'

如果你已经开始安装且安装计划卡住,请在此时运行该 patch。OLM 会重试并完成安装(测试中约需 30 秒)。

5.2 安装

按照安装中的说明,从 OperatorHub 安装 milvus-operator,channel 为 stable。它仅支持 AllNamespaces (集群)安装模式。

当 OLM 安装已存在的 CRD 时,它会更新现有 CRD,而不是失败。更新前会:

  1. 根据新 schema 验证所有现有自定义资源;如果任何现有自定义资源未通过验证,则拒绝更新;
  2. 如果新 CRD 删除了现有 CRD 的 status.storedVersions 中列出的版本,则拒绝更新;
  3. 然后使用 bundle 中的定义替换 CRD。

对 Milvus 而言,这意味着:

  • 已存储的版本:bundle 提供 chart 曾提供的所有版本。请在安装前检查当前版本: kubectl get crd milvuses.milvus.io -o jsonpath='{.status.storedVersions}'。
  • Schema:测试中,1.3.5 operator 接受的自定义资源通过了验证。
  • 接管后,三个 CRD 的转换方式均为 None,带有 OLM 标签 (olm.managed: "true"),且不再包含 Helm 元数据(keep 注解和 meta.helm.sh/* 注解均已移除)。无需手动移除任何内容。

如果安装计划在某个 CRD 步骤失败,该 CRD 不会更改,也不会触及任何自定义资源。修复原因后,OLM 会重试;或者执行回滚(第 6 节)。(较早的 CRD 步骤成功后发生部分失败:未测试。)

6. 验证现有实例已被接管

新 operator 会协调所有现有 Milvus 自定义资源。请针对每个实例检查以下内容。

  • 运行状况:kubectl get milvus -A 会在几分钟内再次显示 Healthy。

  • Milvus pod 会滚动更新一次。 新 operator 渲染 Milvus pod 的方式与 1.3.5 operator 略有不同。因此,每个 Milvus Deployment 都会进行一次滚动更新。旧 pod 会持续提供服务,直到新 pod 就绪。

  • etcd 和 MinIO pod 不会重新创建。 与第 3 节记录的 UID 比较。它们会保留原有 UID 和重启次数。

  • 引擎镜像不会更改。spec.components.image 仍指向之前运行的引擎镜像(chart 1.3.5 上为 2.6.7),而不是新 operator 的默认版本 2.6.24。operator 只会向实例合并一次默认值。将引擎升级到 2.6.24 是单独的操作步骤;请参阅升级 Milvus 引擎。

  • 集群内 MinIO 仍为 MinIO。 新实例的集群内对象存储会使用 Silo。现有 MinIO release 不会转换:operator 会继续使用 MinIO chart 和实例自身的值对其进行协调。不会迁移数据。

  • 没有必要时,不会升级 etcd / MinIO。 只有当根据实例 spec 计算出的值与 release 的值不同时,或 release 状态为 Failed、Unknown 或 Uninstalled 时,operator 才会升级依赖项 release。

  • Milvus pod 的 config init container 使用 operator 镜像。 请检查:

    kubectl -n <instance-ns> get deploy -l app.kubernetes.io/instance=<instance> \
      -o jsonpath='{range .items[*]}{.metadata.name}{"  "}{.spec.template.spec.initContainers[?(@.name=="config")].image}{"\n"}{end}'

    它必须显示已安装 release 的 milvus-operator 镜像,而不是 milvusdb/milvus-operator:main-latest。如果看到 main-latest,新 pod 会停留在 Init:0/1,而旧 pod 会继续提供服务。在实例上设置一次 spec.components.updateToolImage: true,operator 随后会重新渲染 init container。

  • 数据:读取迁移前写入的数据。

  • 日志:operator 日志中不应出现与已接管实例相关的错误。

  • 后果:已接管的集群内 MinIO 会保留旧的 pod spec。该 spec 不符合 Pod Security Standards restricted 要求(缺少 runAsNonRoot / seccompProfile)。它会继续在当前命名空间中运行。若要将该实例迁移到强制执行 restricted 的命名空间,需要由值触发 MinIO release 升级,或重新创建实例。(未测试)

  • Milvus pod 和 restricted PSA:只有在实例设置了 spec.components.runAsNonRoot: true 时,Milvus 组件 pod 才兼容 restricted。operator 也只会在这种情况下添加 pod 级别的 runAsNonRoot。

回滚

仅当尚未使用任何新 operator 功能时,才可以回滚:

  1. 卸载 OLM operator(删除 Subscription 和 ClusterServiceVersion)。卸载 operator 时,OLM 不会删除 CRD,因此自定义资源会保留。
  2. 使用 installCRDs: false 重新安装 chart-milvus-operator 1.3.5 插件,以免它再次尝试接管 CRD。(未测试)

回滚是一种恢复操作,而非常规操作路径。请先在非生产集群上完整测试整个迁移流程。

7. 非目标和已知风险

非目标:

  • 不支持从 chart 插件到 OLM operator 的自动升级或原地升级。
  • 不会发布新版 chart 插件。第 2 节是在已安装的 1.3.5 版本上执行的手动操作步骤。
  • 不迁移 GPU 镜像变体(此版本不提供 GPU 引擎镜像)。
  • 迁移期间不更改 Milvus 引擎版本。
  • 不会将现有集群内 MinIO 中的数据迁移到 Silo。
  • 不支持并行运行 chart 插件和 OLM operator。

已知风险:

  • 跳过第 2 节或验证不当会在卸载时删除所有 Milvus 自定义资源。这是此操作步骤中唯一不可逆的错误。
  • 非托管时间窗口:在第 4 节和第 5 节之间,没有 operator 会协调实例。
  • OLM 拒绝更新 CRD(现有自定义资源未通过 bundle schema 验证,或 bundle 未提供已存储的版本)。安装会停止;不会丢失任何内容。
  • 无法保证回滚成功(见上文)。
  • chart 插件 1.3.5 上的分布式集群内 MinIO。每当设置了镜像 registry 时,1.3.5 内嵌的 MinIO chart 在分布式模式(operator 的默认 MinIO 模式)下都会渲染出无效的镜像引用,因此此类实例无法在 1.3.5 上安装。因此,没有此类实例需要迁移。独立模式的 MinIO 和外部 S3 不受影响。
  • 迁移后的 restricted PSA:已接管的集群内 MinIO release 会保留不合规的 pod spec,而 Milvus pod 只有在设置了 spec.components.runAsNonRoot: true 时才符合要求(两者均在第 6 节中介绍)。

升级 Milvus 引擎

operator 升级和 chart 迁移都不会更改现有实例的引擎版本。从 chart 插件 1.3.5 接管的实例会继续运行 Milvus 2.6.7。将其升级到 Milvus 2.6.24(此版本支持并经过测试的版本)是单独的操作,需在迁移验证通过后针对每个实例分别执行。

此版本未对引擎从 2.6.7 升级到 2.6.24 进行测试。请先在非生产实例上尝试,并按照第 3 节所述进行备份。

将 spec.components.image 设置为此版本的 Milvus 2.6.24 引擎镜像 middleware/milvus:v2.6.24-acp.2(位于平台镜像 registry 中)。operator 为新实例使用的完整镜像引用可从 operator Deployment 中查看:

kubectl get deploy -A -l app.kubernetes.io/name=milvus-operator \
  -o jsonpath='{.items[0].spec.template.spec.containers[0].env[?(@.name=="RELATED_IMAGE_MILVUS")].value}'; echo

然后更新实例,并执行滚动更新,以按依赖顺序替换组件:

kubectl -n <instance-ns> patch milvus <instance> --type merge -p \
  '{"spec":{"components":{"enableRollingUpdate":true,"image":"<engine-image-reference>"}}}'

镜像标签请保持 v2.6.x 格式。operator 会根据引擎镜像标签推断 Milvus 2.6 的行为(例如协调器布局和默认消息流),因此,标签不以 v2.6 开头会导致实例部署不正确。

如果改用 MilvusUpgrade 资源,请务必将 spec.targetImage 显式设置为平台的 v2.6.x 引擎镜像。否则,MilvusUpgrade 会根据 spec.targetVersion 和 operator 的默认基础镜像构建镜像引用,而该镜像可能不是此版本交付的镜像。


Milvus™ 是 The Linux Foundation 的商标。Alauda 是独立供应商。本产品与 The Linux Foundation 无关,未经其认可,也未获其赞助。所有商标均为其各自所有者的财产,在此仅用于标识目的。