Per Process Healthcheck endpoints

https://blueprints.launchpad.net/nova/+spec/per-process-healthchecks

在许多现代部署框架中,应用程序可以暴露一个健康检查端点,以便可以监控二进制文件的状态。Nova 目前没有提供一种原生方式来检查其二进制文件的健康状况,这不利于云监控和维护。虽然我们的基于 WSGI 的 API 二进制文件通过 Oslo 中间件存在有限的健康检查支持,但此蓝图旨在暴露一个本地 HTTP 健康检查端点,以便为所有 Nova 组件一致地解决此功能差距。

问题描述

要监控 Nova 服务的健康状况,需要具备经验来开发和实施一系列外部启发式方法来推断服务二进制文件的状态。

这可以像检查具有心跳的服务的状态一样简单,也可以包括通过看门狗监控日志输出,并在检测到在较长时间内没有输出后重启服务。处理日志以查找已知错误消息并执行补救脚本或其他容易出错的方法也很常见。

这对于没有获得足够的 Nova 操作经验的新 Nova 用户来说也不太友好,他们不知道应该寻找哪些警告信号,例如无法连接到消息总线。然而,Nova 开发人员知道一些重要的健康指标,可以将这些指标作为本地健康检查端点暴露出来,操作员可以使用这些指标。

现有的 Oslo 中间件无法解决此问题,因为

  1. 它只能由 API 和元数据二进制文件使用

  2. 如果服务托管在 Apache 等 WSGI 服务器上,中间件无法告诉你服务是否正常运行,因为中间件独立于 WSGI 应用程序执行。例如,中间件可以通过,但 nova-api 无法连接到数据库,并且以其他方式损坏。

  3. Oslo 中间件在详细模式下会泄露有关主机 Python 内核、Python 版本和主机名的信息,这些信息可用于确定主机是否容易受到 CVE 的攻击,这意味着它绝不能暴露在互联网上。例如:

platform: 'Linux-5.15.2-xanmod1-tt-x86_64-with-glibc2.2.5',
python_version: '3.8.12 (default, Aug 30 2021, 16:42:10) \n[GCC 10.3.0]'

用例

作为操作员,我想要一个简单的 REST 端点,我可以用来了解 Nova 进程是否正常。

作为操作员,我希望此健康检查不要影响服务的性能,以便可以以短间隔频繁地查询它。

作为部署工具的实现者,我希望健康检查是本地的,不需要依赖其他主机或服务来运行,以便我可以将其与 systemd 或 Docker 等服务管理器集成。

作为打包者,我希望使用健康检查端点不需要特殊的客户端或软件包来使用它们。cURL、socat 或 netcat 应该是连接到健康检查并检索服务状态所需要的一切。

作为操作员,我希望能够使用 Nova API 和元数据服务的健康检查来自动管理负载均衡器或反向代理中端点的成员资格。

提议的变更

定义

TTL:健康检查项有效的时间间隔。

pass:所有健康指标均通过,并且它们的 TTL 未过期。

warn:任何健康指标的 TTL 已过期,或者存在部分瞬态故障。

fail:任何健康指标都报告错误,或者所有 TTL 都已过期。

Warn vs fail

通常,如果任何健康检查指标都失败,则应将服务报告为 fail,但是如果特定的错误条件是可恢复的或只是部分故障,则可以使用并应使用 warn 状态。

例如,如果服务与消息总线失去连接。当连接丢失时,它应该进入 warn 状态,如果第一次尝试重新连接失败,它应该进入 fail 状态。瞬态故障应被视为警告,但持续错误应升级为故障。

在许多情况下,外部管理系统会将 warnfail 视为等效,并发出警报或重启服务。虽然此规范没有指定如何从降级状态恢复,但包含描述为什么进入 warnfail 状态的人类可读描述非常重要。

处于 warn 状态的服务在大多数情况下仍然被认为是健康的,但它们可能很快会失败或部分降级。

代码变更

将创建一个新的顶级 Nova 健康检查模块,以封装实现此功能所需的通用代码和数据结构。

将引入一个新的健康检查管理器类,该类将维护健康检查状态以及所有与检索、更新和汇总该状态相关的函数。

健康检查管理器将负责在 nova.conf 中启用时创建健康检查端点,并通过 HTTP 暴露健康检查。

初始实现将支持通过 TCP 的 HTTP,并可选地支持 UNIX 域套接字作为更安全的替代方案,稍后添加。在两种情况下,HTTP 端点都将是未经过身份验证的,并且响应将采用 JSON 格式。

