Cinder Volume 活跃/活跃支持 - 复制

https://blueprints.launchpad.net/cinder/+spec/cinder-volume-active-active-support

正如理所当然,复制 v2.1 仅适用于 Cinder 在其设计和实现时可用和支持的部署配置。

现在我们也在支持活跃/活跃配置,这意味着复制无法在新支持的配置上正常工作。

此规范扩展了复制 v2.1 的功能,以支持活跃/活跃配置,同时保留与非集群配置的向后兼容性。

问题描述

在复制 v2.1 中,故障转移请求是基于每个后端发起的,因此当 API 收到故障转移请求时,它会通过异步 RPC 调用使用该服务的主题消息队列将其重定向到特定的卷服务。冻结和解冻操作也是如此。

当卷服务和存储后端之间存在一对一关系时,它可以工作,但当存在多对一关系时,它就无法工作,因为故障转移 RPC 调用只会由形成存储后端集群的一个服务接收,而其他服务不会意识到这种变化,并将继续使用它们之前使用的相同的复制站点。这将导致某些操作成功(那些发送到执行故障转移的服务),而某些操作失败(因为它们发送到不可用的站点)。

虽然这是主要问题,但并非唯一问题,因为我们还需要在集群级别跟踪复制状态。

用例

用户希望拥有具有灾难恢复功能的、高可用性的 Cinder 服务,并使用复制来实现。

仅仅让各个功能独立可用是不够的,因为他们希望同时拥有它们;因此,能够在不作为活跃/活跃部署的情况下使用复制,或者在不使用复制的情况下部署为活跃/活跃,是不够的。

他们可能可以通过停止集群中的所有卷服务(除了一个)来使其工作,发出故障转移请求,并在完成故障转移后重新启动其他服务,但这将不是解决问题的干净方法。

提议的变更

拟议的更改的核心是将驱动程序中的故障转移操作分解为两个单独的操作,一个将处理与存储后端相关的事情,例如在辅助站点上强制提升卷为主站点,另一个将使驱动程序对辅助存储设备执行所有操作。

正如前面提到的,只有一台卷服务会收到故障转移请求,因此通过拆分操作,管理器将能够请求本地驱动程序执行故障转移的第一部分,一旦完成,它将向集群中处理该后端的 所有卷节点发送信号,表明故障转移已完成,并且它们应该开始指向故障转移后的辅助站点,从而解决某些服务不知道应该使用新站点的问题。

这还需要在卷管理器中对驱动程序的新方法进行两个同名的 RPC 调用:failoverfailover_completed

我们还将复制信息添加到 clusters 表中,以便在集群服务中跟踪集群级别的复制。

鉴于当前冻结和解冻操作的使用情况,似乎没有理由进行相同的拆分,因此这些操作将保持不变,并且仅在请求时由一台卷服务执行。

此更改需要供应商更新其驱动程序以支持活跃/活跃配置上的复制,为了避免意外情况,我们将防止卷服务在未支持活跃/活跃机制的驱动程序上启用复制的情况下在活跃/活跃配置中启动。

备选方案

对于 failover_host 方法的拆分机制非常简单,对拟议更改的唯一替代方案是同时拆分解冻和冻结操作。

数据模型影响

将三个新的与复制相关的字段添加到 clusters 表中。这些将与我们当前在 services 表中拥有的字段相同,并将具有相同的含义

  • replication_status:字符串,存储整个集群的复制状态。

  • active_backend_id:字符串,存储当前哪个复制站点处于活动状态。

  • frozen:布尔值,反映集群是否冻结。

这些字段将在 clusters 表和 services 表之间保持同步,以确保一致性。

REST API 影响

  • 将添加一个名为 failover 的新操作,等效于现有的 failover_host,它将在现有的 failover_host 中已经可用的 host 字段之外,支持一个新的 cluster 参数。

  • 集群列表将接受 replication_statusfrozenactive_backend_id 作为过滤器。

  • 集群列表将返回额外的 replication_statusfrozenactive_backend_id 字段。

安全影响

无。

通知影响

无。

其他最终用户影响

客户端将使用新的微版本返回新字段,并且新的过滤器也将可用。

此微版本的故障转移将接受集群参数。

性能影响

新代码对现有部署没有性能影响,因为它只会影响新的活跃/活跃部署。

其他部署者影响

无。

开发人员影响

希望支持活跃/活跃部署上复制的驱动程序必须实现 failoverfailover_completed 方法以及当前的 failover_host 方法,因为它被用于与基本复制 v2.1 的向后兼容性。

支持此的 easiest 方法是用最少的代码实现 failoverfailover_completed,然后基于这些创建 failover_host

def failover_host(self, volumes, secondary_id):
    self.failover(volumes, secondary_id)
    self.failover_completed(secondary_id)

实现

负责人

主要负责人

Gorka Eguileor (geguileo)

其他贡献者

工作项

  • 更改服务启动以使用来自集群或服务的 active_backend_id

  • 添加新的 failover REST API

  • 更新列表 REST API 方法以接受新的过滤字段并更新视图以返回新信息。

  • 更新 DB 模型并创建迁移

  • 更新 Cluster 版本对象

  • 对管理器进行修改以支持新的 RPC 调用。

依赖项

这项工作没有额外的依赖项,除了活跃/活跃机制已经到位之外,事实证明它已经到位了。

测试

将仅实现单元测试,因为没有引用驱动程序实现复制,并且可以在网关中使用。

我们还缺乏一种机制来实际验证复制是否正常工作。

文档影响

从文档的角度来看,除了与 API 更改相关的更改外,将没有太多需要记录的内容。

参考资料