为节点锁定异常添加重试支持

https://blueprints.launchpad.net/ironic/+spec/add-nodelocked-retry

让我们通过在客户端代表进行多次锁定节点尝试,来减少客户端因与锁定特定节点冲突(节点锁定异常)而出现错误的痛苦。

作为附加好处,这也有助于 tempest 测试,偶尔会在那里看到此错误 [1]。

问题描述

Ironic 客户端在发出某些 REST API 调用时,有时会遇到节点锁定异常/错误。这是因为 conductor(s) 会在执行任何可能更改节点特性的操作之前,获取节点的锁。节点锁定的示例包括

  • 几乎所有的 RPC API 调用(用于满足某些 REST API 请求)都会锁定相关节点,除了:change_node_maintenance_mode、driver_vendor_passthru、get_console_information 和 validate_driver_interfaces。

  • conductor 定期任务以同步电源状态。

  • conductor 定期任务以检查部署超时。

节点锁定的持续时间通常不会很长。我们可以通过简单地重试锁定尝试来消除许多这些错误。诚然,这并不能完全消除问题,但它会使客户端发生错误的概率大大降低,从而提供更好的体验。

提议的变更

TaskManager 类用于控制何时锁定节点。锁本身由数据库后端实现。

我建议我们更改 TaskManager.__init__() 方法以合并重试逻辑,而保持锁的实现(数据库 API 层)不变。这样,如果我们选择更改锁实现,则无需迁移重试逻辑。

备选方案

正在 spec 中讨论一种更永久的解决方案,该解决方案定义了一个异步 REST API [2]

https://review.openstack.org/94923

由于更改 API 所需的工作量,该 spec 预计不会在 Juno 中获得批准。此提案很简单,可以快速实现。

另一种选择是在 RPC 级别实现重试逻辑。这有一个缺点,即会增加 RPC 总线上的流量,并且锁定尝试的等待时间会更长。

第三种选择是更改锁定层本身,并为其提供超时尝试的值。这可能是一个更复杂的更改,如果更改用于锁定的机制,则需要复制该更改。

数据模型影响

REST API 影响

驱动程序 API 影响

Nova 驱动程序影响

安全影响

这可能会根据重试尝试和重试之间的时间间隔的配置值,创建一个 DoS 机会。通过使用强制进行单个锁定尝试的配置值,可以消除这一点。

其他最终用户影响

这对用户唯一的影響是减少了来自 API 请求的节点锁定错误,以及 HTTP 响应的潜在延迟。有关延迟的更多信息,请参阅“性能影响”部分。

可扩展性影响

这有可能对可扩展性产生负面影响。conductor 内生成的 worker 线程如果抛出 NodeLocked 异常,则可能需要更长时间才能处理工作。可以通过增加池中的 worker 数量(workers_pool_size 选项)来减轻这种影响。

性能影响

这会增加对遇到节点锁定错误的 REST API 调用的额外处理时间。这是由于重复调用数据库 API 层以尝试成功锁定节点所致。

如果节点在第一次尝试时成功锁定,则性能不受任何影响。

其他部署者影响

我们应该使用配置变量来控制重试逻辑,以获得最大重试次数和尝试之间的时间间隔。使用合理默认值(设置不执行任何重试尝试的值)应该有助于减轻大部分影响。

建议将以下新的配置变量(及其默认值)添加到 conductor 变量组

  • node_locked_retry_attempts = 3(默认重试 3 次)

  • node_locked_retry_interval = 1(默认尝试之间间隔 1 秒)

node_locked_retry_attempts 的默认值为 3,这可能会影响现有安装在升级时(参见“性能影响”部分),但应该减少遇到的节点锁定错误。

开发人员影响

实现

负责人

主要负责人

<dshrews>

工作项

依赖项

retrying [3] Python 库在这里将非常有用,因为它封装了我们想要的所有逻辑。版本 1.2.2(撰写本文时的最新版本)是我们想要满足的最低版本,因为它包含一个重要的错误修复,与在某些异常上重试有关。

注意:global-requirements.txt 值 [4] 对于 retrying 模块需要进行修改以满足此最低版本要求。

测试

我看不出如何在 tempest 中成功测试这一点(除了消除由于此问题引起的 tempest 中的当前错误),但我认为我们可以添加单元测试来验证它是否按预期工作。

文档影响

参考资料

[1] https://bugs.launchpad.net/ironic/+bug/1321494 [2] https://review.openstack.org/94923 [3] https://pypi.python.org/pypi/retrying [4] https://github.com/openstack/requirements