将引入一个新的 HealthcheckStausItem 数据类来存储单个健康检查数据点。HealtcheckStatusItem 将包含健康检查的名称、其状态、记录时间以及可选的输出字符串,如果状态为 warnfail,则应填充该字符串。

将引入一个新的装饰器,该装饰器将自动从 Nova 上下文对象检索健康检查管理器的引用,并根据被装饰的函数是否引发异常来更新结果。异常列表和健康检查项名称将是可指定的。

装饰器将接受健康检查的名称作为位置参数,并在失败时将异常消息作为健康检查的输出包含在内。请注意,为了简单起见,装饰器仅支持 pass 或 fail 状态;如果 warn 是合适的,则应编写手动检查。如果多个函数充当相同功能的指示器,则应使用相同的名称。

例如:

@healthcheck('database', [SQLAlchemyError])
def my_db_func(self):
    pass

@healthcheck('database', [SQLAlchemyError])
def my_other_db_func(self):
    pass

默认情况下,装饰器将捕获并重新引发所有异常。

此规范暴露的新 REST 健康检查端点最初仅支持一个 URL 路径 /health/health 端点将在其响应中包含一个 Cache-Control: max-age=<ttl> 标头,客户端可以选择使用该标头。

如果需要,端点还可以在初始实现完成后稍后实现一个简单的递增 etag。最初不提供 etag,因为预计响应会很小且查询成本低廉,因此 etag 实际上不会从性能角度提供太多好处。

如果实现,每当服务状态发生变化时,etag 将会递增,并且在服务重启时将重置为 0。

将来可能会支持其他 URL 路径,例如检索正在运行的配置或触发生成 Guru Meditation Reports 或启用调试日志记录。但是,超出 /health 的任何端点都超出此规范的范围。 / 不用于健康检查响应,以便将来支持其他路径。

Example output

GET /health HTTP/1.1
Host: example.org
Accept: application/health+json

HTTP/1.1 200 OK
Content-Type: application/health+json
Cache-Control: max-age=3600
Connection: close

{
    "status": "pass",
    "version": "1.0",
    "serviceId": "e3c22423-cd7a-47dc-b6e9-e18d1a8b3bdf",
    "description": "nova-api",
    "notes": {"host": "controller-1.cloud", "hostname": "controller-1.cloud"}
    "checks": {
        "message_bus": {"status": "pass", "time": "2021-12-17T16:02:55+00:00"},
        "api_db": {"status": "pass", "time": "2021-12-17T16:02:55+00:00"}
    }
}

GET /health HTTP/1.1
Host: example.org
Accept: application/health+json

HTTP/1.1 503 Sevice Unavailable
Content-Type: application/health+json
Cache-Control: no-cache
Connection: close

{
    "status": "fail",
    "version": "1.0",
    "serviceId": "0a47dceb-11b1-4d94-8b9c-927d998be320",
    "description": "nova-compute",
    "notes": {"host": "controller-1.cloud", "hostname": "controller-1.cloud"}
    "checks":{
        "message_bus":{"status": "pass", "time": "2021-12-17T16:02:55+00:00"},
        "hypervisor":{
             "status": "fail", "time": "2021-12-17T16:05:55+00:00",
             "output": "Libvirt Error: ..."
        }
    }
}

备选方案

与其在数据结构中维护进程的状态并返回缓存的状态,我们可以将健康检查实现为一系列主动探测,例如检查数据库模式版本以确保我们可以访问它,或者向单元协调器或我们自己的服务 RPC 端点发出 ping RPC 调用。

这种方法有一些优点,但如果健康检查被频繁查询或在大型部署中,即使是偶尔的查询也可能由于部署规模而降低数据库和消息总线性能,它将产生负面性能影响。

此规范最初建议使用 OKDegradedFaulty 作为状态字段的值。这些值已更新为 passwarnfail,以与 HTTP API 的健康检查响应格式的 IETF RFC 草案 [1] 对齐。

数据模型影响

Nova 上下文对象将扩展为存储对健康检查管理器的引用。

REST API 影响

虽然此更改将暴露一个新的 REST API 端点,但它不会是现有 Nova API 的一部分。

在 Nova API 中,/health 检查路由最初将不会被使用,以允许那些已经启用 Oslo 中间件的用户继续这样做。在未来的版本中,Nova 保留添加 /health 检查端点的权利,该端点可能或可能不对应于 Oslo 中定义的响应格式。将来可以提供 Oslo 响应格式与健康检查模块之间的转换,但这超出此规范的范围。

安全影响

