块存储灾难恢复

RBD Mirror 是 Ceph 块存储(RBD)的一项功能,支持不同 Ceph 集群之间的异步数据复制,实现跨集群的灾难恢复(DR)。其核心功能是以主备模式同步数据,确保主集群故障时备份集群能够快速接管服务。

WARNING
  • RBD Mirror 基于快照进行增量同步,默认快照间隔为每小时一次(可配置)。主备集群之间的差异数据通常对应于一个快照周期内的写入。
  • RBD Mirror 仅提供底层存储数据备份,不包含 Kubernetes 资源备份。请使用平台的 备份与恢复 功能备份 PVC 和 PV 资源。

术语

术语说明
Primary Cluster当前提供存储服务的集群。
Secondary Cluster用作备份的备用集群。

备份配置

前提条件

  • 准备两个能够部署 Alauda Container Platform (ACP) Storage 并使用 Ceph 的集群:一个 Primary 集群和一个 Secondary 集群,且两者之间网络互通。
  • 两个集群必须运行相同的平台版本(v3.12 或更高)。
  • 在 Primary 和 Secondary 集群中分别创建分布式存储服务
  • 在 Primary 和 Secondary 集群中创建同名的块存储池。
  • 请确保以下三个镜像已上传至平台私有镜像仓库:
    • quay.io/csiaddons/k8s-controller:v0.5.0
    • quay.io/csiaddons/k8s-sidecar:v0.8.0
    • quay.io/brancz/kube-rbac-proxy:v0.8.0

操作步骤

启用 Primary 集群块存储池镜像功能

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

Command
Output
kubectl -n rook-ceph patch cephblockpool <block-pool-name> \
--type merge -p '{"spec":{"mirroring":{"enabled":true,"mode":"image"}}}'

参数说明

  • <block-pool-name>:块存储池名称。

获取 Peer Token

该令牌是建立集群镜像连接的关键凭证。

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

Command
Output
kubectl get secret -n rook-ceph \
$(kubectl get cephblockpool.ceph.rook.io <block-pool-name> -n rook-ceph -o jsonpath='{.status.info.rbdMirrorBootstrapPeerSecretName}') \
-o jsonpath='{.data.token}' | base64 -d

参数说明

  • <block-pool-name>:块存储池名称。

在 Secondary 集群创建 Peer Token Secret

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

Command
Output
kubectl -n rook-ceph create secret generic rbd-primary-site-secret \
--from-literal=token=<token> \
--from-literal=pool=<block-pool-name>

参数说明

  • <token>:从步骤 2获取的令牌。
  • <block-pool-name>:块存储池名称。

启用 Secondary 集群块存储池镜像功能

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

Command
Output
kubectl -n rook-ceph patch cephblockpool <block-pool-name> --type merge -p \
'{
  "spec": {
    "mirroring": {
      "enabled": true,
      "mode": "image",
      "peers": {
        "secretNames": [
          "rbd-primary-site-secret"
        ]
      }
    }
  }
}'

参数说明

  • <block-pool-name>:块存储池名称。

在 Secondary 集群部署 Mirror Daemon

该守护进程负责监控和管理 RBD 镜像同步进程,包括数据同步和错误处理。

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

Command
Output
cat << EOF | kubectl apply -f -
apiVersion: ceph.rook.io/v1
kind: CephRBDMirror
metadata:
  name: rbd-mirror
  namespace: rook-ceph
spec:
  count: 1
EOF

验证镜像状态

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

Command
Output
kubectl get cephblockpools.ceph.rook.io <block-pool-name> -n rook-ceph -o jsonpath='{.status.mirroringStatus.summary}'

参数说明

  • <block-pool-name>:块存储池名称。

启用 Replication Sidecar

该功能支持高效的数据复制和同步,且不会中断主应用操作,提升系统的可靠性和可用性。

  1. 部署 csiaddons-controller

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

点击查看
kubectl create -f https://raw.githubusercontent.com/csi-addons/kubernetes-csi-addons/v0.5.0/deploy/controller/crds.yaml
kubectl create -f https://raw.githubusercontent.com/csi-addons/kubernetes-csi-addons/v0.5.0/deploy/controller/rbac.yaml

cat << EOF | kubectl apply -f -
apiVersion: v1
data:
  controller_manager_config.yaml: |
    apiVersion: controller-runtime.sigs.k8s.io/v1alpha1
    kind: ControllerManagerConfig
    health:
      healthProbeBindAddress: :8081
    metrics:
      bindAddress: 127.0.0.1:8080
    webhook:
      port: 9443
    leaderElection:
      leaderElect: true
      resourceName: e8cd140a.openshift.io
