Debian Buster:如何在 systemd 中打开 iscsi 后启动 ZFS

Debian Buster:如何在 systemd 中打开 iscsi 后启动 ZFS

我安装了 Debian 10 (Buster),并从 Backports 添加了 ZFS。我有 4 个 iSCSI-LUN,用作 ZFS 的磁盘。每个 LUN 都有一个单独的 zpool。

到目前为止,ZFS 设置可以正常工作。但系统重启不稳定。有时重启后所有 ZFS 卷都会恢复并正确安装,有时则不会。我认为这种情况发生是因为 ZFS 不会等待 iSCSI 完成。

我试过:

$ cat /etc/systemd/system/zfs-import-cache.d/after-open-iscsi.conf
[Unit]
After=open-iscsi.service
BindsTo=open-iscsi.service
$ systemd-analyze critical-chain zfs-import-cache.service
The time after the unit is active or started is printed after the "@" character.
The time the unit takes to start is printed after the "+" character.

zfs-import-cache.service +1.602s
└─open-iscsi.service @2min 1.033s +286ms
  └─iscsid.service @538ms +72ms
    └─network-online.target @536ms
      └─[email protected] @2min 846ms
        └─apparmor.service @2min 748ms +83ms
          └─local-fs.target @2min 745ms
            └─exports-kanzlei.mount @2min 3.039s
              └─local-fs-pre.target @569ms
                └─keyboard-setup.service @350ms +216ms
                  └─systemd-journald.socket @347ms
                    └─system.slice @297ms
                      └─-.slice @297ms

这并不能解决我的问题。可能是 iSCSI 东西还没有准备好,但已经被 systemd 激活,因此 ZFS 找不到它的设备。

目前唯一非常肮脏的解决方法是制定一些规则/etc/rc.local

systemctl start zfs-import-cache.service
systemctl start zfs-mount.service
systemctl start zfs-share.service
systemctl start zfs-zed.service

zfs mount -a

这可行,但我想要一个干净的解决方案。

我真正不明白的是,让我抓狂的是,Debian 中确实存在/etc/init.d/scriptname单元systemd文件。使用哪一个?sysvinit 还是 systemd?为什么两者都提供?哪一个更好?

所以目前我觉得这里的启动过程不稳定。

答案1

建议的做法可能是使用规则udev,但我不太清楚udev。这是我目前的解决方法(请告诉我如何做得更好):

  1. 为您需要等待的 iSCSI 磁盘设备创建一个服务(/dev/sdb1就我的情况而言):

    $ sudo EDITOR=vim systemctl edit --force --full dev-sdb1.service

  2. 在服务定义中,让 ZFS 依赖它。

  3. 在服务定义中,让它等待设备可用。

3 是棘手的部分。我得到的是:

[Unit]
Description="Monitor the existence of /dev/sdb1"
Before=zfs-import-cache.service
# Requires=dev-sdb1.device
# After=dev-sdb1.device
# I thought this would wait for the device to become available.
# It doesn't, and there appears to be no way to actually do so.

[Service]
Type=oneshot
ExecStart=/bin/sh -c 'while [ ! -e /dev/sdb1 ]; do sleep 10; done'
# pathetic

[Install]
WantedBy=multi-user.target
RequiredBy=zfs-import-cache.service 

显然,最好不使用 shell 脚本来轮询设备。阅读有关设备单元的文档和以下 Stack Exchange 问题的答案后:

并验证启动后是否存在,我预计只需通过添加规则dev-sdb1.device就可以zfs-import-cache.service等待/dev/sdb1

After=dev-sdb1.device
Requires=dev-sdb1.device

到它的定义。这不起作用;它会说服务failed with result 'dependency',不管它是什么意思。我猜想它dev-sdb1.device还不存在,systemd不知道它会很快被创建,而且我找不到指令说“只需等待它”。

替代方法:

  1. 使用路径单元而不是 shell 脚本来等待设备。我还没有尝试过。
  2. 添加udev匹配的规则/dev/sdb/dev/sdb1(如果可能)明确使其设备单元可用。我还没有尝试过;我不明白为什么这会有帮助(设备单元已经在创建中),而且我不知道如何确定这是否会对设备初始化产生任何其他影响并因此破坏任何东西。

相关内容