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 状态的服务仍然被认为是健康的,但它们可能很快会失败或部分降级。

code changes

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

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

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

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

将引入一个新的 HealthcheckStausItem 数据类来存储和单个健康检查数据点。HealthcheckSTatusItem 将包含健康检查的名称、其状态、记录时间以及一个可选的输出字符串,如果状态为 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": "contoler-1.cloud", "hostname": "contoler-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": "contoler-1.cloud", "hostname": "contoler-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: ..."
        }
    }
}

备选方案

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

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

此规范最初建议使用 OKDegradedFaulty 作为状态字段的值。这些已更新为 passwarnfail,以与 IETF RFC 草案保持一致,该草案用于 http API 的健康检查响应格式 [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://:424242

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

[healthcheck] uri=tcp://: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_contol intOpt 来设置 cache_contol 标头中的 max-age 值。默认情况下,它将与 ttl 配置选项具有相同的 max-age。将其设置为 0 将禁用报告标头。将其设置为 -1 将报告 Cache-Control: no-cache 任何其他正整数值将用作 max-age。

开发人员影响

开发人员应注意新的装饰器,并考虑是否应将其添加到更多函数,如果该函数是系统健康的指示器。由于与外部系统的交互(例如 neutron 端口绑定外部事件)导致的故障应谨慎处理。虽然未能接收端口绑定事件可能会导致无法启动 vm,但它不应作为 nova-compute 代理的健康指示器。这是因为这种故障可能是由于 neutron 而不是 nova 造成的。因此,其他操作(例如 vm 快照)可能不受影响,并且 nova 计算服务可能仍然是健康的。但是,如果它阻止 nova 二进制文件正常运行,则与非 OpenStack 服务(例如消息总线、hypervisor 或数据库)的任何连接失败都应被视为 warnfail 健康指示器。

升级影响

实现

负责人

主要负责人

sean-k-mooney

其他贡献者

功能联络人

功能联络人

sean-k-mooney

工作项

  • 添加新模块

  • 引入装饰器

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

  • 添加配置选项

  • 暴露 TCP 端点

  • 暴露 UNIX socket 端点支持

  • 添加文档

依赖项

测试

这完全可以使用单元和功能测试进行测试,但是 devstack 将扩展为暴露端点并使用它来确定 nova 服务是否已启动。

文档影响

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

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

参考资料

历史

修订版

发布名称

描述

瑜伽

引入