Neutron 资源诊断

RFE: https://bugs.launchpad.net/neutron/+bug/1507499

问题描述

云软件复杂且问题不可避免。Neutron 也不例外。为了应对今天的情况,我们有辅助脚本 [1]、博客 [2]、诊断工具 [3]、树外插件实用程序 [4] 等,所有这些都可以从额外的 Neutron 诊断数据 API 中受益。虽然我们当然不希望 Neutron 成为一个新的诊断系统,但其他项目 [5] 发现暴露一定程度的诊断数据对用户(通常是操作员)来说是有价值的,以便深入了解内部情况。

同样,Neutron 提供了一系列由异构技术支持的资源。因此,跨越这个多样化领域标准化一组具体的诊断并非易事。此外,Neutron 资源可以通过多个组件(插件、代理)在多个节点(主机)上实现。因此,任何收集资源诊断数据的提案都必须相应地计划,以支持多个潜在的、不同的诊断参与者。

提议的变更

本规范建议交付一个诊断框架,该框架由以下高级结构组成

  • 诊断检查,实际上是微型插件,包含具体的逻辑来执行给定资源类型(例如 端口网络 等)的诊断检查,以及检查特定元数据,例如检查的名称、描述等。

  • 诊断提供程序,能够发现、管理和执行诊断检查。这些提供程序是诊断的来源,并允许 Neutron 插件和代理与框架无缝集成。

  • 诊断 API 扩展,支持现有 Neutron 资源上的 /diagnostics URI,并通过发现和执行适用提供程序上的检查来服务请求,并将响应汇总。

以下各结构将在后续章节中进行更详细的讨论。

诊断检查

诊断检查实际上是小型插件,提供以下内容

  • 检查特定元数据,包括

    • 检查的唯一名称。

    • (可选)检查诊断的描述。

    • 一个布尔标志,指示检查是必需的还是可选的。

    • 一组资源类型(例如 端口网络 等),检查适用于这些资源类型。

  • 实际的诊断检查逻辑。当为受检查支持的资源类型的特定资源实例收集诊断信息时,将调用此逻辑。检查返回格式良好的响应,包括响应代码、(可选)文本消息等。如果检查支持多种资源类型,其实现可以根据框架传递的资源类型进行区分。

作为这项工作的一部分,将为服务器端和代理端插件提供一个示例检查,说明如何使用该框架。

诊断提供程序

诊断提供程序只是诊断检查的“来源”,包含发现、管理和执行检查的逻辑。希望贡献诊断信息的部署中的服务将因此实现一个诊断提供程序。对于这项工作,我们将为 Neutron 服务以及基于 Neutron 的代理提供一个诊断提供程序绑定。

诊断提供程序具有以下特征

  • 发现和加载已知检查的手段。更多细节将在后续章节中介绍。

  • 已加载检查的内部缓存和公共 API,用于

    • 确定提供程序是否具有给定资源类型或资源类型列表的检查。

    • 列出提供程序具有检查的资源类型。

    • 执行适用于指定资源类型和资源实例的所有检查,收集格式良好的结果并返回它们。

通过这项工作交付的 Neutron 服务器诊断提供程序绑定将作为服务插件实现;希望调用其 API 的使用者可以通过 Neutron 管理器获取插件实例的引用。此外,其他插件可以通过支持扩展并实现所需的诊断方法来充当诊断提供程序。这种方法也适用于无代理插件,并模仿了此类插件在实现中支持扩展时通常的做法。

通过此实现交付的 Neutron 代理基于诊断提供程序绑定将使用代理扩展框架;为所有基于 Neutron 的代理提供支持。但是,由于代理绑定是远程到 Neutron API 服务器的,因此它具有以下显着差异

  • 为了指示代理诊断提供程序支持的资源类型,一组(字符串)资源类型将返回到代理状态报告中并存储在代理数据库中。在代理上,此集合是通过从其管理的检查中收集受支持的资源类型来构建的。在服务器端,API 扩展控制器逻辑可以使用代理的支持资源列表来确定代理是否适用于特定的诊断请求。

  • 调用特定资源类型和资源实例上的检查的公共 API 是可远程调用的,因此可以通过 RPC 调用它们。

诊断提供程序:加载检查

诊断提供程序负责在启动时加载检查(例如,当服务插件启动或代理启动时)。有多种方法可以支持检查插件,包括

  • 将每个检查作为 stevedore 入口点;然后通过驱动程序管理器加载和管理它们。

  • 定义一个特定的检查目录,该目录仅包含 Python 模块,其中每个模块都是一个检查(插件),并从该目录发现 + 导入它们。

  • 静态定义诊断提供程序绑定代码中的检查。这正是它的含义;而不是动态发现 + 加载,而是静态地列出代码中的检查。

上述每种方法都有其优缺点。对于初始实现,我们建议使用后一种方法,即在代码中静态定义检查。虽然这种方法不是最可靠的,但它可以最大限度地减少复杂性,并允许我们更快地获得一个试用版,然后我们可以根据用户的反馈进行迭代。

诊断提供程序:数据模型

如前所述,基于 Neutron 代理的诊断提供程序报告其管理的检查支持的资源类型。这是一个唯一的字符串资源类型列表,通过代理状态报告中的一个新键/值传输。此列表存储在数据库中的一个新表中,在与代理表条目对应的列中,名为 diagnostic_resource_types

无(默认)或空列表表示代理不提供诊断数据,因此不会被调用来服务诊断请求。Neutron (OVO) 对象将根据需要进行更新。

API 扩展插件

