对象存储灾备

Ceph RGW Multi-Site 功能是一种跨集群异步数据复制机制,旨在同步地理分布的 Ceph 集群之间的对象存储数据,提供高可用(HA)和灾难恢复(DR)能力。

术语

术语说明
Primary Cluster当前提供存储服务的集群。
Secondary Cluster用于备份的备用集群。
Realm, ZoneGroup, Zone
  • Realm:Ceph 对象存储中最高级别的逻辑分组。它代表一个完整的对象存储命名空间,通常用于多站点复制和同步。一个 Realm 可以跨越不同的地理位置或数据中心。
  • ZoneGroup:Realm 内的逻辑分组,包含多个 Zone。ZoneGroup 实现跨 Zone 的数据同步和复制,通常在同一地理区域内。
  • Zone:ZoneGroup 内的逻辑分组,物理存储数据。每个 Zone 独立管理和存储对象,并可以拥有自己的数据/元数据池配置。

前提条件

  • 准备两个可部署 Rook-Ceph 的集群(Primary 和 Secondary 集群),且它们之间网络连通。
  • 两个集群必须使用相同的平台版本(v3.12 或更高)。
  • 确保 Primary 和 Secondary 集群均未部署 Ceph 对象存储。
  • 参考创建存储服务文档部署 Operator 并创建集群。集群创建后不要通过向导创建对象存储池,需使用 CLI 工具按下述方式配置。

操作流程

本指南提供同一 ZoneGroup 内两个 Zone 之间的同步方案。

在 Primary 集群创建对象存储

本步骤创建 Realm、ZoneGroup、Primary Zone 及 Primary Zone 的网关资源。

在 Primary 集群的 Control 节点执行以下命令:

命令
输出
cat << EOF | kubectl apply -f -
---
apiVersion: ceph.rook.io/v1
kind: CephObjectRealm
metadata:
  name: <realm-name>
  namespace: rook-ceph

---
apiVersion: ceph.rook.io/v1
kind: CephObjectZoneGroup
metadata:
  name: <zonegroup-name>
  namespace: rook-ceph
spec:
  realm: <realm-name>

---
apiVersion: ceph.rook.io/v1
kind: CephObjectZone
metadata:
  name: <primary-zone-name>
  namespace: rook-ceph
spec:
  zoneGroup: <zonegroup-name>
  metadataPool:
    failureDomain: host
    replicated:
      size: 3
      requireSafeReplicaSize: true
  dataPool:
    failureDomain: host
    replicated:
      size: 3
      requireSafeReplicaSize: true
    parameters:
      compression_mode: none
  preservePoolsOnDelete: false

---
cat << EOF | kubectl apply -f -
apiVersion: ceph.rook.io/v1
kind: CephObjectStore
metadata:
  name: <object-store-name>
  namespace: rook-ceph
spec:
  gateway:
    port: 7480
    instances: 2
  zone:
    name: <zone-name>
EOF

参数

  • <realm-name>:Realm 名称。
  • <zonegroup-name>:ZoneGroup 名称。
  • <primary-zone-name>:Primary Zone 名称。
  • <object-store-name>:网关名称。

