使用 Tooz 替换本地文件锁

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

目前 cinder-volume 服务只能以 Active/Passive HA 方式运行。其中一些原因是

  • 在 manager 中用于保护资源的文件锁。例如,当从 volume B 创建 volume A 时,会在 B 上创建一个锁,以防止在创建 A 期间删除 B。

  • 在驱动程序(如 RemoteFS 等)中的本地文件锁。这些锁用于阻止不能并发运行的操作(例如,在基于 RemoteFS 的驱动程序中获取快照)。

此蓝图建议切换到使用 Tooz 库进行分布式锁。

问题描述

当前每个 volume 后端只能有一个活动的 cinder-volume 服务。这意味着为了实现其高可用性,我们需要一个外部服务(如 Pacemaker),它会监控 c-vol 的状态,并在之前的实例发生故障时激活新的实例。这也使得 c-vol 无法扩展,因为操作员不能仅仅启动额外的服务来处理高负载,而需要依赖于只有一个实例。

在 c-vol 的 manager 和一些驱动程序中使用的本地文件锁阻止了这一点,因为锁不能在运行在不同主机上的不同 c-vol 服务之间共享。这可能会导致多种问题,甚至导致数据丢失。

用例

操作员希望部署多个 cinder-volume 服务。动机可能是运行多个 cinder-volume,它们连接到单个存储后端,以提高请求吞吐量,从而提高性能。另一个优势是在运行服务的多个实例时,提高了对硬件故障的弹性。

云用户将获得更好的云。

提议的变更

在 Mitaka 设计峰会上,有一个关于 允许项目对 DLM 软件有硬性要求的会议。会议的主要结论是

  • 项目可以硬性依赖于 DLM 的存在。

  • Tooz 将是抽象层。

因此,建议的解决方案是将当前本地锁转换为使用 Tooz 抽象层。

这将需要统一当前的方法(因为一些锁是通过 cinder.utils.synchronized 方法完成的,而另一些则直接使用 oslo.concurrency.lockutils)。默认情况下,Tooz 将配置为使用文件锁,因此一切都将像今天一样工作。如果操作员希望运行多个 cinder-volume 服务,则需要配置 Tooz 后端服务并在 cinder.conf 中设置它。目前最可靠的 Tooz 后端是 ZooKeeper 和 Redis。

Tooz 中的 Redis 后端需要发送周期性的心跳,因此 cinder-volume manager 将启动一个新线程来处理此任务。这将是一个常规线程(非 eventlet),以防止 eventlet green 线程被阻塞。 仅当 Tooz 需要时才打算生成此线程,因此如果使用 FileDriver 或 ZooKeeper 作为后端,则不会执行此操作。

备选方案

为了解决基于 RemoteFS 的 volume 驱动程序中的锁问题,我们可以简单地弃用它们,并让操作员切换到使用无锁驱动程序。但这可能很难实现,因为根据 OpenStack 用户调查,19% 的 Cinder 部署使用这些驱动程序。 此外,一些非 RemoteFS 驱动程序也使用本地锁。

我们也可以用一些基于 DB 的锁来替换当前的锁。 gegulieo 在 specs 中提出了这个建议,以从 managerdrivers 中删除本地锁,但这会增加解决方案的复杂性,并且可能比依赖于广泛使用的 DLM 软件需要更多的测试。

在未来,我们可能希望尝试使用其他方式(例如基于状态的锁)从 volume manager 中删除锁。这将使我们能够在没有 DLM 的情况下以 A/A 方式运行 c-vol(在运行不进行锁定的 volume 驱动程序时)。

数据模型影响

REST API 影响

安全影响

通知影响

其他最终用户影响

性能影响

使用外部服务进行锁会影响性能。 geguileo 进行了一些 性能测试。 此外,心跳线程可能会增加很小的性能开销。

如果用户坚持使用文件锁并决定以今天的方式运行 c-vol,这些将不存在。

其他部署者影响

部署工具将会在 [coordination] 部分拥有新的选项

  • backend_url=file://$state_path - Tooz 后端连接字符串。

  • heartbeat=1.0 - 分布式协调的心跳间隔秒数。

  • initial_reconnect_backoff=0.1 - 失败后重新连接到 Tooz 后端的秒数。

  • max_reconnect_backoff=60.0 - 重新连接到 Tooz 后端的连续重试之间的最大秒数。

部署工具维护者需要决定是否希望使用新的可能性。 如果是,他们需要在其环境中设置一个 Tooz 后端(ZooKeeper、Redis 或不太推荐的 memcached)。

开发人员影响

开发人员只需要通过 Tooz 库抽象层在 cinder-volume 服务中使用锁,并意识到可以运行服务的多个实例。

实现

负责人

主要负责人

Michal Dulko (dulek)

其他贡献者

Szymon Wroblewski (bluex-pl)

工作项

  • Cinder 中的 Tooz 锁实现(已完成)。

  • 将当前锁切换为使用 Tooz 实现。

    • 我们已经完成了一些 工作。 我们应该将其拆分为每个驱动程序,并与驱动程序维护者合作以合并补丁。

  • 添加 DevStack 补丁以设置 CI 测试 Cinder,使用 Redis 或 ZooKeeper 作为 Tooz 后端。

依赖项

测试

将添加 Tooz 代码的单元测试,并配置 CI 以使用 Redis 或 ZooKeeper 作为锁后端来测试 Cinder。 也许我们可以使用 multinode Tempest 来完成此操作。

文档影响

需要更新文档和 Openstack HA 指南,以包含有关如何配置 Tooz 以及以 A/A 方式部署 cinder-volume 的说明。

参考资料