设置 CDC 复制

本指南介绍如何使用 Milvus Operator 部署两个独立的 Milvus 集群,并配置 CDC 复制从源集群到目标集群。

示例使用

  • source-cluster 作为主群集。
  • target-cluster 作为备用群集。
  • milvus 作为 Milvus 群集的命名空间。
  • milvus-operator 作为 Milvus Operator 的命名空间。

开始之前,请阅读Milvus CDC以了解主备模型和故障转移选项。

先决条件

  • Milvus v2.6.16 或更高版本。
  • Milvus Operator v1.3.4 或更高版本。
  • Kubernetes 集群可用。
  • 源群集和目标群集可以通过网络相互连接。
  • 拥有两个 Milvus 集群的管理员凭证。
  • 知道每个群集的物理通道数。

步骤 1:升级 Milvus 操作符

添加 Milvus Operator Helm 资源库:

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

更新版本库:

helm repo update zilliztech-milvus-operator

安装或升级 Milvus Operator:

helm -n milvus-operator upgrade --install milvus-operator \
  zilliztech-milvus-operator/milvus-operator \
  --create-namespace

检查操作符 pod 是否正在运行:

kubectl get pods -n milvus-operator

输出示例:

NAME                               READY   STATUS    RESTARTS   AGE
milvus-operator-6f7d8c9c7d-xm4tj   1/1     Running   0          54s

步骤 2:部署源群集

创建名为milvus_source_cluster.yaml 的文件:

apiVersion: milvus.io/v1beta1
kind: Milvus
metadata:
  name: source-cluster
  namespace: milvus
  labels:
    app: milvus
spec:
  mode: standalone
  components:
    image: milvusdb/milvus:v2.6.16
    cdc:
      replicas: 1
  dependencies:
    msgStreamType: woodpecker

应用配置:

kubectl create namespace milvus
kubectl apply -f milvus_source_cluster.yaml

检查源群集 pod 是否正在运行:

kubectl get pods -n milvus

示例输出:

NAME                                                   READY   STATUS    RESTARTS   AGE
source-cluster-etcd-0                                  1/1     Running   0          3m
source-cluster-minio-6d8f7d9b9f-9t7j2                  1/1     Running   0          3m
source-cluster-milvus-standalone-7f8d9c8f6d-r2m5x      1/1     Running   0          2m
source-cluster-milvus-cdc-66d64747bd-sckxj             1/1     Running   0          2m

确保 CDC pod(如source-cluster-milvus-cdc-... )处于Running 状态。

第 3 步:部署目标群集

创建名为milvus_target_cluster.yaml 的文件:

apiVersion: milvus.io/v1beta1
kind: Milvus
metadata:
  name: target-cluster
  namespace: milvus
  labels:
    app: milvus
spec:
  mode: standalone
  components:
    image: milvusdb/milvus:v2.6.16
    cdc:
      replicas: 1
  dependencies:
    msgStreamType: woodpecker

CDC 组件也已在目标群集上启用。在目标群集为备用群集时,该组件处于空闲状态,但如果目标群集在切换后成为主群集,则需要该组件。

应用配置:

kubectl apply -f milvus_target_cluster.yaml

检查目标群集 pod 是否正在运行:

kubectl get pods -n milvus | grep -E 'NAME|target-cluster'

输出示例:

NAME                                                   READY   STATUS    RESTARTS   AGE
target-cluster-etcd-0                                  1/1     Running   0          3m
target-cluster-minio-5f7c8d9b6f-k8s2q                  1/1     Running   0          3m
target-cluster-milvus-standalone-66dc8d9f7f-5n6bp      1/1     Running   0          2m
target-cluster-milvus-cdc-7f8c9d6b8c-q4t9m             1/1     Running   0          2m

步骤 4:准备群集信息

获取两个群集的 Milvus 服务地址:

kubectl get svc -n milvus | grep -E 'NAME|source-cluster|target-cluster'

输出示例

NAME                                  TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)              AGE
source-cluster-milvus                 ClusterIP   10.98.124.90     <none>        19530/TCP,9091/TCP   8m
target-cluster-milvus                 ClusterIP   10.109.234.172   <none>        19530/TCP,9091/TCP   3m

准备两种地址:

  • 群集地址被写入复制配置并由 CDC 组件使用。这些地址必须可以从 CDC pod 到达。
  • 客户端地址仅在调用 Milvus API 时由 Python 客户端使用。如果在 Kubernetes 集群外运行 Python 客户端,请通过正常访问方法(如负载平衡器、入口或端口转发)公开 Milvus 服务。

为两个集群准备连接信息和 pchannel 列表:

source_cluster_addr = "http://source-cluster-milvus.milvus.svc.cluster.local:19530"
target_cluster_addr = "http://target-cluster-milvus.milvus.svc.cluster.local:19530"

source_client_addr = source_cluster_addr
target_client_addr = target_cluster_addr

