第 12 章 在 OpenShift Data Foundation 中恢复 ceph-monitor 仲裁

在某些情况下,ceph-mons 可能会丢失仲裁。如果 mons 无法再次形成仲裁,则需要一个手动过程来再次进入仲裁。唯一的要求是,至少有一个 mon 必须健康。以下步骤从仲裁中删除不健康状态的 mons,并可让您使用单个 mon 重新组成仲裁,然后将仲裁回到原始大小。

例如,如果您有三个 mons 并失去了仲裁,您需要从仲裁中删除两个有问题的 mons,通知可以正常工作的 mon 它是仲裁中唯一的 mon,然后重启这个可以正常工作的 mon

流程

  1. 停止 rook-ceph-operator,以便在修改 monmap 时不通过 mons 失败。

    # oc -n openshift-storage scale deployment rook-ceph-operator --replicas=0
  2. 注入一个新的 monmap

    警告

    您必须非常仔细注入 monmap。如果运行不正确,您的集群可以被永久销毁。Ceph monmap 来跟踪 mon 仲裁。monmap 被更新为仅包含健康的 mon。在本例中,健康的 mon 是 rook-ceph-mon-b,而不健康的 monsrook-ceph-mon-arook-ceph-mon-c

    1. 备份当前的 rook-ceph-mon-b 部署:

      # oc -n openshift-storage get deployment rook-ceph-mon-b -o yaml > rook-ceph-mon-b-deployment.yaml
    2. 打开 YAML 文件,并从 mon 容器复制命令参数(请参见以下示例中的容器列表)。这是 monmap 更改所需要的。

      [...]
        containers:
        - args:
          - --fsid=41a537f2-f282-428e-989f-a9e07be32e47
          - --keyring=/etc/ceph/keyring-store/keyring
          - --log-to-stderr=true
          - --err-to-stderr=true
          - --mon-cluster-log-to-stderr=true
          - '--log-stderr-prefix=debug '
          - --default-log-to-file=false
          - --default-mon-cluster-log-to-file=false
          - --mon-host=$(ROOK_CEPH_MON_HOST)
          - --mon-initial-members=$(ROOK_CEPH_MON_INITIAL_MEMBERS)
          - --id=b
          - --setuser=ceph
          - --setgroup=ceph
          - --foreground
          - --public-addr=10.100.13.242
          - --setuser-match-path=/var/lib/ceph/mon/ceph-b/store.db
          - --public-bind-addr=$(ROOK_POD_IP)
          command:
          - ceph-mon
      [...]
    3. 清理复制的 commandargs 字段以形成过去的命令,如下所示:

      # ceph-mon \
          --fsid=41a537f2-f282-428e-989f-a9e07be32e47 \
          --keyring=/etc/ceph/keyring-store/keyring \
          --log-to-stderr=true \
          --err-to-stderr=true \
          --mon-cluster-log-to-stderr=true \
          --log-stderr-prefix=debug \
          --default-log-to-file=false \
          --default-mon-cluster-log-to-file=false \
          --mon-host=$ROOK_CEPH_MON_HOST \
          --mon-initial-members=$ROOK_CEPH_MON_INITIAL_MEMBERS \
          --id=b \
          --setuser=ceph \
          --setgroup=ceph \
          --foreground \
          --public-addr=10.100.13.242 \
          --setuser-match-path=/var/lib/ceph/mon/ceph-b/store.db \
          --public-bind-addr=$ROOK_POD_IP
      注意

      确保删除括起了 --log-stderr-prefix 标记的单引号,以及包括 ROOK_CEPH_MON_MON_MON_MON_HOSTROOK_CEPH_MON_MON_CEPH_MON_INITIAL_MEMBERSROOK_POD_IP 变量的括号。

    4. 修补 rook-ceph-mon-b 部署,在不删除 mon 的情况下停止这个 mon 工作。

      # oc -n openshift-storage patch deployment rook-ceph-mon-b  --type='json' -p '[{"op":"remove", "path":"/spec/template/spec/containers/0/livenessProbe"}]'
      
      # oc -n openshift-storage patch deployment rook-ceph-mon-b -p '{"spec": {"template": {"spec": {"containers": [{"name": "mon", "command": ["sleep", "infinity"], "args": []}]}}}}'
    5. mon-b pod 上执行以下步骤:

      1. 连接到健康 mon 的 pod 并运行以下命令:

        # oc -n openshift-storage exec -it <mon-pod> bash
      2. 设置变量。

        # monmap_path=/tmp/monmap
      3. monmap 提取到一个文件,从健康的 mon 部署中粘贴 ceph mon 命令并添加 --extract-monmap=${monmap_path} 标记。

        # ceph-mon \
               --fsid=41a537f2-f282-428e-989f-a9e07be32e47 \
               --keyring=/etc/ceph/keyring-store/keyring \
               --log-to-stderr=true \
               --err-to-stderr=true \
               --mon-cluster-log-to-stderr=true \
               --log-stderr-prefix=debug \
               --default-log-to-file=false \
               --default-mon-cluster-log-to-file=false \
               --mon-host=$ROOK_CEPH_MON_HOST \
               --mon-initial-members=$ROOK_CEPH_MON_INITIAL_MEMBERS \
               --id=b \
               --setuser=ceph \
               --setgroup=ceph \
               --foreground \
               --public-addr=10.100.13.242 \
               --setuser-match-path=/var/lib/ceph/mon/ceph-b/store.db \
               --public-bind-addr=$ROOK_POD_IP \
               --extract-monmap=${monmap_path}
      4. 检查 monmap 的内容。

        # monmaptool --print /tmp/monmap
      5. monmap 中删除错误的 mons

        # monmaptool ${monmap_path} --rm <bad_mon>

        在本例中,我们移除了 mon0mon2

        # monmaptool ${monmap_path} --rm a
        # monmaptool ${monmap_path} --rm c
      6. 把修改过的 monmap 注入到健康的 mon中,粘贴 ceph mon 命令并添加 --inject-monmap=${monmap_path} 标记:

        # ceph-mon \
               --fsid=41a537f2-f282-428e-989f-a9e07be32e47 \
               --keyring=/etc/ceph/keyring-store/keyring \
               --log-to-stderr=true \
               --err-to-stderr=true \
               --mon-cluster-log-to-stderr=true \
               --log-stderr-prefix=debug \
               --default-log-to-file=false \
               --default-mon-cluster-log-to-file=false \
               --mon-host=$ROOK_CEPH_MON_HOST \
               --mon-initial-members=$ROOK_CEPH_MON_INITIAL_MEMBERS \
               --id=b \
               --setuser=ceph \
               --setgroup=ceph \
               --foreground \
               --public-addr=10.100.13.242 \
               --setuser-match-path=/var/lib/ceph/mon/ceph-b/store.db \
               --public-bind-addr=$ROOK_POD_IP \
               --inject-monmap=${monmap_path}
      7. 退出 shell 以继续。
  3. 编辑 Rook configmaps

    1. 编辑 operator 用来跟踪 monsconfigmap

      # oc -n openshift-storage edit configmap rook-ceph-mon-endpoints
    2. 验证在数据元素中,您可以看到如下三个 mon (具体取决于您的 moncount,可能会更多):

      data: a=10.100.35.200:6789;b=10.100.13.242:6789;c=10.100.35.12:6789
    3. 从列表中删除有问题的 mons,以使用一个好的 mon 结束。例如:

      data: b=10.100.13.242:6789
    4. 保存文件并退出。
    5. 现在,您需要使用用于 mons 和其他组件的 Secret

      1. 为变量 good_mon_id 设置一个值。

        例如:

        # good_mon_id=b
      2. 您可以使用 oc patch 命令来修补 rook-ceph-config secret,并更新两个键/值对 mon_hostmon_initial_members

        # mon_host=$(oc -n openshift-storage get svc rook-ceph-mon-b -o jsonpath='{.spec.clusterIP}')
        
        # oc -n openshift-storage patch secret rook-ceph-config -p '{"stringData": {"mon_host": "[v2:'"${mon_host}"':3300,v1:'"${mon_host}"':6789]", "mon_initial_members": "'"${good_mon_id}"'"}}'
        注意

        如果使用 hostNetwork: true,则需要将 mon_host 变量替换为代表 mon 固定到的节点 IP(nodeSelector)。这是因为在那个 "mode" 中创建了 rook-ceph-mon-* 服务。

  4. 重新启动 mon

    您需要使用原始 ceph-mon 命令重启好的 mon pod,以获取这些更改。

    1. mon 部署 YAML 文件的备份中使用 oc replace 命令:

      # oc replace --force -f rook-ceph-mon-b-deployment.yaml
      注意

      选项 --force 删除部署并创建新部署。

    2. 验证集群的状态。

      状态应该在仲裁中显示 mon。如果状态正常,您的集群应该再次处于健康状态。

  5. 删除不再预期在仲裁中的两个 mon 部署。

    例如:

    # oc delete deploy <rook-ceph-mon-1>
    # oc delete deploy <rook-ceph-mon-2>

    在本例中,要删除的部署有 rook-ceph-mon-arook-ceph-mon-c

  6. 重启 Operator。

    1. 再次启动 rook 运算符,以恢复监控集群的健康状况。

      注意

      忽略多个资源已存在的错误是安全的。

      # oc -n openshift-storage scale deployment rook-ceph-operator --replicas=1

      根据 mon 数量,Operator 会自动添加更多 mons 来再次增加仲裁大小。