MinIO 到 Rook Ceph RGW 数据迁移指南

1. 概述与架构

本文档说明如何使用已安装的 Alauda Build of VolSync Operator 镜像中内嵌的 Rclone 组件,将 Kubernetes 中高可用(HA)MinIO 部署的全部数据迁移至 Rook Ceph RGW。

1.1 架构说明

  • 安全镜像复用:该方案通过调度 Kubernetes Job,复用安全加固的 build-harbor.alauda.cn/acp/volsync Operator 镜像,覆盖默认入口,直接调用镜像内置的 Rclone 二进制文件,执行标准的 S3-to-S3 API 级对象同步。

1.2 同步策略

采用三阶段策略:“全量 -> 增量 -> 切换”

  1. 初始同步(全量同步):保持服务在线,迁移历史数据。
  2. 增量同步:保持服务在线,多次运行以追赶新增或修改的数据。
  3. 切换同步:停止写入,强制严格一致性校验,完成最终切换。

2. 前提条件与准备工作

2.1 验证 Alauda VolSync 安装及提取版本(关键前提)

执行本方案前,确保在 volsync-system 命名空间已安装 Alauda Build of VolSync Operator。迁移 Job 镜像版本必须严格匹配当前运行的 Operator 版本。

关于 Alauda Build of VolSync 的详细安装说明,请参见 Configure PVC DR with VolSync

获取版本方法:
登录集群管理控制台,进入 Marketplace / OperatorHub,打开 Installed Operators,找到 VolSync Operator,记录显示的版本号(例如 v0.8.0v0.9.0)。将此值保存为 <OPERATOR_VERSION>,后续配置时使用。