交付的实现将包括一个 API 扩展插件,该插件充当诊断的 REST API 控制器。如 REST API 部分所述,/diagnostics URI 悬挂在现有的 Neutron 资源上,仅支持带有空请求体的 POST,从而触发来自所有适用注册诊断提供程序的诊断数据收集。虽然本规范建议在初始实现中同步运行诊断收集,但未来的工作可以使收集作业基于后台异步运行。

以下伪代码概述了控制器处理请求的逻辑

  • 从 Neutron 管理器获取所有支持诊断扩展的插件实例的列表,并将其过滤为仅支持所述资源类型的插件。

  • 从数据库获取所有活动代理的列表,并将其过滤为仅在其 diagnostic_resource_types 列中具有所述资源类型的代理。

  • 从支持给定资源类型的插件和代理提供程序列表中,调用其 API 来运行其了解的检查,针对所述资源类型和资源实例。

  • 收集诊断结果,将其汇总成一个漂亮的响应并将其返回给调用者。

REST API

启用后,此实现将在 Neutron 资源上悬挂一个 /diagnostics URI。此 URI 支持的唯一 HTTP 方法是 POST(带有空请求体),它会触发来自所有适用注册诊断提供程序的诊断数据收集。虽然本规范建议在初始迭代的实现中同步运行诊断收集,但未来的工作可以使收集作业基于后台异步运行。

诊断 URL 的通用形式是

POST /v2.0/{resource}/{resource_id}/diagnostics

响应是诊断(字典)对象的列表,每个 诊断 一个对象。诊断是检查的 {resource} 的一个方面,包含一个 描述 以及一个诊断 状态 对象和为所述诊断运行的单个 检查 列表。诊断框架根据所述资源 诊断 的所有检查的结果设置诊断 状态

返回的每个诊断的 检查 数组包括有关检查的高级详细信息,例如 名称描述提供程序。此外,检查根据其检查执行的结果报告其自身的 状态。如果检查不成功,则检查必须返回一个 修复,以描述修复失败检查的潜在方法。

框架处理诊断级别的 状态,可以是以下之一

  • OK:诊断的所有检查都成功。

  • ERROR:一个或多个检查失败。

  • INACTIVE:一个或多个提供程序处于非活动状态,无法调用以运行诊断检查。

  • DEGRADED:检查可以注册为可选。如果检查是可选的并且失败,或者处于 INACTIVE 状态,则诊断状态将为 DEGRADED

例如

POST /v2.0/subnets/315ec9bb-34f5-4f7a-a44c-b13015a26803/diagnostics
EMPTY POST BODY
==> All successful DHCP diagnostics
{
    "diagnostics": [
        {
            "diagnostic": "dhcp",
            "description": "Neutron network DHCP diagnostics.",
            "status": {
                "code": "DS000",
                "label": "OK",
                "message": "All checks completed successfully."
            },
            "checks": [
                {
                    "name:": "check1",
                    "description": "Check1 does this and that.",
                    "status": {
                        "code": "DS000",
                        "label": "OK",
                        "message": null
                    },
                    "provider": {
                        "name": "DHCP Agent",
                        "host": "dhcp-host1"
                    },
                    "remediation": {}
                },
                {
                    "name:": "check2",
                    "description": "Check2 does cool stuff.",
                    "status": {
                        "code": "DS000",
                        "label": "OK",
                        "message": null,
                    },
                    "provider": {
                        "name": "DHCP Agent",
                        "host": "dhcp-host2"
                    },
                    "remediation": {}
                }
            ]
        }
    ]
}

POST /v2.0/subnets/315ec9bb-34f5-4f7a-a44c-b13015a26803/diagnostics
EMPTY POST BODY
==> A failed dhcp diagnostic
{
    "diagnostics": [
        {
            "diagnostic": "dhcp",
            "description": "Neutron network DHCP diagnostics.",
            "status": {
                "code": "DS002",
                "label": "ERROR",
                "message": "Check 'check1' failed. See the check details for more info."
            },
            "checks": [
                {
                    "name:": "check1",
                    "description": "Check1 does this and that.",
                    "status": {
                        "code": "DHCPE001",
                        "label": "ERROR",
                        "message": "The dnsmasq process is not running."
                    },
                    "provider": {
                        "name": "DHCP Agent",
                        "host": "dhcp-host1"
                    },
                    "remediation": {
                        "code": "DHCPR001",
                        "message": "Re-enable DHCP for this network, then rerun this check."
                    }
                },
                {
                    "name:": "check2",
                    "description": "Check2 does cool stuff.",
                    "status": {
                        "code": "DS000",
                        "label": "OK",
                        "message": null,
                    },
                    "provider": {
                        "name": "DHCP Agent",
                        "host": "dhcp-host2"
                    },
                    "remediation": {}
                }
            ]
        }
    ]
}

/diagnostics 的访问控制通过标准策略定义处理。默认访问控制是 admin_only,但操作员可以根据需要在 policy.json 中更改此设置。

好处

这项工作的的主要目的是启动 Neutron 中的诊断并开始构建管道,但此功能对于使用者和树外插件来说也立即有价值。

例如

  • python-don 项目 [3] 可以实现用于其分析中使用的数据的诊断数据收集。

  • vmware-nsx 插件可以将一些操作员 CLI 功能 [4] 迁移到诊断数据中。

  • 可以增强实现以收集类似于 Nova 诊断 [5] 收集的接口统计信息。

未来工作

  • 一旦 API 稳定,可以添加一个 CLI 来支持诊断。

参考资料