XenAPI
#!wiki caution '''Warning''' This is the original blueprint for the XenAPI development. It is now 18 months out of date. It is only here for historical purposes now. If you want documentation about how Xen``Server / XCP works with Open``Stack today, please see https://wiki.openstack.org/XenServer/XenXCPAndXenServer.
- Launchpad Entry: NovaSpec:austin-xenapi
- 创建: 2010年9月7日
- 最后更新: 2010年10月16日
- 贡献者: Ewan Mellor
总结
XenServer: Commercial, supported product from Citrix.
Xen Cloud Platform (XCP): Open-source equivalent of XenServer (and the development project for the toolstack). Everything said about XenServer below applies equally to XCP.
XenAPI: The management API exposed by XenServer and XCP.
xapi: The primary daemon on XenServer and Xen Cloud Platform; the one that exposes the XenAPI.
本文档描述了 Nova 对 XenServer 和 XCP 通过 XenAPI 的支持。请注意,这并不意味着对其他基于 Xen 的平台(如 RHEL 5 或 SUSE 提供的平台)的支持。
发布说明
Nova 现在可以使用 XenServer 或 Xen Cloud Platform 作为虚拟化平台。
原理
用户故事
前提条件
OpenStack 项目不会发布 XenAPI.py 模块。用户需要从 http://wiki.xensource.com/xenwiki/XCP_SDK 或 http://community.citrix.com/cdn/xs/sdks 获取该模块。
设计
Nova 与虚拟化平台之间现有的接口是通过 libvirt 实现的,Nova 的计算和监控层会向 libvirt (和 virsh) 发出各种调用。还有一个 libvirt 模拟模块,用于在不向平台发出调用的情况下进行单元测试。
为了添加 XenAPI 支持,我们建议创建一个新的层 (nova.virt),该层抽象了对 libvirt 的调用。通过这个抽象接口,Nova 的主体可以进行虚拟化调用,而无需引用任何特定平台。然后,该接口将由 libvirt (nova.virt.libvirt_conn)、XenAPI (nova.virt.xenapi) 或模拟器 (nova.virt.fake) 的模块实现。
一个特别的需求是让 nova-compute 能够在非特权域中运行。这意味着它从域 0 接收一个单独的 VCPU,可以独立于域 0 进行调度,并且可以在发生故障时立即重启。这意味着 Nova 可以选择自己的 Python 版本,这很重要,因为 XenServer 域 0 仍然默认使用 Python 2.4。这也意味着 nova-compute 中的任何漏洞都不会暴露域 0,虽然这不能阻止大多数恶意行为(一旦你攻破了 nova-compute,你就可以造成各种破坏),但可以防止最危险和最隐蔽的攻击,例如悄悄地修改主机上每个 VM 的块流量。为了实现这一点,virt.xenapi 将仅通过其远程接口与 XenAPI 通信。任何实际上需要在域 0 中运行的操作,例如从 nova-objectstore 或 Glance 流式传输磁盘镜像,都将作为 xapi 插件实现。
未来
XenAPI 支持的 Austin 版本将不包括以下功能。这些功能计划在 Bexar 版本中实现
- Glance 集成
- nwfilter 样式的多租户网络
讨论
Soren Hansen 提问:“我对 libvirt 实际上可以自行支持 XenAPI 感到有些惊讶。因此,我不确定为什么我们需要一个完全独立的 XenAPI 驱动程序?”
“我认为通过整合到 libvirt 会更有益。毕竟,它应该成为/the/开源虚拟化抽象工具包。如果您觉得 libvirt 缺少某些特定功能使其有用,您能否列举这些不足之处,以便我们或许可以投入一些开发资源?”
Ewan Mellor 回复
鉴于 libvirt 旨在成为所有虚拟化平台的通用 API,可以保证它不会支持某些功能。引用 http://libvirt.org/goals.html
“libvirt 的目标:为安全地管理节点上的域提供一个通用的、稳定的层。”
...
这意味着……一些非常具体的能力,如果不够通用,可能不会作为 libvirt API 提供。”
这很好:有人尝试为启动/停止/监控/迁移用例提供这个通用层,并且如果所有你需要的都是 libvirt 可以提供的,那么使用它显然是最简单的。但并非仅仅是那些深奥的东西缺失:libvirt 并不支持很多对 XenAPI 设计至关重要且对 Nova 非常有用的东西。libvirt 对 XenAPI 的支持充其量是表面的。在许多方面,libvirt 的标准模型与 XenAPI 根本不同,这使得它们在实际上不兼容。
示例
池:XenAPI 有一个池的概念,该池由主机组成,代表了对共享存储等决策的锁定域。这种安排的拓扑结构(属于池的主机、池中所有主机共享的存储、池中主机之间的共享网络基础设施)在 XenAPI 中被显式表示。libvirt 没有这样的概念。这对于 Nova 在我们研究迁移场景(例如负载均衡或主机维护)时将非常重要,因为池是可以在不移动 VM 磁盘的情况下执行实时迁移的域。
存储 1:libvirt 在其内部对许多存储类型进行了硬编码(参见 http://libvirt.org/formatstorage.html#StoragePool)。其中一些映射到 XenServer 上的类似存储类型,但没有一个接近我们拥有的高级存储类型,因此你最终要么在 libvirt 层撒谎,要么拒绝表示某些类型。这甚至包括 XenServer 上的默认本地存储,因此这不是一个深奥的角落案例。此外,XenAPI 包含一个扩展机制,允许通过 API 支持新的存储类型。这不能用 libvirt 完成(类型在 virStoragePoolType 枚举中硬编码)。这对于 Nova 来说将很重要,因为我们将要实现与 EBS 或现有 AoE 支持等效的功能。
存储 2:libvirt 的存储模型在脱机管理方面很薄弱且可能存在缺陷。libvirt 通常要求调用者知道特定存储元素的本地路径,因此你最终可能会在网络上传递 '/dev/sdb'。XenAPI 的观点是,不应该发生这种情况;远程客户端不需要知道主机本地路径。为了实现这一点,XenServer 具有一个存储管理层,该层处理连接和断开连接调用,并维护数据中心全局 ID(主机名、IQN、LUN、WWN 等)与相应本地设备之间的映射。使用 libvirt 无法以这种方式管理存储。
错误:XenAPI 使用一种错误报告方案,该方案专为程序化分析和国际化而设计。它返回一个字符串错误代码,以及一个字符串列表,用于提供该错误的参数。这允许客户端智能地响应错误,或正确地国际化错误消息。例如,响应 ["HOST_DISABLED", "<some UUID>"] 允许客户端识别错误和涉及的对象,并在用户界面上突出显示该对象,或者可以简单地转换为“服务器 <hostname> 已经禁用”,或另一种语言的等效翻译。libvirt 具有国际化功能,但在库侧,使用 gettext。这对于客户端应用程序来说很好,但对于 Nova 这样的服务器来说用处不大。现在,Nova 的用户界面 API 在这方面还不够好,但从长远来看,我希望增强用户界面 API,以便将良好的可国际化的错误传递到客户端。
主机插件:XenAPI 具有一个扩展机制,允许你在主机侧安装一个 Python 脚本(通常是这样,但它可以是任何可执行文件),然后通过 XenAPI 调用它。当前 virt.xenapi 实现使用它从 nova-objectstore 将磁盘流式传输到主机。如果使用 libvirt,则无法调用这些插件。这种机制的可用性意味着你的主机端安装可以更轻量级(一个脚本,而不是一个代理),并且你不需要为它单独的 RPC 机制,从而使整体实现更简单。这对于 Nova 来说尤其重要,因为我们将要集成 Glance,并且可能也会用于实现一些关于网络配置和隔离的更有趣的想法。
任务/作业:XenAPI 的任务类返回有关正在运行的任务(即异步操作)的信息。libvirt 将相同的概念作为作业公开。但是,libvirt 的作业绑定到特定的域,因此每个域只能发生一个操作,并且无法表示主机级别的异步操作。XenAPI 也可以异步地执行主机级别操作,因此 Nova 可以运行这些操作而无需占用线程。特别是,主机插件可以异步调用,我们正在使用它进行磁盘流式传输。
VM 状态:libvirt 具有一个 virDomainState 枚举,其中包含各种域状态。正如不久前在 Nova 邮件列表中讨论的那样,这些状态是各种条件的混合:有些是电源状态(VM 是否正在运行、暂停、暂停或停止),一个是状态之间的转换(VM 是否被要求优雅地关闭,但奇怪的是,没有一个用于 VM 被要求优雅地重新启动或暂停),一个是进入电源状态的原因(VM 是否崩溃)。剩下的一个是指 VM 是否被阻止,这是一个每 CPU 属性,而且无论如何,在检索时间尺度远超过该状态存在的粒度的情况下,它都不应该存在于远程 API 中。XenAPI 将这三个主要问题分离为电源状态、正在进行的任务(涵盖重新启动和暂停以及关闭)以及上次关闭原因(涵盖内部和外部关闭或重新启动命令以及崩溃)。关于运行/可运行/阻止的每 CPU 统计信息(以及其他更有用和更微妙的统计信息)以汇总形式收集(如下所述),这比任何尝试使用单个 virDomainState 更有用。这是 libvirt 设计的一个基本部分,即使这是一个基本缺陷,我也看不到它会被修复。任何基于 libvirt 的实现都将受到这种设计缺陷的阻碍。
监控 1:libvirt 包含用于收集每个设备上的块和网络统计信息的 API 调用。这些是单个计数器,给出当前值,这意味着如果客户端想要收集汇总统计信息,则必须一直轮询。Nova 在 monitor.py 中执行此操作,然后将它们聚合到 RRD 中,最终由客户端收集。这是一种昂贵的收集统计信息的方式。XenAPI 包含一个请求汇总 RRD(使用 rrdxport 格式,通过 HTTP)的请求。这意味着客户端请求可以直接传递到主机,并且无需轮询主机并存储中间数据。Nova 将能够直接利用 XenServer 的 RRD,并通过消除轮询来减少主机负载。
监控 2:libvirt 仅包含基本的块和网络 I/O 统计信息,以及一个相当全面的域内存统计信息块。XenServer 具有更丰富的统计信息集合,包括主机级别以及客户机级别统计信息,以及关于 VM 行为的微妙统计信息(例如 VM 浪费周期卡在锁中的比例,表明存在并发危险)。Nova 可以收集所有这些统计信息,而通过 libvirt 会限制你使用基本集合。