2.2 收集 MinIO 源信息

  • Endpoint:MinIO 内部 Service 地址(例如:http://minio.tenant-ns.svc:9000)。
  • 凭证:具备所有桶的 ReadList 权限的 Access Key / Secret Key。

2.3 创建 Ceph RGW 用户(目标端)

在 Rook Ceph 集群中应用以下 YAML,创建专用迁移用户并授予桶创建权限。

apiVersion: ceph.rook.io/v1
kind: CephObjectStoreUser
metadata:
  name: volsync-migration-user
  namespace: rook-ceph
spec:
  store: object-store
  displayName: "VolSync Migration Admin"
  capabilities:
    bucket: "*"

为最小权限原则,该迁移账号仅保留桶级权限,不授予 user 管理能力。

提取并解码 Ceph 凭证以备后用:

# 获取 Access Key
kubectl -n rook-ceph get secret rook-ceph-object-user-object-store-volsync-migration-user -o jsonpath='{.data.AccessKey}' | base64 -d
# 获取 Secret Key
kubectl -n rook-ceph get secret rook-ceph-object-user-object-store-volsync-migration-user -o jsonpath='{.data.SecretKey}' | base64 -d

3. 部署配置(清单)

建议在目标端命名空间(Ceph RGW)或专用运维命名空间部署迁移任务。

应用清单前,先创建两个清单共用的命名空间:

kubectl create ns migration-ops

部署位置建议(重要)

迁移过程中,Rclone 本地读取数据处理后上传至目标 S3 集群,迁移任务所在集群的网络位置直接影响带宽和完成时间。建议将 VolSync Operator/迁移 Job 部署在 MinIO 或 Ceph 集群,以减少跨集群网络开销,提高传输稳定性。

3.1 创建 Rclone 配置 Secret

将源和目标 S3 凭证写入 Secret。重要:不要在 endpoint 或密钥值周围添加引号。

apiVersion: v1
kind: Secret
metadata:
  name: volsync-rclone-config-secret
  namespace: migration-ops
type: Opaque
stringData:
  rclone.conf: |
    [source-minio]
    type = s3
    provider = Minio
    env_auth = false
    access_key_id = MINIO_ACCESS_KEY_HERE
    secret_access_key = MINIO_SECRET_KEY_HERE
    endpoint = MINIO_ENDPOINT_HERE
    no_check_certificate = true

    [dest-ceph]
    type = s3
    provider = Ceph
    env_auth = false
    access_key_id = CEPH_ACCESS_KEY_HERE
    secret_access_key = CEPH_SECRET_KEY_HERE
    endpoint = CEPH_ENDPOINT_HERE
    list_version = 2

3.2 定义迁移 Job

部署一个调用安全加固的 Alauda VolSync 镜像执行 S3 数据同步的 Job。

关于 remote:bucket[/prefix]remote:(重要)

  • 对于 S3 后端,Rclone 常用模式是 remote:bucketremote:bucket/prefix,这是定义作用域最清晰且安全的方式。
  • 本文档故意保持 source-minio: -> dest-ceph:,以支持全实例级迁移(源端所有可见桶)。
  • 风险提示remote: 范围更广,若凭证权限过大,可能迁移到非预期桶。务必先在测试环境验证,生产切换时建议改用明确的 remote:bucket[/prefix] 白名单模式。

请务必将下方 YAML 中的 <OPERATOR_VERSION> 替换为第 2.1 节中获取的实际版本号。

apiVersion: batch/v1
kind: Job
metadata:
  name: volsync-s3-sync-job
  namespace: migration-ops
spec:
  backoffLimit: 0
  template:
    spec:
      restartPolicy: Never
      containers:
        - name: rclone
          # 使用 Alauda 加固的 volsync 镜像,版本必须与 OperatorHub 完全一致。
          image: build-harbor.alauda.cn/acp/volsync:<OPERATOR_VERSION>
          # 注意:ACP 集群中,该镜像引用在 Pod 创建后会自动重写为内网镜像地址
          # (例如:registry.alauda.cn:60070/acp/volsync:<OPERATOR_VERSION>)。
          # 这是预期行为。
          # 可通过 `kubectl describe pod <pod-name>` 查看实际 Image / ImageID。
          imagePullPolicy: IfNotPresent
          # 覆盖默认入口,直接调用镜像内的 rclone
          command: ["rclone"]
          args:
            - "sync"
            - "source-minio:"
            - "dest-ceph:"
            - "--progress"
            - "--create-empty-src-dirs"
            - "--ignore-errors"
            # --- 性能调优参数 ---
            - "--transfers=32"      # 并行文件传输数
            - "--checkers=64"       # 并行校验数
            - "--s3-chunk-size=64M" # 大对象分块大小,减少 RGW 碎片
            - "--fast-list"         # 使用 ListObjectsV2 减少 API 请求
            - "--metadata"          # 同步对象元数据
          resources:
            requests:
              cpu: "2000m"
              memory: "4Gi"
            limits:
              cpu: "4000m"
              memory: "8Gi"
          env:
            - name: RCLONE_CONFIG
              value: "/config/rclone.conf"
          volumeMounts:
            - name: config-volume
              mountPath: /config
              readOnly: true
      volumes:
        - name: config-volume
          secret:
            secretName: volsync-rclone-config-secret

4. 执行流程

阶段 1:初始全量同步

  1. 创建运维命名空间:kubectl create ns migration-ops
  2. 应用 Secret:kubectl apply -f rclone-secret.yaml
  3. 启动 Job:kubectl apply -f rclone-job.yaml
  4. 监控进度:kubectl -n migration-ops logs -f job/volsync-s3-sync-job

阶段 2:增量同步

为追赶全量同步期间新增数据,按需重复执行此步骤。

  1. 删除之前的 Job:kubectl -n migration-ops delete job volsync-s3-sync-job
  2. 重新创建 Job:kubectl apply -f rclone-job.yaml

机制说明:默认情况下,Rclone 通过比较 Size 和 ModTime 决定是否需要传输,已存在且未修改的文件会被跳过。

阶段 3:最终切换

  1. 停止写入:在应用层停止对 MinIO 的写入,或通过负载均衡/Ingress 阻断写流量。
  2. 严格同步校验
  • 删除当前 Job:kubectl -n migration-ops delete job volsync-s3-sync-job
  • 修改 rclone-job.yaml:去掉最终切换运行中的 - "--ignore-errors",并在 args 中追加 - "--checksum"。此举避免掩盖失败对象,优先使用 Size+Checksum(可用时)进行差异检测。
  • 一致性建议(必需):切换前不要单纯依赖对象数量或 ETag。运行 rclone check source-minio: dest-ceph: --download --checksum(或对关键对象抽样下载并计算 SHA256)以减少因分段/ETag 差异导致的误报。
  • 重新应用 Job:kubectl apply -f rclone-job.yaml
  1. 验证并切换:Job 状态变为 Completed 且日志无错误后,更新应用的 S3 Endpoint 和凭证为 Ceph RGW。

5. 故障排查与调优建议

现象技术诊断解决方案
ImagePullBackOff节点无法拉取镜像,或版本不匹配。ACP 集群会自动将 build-harbor.alauda.cn 重写为内网镜像地址。先运行 kubectl describe pod <pod-name> 验证实际 Image(是否被重写)和 ImageID,再确认 <OPERATOR_VERSION> 是否正确,检查网络/认证配置(imagePullSecrets)是否正确指向有效镜像仓库。
Pod OOMKilled--fast-list 在大量小对象场景下批量加载元数据,消耗较高内存。增加 Pod 内存限制至 8Gi 以上,或移除 --fast-list(但会增加 API 请求次数,遍历速度变慢)。
403 Forbidden目标 Ceph 用户缺少桶创建权限。检查 CephObjectStoreUser 配置,确保 capabilities 包含 bucket: "*".
dial tcp: lookup "http: no such host"Secret 配置格式错误,endpoint URL 被加了引号。编辑 Secret,去除 endpoint URL 周围的引号,确保格式严格为:endpoint = http://...
503 Service Unavailable迁移并发过高,导致 Ceph RGW 写压力过大。降低 Job 中 args--transfers 参数,或增加 --bwlimit 限制传输带宽。