配置 Primary Zone 的外部访问

  1. 获取 ObjectStore 的 UID {#uid}

    kubectl -n rook-ceph get cephobjectstore <object-store-name> -o jsonpath='{.metadata.uid}'

    参数

    • <object-store-name>:在步骤 1中配置的网关名称。
  2. 创建外部访问 Service

    cat << EOF | kubectl apply -f -
    apiVersion: v1
    kind: Service
    metadata:
      name: rook-ceph-rgw-<object-store-name>-external
      namespace: rook-ceph
      labels:
        app: rook-ceph-rgw
        rook_cluster: rook-ceph
        rook_object_store: <object-store-name>
      ownerReferences:
        - apiVersion: ceph.rook.io/v1
          kind: CephObjectStore
          name: <object-store-name>
          uid: <object-store-uid>
    spec:
      ports:
        - name: rgw
          port: 7480
          targetPort: 7480
          protocol: TCP
      selector:
        app: rook-ceph-rgw
        rook_cluster: rook-ceph
        rook_object_store: <object-store-name>
      sessionAffinity: None
      type: NodePort
    EOF

    参数

    • <object-store-name>:在此处配置的网关名称。
    • <object-store-uid>:在此处获取的 UID。
  3. 向 CephObjectZone 添加外部端点。

    kubectl -n rook-ceph patch cephobjectzone <primary-zone-name> --type merge -p '{"spec":{"customEndpoints":["<external-endpoint>"]}}'

    参数

    • <zone-name>:在此处配置的 Primary Zone 名称。
    • <external-endpoint>:从 Primary 集群获取的外部地址

获取 access-keysecret-key

kubectl -n rook-ceph get secrets <realm-name>-keys -o yaml | grep access-key
kubectl -n rook-ceph get secrets <realm-name>-keys -o yaml | grep secret-key

参数

  • <realm-name>:在此处配置的 Realm 名称。

创建 Secondary Zone 并配置 Realm 同步

本节说明如何创建 Secondary Zone 并通过从 Primary 集群拉取 Realm 信息配置同步。

在 Secondary 集群的 Control 节点执行以下命令:

cat << EOF | kubectl apply -f -
apiVersion: v1
kind: Secret
metadata:
  name: <realm-name>-keys
  namespace: rook-ceph
data:
  access-key: <access-key>
  secret-key: <secret-key>

---
apiVersion: ceph.rook.io/v1
kind: CephObjectRealm
metadata:
  name: <realm-name>
  namespace: rook-ceph
spec:
  pull:
    endpoint: <realm-endpoint>

---
apiVersion: ceph.rook.io/v1
kind: CephObjectZoneGroup
metadata:
  name: <zone-group-name>
  namespace: rook-ceph
spec:
  realm: <realm-name>

---
apiVersion: ceph.rook.io/v1
kind: CephObjectZone
metadata:
  name: <new-zone-name>
  namespace: rook-ceph
spec:
  zoneGroup: <zone-group-name>
  metadataPool:
    failureDomain: host
    replicated:
      size: 3
      requireSafeReplicaSize: true
  dataPool:
    failureDomain: host
    replicated:
      size: 3
      requireSafeReplicaSize: true
  preservePoolsOnDelete: false

---
apiVersion: ceph.rook.io/v1
kind: CephObjectStore
metadata:
  name: <secondary-object-store-name>
  namespace: rook-ceph
spec:
  gateway:
    port: 7480
    instances: 2
  zone:
    name: <secondary-zone-name>
EOF

参数

  • <access-key>:从此处获取的 AK。
  • <secret-key>:从此处获取的 SK。
  • <realm-endpoint>:从 Primary 集群获取的外部地址
  • <realm-name>Realm
  • <zone-group-name>ZoneGroup
  • <secondary-zone-name>:Secondary Zone 名称。
  • <secondary-object-store-name>:Secondary 网关名称。

配置 Secondary Zone 的外部访问

  1. 获取 Secondary 网关的 UID {#uids}

    kubectl -n rook-ceph get cephobjectstore <secondary-object-store-name> -o jsonpath='{.metadata.uid}'

    参数

    • <secondary-object-store-name>:Secondary 集群中网关名称。
  2. 创建外部访问 Service

    cat << EOF | kubectl apply -f -
    apiVersion: v1
    kind: Service
    metadata:
      name: rook-ceph-rgw-<object-store-name>-external
      namespace: rook-ceph
      labels:
        app: rook-ceph-rgw
        rook_cluster: rook-ceph
        rook_object_store: <object-store-name>
      ownerReferences:
        - apiVersion: ceph.rook.io/v1
          kind: CephObjectStore
          name: <object-store-name>
          uid: <object-store-uid>
    spec:
      ports:
        - name: rgw
          port: 7480
          targetPort: 7480
          protocol: TCP
      selector:
        app: rook-ceph-rgw
        rook_cluster: rook-ceph
        rook_object_store: <object-store-name>
      sessionAffinity: None
      type: NodePort
    EOF

    参数

    • <secondary-object-store-name>:Secondary 网关。
    • <secondary-object-store-uid>:Secondary 网关 UID。
  3. 向 Secondary CephObjectZone 添加外部端点

    kubectl -n rook-ceph patch cephobjectzone <secondary-zone-name> --type merge -p '{"spec":{"customEndpoints":["<external-endpoint>"]}}'

    参数

    • <secondary-zone-name>:Secondary Zone 名称。
    • <secondary-zone-external-endpoint>:从 Secondary 集群获取的外部地址

故障切换

当 Primary 集群发生故障时,需要将 Secondary Zone 提升为 Primary Zone。切换后,Secondary Zone 的网关可继续提供对象存储服务。

操作流程

在 Secondary 集群的 rook-ceph-tool pod 中执行以下命令:

radosgw-admin zone modify --rgw-realm=<realm-name> --rgw-zonegroup=<zone-group-name> --rgw-zone=<secondary-zone-name> --master

参数

  • <realm-name>:Realm 名称。
  • <zone-group-name>:Zone Group 名称。
  • <secondary-zone-name>:Secondary Zone 名称。

相关操作

获取外部地址

  1. 进入 平台管理

  2. 在左侧导航栏点击 存储管理 > 分布式存储

  3. 集群信息 标签页,向下滚动至 存储池 区域,点击对象存储池旁的 ⋮,选择 查看地址