rootwrap 守护模式

https://blueprints.launchpad.net/neutron/+spec/rootwrap-daemon-mode

Neutron 是一个严重依赖在网络节点上执行需要 Linux 系统 root 权限的操作的项目。目前,这是通过 oslo.rootwrap 实现的,需要使用 sudo 运行。sudo 和 rootwrap 都会产生显著的性能开销。本蓝图涵盖了通过使用 rootwrap 操作的新模式,称为“守护模式”,来减轻 sudo 和 rootwrap 引入的部分开销。

问题描述

正如 Miguel Angel Ajo 在 [2] 中所述

在拥有 1 个公用网络、192 个私有网络、192 个路由器和 192 个纳米 VM 的数据库上,使用 OVS 插件

网络节点设置时间 (rootwrap): 24 分钟

网络节点设置时间 (sudo): 10 分钟

如您所见,rootwrap 与纯粹的 sudo 使用相比,存在巨大的开销,并且大部分开销是由于每个请求所需的漫长的 Python 解释器启动时间造成的。开销的详细信息在 [1] 中介绍。

提议的变更

本蓝图建议采用 oslo.rootwrap 守护模式,该模式允许将 rootwrap 作为守护进程运行。守护进程的工作方式与普通的 rootwrap 相同,但将通过经过身份验证的 UNIX 域套接字而不是命令行接受要运行的命令,并在后台持续运行。rootwrap 守护进程的概述在 [3] 中。

应添加两个新的配置选项

  • rootwrap_mode = daemon | process 将使代理使用守护进程或通常的 rootwrap 进程;默认情况下将启用守护进程。如果守护模式的性能符合我们的预期,则此选项将来可能会被弃用。

  • rootwrap_config 将提供用于运行守护进程的 rootwrap 配置文件路径,默认情况下,它将指向 neutron 提供程序的 rootwrap 文件。

由于 root_helper 在 Neutron 中传递(与其他项目中使用全局配置相反),因此我们必须将 root_helper 作为某种对象,封装所有必要的信息以使用 root 权限运行命令。这是在第一个补丁 [4] 中完成的。

该补丁引入了两个 root helper 类

  • ProcessHelper (基类) 只是按原样运行命令,不带任何包装器;

  • WrappedProcessHelper 使用包装器运行命令,就像 root_helper 选项过去那样。

这些类具有两个接口方法

  • create_process 启动一个进程并返回与之关联的 Popen 实例;

  • execute 启动一个进程(默认情况下使用 create_process),向其提供一些输入并捕获返回码以及 stdout 和 stderr 输出。

请注意,create_processexecute 方法在 neutron.agent.linux.utils 模块中仍然存在,但它们只是预处理参数并将它们传递给 root_helper 的适当方法。

第二步 [5] 将是创建这些配置选项并添加另一个 root helper 类 RootwrapDaemonHelper。该类将为具有相同 rootwrap_config 的所有实例使用一个 rootwrap 客户端。它的 execute 方法将只是调用 rootwrap 客户端的 execute 方法,该方法会将请求传递给守护进程。

请注意,我们当前无法使用守护进程启动长期运行的进程,因此 create_process 将使用普通的 rootwrap 启动该进程。此外,对于长期运行的进程,收益可以忽略不计。

数据模型影响

REST API 影响

安全影响

此更改将启动作为 root 运行的 oslo rootwrap 守护进程,并通过经过良好身份验证(OTP)的 unix 域套接字提供给 neutron。

因此,neutron-rootwrap-daemon 应添加到 sudoers 文件中,并使用与 neutron-rootwrap 相同的设置。

安全性由 oslo-rootwrap 处理,该工具已经经过了充分的验证。

[1] 中涵盖了使用客户端+守护进程而不是纯 rootwrap 的所有安全问题。

通知影响

其他最终用户影响

性能影响

此更改为依赖于调用大量使用 rootwrap 命令的代理程序带来性能提升。当前 rootwrap 守护程序的状态显示,与通常的 sudo rootwrap 调用相比,速度提高了 10 倍以上。代理程序的总速度提升不会那么令人印象深刻,但应该非常明显。rootwrap 守护程序实现包含一个基准测试,该基准测试生成了速度提升结果。

其他部署者影响

此更改引入了两个新的配置变量

  • rootwrap_mode 使用 daemon 作为默认值;

  • rootwrap_config 必须指向部署给 Neutron 的 rootwrap.conf(默认 /etc/neutron/rootwrap.conf)。

请注意,默认情况下 use_rootwrap_daemon 将被关闭,因此要获得速度提升,必须将其打开。启用后,root_helper 配置选项将被忽略,并且 neutron-rootwrap-daemon 将用于运行大多数需要 root 权限的命令。

此更改还引入了新的二进制文件 neutron-rootwrap-daemon,该文件应与 neutron-rootwrap 一起部署,并添加到 sudoers 中。

开发人员影响

社区影响

社区普遍对更快的代理操作感兴趣。

备选方案

  • 不使用 rootwrap 的 sudo,以牺牲安全性为代价,或者通过实现特定的 sudo 插件来允许等效的 rootwrap 过滤。这将需要维护针对 openstack 的 C sudo 插件。

  • 将 rootwrap 重写为 C,但这需要代码审计,并且也偏离了 openstack 社区的标准 python。

  • 自动将 rootwrap 转换为 C++,并获得编译版本,这个选项已经被探索过,并且似乎可以通过 shedskin 进行修改 rootwrap 以避免动态类型来实现。顺便说一下,shedskin 是实验性的,并且一些 python 模块没有实现。此外,生成的 C++ 代码不易于人类阅读,可能需要进行安全评估。此解决方案并不能消除 sudo 性能影响,这并非微不足道。

其他解决方案

其他解决方案主要与 rootwrap 优化有关,并在 [1] 中介绍(其中一些在 [6] 中介绍)。

这并不是 Neutron 方面除了切换到 rootwrap 守护进程之外可以做的唯一选择(有关详细信息,请参阅 [6]

  • 避免 L3 代理中路由器处理中的不必要的锁定

  • 避免不必要的调用

  • 合并系统调用:Carl Baldwin 探索了这个选项,并证明它对代码库来说非常困难和具有侵入性。

所有这些都可以与 rootwrap 守护进程一起完成,因为每次调用守护进程仍然会产生一些开销。

IPv6 影响

实现

负责人

主要负责人
  • twilson (Terry Wilson, otherwiseguy @ freenode)

原始贡献者
  • yorik-sar (Yuriy Taraday, YorikSar @ freenode)

工作项

  • 将 root_helper 调用抽象化为类 - 完成 [4]

  • 实现 rootwrap 守护进程支持 - 完成,需要重新合并 [5]

依赖项

测试

Tempest 测试

此更改不会更改 API,因此不需要额外的集成测试。如果 tempest 对启用 use_rootwrap_daemon 感到满意,则该功能有效。

功能测试

现有的功能测试将在执行代理功能测试时对 rootwrap 客户端进行测试。Rootwrap 也有自己的功能测试,用于 rootwrap 客户端/守护进程组件 [7]

API 测试

不需要 API 测试。

文档影响

用户文档

由于我们包括两个新的配置设置,因此需要正确记录这些设置。

开发人员文档

如果对接口进行了任何更改,开发人员文档可能会更新,以描述如何使用新的接口来执行系统命令。

参考资料