Mistral Notifications¶
https://blueprints.launchpad.net/zaqar/+spec/mistral-notifications
允许一条 Zaqar 队列中的消息通过 Zaqar 通知机制触发 Mistral 工作流。
问题描述¶
云应用程序的开发者期望能够构建自主的云应用程序。也就是说,能够通过访问云的 API 来操作自身基础设施来管理自身的应用程序。(例如,自动伸缩和自动恢复。)这是云平台与简单虚拟化平台之间的主要区别之一(另一个是多租户)。为此需要集成两个部分,而此蓝图的目的就是实现这些集成。
第一点是应用程序必须能够从云接收信息。例如,一个 Aodh 警报指示服务器过载。这些通知必须是异步的,因为云是多租户的,不能阻塞等待任何一个用户应用程序的确认。它们还必须表现出队列语义,具有至少一次传递和高持久性,因为如果应用程序错过来自云的通知,可能会变得不可靠。并非巧合,Zaqar 在公共的、经过 Keystone 认证的 API 中提供了这些语义,该 API 可供应用程序访问,因此是一个自然的选择。因此,许多 OpenStack 项目已经开始将用户通知分发到 Zaqar,并且预计未来会有更多项目加入。Aodh 警报已经支持 Zaqar 作为目标,Heat 也可以推送堆栈和资源事件以及关于用户钩子被触发的通知到 Zaqar。
第二点是应用程序必须能够执行任意且任意复杂的动作。这是因为在实践中,像自动伸缩和自动恢复这样的情况下的正确做法是特定于应用程序的。还有整个宇宙的特定于应用程序的动作是用户可能想要创建的。当然,应用程序可以在使用 Nova 配置的服务器上运行这些动作,但这通常会使事情变得更加复杂(并且通常更昂贵)。例如,在正在进行自动恢复的服务器上托管自动恢复代码,同时保持可靠性非常困难。最后,OpenStack 使得向使用 Nova 配置的服务器提供适当的 Keystone 凭证变得困难。Mistral 通过提供一种轻量级、多租户的方式来可靠地运行潜在的长期运行的进程来解决这些问题,这些进程可以访问 OpenStack API 以及许多其他动作(其中一些,例如发送电子邮件和 Webhook,类似于 Zaqar 的通知)。
构建完全自主应用程序的缺失环节是 Zaqar 队列上的消息能够触发 Mistral 工作流(可能但不一定调用其他 OpenStack API)。这将为云应用程序的开发者提供一种极其灵活的方式来连接事件驱动的、特定于应用程序的、自主的动作。
提议的变更¶
为 Mistral 创建一个 Zaqar 通知接收插件。向此接收发送通知的效果是创建一个 Mistral 工作流 Execution(即触发一个预先存在的 Mistral 工作流)。
subscriber URI 应该是 Mistral executions 端点的 URL,URI 方案为 trust+http 或 trust+https。例如,trust+https://mistral.example.net/v2/executions。此方案指示 Zaqar 应该创建一个 Keystone trust,允许它代表用户在未来对 Mistral 进行 API 调用。trust ID 将在存储之前插入到 URL 中,形式为 trust+http://trust_id@host/path。这种形式是对 Aodh 使用的一种的建模。
trust 的生命周期应该略长于订阅的 TTL,或者如果没有订阅的 TTL,则为无限期。Zaqar 必须在删除订阅时删除 trust。
发送通知时,Zaqar 将使用它自己的服务用户 token 和存储在 URL 中的 trust ID 从 Keystone 检索 trust token。这样获得的 trust token 应该包含正确的租户信息,以便代表原始用户进行请求。
由于将来 Zaqar 可能希望使用 trust+http 请求到其他 API 端点,因此它应该在不仅仅是 URI 方案上进行区分。当创建订阅时,Zaqar 应该需要使用 Keystone catalog 获得的 Mistral executions 端点 URL 来比较 URI,以便区分 Mistral 工作流触发器和普通的 Webhook。幸运的是,URL 对于给定的云是固定的,因此 catalog 可能只需要读取一次,并且从那时起就可以进行简单的字符串比较。
options 字典应该包含以下键
workflow_id- 要触发的工作流的 IDparams- 一个参数字典,具体取决于工作流类型。例如,一个“反向工作流”需要一个task_name参数来定义目标任务。input- 一个任意的键值字典,作为输入传递给通过此通知触发的每个工作流执行。
创建 Mistral execution 时,消息的内容和(稍后)消息 ID 将传递到环境(params 中的 env 键)。这允许工作流访问消息数据,但不需要它声明特定的输入(因此可以使用通知来触发任何工作流)。将消息内容解释为 JSON 后,将传递到名为 notification 的 Mistral 环境变量中。当 Zaqar 支持在通知中传递消息 ID 时,它将作为 Mistral 环境变量 notification_id 发送。如果这些名称与 params 中用户传递的 env 冲突,则用户提供的数据将被消息中接收到的数据覆盖。 env 中的任何其他键都将被保留。如果用户没有指定 env,则将创建一个。
虽然所有数据都可用于进行原始 HTTP 请求,但如果这些调用通过 python-mistralclient 库进行,则更可取。
备选方案¶
与其使用推送模型,即 Zaqar 接收消息并通知 Mistral,也可以使用拉取模型,即 Mistral 轮询 Zaqar 主题以获取消息。但是,虽然 Zaqar 通知实现已经存在,但 Mistral 中没有这样的现有组件适合轮询触发器。它需要轮询不同租户中的大量主题。类似的方案被考虑过并被 Zaqar 的通知功能拒绝;相同的论点也适用于此处。
另一种身份验证方法可能是使用预签名 URL,这些 URL 位于 Mistral 路线图 上。这可能更快地实现,但在长期来看,Keystone trust 可能更可取。
与其白名单 Mistral executions URL,不如可以使用 trust+http 方案来对任何 OpenStack 端点进行请求。但是,通常使用 options 字典中的静态信息与消息内容结合以获得调用参数的正确方法对于每个 API 而言都不同。由于 Mistral 已经可以调用大多数 OpenStack API 并支持一种用于使用来自通知和其他输入的计算参数的语言(YAQL),因此最简单的方法是让用户将他们希望进行的任何其他 OpenStack API 调用封装在 Mistral 工作流中(这也允许他们定义自定义错误处理)。
如果有一种方法可以在不一定需要 URL(包含关于端点位置的冗余信息)的情况下使用 URI 来标识 OpenStack 资源,那将会很好。AWS 使用一个 非官方的 URN 样式的标识符,带有 arn:(而不是 urn:)方案用于此目的。在 OpenStack 的其他上下文中,类似的东西也可能很有用(例如,在 Heat 中,我们希望能够区分 Swift 容器中的文件或 Glare 链接和用于上传用户数据的普通 HTTP URL,尽管在 Swift 的情况下已经有一些先例使用 swift+http 作为方案)。但是,这至少需要广泛的跨项目协议(并且可能需要 IANA 注册)。OpenStack 中没有类似的东西的现有示例。
实现¶
负责人¶
这是一个我抛出来看看谁会接手的蓝图。
里程碑¶
- 完成目标里程碑
Newton-3
工作项¶
实现 Mistral 通知插件
在设置
trust+http(s)通知时,创建一个 Keystone trust 并将其 ID 存储在 URI 中。删除通知时再次删除 trust。添加区分 Mistral URL 和其他
trust+http(s)URL 的能力,这些 URL 位于通知 URI 中
依赖项¶
在 https://review.opendev.org/#/c/276968/ 或类似内容合并之前,我们无法传递消息 ID。但是,由于稍后可以将它添加到 Mistral 环境中,而无需重写任何现有工作流(以声明新的输入),因此这绝不是一个障碍。
注意
本作品采用知识共享署名 3.0 非移植许可协议授权。 http://creativecommons.org/licenses/by/3.0/legalcode