新的健康检查端点默认情况下将被禁用。启用后,它不会提供任何身份验证或显式访问控制。文档将详细说明启用后,TCP 端点应绑定到 localhost,并且应使用文件系统权限来保护 UNIX 套接字。

TCP 配置选项不会阻止将其绑定到可路由的 IP,如果操作员选择这样做。意图是端点中包含的数据是非特权的,但它可能包含主机名/FQDN 或其他基础设施信息,例如服务 UUID,因此不应从互联网访问。

通知影响

虽然健康检查将使用发送通知的能力作为输入来确定系统的健康状况,但此规范不会引入任何新的通知,因此它不会影响 Nova 中的通知子系统。不添加新的通知,因为这会产生性能开销。

其他最终用户影响

目前,不计划扩展 Nova 客户端或统一客户端来查询新的端点。cURL、socat 或任何其他 UNIX 套接字或 TCP HTTP 客户端可用于调用端点。

性能影响

我们预计性能影响很小或没有,因为我们将采取一种微创方法来将健康指标添加到关键函数,这些函数将在内存中缓存。虽然这会略微增加内存使用量,但预计不会对系统性能产生影响。

其他部署者影响

将在 nova.conf 中添加一个新的配置部分 healthcheck

将引入一个 uri 配置选项以启用健康检查功能。配置选项将是一个字符串选项,支持逗号分隔的 URI 列表,格式如下

uri=<scheme>://[host:port|path],<scheme>://[host:port|path]

例如:

[healthcheck]
uri=tcp://localhost:424242

[healthcheck]
uri=unix:///run/nova/nova-compute.sock

[healthcheck]
uri=tcp://localhost:424242,unix:///run/nova/nova-compute.sock

URI 应该限制在以下字符中 [a-zA-Z0-9_-], 被保留作为分隔符,. 只能在 IPv4 地址中使用,并且 : 用于端口分隔,除非地址是 IPv6 地址。IPv6 地址必须包含在 [] 中。 / 可以与 UNIX 协议一起使用,但是不支持相对路径。这些约束以及 URI 的解析将由 RFC3986 lib 强制执行并提供,该库位于 https://pypi.ac.cn/project/rfc3986/

将添加一个 ttl IntOpt,默认值为 300 秒。如果设置为 0,健康检查项的生存时间将是无限的。如果 TTL 过期,则状态将被视为未知,并且健康检查项将被丢弃。

一个 `cache_control` IntOpt 将被提供,用于设置 `cache_control` 头部中的 `max-age` 值。默认情况下,它将与 TTL 配置选项具有相同的 `max-age`。将其设置为 0 将禁用该头部的报告。将其设置为 -1 将报告 `Cache-Control: no-cache`。任何其他正整数值都将用作 `max-age`。

开发人员影响

开发者应该意识到新的装饰器,并考虑是否应该将其添加到更多函数中,如果该函数是系统健康状况的指标。与外部系统(如 Neutron 端口绑定外部事件)交互导致的故障应谨慎处理。虽然未能接收到端口绑定事件很可能会导致虚拟机无法启动,但它不应被用作 nova-compute agent 的健康指标。这是因为这种故障可能是由于 Neutron 故障,而不是 Nova 故障。因此,其他操作(如 VM 快照)可能不受影响,Nova 计算服务可能仍然正常运行。任何无法连接到非 OpenStack 服务(如消息总线、hypervisor 或数据库)的故障,如果阻止 Nova 二进制文件正常运行,应被视为 `warn` 或 `fail` 健康指标。

升级影响

实现

负责人

主要负责人

sean-k-mooney

其他贡献者

melwitt

功能联络人

功能联络人

sean-k-mooney

工作项

  • 添加新模块

  • 引入装饰器

  • 扩展上下文对象以存储对健康检查管理器的引用

  • 添加配置选项

  • 暴露 TCP 端点

  • 暴露 UNIX socket 端点支持

  • 添加文档

依赖项

测试

这可以通过单元测试和功能测试完全测试,但是,Devstack 将被扩展以暴露该端点并使用它来确定 Nova 服务是否已启动。

文档影响

配置选项将在配置参考中记录,并为该功能添加发布说明。

将在管理文档中添加一个新的健康检查部分,描述当前的响应格式以及如何启用该功能及其预期用途。每当格式更改或超出此规范范围的功能添加时,应更新此文档。

参考资料

历史

修订版

发布名称

描述

瑜伽

引入

2023.1 Antelope

重新提出

2024.1 Caracal

重新提出

2024.2 达尔马提安

重新提出