# If your Python client runs outside the Kubernetes cluster, replace only
# source_client_addr and target_client_addr with externally reachable addresses.
# Keep source_cluster_addr and target_cluster_addr reachable from CDC pods.
# For example:
# source_client_addr = "http://127.0.0.1:19530"
# target_client_addr = "http://127.0.0.1:19531"

source_cluster_token = "root:Milvus"
target_cluster_token = "root:Milvus"

source_cluster_id = "source-cluster"
target_cluster_id = "target-cluster"

pchannel_num = 16
source_cluster_pchannels = [
    f"{source_cluster_id}-rootcoord-dml_{i}"
    for i in range(pchannel_num)
]
target_cluster_pchannels = [
    f"{target_cluster_id}-rootcoord-dml_{i}"
    for i in range(pchannel_num)
]

将地址替换为环境中实际的 Milvus 服务地址。不要将source_cluster_addrtarget_cluster_addr 设置为本地端口转发地址,除非 CDC pod 也能到达该地址。pchannel 列表必须与 Milvus 部署相匹配。请勿在未检查群集配置的情况下复制示例值。

第 5 步:创建复制配置

创建从source-clustertarget-cluster 的复制配置:

replicate_config = {
    "clusters": [
        {
            "cluster_id": source_cluster_id,
            "connection_param": {
                "uri": source_cluster_addr,
                "token": source_cluster_token,
            },
            "pchannels": source_cluster_pchannels,
        },
        {
            "cluster_id": target_cluster_id,
            "connection_param": {
                "uri": target_cluster_addr,
                "token": target_cluster_token,
            },
            "pchannels": target_cluster_pchannels,
        },
    ],
    "cross_cluster_topology": [
        {
            "source_cluster_id": source_cluster_id,
            "target_cluster_id": target_cluster_id,
        }
    ],
}

第 6 步:应用复制配置

对两个群集应用相同的配置:

from pymilvus import MilvusClient

source_client = MilvusClient(
    uri=source_client_addr,
    token=source_cluster_token,
)
target_client = MilvusClient(
    uri=target_client_addr,
    token=target_cluster_token,
)

try:
    source_client.update_replicate_configuration(**replicate_config)
    target_client.update_replicate_configuration(**replicate_config)
finally:
    source_client.close()
    target_client.close()

对于生产自动化,请使用单独的短命客户机进行此控制平面操作。这样可以避免在群集角色发生变化时与应用程序 DML 流量共享同一个 gRPC 通道。

应用配置后,写入source-cluster 的更改将复制到target-cluster

第 7 步:验证数据复制

验证复制是否有效:

  1. 连接到source-cluster
  2. 创建 Collections。
  3. 将数据插入 Collections。
  4. 加载 Collections 并在source-cluster 上运行查询或搜索。
  5. 连接到target-cluster
  6. target-cluster 上运行相同的查询或搜索,无需在备用群集上手动加载 Collections。
  7. 确认预期数据在两个群集上都可见。

目标群集是此拓扑中的备用群集。请勿在备用群集上运行手动 DDL 或 DCL 操作,如load_collection 。这些操作应在源群集上执行,并复制到目标群集。

确切的验证码取决于您的 Collections Schema。有关基本的 Milvus Collections 工作流程,请参阅 Milvus 快速入门文档。

CDC 滞后

CDC 滞后是指主集群和备用集群之间的数据窗口。配置复制后,应持续监控它。

CDC 滞后会在以下情况下增加:

  • 主写入率高。
  • 群集之间的网络延迟或数据包丢失增加。
  • 备用群集超载。
  • CDC 节点配置不足。
  • 正在运行大型 DDL 或导入操作。

使用 CDC 滞后来指导操作符决策:

  • 如果滞后较低,切换应更快完成。
  • 如果滞后较高,故障切换可能会丢失更多数据。

可以使用以下 PromQL 查询估算 CDC 滞后:

clamp_min(
  max by (channel_name) (
    milvus_wal_last_confirmed_time_tick
  )
  -
  min by (channel_name) (
    milvus_cdc_last_replicated_time_tick
  ),
  0
)

结果以秒为单位。对于每个源通道,该查询将最新确认的 WAL 时间戳与 CDC 复制的最后一个时间戳进行比较。如果主集群复制到多个备用集群,min by (channel_name) 表达式会报告该通道最慢的复制进度。

如果 Prometheus 扫描多个 Milvus 群集,请添加与部署相匹配的标签过滤器,如namespaceapp_kubernetes_io_instance ,以避免混合来自不同群集的指标。

常见问题

我需要在两个集群上都调用update_replicate_configuration 吗?

需要。对所有参与的群集应用相同的拓扑结构。如果一个群集在调用时不是主群集,它将等待,直到通过 CDC 应用拓扑。

如何选择cluster_id

为每个群集使用一个稳定、唯一的 ID。该 ID 也用于 pchannel 名称和复制拓扑引用。

配置复制后,能否更改 pchannel?

可以更新拓扑,但 pchannel 列表必须与群集布局相匹配。将 pchannel 更改视为高级操作符,并在更改后仔细验证复制。