通过 REST API 进行动态日志级别控制

https://blueprints.launchpad.net/cinder/+spec/dynamic-log-levels

添加 REST API 以动态控制 Cinder 服务的日志级别。

问题描述

要更改服务的日志级别,需要更改服务的配置文件并重新启动服务。 重新启动可以通过重新启动服务本身或通过 SIGHUP 信号请求内部重新启动来完成。

在某些服务中,重新启动不是什么大问题,API 和调度器,因为它们仅在控制平面中运行,并且不执行长时间运行的操作,但在其他服务中,Volume 和 Backup,这是一个更大的问题,因为它们也在数据平面中,并且重新启动服务可能需要很长时间。

我们应该能够根据需要动态更改服务日志级别,即使它们在重新启动时会恢复到默认值。

能够动态更改日志级别的一个缺点是,我们将不再确定服务在给定时间运行的日志级别,因此我们还需要一种机制来查询服务的当前日志级别。

用例

云用户在使用云时遇到问题并联系支持,因此系统操作员开始查看日志,却发现正确的日志级别不足以确定问题的根本原因,并且需要将日志级别更改为 DEBUG

实现此规范的副作用的另一个用例是,当系统管理员想要确认服务中的消息代理连接时,因为日志级别查询机制可以用作通过消息代理向服务发送的 ping。

提议的变更

建议引入 2 个新的服务 REST API 操作,一个用于在运行时修改调试级别,另一个用于查询它们。 日志级别更改的生命周期将是当前服务运行,因为它们将在重新启动时恢复到配置文件中定义的那些级别。

设置日志级别对于所有 Volume、Scheduler 和 Backup 服务来说是可行的,但 API 服务仅限于接收请求的服务进程,因为目前没有机制将请求传播到其他 API 节点,并且为该功能添加这种机制目前是不必要的复杂性。

这是一个合理的限制,因为 API 服务可以轻松地重新启动而不会影响云,因为它们仅在控制平面中,并且通常以 Active/Active 配置部署。 如果它们没有以 Active/Active 配置部署,那么只有一个 API 服务正在运行,并且无法传播 API 日志级别更改也不是什么大问题。

虽然一些操作员可能更喜欢重新启动 API 服务以更改日志级别,但另一些操作员可能更喜欢直接对所有 API 节点进行动态日志级别更改,跳过负载均衡器以避免重新启动,还有一些人会动态更改一个 API 节点,跳过负载均衡器并向该 API 节点发送测试请求。

设置日志级别的机制应该足够通用,以便在想要进行多次更改时不需要编写脚本。 实现此方法是允许更改所有可寻址服务的日志级别,或按二进制文件和/或服务器进行限制。

还可以决定更改服务中的哪些日志级别,因此我们不仅可以更改 cinder 服务本身的日志级别,还可以更改其库的日志级别(例如,SQLAlchemy 库)。

两种机制都允许设置/查询多个服务,但仅适用于 DB 心跳检测认为正在运行的服务。

备选方案

另一种选择是在修改 cinder.conf 后支持动态重新配置,但这将是一个更大的问题,需要更多的代码更改,虽然它会更强大,但也有一些缺点,因为它需要访问节点才能更改每个服务的配置并触发它们的重新加载。

拥有日志级别 API 的好处是,您无需访问基础设施,因为可以通过 REST API 请求更改,然后检查日志监控服务中的日志。

数据模型影响

REST API 影响

  • 设置日志级别:这将实现为类似于 enabledisable 的服务操作,但将使用 set-log 标识符。 有效 URL /v3/{tenant_id}/os-services/set-log 将在正文中接受以下参数

    • binary(可选):一个字符串参数,指示要更改的服务的二进制文件,它可以采用以下值:cinder-volumecinder-schedulercinder-backupcinder-api*null、空字符串或缺失。 后四种可能性等同于所有服务。

    • server(可选):一个字符串参数,指示要更改的服务器,可以是主机或集群引用 - host@backendcluster@backend -,或者 null、空字符串或缺失,用于匹配 binary 的所有服务器。

    • prefix(可选):一个字符串,指示日志路径的前缀,例如 cinder.sqlalchemy.engine。 如果未提供,将更改所有日志。

    • level(必需):一个字符串,包含要设置的日志级别,不区分大小写,接受的值为 INFOWARNINGERRORDEBUG

  • 获取日志级别:使用 get-log 标识符的服务操作。 有效 URL /v3/{tenant_id}/os-services/get-log 将在正文中接受以下参数

    • binary(可选):一个字符串参数,指示要查询的服务的二进制文件,它可以采用以下值:*、空字符串、nullcinder-volumecinder-schedulercinder-backupcinder-api。 如果缺失或传递了 * 或空字符串,则将使用所有二进制文件。

    • server(可选):一个字符串参数,指示要查询的服务器,可以是主机或集群引用 - host@backendcluster@backend

    • prefix(可选):一个字符串,指示我们要查询的日志路径的前缀,例如 cinder.sqlalchemy.engine。 如果未提供或传递了空字符串,将检索所有日志级别。

get-log 的示例响应

{
   "log_levels":[
       {
          "binary": "cinder-api",
          "host": "hostname1",
          "levels":{
             "cinder.api": "DEBUG",
             "cinder.api.common": "DEBUG"
             "cinder.db.sqlalchemy.api": "DEBUG"
       },
       {
          "binary": "cinder-scheduler",
          "host": "hostname1",
          "levels":{
             "cinder": "DEBUG",
             "cinder.scheduler.manager": "DEBUG"
             "eventlet": "ERROR"
          }
       },
       {
          "binary": "cinder-volume",
          "host": "hostname2@backend#pool",
          "levels":{
             "cinder": "DEBUG",
             "cinder.volume.drivers.rbd": "DEBUG",
             "sqlalchemy": "WARNING"
          }
       }
   ]
}

安全影响

无,因为它将使用用于 enable、disable 和 freeze 等操作的服务更新访问控制策略…

通知影响

为了审计目的,每次动态日志级别更改时都会发出一个新的通知。

其他最终用户影响

性能影响

除了更改为更高日志级别(例如 debug)时可能的日志量增加之外,没有其他问题。

其他部署者影响

无。

开发人员影响

实现

负责人

主要负责人

Gorka Eguileor (geguileo)

工作项

  • 在服务上添加设置 API 端点和机制

  • Cinder 客户端支持 set 操作

  • 在服务上添加获取 API 端点和机制

  • Cinder 客户端支持 get 操作

依赖项

测试

新 API 行为的单元测试。

文档影响

只需要记录 API 的更改。

参考资料