在重启
systemd-journald
后, 意外的发现, 本台服务器上的其他由 systemd 托管的部分服务, 却意外被 stop 掉了, 由于大部分服务的 unit 文件中都配置了 Restart 规则为 on-failure. 所以如果是异常的退出, 这些服务应该会重启才对. 很明显, 这些服务是被”正常”关闭的.
在查看被 stop 的应用状态时, 发现了以下线索
1 | $ sudo systemctl status kube-apiserver |
code=killed, signal=PIPE
这些信息告诉我们, 这个进程是被SIGPIPE
信号关闭的. 在网上查阅资料时, 发现 github 中大量的项目 issue 下都有相关的问题. 而问题的矛头都指向了systemd-journald
这个服务的重启事件!
问题的原因在于: systemd-journald
这个服务重启的时候, 会给所有的进程发送SIGPIPE
信号, 而在默认的 systemd 定义中, SIGPIPE
信号属于正常退出的范围. 所以即使 unit 文件配置了Restart on-failure
也不会被重启
该问题是 systemd 的已知 BUG 之一. 规避该问题的方式有很多种, 其中以下这种方式并没有生效
1 | $ systemctl show kube-apiserver | grep PIPE |
默认情况下, IgnoreSIGPIPE=yes
是配置好的, 理论上会忽略掉接收到的SIGPIPE
信号, 但实际情况表明, 并没有被忽略
解决方案:
- 在 systemd 的 unit 文件中的
Restart
策略设置为Always
, 这样即使是正常的关闭, 也会重启服务 - 在 systemd 的 unit 文件中配置
RestartForceExitStatus=SIGPIPE
指定收到这个信号时, 强制重启服务
坏消息:
RestartForceExitStatus
的配置在 systemd 215中才被加入, 对于使用之前版本的情况来说, 并没有什么帮助, 可能Always
是唯一的选择
病友:
- https://github.com/influxdata/influxdb/issues/7040
- https://github.com/syncthing/syncthing/issues/2350
- https://github.com/moby/moby/issues/7087
- https://github.com/systemd/systemd/issues/6620
参考文档:
- systemd-journald BUG记录: https://bugs.freedesktop.org/show_bug.cgi?id=84923
- systemd.service 中文手册: http://www.jinbuguo.com/systemd/systemd.service.html