资讯动态

Rook Stretch Cluster(弹性集群)设计与实战:基于 Arbiter 仲裁节点的双可用区数据保护

发布时间:2026/9/23 21:39:04 来源:尧图企业网站定制
云原生存储容器编排运维【免费下载链接】rookStorage Orchestration for Kubernetes项目地址https://gitcode.com/gh_mirrors/roo/rook点击查看免费下载本文以 design/ceph/ceph-stretch-cluster.md 设计文档为主体骨架结合当前仓库中 CRD 类型定义、mon 编排源码、Ceph 客户端封装与部署示例系统讲解 Rook 如何在只有两个可用数据失效域的环境中借助 Ceph 的 stretch mode 与 arbiter 仲裁 mon实现任意单个失效域故障后数据仍可读写的高可用能力。读者将掌握 stretch cluster 的架构原理、CephCluster与CephBlockPool的完整配置方法、mon 故障切换与存储策略以及底层 Rook 自动执行的 Ceph 命令序列。1. 背景当只有两个可用失效域时生产环境通常期望拥有三个失效域failure domain每个失效域各存一份副本任意一个失效域整体宕机数据仍可在其余两个失效域中继续读写。但很多物理环境如仅有双机房/双可用区的数据中心只有两个可用于数据复制的失效域。此时要保证丢失任意一个失效域后数据在剩余失效域中依然完整可用就需要特殊的集群形态。Ceph 通过stretch cluster弹性集群 arbiter mon仲裁 mon机制从上游支持了这一场景数据在两个失效域中各放置多份副本第三个仅运行单个 mon 的仲裁区负责在双区之间出现脑裂时做出裁决仲裁区不存放数据。Rook 的目标则是管理员只需在常规 Rook CRD 中声明需求即可让 Rook 自动完成 stretch cluster 的全部编排与 Ceph 配置无需手工执行底层命令。本设计文档定位的目标版本为 Rook 1.5而当前仓库中该能力已演进为正式功能见 Documentation/CRDs/Cluster/stretch-cluster.md并配套了可直接部署的示例清单 deploy/examples/cluster-stretched.yaml。2. 架构设计2.1 三个 Zone 的角色划分基于 Ceph stretch 架构Rook 要求集群拓扑中存在三个 zone数据区 A 与 Bdata zones运行所有类型的 Rook Pod。每个数据区运行2 个 mon原因有二OSD 只能连接到本 zone 内的 mon因此数据区内需要不止一个 mon 以提供冗余Ceph 判定某个 zone 已宕机的依据是该 zone 内的 mon 全部不可用双 mon 确保判定依据可靠。仲裁区arbiter zone仅运行1 个 mon即tiebreaker或arbiter仲裁者不运行任何其他 Rook 或 Ceph 守护进程。Rook Stretch Cluster 架构两个数据区各运行 2 个 mon 并存放数据副本仲裁区仅运行 1 个 tiebreaker mon。仲裁区在实践中通常只包含单个节点且该节点往往同时是 Kubernetes 的 master/control-plane 节点当然仲裁区也可以包含更多节点。stretch cluster 使用的失效域类型最常见是 zone但可以配置为其他失效域如 datacenter、region只要该标签被 OSD 拓扑所支持。2.2 延迟约束分布式系统的关键组件间网络延迟会直接影响可用性。在 stretch cluster 场景下最关键的延迟瓶颈是 Kubernetes 的 EtcdK8s 仅支持最高约5ms往返 10ms的延迟而 Ceph 组件对延迟的容忍度更高Ceph mon 可支持高达700ms 往返的延迟。也就是说stretch cluster 对网络延迟的要求实际上是由 K8s 侧的 Etcd 决定的部署前应评估两数据区之间的网络 RTT 是否满足 Etcd 约束。3. 失效域配置节点拓扑标签集群的拓扑结构由管理员在 Rook 之外决定Rook 只负责检测已添加到节点上的拓扑标签并据此推导失效域。若目标失效域为 zone需要在节点上添加topology.kubernetes.io/zone标签。OSD 支持的任意拓扑标签详见 Documentation/CRDs/Cluster/ceph-cluster-crd.md 中关于 OSD 拓扑的说明都可使用。最小配置为每个数据区 2 个节点、仲裁区 1 个节点共 5 个节点打上标签例如topology.kubernetes.io/zonea topology.kubernetes.io/zonea topology.kubernetes.io/zoneb topology.kubernetes.io/zoneb topology.kubernetes.io/zonearbiter4. Rook 集群设计mon 与 zone 的绑定Rook 侧的核心改动是将 mon 与所需 zone 关联起来具体约束为必须创建5 个 monstretch cluster 不支持其他数量的 mon1 个 mon 分配给仲裁区两个数据区各分配 2 个 mon同一 zone 内的两个 mon 之间配置节点反亲和node antiaffinity确保它们落在不同节点上。新的配置位于spec.mon.stretchCluster下必须列出全部三个 zone 并指明哪个是仲裁区mon: count: 5 allowMultiplePerNode: false stretchCluster: # 集群最常见的场景是跨 zone 拉伸也可以使用 datacenter、region 等其他失效域 # 取值必须是 OSD 使用的标签之一参考 ceph-cluster-crd 的 osd topology 文档。 failureDomainLabel: topology.kubernetes.io/zone zones: # 列表中必须恰好有三个 zone且其中一个为 arbiter - name: arbiter arbiter: true - name: a - name: b上述字段在 CRD 类型定义中有完整对应见 pkg/apis/ceph.rook.io/v1/types.goMonSpec通过两条 CEL 校验规则约束合法性zones数量必须小于等于count若配置了stretchCluster则其zones数量必须等于 3stretchCluster zones must be equal to 3StretchClusterSpec包含failureDomainLabel失效域标签如 zone、subFailureDomainzone 内的次级失效域默认host、以及zones列表MonZoneSpec包含name、arbiter是否为仲裁区、以及可选的volumeClaimTemplate该 zone 独立的 PVC 模板。4.1 判定与 zone 分配Rook 通过ClusterSpec.IsStretchCluster()判定是否启用 stretch 模式只要stretchCluster.zones列表非空即视为 stretch cluster若未列出任何 zone则不作为 stretch cluster 处理若 zone 数量不是 3则视为配置错误集群不会被配置成功。对应实现见 pkg/apis/ceph.rook.io/v1/cluster.go。operator 会持续跟踪每个 mon 所属的 zonezone 分配信息存放在rook-ceph-mon-endpointsConfigMap中数据结构与带节点亲和node affinity的 mon 的主机分配一致。例如三个 zone 名为arbiter、zone1、zone2时ConfigMap 内容形如data: data: a10.99.109.200:6789,b10.98.18.147:6789,c10.96.86.248:6789,d10.96.86.249:6789,e10.96.86.250:6789 mapping: {node:{a:arbiter,b:zone1,c:zone1,d:zone2,e:zone2}} maxMonId: 4mon 的失效域标签取值逻辑在 pkg/operator/ceph/cluster/mon/spec.go 的GetFailureDomainLabel中stretch 模式下优先取stretchCluster.failureDomainLabel否则回退到 K8s 标准 zone 标签topology.kubernetes.io/zone。mon Pod 还会被打上zone标签spec.go供调度与服务发现使用。4.2 Mon 故障切换Mon Failoverstretch cluster 中 mon 的故障切换遵循同 zone 替换原则某个 mon 失效后新 mon 会在原 mon 所在的 zone 内重建从而始终保持仲裁区 1 个 数据区各 2 个的拓扑。源码层面pkg/operator/ceph/cluster/mon/health.go 的findExtraMonToRemoveFromStretchCluster会依据 stretch 拓扑收缩多余的 mon仲裁区超过 1 个、或数据区超过 2 个时多余 mon 会被移除而 mon.go 的findAvailableZone则负责在故障切换时为 mon 找到仍缺额如非仲裁区已有 1 个 mon、还差 1 个的 zone。仲裁 mon 的身份会被记录在c.arbiterMon中供后续 stretch 配置使用。4.3 Mon 存储stretch cluster 的 mon 与普通 Rook 集群一样既可以用 hostPath 也可以用 PVC 作为后端存储。以下示例让全部 5 个 mon 共享同一个 PVC 模板mon: count: 5 allowMultiplePerNode: false stretchCluster: zones: - name: arbiter arbiter: true - name: a - name: b volumeClaimTemplate: spec: storageClassName: gp2 resources: requests: storage: 10Gi不同 zone 的 mon 也可能需要不同类型的存储。此时可在zone 级别指定volumeClaimTemplate它将覆盖默认的全局存储设置。例如让仲裁区使用独立的存储后端mon: count: 5 allowMultiplePerNode: false stretchCluster: zones: - name: arbiter arbiter: true volumeClaimTemplate: spec: storageClassName: alternative-storage resources: requests: storage: 10Gi - name: a - name: b volumeClaimTemplate: spec: storageClassName: gp2 resources: requests: storage: 10Gi实现上pkg/operator/ceph/cluster/mon/mon.go 会先判断当前 mon 所属 zone 是否带有独立的volumeClaimTemplate有则优先使用否则回退到全局模板PVC 的构建逻辑AccessModes 固定为 ReadWriteOnce、存储请求缺省值等见 pkg/operator/ceph/cluster/mon/spec.go。设计文档遗留问题是否存在一个 zone 的 mon 使用dataDirHostPath、而其他 zone 使用 PVC 的需求目前的设计假定所有 mon 要么统一使用 PVC、要么统一使用 hostPath不支持混用。5. Rook 自动执行的 Ceph 配置当管理员通过 CRD 请求 stretch cluster 后Rook 会在 mon 编排阶段自动完成三件事对应 pkg/operator/ceph/cluster/mon/mon.go 的configureStretchCluster切换 mon 选举策略为新的 connectivity 算法mon election default strategy: 3为每个 mon 设置所在 zone使 Ceph 将 mon 关联到正确的失效域ceph mon set_location mon zone启用 stretch 模式$ ceph mon enable_stretch_mode tiebreaker_mon mon new_crush_rule rule dividing_bucket zone这些命令在 Rook 源码中有精确对应pkg/daemon/ceph/client/mon.go 的EnableStretchElectionStrategy执行mon set election_strategy connectivity。值得注意的是Ceph Squid 及之后版本一旦启用 stretch 模式就拒绝再修改选举策略因此 Rook 会先读取mon dump判断 stretch 模式是否已启用未启用才设置选举策略同文件的SetMonStretchTiebreakermon.go执行mon enable_stretch_mode arbiter default-stretch-rule bucketType并对stretch mode is already engaged的幂等错误做了兼容处理SetNewTiebreakermon.go用于故障切换后更换 tiebreaker monCreateDefaultStretchCrushRulemon.go基于failureDomain与subFailureDomain创建默认的 stretch CRUSH 规则默认规则会应用到所有池。启用仲裁ConfigureArbiter的完整流程mon.go还包含严格的先后依赖检查当前mon dump若 stretch 模式已启用且 tiebreaker 未变化则直接返回若 tiebreaker 变了则先set_new_tiebreaker轮询等待 CRUSH map 中出现至少两个目标失效域OSD 完成初始化后最多等待 2 分钟超时后 operator 会重新入队再次尝试等待基于默认 stretch 规则创建的内置.mgr池就绪stretch 模式必须在至少一个 stretch 池存在后才能进入最后执行ceph mon enable_stretch_mode设置 tiebreaker mon。此外readyToConfigureArbiter 会等待 OSD Pod 全部 Running、校验 CRUSH 权重平衡若检测到的失效域多于 2 个会直接报错cannot configure stretch cluster with more than 2 failure domainsCRUSH 权重偏差受 Cephmon_stretch_max_bucket_weight_delta默认 10%约束Ceph v20.2.2即relaxedStretchCrushWeightCheckVersion见 mon.go起允许最多 10% 的权重差异。6. 数据池配置副本与 CRUSH 规则为在 stretch cluster 中获得数据保护所有池都应采用以下配置包括 rbd 存储类对应的CephBlockPool、共享文件系统的CephFilesystem、对象存储的CephObjectStore所使用的池副本数Replica4失效域Failure domainzone每个 zone 存放 2 份副本通过replicasPerFailureDomain: 2指定由一条专用 CRUSH 规则实现apiVersion: ceph.rook.io/v1 kind: CephBlockPool metadata: name: stretchedreplica namespace: rook-ceph spec: failureDomain: zone replicated: size: 4 replicasPerFailureDomain: 2replicasPerFailureDomain在 CRD 类型中的定义见 pkg/apis/ceph.rook.io/v1/types.go。Rook 在创建池前会做严格校验pkg/operator/ceph/pool/validate.gosize必须大于replicasPerFailureDomainreplicasPerFailureDomain必须是size的因子size % replicasPerFailureDomain 0。配套的单元测试覆盖了这些失败场景如 size 与 replicasPerFailureDomain 相等、非因子关系等见 pkg/operator/ceph/pool/validate_test.go。当前 Ceph 的 stretch cluster 尚不支持纠删码Erasure Coded池这是重要的选型限制。7. 端到端示例cluster-stretched.yaml仓库提供了完整可部署的示例 deploy/examples/cluster-stretched.yaml其中包含 CephCluster 与内置.mgr池两个资源核心要点如下apiVersion: ceph.rook.io/v1 kind: CephCluster metadata: name: rook-ceph namespace: rook-ceph spec: dataDirHostPath: /var/lib/rook mon: # stretch 模式必须创建 5 个 mon count: 5 allowMultiplePerNode: false stretchCluster: failureDomainLabel: topology.kubernetes.io/zone # subFailureDomain 是次级放置层级默认 host每个 zone 至少需要两个节点 # 若设为 osd则同一 zone 内的 OSD 可以落在同一节点上 # 若设为 rack 等中间层级则需在节点上额外打相应标签。 subFailureDomain: host zones: - name: a arbiter: true - name: b - name: c mgr: count: 2 cephVersion: image: quay.io/ceph/ceph:v20.2.4 allowUnsupported: true storage: useAllNodes: true useAllDevices: true deviceFilter: placement: # arbiter mon 可以拥有独立的 placement未指定时与其他 mon 相同。 # 本例为仲裁 mon 添加容忍度使其可调度到 control-plane 节点k8s 1.24 及以后使用 # node-role.kubernetes.io/control-plane 污点更早版本为 node-role.kubernetes.io/master。 arbiter: tolerations: - key: node-role.kubernetes.io/control-plane operator: Exists effect: NoSchedule # OSD placement 期望只包含非仲裁 zone osd: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: topology.kubernetes.io/zone operator: In values: - b - c priorityClassNames: mon: system-node-critical osd: system-node-critical mgr: system-cluster-critical disruptionManagement: managePodBudgets: true --- apiVersion: ceph.rook.io/v1 kind: CephBlockPool metadata: name: builtin-mgr namespace: rook-ceph spec: name: .mgr failureDomain: zone replicated: size: 4 requireSafeReplicaSize: true replicasPerFailureDomain: 2 subFailureDomain: host部署方式与普通 Rook 集群一致kubectl create -f deploy/examples/crds.yaml -f deploy/examples/common.yaml -f deploy/examples/operator.yaml kubectl create -f deploy/examples/cluster-stretched.yaml注意该示例至少需要3 个节点两个数据区 一个仲裁区。示例中.mgr池也按 stretch 规则创建size 4、replicasPerFailureDomain 2、failureDomain zone、subFailureDomain host这正是第 5 节所述启用 stretch 模式前必须等待基于默认 stretch 规则的内置池就绪所对应的池其规格与 Documentation/CRDs/Cluster/stretch-cluster.md 文档示例中的写法一致。8. 限制与注意事项综合设计文档与当前实现使用 stretch cluster 前应明确以下边界zone 数量固定为 3mon 数量固定为 5其他配置不会生效CRD 校验直接拒绝见 types.go纠删码池不受支持所有池必须使用 4 副本 replicasPerFailureDomain: 2的复制模式网络延迟受K8s Etcd 5ms往返 10ms上限约束尽管 Ceph mon 可容忍 700ms 往返延迟CRUSH map 中检测到超过 2 个数据失效域时会拒绝配置且各失效域 CRUSH 权重偏差需满足 Ceph 的权重检查v20.2.2 起允许最多 10% 偏差stretch 模式下external mon IDs 配置会被忽略见 pkg/operator/ceph/cluster/mon/health.go 中的警告日志逻辑mon 的存储要么统一使用 PVC、要么统一使用 hostPath暂不支持混用设计文档明确标注的开放问题OSD 的 placement 应显式限定在非仲裁 zone仲裁区不应调度任何 OSD 或数据守护进程。9. 进一步阅读本文主体设计文档design/ceph/ceph-stretch-cluster.md用户文档当前版本Documentation/CRDs/Cluster/stretch-cluster.mdCRD 参考OSD 拓扑标签说明Documentation/CRDs/Cluster/ceph-cluster-crd.md部署示例deploy/examples/cluster-stretched.yamlCRD 类型定义pkg/apis/ceph.rook.io/v1/types.go、pkg/apis/ceph.rook.io/v1/cluster.gomon 编排实现pkg/operator/ceph/cluster/mon/mon.go、pkg/operator/ceph/cluster/mon/health.go、pkg/operator/ceph/cluster/mon/spec.goCeph 命令封装pkg/daemon/ceph/client/mon.go池校验逻辑pkg/operator/ceph/pool/validate.go 及对应测试 pkg/operator/ceph/pool/validate_test.go赞分享云原生存储容器编排运维【免费下载链接】rookStorage Orchestration for Kubernetes项目地址https://gitcode.com/gh_mirrors/roo/rook点击查看免费下载相关推荐Rook 拉伸集群Stretch Cluster实战利用 Arbiter 仲裁节点在双故障域中实现高可用 Ceph 存储Rook 拉伸集群Stretch Cluster实战利用 Arbiter 仲裁节点在双故障域中实现高可用 Ceph 存储 本文基于 Rook 官方文档与仓云原生存储容器编排运维基于 DRBD 的双节点 Rook Ceph 集群搭建指南floating mon 架构与实战基于 DRBD 的双节点 Rook Ceph 集群搭建指南floating mon 架构与实战 本文介绍如何在只有两个物理节点的 Kubernetes/Ope云原生存储容器编排运维Rook 两节点高可用TNF架构解析基于浮动 Mon 与 DRBD 镜像的 Ceph 集群设计Rook 两节点高可用TNF架构解析基于浮动 Mon 与 DRBD 镜像的 Ceph 集群设计 Two Node with FencingTNF是 R云原生存储容器编排运维创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价