kind: ConfigMap
metadata:
  name: csi-addons-manager-config
  namespace: csi-addons-system
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app.kubernetes.io/name: csi-addons
  name: csi-addons-controller-manager
  namespace: csi-addons-system
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: csi-addons
  template:
    metadata:
      annotations:
        kubectl.kubernetes.io/default-container: manager
      labels:
        app.kubernetes.io/name: csi-addons
    spec:
      containers:
      - args:
        - --secure-listen-address=0.0.0.0:8443
        - --upstream=http://127.0.0.1:8080/
        - --logtostderr=true
        - --v=10
        image: <registry>/brancz/kube-rbac-proxy:v0.8.0
        name: kube-rbac-proxy
        ports:
        - containerPort: 8443
          name: https
          protocol: TCP
        resources:
          limits:
            cpu: 500m
            memory: 128Mi
          requests:
            cpu: 10m
            memory: 64Mi
      - args:
        - --health-probe-bind-address=:8081
        - --metrics-bind-address=127.0.0.1:8080
        - --leader-elect
        command:
        - /manager
        image: <registry>/csiaddons/k8s-controller:v0.5.0
        livenessProbe:
          httpGet:
            path: /healthz
            port: 8081
          initialDelaySeconds: 15
          periodSeconds: 20
        name: manager
        readinessProbe:
          httpGet:
            path: /readyz
            port: 8081
          initialDelaySeconds: 5
          periodSeconds: 10
        resources:
          limits:
            cpu: 500m
            memory: 128Mi
          requests:
            cpu: 10m
            memory: 64Mi
        securityContext:
          allowPrivilegeEscalation: false
      securityContext:
        runAsNonRoot: true
      serviceAccountName: csi-addons-controller-manager
      terminationGracePeriodSeconds: 10
EOF

参数说明

  • <registry>:平台的镜像仓库地址。
  1. 启用 csi sidecar

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

kubectl patch cm rook-ceph-operator-config -n rook-ceph --type json --patch \
'[
  {
    "op": "add",
    "path": "/data/CSI_ENABLE_OMAP_GENERATOR",
    "value": "true"
  },
  {
    "op": "add",
    "path": "/data/CSI_ENABLE_CSIADDONS",
    "value": "true"
  }
]'

创建 VolumeReplicationClass

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

Command
Output
cat << EOF | kubectl apply -f -
apiVersion: replication.storage.openshift.io/v1alpha1
kind: VolumeReplicationClass
metadata:
  name: rbd-volumereplicationclass
spec:
  provisioner: rook-ceph.rbd.csi.ceph.com
  parameters:
    mirroringMode: snapshot
    schedulingInterval: "<scheduling-interval>"
    replication.storage.openshift.io/replication-secret-name: rook-csi-rbd-provisioner
    replication.storage.openshift.io/replication-secret-namespace: rook-ceph
EOF
  1. <scheduling-interval>:调度间隔(例如,schedulingInterval: "1h" 表示每小时执行一次)。

为 PVC 启用镜像功能

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

Command
Output
cat << EOF | kubectl apply -f -
apiVersion: replication.storage.openshift.io/v1alpha1
kind: VolumeReplication
metadata:
  name: <vr-name>
  namespace: <namespace>
spec:
  autoResync: false
  volumeReplicationClass: rbd-volumereplicationclass
  replicationState: primary
  dataSource:
    apiGroup: ""
    kind: PersistentVolumeClaim
    name: <pvc-name>
EOF
  1. <vr-name>:VolumeReplication 对象名称,建议与 PVC 名称相同。
  2. <namespace>:VolumeReplication 所属命名空间,必须与 PVC 命名空间一致。
  3. <pvc-name>:需要启用镜像的 PVC 名称。

注意 启用后,Secondary 集群中的 RBD 镜像将变为只读。

故障切换

当 Primary 集群发生故障时,需要切换 RBD 镜像的主备关系。

前提条件

  • 已将 Primary 集群的 Kubernetes 资源备份并恢复至 Secondary 集群,包括 PVC、PV、应用工作负载等。

操作步骤

创建 VolumeReplication

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

cat << EOF | kubectl apply -f -
apiVersion: replication.storage.openshift.io/v1alpha1
kind: VolumeReplication
metadata:
  name: <vr-name>
  namespace: <namespace>
spec:
  autoResync: false
  dataSource:
    apiGroup: ""
    kind: PersistentVolumeClaim
    name: <mirror-pvc-name>
  replicationHandle: ""
  replicationState: primary
  volumeReplicationClass: rbd-volumereplicationclass
EOF
  1. <vr-name>:VolumeReplication 名称。
  2. <namespace>:PVC 命名空间。
  3. <mirror-pvc-name>:PVC 名称。

注意 创建后,Secondary 集群上的 RBD 镜像将变为主用且可写。