使用 Systemd 在 DevStack 中¶
默认情况下,DevStack 以所有服务作为 systemd 单元文件运行。Systemd 现在是几乎所有 Linux 发行版的默认 init 系统,systemd 编码并解决了许多与运行不佳的进程相关的问题。
为什么选择它而不是 screen?¶
screen 模型是为 DevStack 设计的,当时 DevStack 用户要运行的服务数量通常小于 10 个。这使得 screen 热键跳转非常容易。但是,情况已经发生了变化(并非所有服务都可以在 screen 中停止,因为有些服务在 Apache 下运行,通常至少有 20 个项目)
还有一种常见的开发人员工作流程是更改多个服务的代码,并且需要重新启动许多服务才能使更改生效。
单元结构¶
注意
最初,我们实际上希望将其作为用户单元来完成,但是在使用非交互式 shell 下运行存在问题。现在,我们将作为系统单元运行。保留了一些用户单元代码,以防万一我们以后可以切换回来。
所有 DevStack 用户单元都是作为 DevStack 切片的一部分创建的,名称为 devstack@$servicename.service。这使得很容易理解哪些服务是 devstack 运行的一部分,并允许我们使用单个命令禁用/停止它们。
操作单元¶
假设单元 n-cpu 以使示例更清晰。
启用单元(允许其启动)
sudo systemctl enable devstack@n-cpu.service
禁用单元
sudo systemctl disable devstack@n-cpu.service
启动单元
sudo systemctl start devstack@n-cpu.service
停止单元
sudo systemctl stop devstack@n-cpu.service
重新启动单元
sudo systemctl restart devstack@n-cpu.service
查看单元状态
sudo systemctl status devstack@n-cpu.service
一次操作多个单元¶
Systemd 支持单元操作的通配符。要重新启动 devstack 中的每个服务,您可以执行以下操作
sudo systemctl restart devstack@*
或者要查看所有 Nova 进程的状态,您可以执行以下操作
sudo systemctl status devstack@n-*
我们将最终使单元名称更有意义,以便更容易理解您正在重新启动的内容。
查询日志¶
systemd 带来的另一个主要好处是 journald,这是一种集中访问日志的方式(包括通过结构化元数据查询)。用户通过 journalctl 命令访问它。
可以通过 journalctl 访问日志。journalctl 具有强大的查询功能。我们从一些常用选项开始。
跟踪特定服务的日志
sudo journalctl -f --unit devstack@n-cpu.service
同时跟踪多个服务的日志
sudo journalctl -f --unit devstack@n-cpu.service --unit devstack@n-cond.service
或者您甚至可以使用通配符来跟踪所有 nova 服务
sudo journalctl -f --unit devstack@n-*
使用更高精度的时间戳
sudo journalctl -f -o short-precise --unit devstack@n-cpu.service
默认情况下,journalctl 会删除“不可打印”字符,包括 ASCII 颜色代码。要保留颜色代码(可以由适当的终端/分页器解释 - 例如 less,默认值)
sudo journalctl -a --unit devstack@n-cpu.service
在默认分页器中使用输出到终端时,长行将被截断,但可以通过左右箭头键支持水平滚动。您可以通过将 SYSTEMD_LESS 环境变量设置为例如 FRXM 来覆盖此设置。
您可以将输出管道传输到另一个工具,例如 grep。例如,要在 nova 日志中找到服务器实例 UUID
sudo journalctl -a --unit devstack@n-* | grep 58391b5c-036f-44d5-bd68-21d3c26349e6
有关更多信息,请参阅 man 1 journalctl。
调试¶
使用 pdb¶
为了在 systemd 控制的服务中进入常规 pdb 会话,您需要手动调用该过程 - 也就是说,将其从 systemd 的控制之外取出。
发现 systemd 用于运行服务的命令
systemctl show devstack@n-sch.service -p ExecStart --no-pager
停止 systemd 服务
sudo systemctl stop devstack@n-sch.service
在源代码中注入您的断点,例如:
import pdb; pdb.set_trace()
手动调用该命令
/usr/local/bin/nova-scheduler --config-file /etc/nova/nova.conf
某些可执行文件,例如 nova-compute,需要使用特定的组执行。这将在 systemd 单元文件中显示
sudo systemctl cat devstack@n-cpu.service | grep Group
Group = libvirt
使用 sg 工具以该组执行该命令
sg libvirt -c '/usr/local/bin/nova-compute --config-file /etc/nova/nova-cpu.conf'
使用 remote-pdb¶
remote-pdb 在进程受 systemd 控制时有效。
确保您已安装 remote-pdb
sudo pip install remote-pdb
在源代码中注入您的断点,例如:
import remote_pdb; remote_pdb.set_trace()
重新启动相关服务
sudo systemctl restart devstack@n-api.service
remote-pdb 代码在调用 set_trace() 时配置 telnet 端口。尽一切努力命中检测到的代码路径,并检查日志以获取显示侦听端口的消息
Sep 07 16:36:12 p8-100-neo devstack@n-api.service[772]: RemotePdb session open at 127.0.0.1:46771, waiting for connection ...
telnet 到该端口以进入 pdb 会话
telnet 127.0.0.1 46771
有关更多选项,请参阅 remote-pdb 主页。
未来工作¶
用户单元¶
如果我们能将服务作为用户单元来完成,那就太好了,这样就可以清楚地区分作为非 root 运行的代码,以确保以 root 身份运行绝不会意外地作为服务的假设。
也许有一天我们可以弄清楚。
参考¶
Arch Linux Wiki - https://wiki.archlinux.org.cn/index.php/Systemd/User
Python 访问 journald 的接口 - https://www.freedesktop.org/software/systemd/python-systemd/journal.html
Systemd 关于服务文件的文档 - https://www.freedesktop.org/software/systemd/man/systemd.service.html
Systemd 关于 exec 的文档(可用于影响服务运行) - https://www.freedesktop.org/software/systemd/man/systemd.exec.html