将 Inspector 分割为 API 和 Worker¶
https://bugs.launchpad.net/ironic-inspector/+bug/1525218
这项工作是 Ironic Inspector 的高可用性 规范的一部分。为了实现 inspector 的高可用性和可扩展性,需要将单个 inspector 服务分割为 API 服务和 worker 服务。本规范重点描述上述工作的重要部分——上述服务之间的内部通信。
问题描述¶
inspector 是一个单体服务,包含 API、后台处理、防火墙和 DHCP 管理。因此,inspector 无法很好地处理大量的 ironic 裸机节点,也不适合大规模部署。引入新服务来解决这些问题也会带来一些复杂性,因为它需要一种内部服务通信机制。
提议的变更¶
节点内省是一个异步任务序列。一个任务可以描述为 inspector 状态机的 FSM 转换 1,由诸如以下事件触发:
starting(wait) -> waiting
waiting(process) -> processing
waiting(timeout) -> error
processing(finish) -> finished
可以异步执行的 API 请求可以被认为是异步任务。正是这些任务允许将服务分割为 API 和 Worker 部分,前者创建任务,后者消费这些任务。这些服务部分之间的通信需要一种媒介,即 队列,这三者共同构成了 消息队列范例。OpenStack 项目使用一种称为 AMQP 的开放标准消息中间件。这种消息中间件,oslo.messaging,使在多台服务器上运行的服务能够相互通信。
每个 inspector worker 提供一个 worker 线程池,该线程池通过队列从 API 服务获取状态转换请求。API 服务调用 worker 上的方法,最终成为一个任务。换句话说,存在 client 角色,由 API 服务执行,以及 server 角色,由 worker 线程执行。服务器通过 oslo.messaging 提供 RPC 接口供客户端使用。
客户端 - inspector API¶
inspector API 将实现一个简单的 oslo.messaging 客户端,该客户端将连接到消息传输并发送带有状态转换事件的消息。
- 方法可以通过两种方式调用,请参阅 2
cast - 方法异步调用,不向调用者返回结果。
call - 方法同步调用,并将结果返回给调用者。
inspector 端点,调用 RPC
方法 |
RPC 类型 |
API |
Worker |
|---|---|---|---|
POST /introspection/<node_id> |
cast |
检查配置状态,验证电源接口,设置 starting 状态,<RPC> cast inspect |
添加查找属性,更新 pxe 过滤器,将 pxe 设置为启动设备,重新启动节点,设置 waiting 状态 |
POST /continue |
cast |
节点查找,检查配置状态,<RPC> cast process |
设置 processing 状态,运行处理钩子,应用规则,更新 pxe 过滤器,保存内省数据,关闭节点电源,设置 finished 状态 |
|
cast |
在缓存中查找节点,<RPC> cast abort |
强制关闭电源,更新 pxe 过滤器,设置 error 状态 |
|
cast |
在缓存中查找节点,<RPC> cast reapply |
获取内省数据,设置 reapplying 状态,运行处理钩子,保存内省数据,应用规则,设置 finished 状态 |
内省的流程如下所示:
Client API Worker Node Ironic
+ + + + +
| <HTTP>Start | | | |
+--inspection---> | | |
| X Validate power| | |
| X interface, | | |
| X initiate task | | |
| X for inspection| | |
| X | | |
| X <RPC> Cast | | |
X +- inspection---> | |
X | X Update pxe | |
X | X filters, set | |
X | X lookup attrs | |
X | X | |
X | X <HTTP> Set pxe | |
X | +-boot dev,reboot+--------------->
X | | | Reboot |
X | | <---------------+
X | | DHCP, boot, X |
X | | Collect data X |
X | | X |
X |Send inspection data to inspector |
X <---------------+----------------+ |
X X Node lookup, | | |
X X verify collect| | |
X X failures | | |
X X | | |
X X <RPC> Cast | | |
X +-process data--> | |
X | X Run process | |
X | X hooks, apply | |
X | X rules, update | |
X | X filters | |
X | X <HTTP> Set power off |
X | +----------------+--------------->
X | | | Power off |
X + + <------------- +
服务器 - inspector worker¶
一个 RPC 服务器暴露 inspector 端点,包含一组可以由客户端通过给定的传输远程调用的方法。传输驱动程序将根据用户的消息配置加载。有关配置选项的更多详细信息,请参阅 3。
一个 inspector worker 将实现一个单独的 oslo.service 进程,并拥有自己的绿色线程池。worker 将定期消费和处理来自客户端的消息。
RPC 可靠性¶
对于客户端通过 cast(异步)发送的每条消息,都会立即发送回确认消息,并且消息将从队列中删除。因此,无法保证 worker 将处理内省任务。
这种模型,称为 最多一次传递,如果 worker 死亡,则不能保证异步任务的处理。
如果 worker 在处理内省数据期间死亡(连接关闭或丢失),则任务请求消息将消失,内省任务将挂在 processing 状态,直到发生 timeout。
备选方案¶
使用 Kombu 库实现我们自己的 Publisher/Consumer 功能。这种方法有一些好处:
支持 至少一次传递 语义。对于每个被消费者检索和处理的消息,都会向消息生产者发送回确认消息。如果未在一定时间内收到此确认消息,则消息将被重新发送
API Worker thread + + | | +--------------------->+ | | | +--------+ | | | | Process| | | Request| | | | | | +------->+ | ACK | +<---------------------+ | | + +如果消费者在不发送确认的情况下死亡,则消息未被处理,如果有其他消费者同时在线,则消息将被重新处理。
另一方面,这种方法也有相当大的缺点:
实现我们自己的 Publisher/Consumer。这意味着支持新功能的复杂性,缺乏与 oslo.messaging 相比的受支持后端,例如 0MQ。
更糟糕的部署者 UX。inspector 中的消息后端配置将与其它服务(包括 ironic)不同,这给部署者带来了一些痛苦。
数据模型影响¶
无
HTTP API 影响¶
端点 /continue 将返回 ACCEPTED 而不是 OK。
客户端 (CLI) 影响¶
无
Ironic python agent 影响¶
无
性能和可扩展性影响¶
提议的更改将允许用户在未来进行更多工作后,水平扩展 ironic-inspector,包括 API 和 Worker。有关更多详细信息,请参阅 Ironic Inspector 的高可用性。
部署者影响¶
新引入的消息总线层需要一些消息代理来连接 inspector API 和 worker。OpenStack 安装中最常用的代理实现是 RabbitMQ,有关更多详细信息,请参阅 5。
为了实现弹性,应将多个 API 服务和 worker 服务实例部署在多个物理主机上。
还添加了新的配置选项,请参阅 3
开发者影响¶
开发人员需要在添加需要作为后台任务处理的新功能时,考虑新的架构和 inspector API 和 Worker 通信细节。
升级和向后兼容性¶
当前的 inspector 服务是一个单一进程,因此部署者可能需要添加更多服务,新添加的 inspector Worker,消息传输后端(RabbitMQ)。控制脚本 ironic-inspector 可以更改为使用 in-memory 后端运行 API 和 Worker 服务,用于消息传输。这允许以向后兼容的方式运行 ironic-inspector - 在单个主机上运行两个服务,而无需消息代理。
依赖项¶
无
测试¶
所有新功能都将通过功能测试和单元测试进行测试。已经运行的 Tempest 测试以及使用 Grenade 进行的升级测试也将涵盖添加的功能。
功能测试同时运行 Inspector API 和 Worker,并使用 in-memory 后端。
完成所有工作项将允许设置多节点 devstack 并最终在集群模式下测试 Inspector。